Python Blockchain 简明教程
Python Blockchain - Creating Miners
为了启用挖矿,我们需要开发一个挖矿函数。挖矿功能需要针对一个给定的字符串生成一个摘要,并提供一个工作证明。让我们在本章讨论这些内容。
For enabling mining, we need to develop a mining function. The mining functionality needs to generate a digest on a given message string and provide a proof-of-work. Let us discuss this in this chapter.
Message Digest Function
我们将编写一个名为 sha256 的实用程序函数,用于针对一个给定的字符串创建摘要——
We will write a utility function called sha256 for creating a digest on a given message −
def sha256(message):
return hashlib.sha256(message.encode('ascii')).hexdigest()
sha256 函数采用一个 message 作为参数,将其编码成 ASCII 码,生成一个十六进制摘要,并将值返回给调用方。
The sha256 function takes a message as a parameter, encodes it to ASCII, generates a hexadecimal digest and returns the value to the caller.
Mining Function
现在我们开发一个实现了我们自己挖矿策略的 mine 函数。我们在这种情况下的策略是针对给定的消息生成一个哈希,该哈希以给定的 1 的个数作为前缀。给定的 1 的个数指定为 mine 函数的参数,其指定为难度级别。
We now develop the mine function that implements our own mining strategy. Our strategy in this case would be to generate a hash on the given message that is prefixed with a given number of 1’s. The given number of 1’s is specified as a parameter to mine function specified as the difficulty level.
例如,如果你指定一个难度级别为 2,则针对给定消息生成的哈希应当以两个 1 开始——比如 11xxxxxxxx。如果难度级别为 3,则生成的哈希应当以三个 1 开始——比如 111xxxxxxxx。考虑到这些要求,我们现在将按照以下给定的步骤来开发挖矿函数。
For example, if you specify a difficulty level of 2, the generated hash on a given message should start with two 1’s - like 11xxxxxxxx. If the difficulty level is 3, the generated hash should start with three 1’s - like 111xxxxxxxx. Given these requirements, we will now develop the mining function as shown in the steps given below.
Step 1
挖矿函数采用两个参数——消息和难度级别。
The mining function takes two parameters - the message and the difficulty level.
def mine(message, difficulty=1):
Step 2
难度级别需要大于或等于 1,我们通过以下断言语句来确保这一点——
The difficulty level needs to be greater or equal to 1, we ensure this with the following assert statement −
assert difficulty >= 1
Step 3
我们使用设置的难度级别创建一个 prefix 变量。
We create a prefix variable using the set difficulty level.
prefix = '1' * difficulty
请注意,如果难度级别为 2,则前缀将是“11”,如果难度级别为 3,则前缀将是“111”,以此类推。我们将检查此前缀是否存在于消息的生成摘要中。为了对消息本身进行摘要,我们使用以下两行代码——
Note if the difficulty level is 2 the prefix would be “11” and if the difficulty level is 3, the prefix would be “111”, and so on. We will check if this prefix exists in the generated digest of the message. To digest the message itself, we use the following two lines of code −
for i in range(1000):
digest = sha256(str(hash(message)) + str(i))
我们不断向每个迭代的消息哈希中添加一个新数字 i ,并在组合消息中生成一个新的摘要。由于 sha256 函数的输入在每次迭代中都会发生变化,所以 digest 值也会发生变化。我们检查此 digest 值是否高于已设置 prefix 。
We keep on adding a new number i to the message hash in each iteration and generate a new digest on the combined message. As the input to the sha256 function changes in every iteration, the digest value would also change. We check if this digest value has above-set prefix.
if digest.startswith(prefix):
如果满足条件,我们将终止 for 循环并将 digest 值返回给调用者。
If the condition is satisfied, we will terminate the for loop and return the digest value to the caller.
整个 mine 代码如下所示 −
The entire mine code is shown here −
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 语句,它在返回调用函数之前会打印摘要值和满足条件前需要的迭代次数。
For your understanding, we have added the print statement that prints the digest value and the number of iterations it took to meet the condition before returning from the function.
Testing Mining Function
要测试挖掘函数,只需执行以下语句 −
To test our mining function, simply execute the following statement −
mine ("test message", 2)
当运行以上代码时,看到的输出将与以下内容类似 −
When you run the above code, you will see the output similar to the one below −
after 138 iterations found nonce:
11008a740eb2fa6bf8d55baecda42a41993ca65ce66b2d3889477e6bfad1484c
请注意,生成的摘要以 “11” 开头。如果难度等级更改为 3,生成的摘要将以 “111” 开头,而且当然需要更多的迭代次数了。正如你所见,处理能力越强的矿工越早就能挖到给定的消息。矿工们之间就是以这种方式竞争,以赚取收益。
Note that the generated digest starts with “11”. If you change the difficulty level to 3, the generated digest will start with “111”, and of course, it will probably require more number of iterations. As you can see, a miner with more processing power will be able to mine a given message earlier. That’s how the miners compete with each other for earning their revenues.
现在,我们可以为区块链添加更多的区块了。让我们在下一章学习。
Now, we are ready to add more blocks to our blockchain. Let us learn this in our next chapter.