手把手教你打造属于你自己的'比特币'(中)
上一篇内容是在编译器内生成块。本篇将做本地服务器的挖矿和交易,WEB服务器是用flask框架搭建,flask框架够轻量。
我们将创建三个接口:/mine,告诉服务器去挖矿,/blocks,返回所有块,/txion,创建一个交易并添加到块。CCHcoin的数据将是一些交易记录,所以每个区块的数据区将会是一个由交易记录组成的列表。每个交易记录都会是一个JSON对象,列举着CCHcoin的发送方,CCHcoin的接收方和CCHcoin转让的数量。
{"from": "network", "to": miner_address, "amount": 1}
现在我们知道了我们的交易记录是怎样的了,我们需要把它们加入一台我们区块链网络中的电脑,这被称为节点。为了这样做,我们会创建一个简单的HTTP服务器,这样任何用户都可以让我们的节点知道一个新的交易记录产生了。一个节点将能够接受一个以交易记录作为body的POST请求。这就是为什么交易记录是JSON格式的原因,我们需要把它们作为一个请求的body传送到我们的服务器。
# 接受WEB请求 @node.route('/txion', methods=['POST']) def transaction(): # 每一次新的 POST 请求, # 我们要的传输data new_txion = request.get_json() # 把传输任务添加都列表中 this_nodes_transactions.append(new_txion) # 传输成功,把信息打到控制台 print ("New transaction") print ("FROM: {}".format(new_txion['from'].encode('ascii', 'replace'))) print ("TO: {}".format(new_txion['to'].encode('ascii', 'replace'))) print ("AMOUNT: {}\n".format(new_txion['amount'])) # 让客户端知道成功了 return "Transaction submission successful\n"
现在当用户互相间发送CCHCoin时,我们有了一个可以保存记录的方法。这就是为什么人们把区块链称为公开的,分布式的分类账:所有交易记录的存储对所有人可见,并且被保存在网络的每一个节点中。
现在还没有CCHCoin这样的东西,因为还没有创造和发行任何一个CCHCoin。为了创造新的CCHCoin,人们必须去挖掘CCHCoin的新区块。当他们成功的挖掘到新区块,一个新的CCHCoin就被创造了,并且被奖励给挖到区块的人。这个CCHCoin在矿工把它发送给其他人之后开始流通。
@node.route('/mine', methods=['GET']) def mine(): # 获取最近的POW last_block = blockchain[len(blockchain) - 1] last_proof = last_block.data['proof-of-work'] # 找到最新块的工作量证明 # Note: 这个程序会一直挂到最新块被挖出来 proof = proof_of_work(last_proof) # 一旦我们找到有效的工作量证明 # 当我们知道挖到块 我们就在交易中奖励矿工 this_nodes_transactions.append( {"from": "network", "to": miner_address, "amount": 1} ) # 现在我们能收集需要创造新块的数据 new_block_data = { "proof-of-work": proof, "transactions": list(this_nodes_transactions) } new_block_index = last_block.index + 1 new_block_timestamp = this_timestamp = date.datetime.now() last_block_hash = last_block.hash # 空的交易列表 this_nodes_transactions[:] = [] # 建新块 mined_block = Block( new_block_index, new_block_timestamp, new_block_data, last_block_hash ) blockchain.append(mined_block) # 让客户端知道挖到矿 #json结构 return json.dumps({ "index": new_block_index, "timestamp": str(new_block_timestamp), "data": new_block_data, "hash": last_block_hash }) + "\n"
使用工作量证明(PoW)算法,来证明是如何在区块链上创建或挖掘新的区块。PoW 的目标是计算出一个符合特定条件的数字,这个数字对于所有人而言必须在计算上非常困难,但易于验证。这是工作证明背后的核心思想。
我们将看到一个简单的例子帮助你理解:
假设一个整数 x 乘以另一个整数 y 的积的 Hash 值必须以 0 结尾,即 hash(x * y) = ac23dc...0。设 x = 5,求 y ?用 Python 实现:
假设一个整数 x 乘以另一个整数 y 的积的 Hash 值必须以 0 结尾,即 hash(x * y) = ac23dc...0。设 x = 5,求 y ?用 Python 实现:
from hashlib import sha256 x = 5 y = 0 # We don't know what y should be yet... while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0": y += 1 print(f'The solution is y = {y}')
结果是: y = 21。因为,生成的 Hash 值结尾必须为 0。
hash(5 * 21) = 1253e9373e...5e3600155e860
在比特币中,工作量证明算法被称为 Hashcash ,它和上面的问题很相似,只不过计算难度非常大。这就是矿工们为了争夺创建区块的权利而争相计算的问题。 通常,计算难度与目标字符串需要满足的特定字符的数量成正比,矿工算出结果后,就会获得一定数量的比特币奖励(通过交易)。
在CCHCoin,我们会创建一个稍微简单的工作量证明算法。为了创建一个新的区块,一台矿工的电脑必须要增加一个数字。当这个数字可以被7(“CCHCoin”字母的数量)和上一个区块的证明数字整除,一个新的CCHCoin区块就被挖掘出来,并且矿工将会得到一个崭新的CCHCoin。
def proof_of_work(last_proof): # 产生一个我们能找到写一个工作量证明的变量 incrementor = last_proof + 1 # 知道有一个数能被9整除 # 同时 这个工作量证明包含前一个区块 while not (incrementor % 9 == 0 and incrementor % last_proof == 0): incrementor += 1 # 一旦数字被找到,返回POW return incrementor
现在,我们能控制一定时间周期内挖掘的区块数量了,并且我们能在网络上发行CCHCoin给人们,使他们能互相发送了。但正如我们所说,我们只在一台电脑上做到了这些。如果区块链是去中心化的,我们如何能够确定每一个节点中的链是一样的呢?为了做到这一点,我们让每一个节点广播它的链的版本给其他节点,并且允许他们接受其他节点的链。这之后,每一个节点必须核实其他节点的链,所以每一个网络中的节点都与产生的区块链看起来一致了。这被称为共识(consensus)算法。
我们的共识算法会更简单:如果一个节点的链与另一个节点的不一样(就是说有冲突),然后网络中最长的链会保留下来,其他较短的链将会被删除。如果我们网络中的链之间没有冲突,那么我们继续。
日常深推公众号: