使用python搭建简易区块链

本篇参考Daniel van Flymen博客,项目地址https://github.com/dvf/blockchain-book

  1. 环境搭建
    安装python3.6以上版本
  2. 创建一个Blockchain类用于管理区块,构造函数中存放用于存储区块的列表和用于存储交易的列表
    class Blockchain:
    def init(self):
    self.current_transactions = []
    self.chain = []
  3. 定义区块,区块中存放索引、时间戳、交易列表、证明和前一个区块的哈希值
    以下为示例
    block = {'index': 1,
    'timestamp': 1506057125.900785,
    'transactions': [
    {'sender': "8527147fe1f5426f9dd545de4b27ee00", 'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f", 'amount': 5, }
    ],
    'proof': 324984774000, 'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"}
    每个区块都包含上一个区块的哈希值,就相当于通过上一个区块的哈希值连接到到上一个区块,这样就形成一个链式结构的区块链。
  4. 创建创世区块(区块链上的第一个区块)
    这里要先引入PoW(Proof of Work),即工作量证明。PoW指系统为达到某一目标而设置的度量方法。简单理解就是一份证明,用来确认你做过一定量的工作。如果想生成一个新的区块并写入区块链,必须解出工作量证明谜题,谁先解出答案,谁就可以写入区块链。
    工作量证明谜题本质是数学问题,引用原博客的观点就是“找到一串解决某个数学问题的数字,这个数字必须符合两个条件:第一,难找;第二,很容易被验证(而且是很容易被任何人验证)。”
    项目中举了一个简单易懂的例子:
    某个整数x乘以另外一个数y,得到的结果的哈希值必须是以 0 结尾。可以简单表示为:hash(x y) = ac23dc...0。所以,我们的目标是找到满足这个条件的一个y值。为了方便理解,我们暂定x=5。
    经过计算得出:hash(5
    21) = 1253e9373e...5e3600155e860
    使用相似的工作量证明方法实现我们的区块链的工作量证明:找到一个数字p,它和前边一个区块的解决数字进行散列,生成前4位为 0 的哈希值。
    def proof_of_work(self, last_block):

last_proof = last_block['proof']
last_hash = self.hash(last_block)

proof = 0
while self.valid_proof(last_proof, proof, last_hash) is False:
proof += 1
return

def valid_proof(last_proof, proof, last_hash):

guess = f'{last_proof}{proof}{last_hash}'.encode()
guess_hash = hashlib.sha256(guess).hexdigest()
return guess_hash[:4] == "0000"

创世区块需要被证明,也就是通过上述的工作量证明完成证明然后进行创建,添加到其中。

  1. 定义添加交易,区块的方法
    def new_block(self, proof, previous_hash):

block = {
'index': len(self.chain) + 1,
'timestamp': time(),
'transactions': self.current_transactions,
'proof': proof,
'previous_hash': previous_hash or self.hash(self.chain[-1]),
}

self.current_transactions = []

self.chain.append(block)
return block

def new_transaction(self, sender, recipient, amount):

self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})

return self.last_block['index'] + 1
在上面的实践中,我们完成了工作量证明,此次我们需要添加增加新区块的方法。区块中存放着索引、时间戳、交易列表、证明和前一个区块的哈希值。添加区块时,需将自己证明的proof以及上一区块的hash值放入其中。因为验证工作量时需要上一区块的hash值以及proof(PoW算法决定)。其他值根据链的情况进行更新(交易列表在后文说明)。最后加入区块链中。
交易时,将交易双方及金额保存到current_transactions。每次创建新节点时保存当前的current_transactions。目前,主流交易数据保存在主链上,区块中存放交易hash值,与本文情况不太一样,如读者对此感兴趣可以查阅相关资料。

  1. 添加挖矿
    def mine():
    last_block = blockchain.last_block
    proof = blockchain.proof_of_work(last_block)

blockchain.new_transaction(
sender="0",
recipient=node_identifier,
amount=1,
)

previous_hash = blockchain.hash(last_block)
block = blockchain.new_block(proof, previous_hash)

response = {
'message': "New Block Forged",
'index': block['index'],
'transactions': block['transactions'],
'proof': block['proof'],
'previous_hash': block['previous_hash'],
}
return jsonify(response)
在上面介绍的proof_of_work方法中,它初步介绍了挖矿的原理。
def proof_of_work(self, last_block):

last_proof = last_block['proof']
last_hash = self.hash(last_block)

proof = 0
while self.valid_proof(last_proof, proof, last_hash) is False:
proof += 1
return
从上一个证明结果proof开始验证。当proof验证不合要求时,就将proof自增,在验证直到结果验证为真。挖矿的原理也就是在不断找到工作量证明问题的解,然后对找到此问题解的人给与奖励。
向解决此问题的人提供金额奖励。自动添加交易,发送者可固定为一个定值(非任何用户地址),接收者为解决问题的人。这也就是出块奖励。

  1. 添加web框架
    使用Django或Flask都可完成
    区块链架设在网络上。让更多人参与进来,节约信任成本。

Leave a Reply

Your email address will not be published.