Python 区块链 - 创建矿工

为了实现挖矿,我们需要开发挖矿功能。挖矿功能需要对给定的消息字符串生成摘要并提供工作量证明。让我们在本章中讨论这个问题。

消息摘要函数

我们将编写一个名为sha256的实用函数,用于在给定消息上创建摘要 −

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

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

挖掘函数

我们现在开发mine函数来实现我们自己的挖掘策略。在这种情况下,我们的策略是在给定消息上生成一个以给定数量的1为前缀的哈希值。给定的 1 的数量被指定为 mine 函数的参数,该参数指定为难度级别。

例如,如果您指定难度级别为 2,则给定消息上生成的哈希值应以两个 1 开头 - 如 11xxxxxxxx。如果难度级别为 3,则生成的哈希值应以三个 1 开头 - 如 111xxxxxxxx。鉴于这些要求,我们现在将按照以下步骤开发挖掘函数。

步骤 1

挖掘函数采用两个参数 - message(消息)和difficulty(难度级别)。

def mine(message, difficulty=1):

步骤 2

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

assert difficulty >= 1

步骤 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 语句,该语句打印摘要值以及在从函数返回之前满足条件所需的迭代次数。

测试挖掘函数

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

mine ("test message", 2)

运行上述代码时,您将看到类似于以下的输出 −

after 138 iterations found nonce:
11008a740eb2fa6bf8d55baecda42a41993ca65ce66b2d3889477e6bfad1484c

请注意,生成的摘要以"11"开头。如果将难度级别更改为 3,则生成的摘要将以"111"开头,当然,它可能需要更多次迭代。如您所见,具有更多处理能力的矿工将能够更早地挖掘给定的消息。这就是矿工们相互竞争以赚取收入的方式。

现在,我们准备向我们的区块链添加更多区块。让我们在下一章中学习这一点。