Python Blockchain 简明教程

Python Blockchain - Creating Miners

为了启用挖矿,我们需要开发一个挖矿函数。挖矿功能需要针对一个给定的字符串生成一个摘要,并提供一个工作证明。让我们在本章讨论这些内容。

Message Digest Function

我们将编写一个名为 sha256 的实用程序函数,用于针对一个给定的字符串创建摘要——

def sha256(message):
return hashlib.sha256(message.encode('ascii')).hexdigest()

sha256 函数采用一个 message 作为参数,将其编码成 ASCII 码,生成一个十六进制摘要,并将值返回给调用方。

Mining Function

现在我们开发一个实现了我们自己挖矿策略的 mine 函数。我们在这种情况下的策略是针对给定的消息生成一个哈希,该哈希以给定的 1 的个数作为前缀。给定的 1 的个数指定为 mine 函数的参数,其指定为难度级别。

例如,如果你指定一个难度级别为 2,则针对给定消息生成的哈希应当以两个 1 开始——比如 11xxxxxxxx。如果难度级别为 3,则生成的哈希应当以三个 1 开始——比如 111xxxxxxxx。考虑到这些要求,我们现在将按照以下给定的步骤来开发挖矿函数。

Step 1

挖矿函数采用两个参数——消息和难度级别。

def mine(message, difficulty=1):

Step 2

难度级别需要大于或等于 1,我们通过以下断言语句来确保这一点——

assert difficulty >= 1

Step 3

我们使用设置的难度级别创建一个 prefix 变量。

prefix = '1' * difficulty

请注意,如果难度级别为 2,则前缀将是“11”,如果难度级别为 3,则前缀将是“111”,以此类推。我们将检查此前缀是否存在于消息的生成摘要中。为了对消息本身进行摘要,我们使用以下两行代码——

for i in range(1000):
   digest = sha256(str(hash(message)) + str(i))

我们不断向每个迭代的消息哈希中添加一个新数字 i ,并在组合消息中生成一个新的摘要。由于 sha256 函数的输入在每次迭代中都会发生变化,所以 digest 值也会发生变化。我们检查此 digest 值是否高于已设置 prefix

if digest.startswith(prefix):

如果满足条件,我们将终止 for 循环并将 digest 值返回给调用者。

整个 mine 代码如下所示 −

def mine(message, difficulty=1):
   assert difficulty >= 1
   prefix = '1' * difficulty
   for i in range(1000):
      digest = sha256(str(hash(message)) + str(i))
      if digest.startswith(prefix):
         print ("after " + str(i) + " iterations found nonce: "+ digest)
      return digest

为了帮助理解,我们添加了 print 语句,它在返回调用函数之前会打印摘要值和满足条件前需要的迭代次数。

Testing Mining Function

要测试挖掘函数,只需执行以下语句 −

mine ("test message", 2)

当运行以上代码时,看到的输出将与以下内容类似 −

after 138 iterations found nonce:
11008a740eb2fa6bf8d55baecda42a41993ca65ce66b2d3889477e6bfad1484c

请注意,生成的摘要以 “11” 开头。如果难度等级更改为 3,生成的摘要将以 “111” 开头,而且当然需要更多的迭代次数了。正如你所见,处理能力越强的矿工越早就能挖到给定的消息。矿工们之间就是以这种方式竞争,以赚取收益。

现在,我们可以为区块链添加更多的区块了。让我们在下一章学习。