# 4 工作量证明 (Proof-of-Work)

## 原文与翻译

To implement a distributed timestamp server on a peer-to-peer basis, we will need to use a proof-of-work system similar to Adam Back's Hashcash[6], rather than newspaper or Usenet posts. The proof-of-work involves scanning for a value that when hashed, such as with SHA-256, the hash begins with a number of zero bits. The average work required is exponential in the number of zero bits required and can be verified by executing a single hash.

For our timestamp network, we implement the proof-of-work by incrementing a nonce in the block until a value is found that gives the block's hash the required zero bits. Once the CPU effort has been expended to make it satisfy the proof-of-work, the block cannot be changed without redoing the work. As later blocks are chained after it, the work to change the block would include redoing all the blocks after it.

The proof-of-work also solves the problem of determining representation in majority decision making. If the majority were based on one-IP-address-one-vote, it could be subverted by anyone able to allocate many IPs. Proof-of-work is essentially one-CPU-one-vote. The majority decision is represented by the longest chain, which has the greatest proof-of-work effort invested in it. If a majority of CPU power is controlled by honest nodes, the honest chain will grow the fastest and outpace any competing chains. To modify a past block, an attacker would have to redo the proof-of-work of the block and all blocks after it and then catch up with and surpass the work of the honest nodes. We will show later that the probability of a slower attacker catching up diminishes exponentially as subsequent blocks are added.

To compensate for increasing hardware speed and varying interest in running nodes over time, the proof-of-work difficulty is determined by a moving average targeting an average number of blocks per hour. If they're generated too fast, the difficulty increases.

## Nonce 生成实战

【Python 知识点】 点击链接跳转至《自学是门手艺》相应知识点

import hashlib
import random
import time

text = "Long bitcoin, short the world."

# 定义 valid 函数，如果生成的 hash 开头有 zero_num 个零，则 nonce 达到要求
def valid(hash,zero_num):
return hash[0: zero_num] == "0" * zero_num

# 通过随机碰撞💥寻找 Nonce 的函数
def find_nonce(text, zero_num):
start = time.time()
find = False
while not find:
nonce = random.randint(1, 10000000)
if valid(hash,zero_num):
print("sha256({} + text) => {}".format(nonce, hash))
print("nonce is {}".format(nonce))
end = time.time()
print("找到 nonce 时间: {}".format(end-start))
find = True

find_nonce(text, 1)

sha256(8676133 + text) => 0ae8c647021d4f38c4325fe38f7474ea6b8ceb851632e40eb0abfddcc472e5df
nonce is 8676133


find_nonce(text, 2)

sha256(4350470 + text) => 00165f427b28a8e8ec8a83e5cab331a43121ef9752a7c821d8a666a4b57f3af9
nonce is 4350470


find_nonce(text, 3)

sha256(7990813 + text) => 000a4e2d72e1d447f9a564d718434db5eaf5ba2690b42207d952a640bfeb1ef9
nonce is 7990813


find_nonce(text, 5)

sha256(8812787 + text) => 000007e8cf2efd2ad71a5e207a112c60d35aef3bc227e707727365d6982d3ae2
nonce is 8812787



1）计算 Nonce 需要花费时间进行随机碰撞，但是验证 Nonce 只需要一次哈希运算；

2）调整难度便是调整「出块速度」。