手把手教你打造属于你自己的'比特币'(中)

上一篇内容是在编译器内生成块。本篇将做本地服务器的挖矿和交易,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 实现:
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)算法。

我们的共识算法会更简单:如果一个节点的链与另一个节点的不一样(就是说有冲突),然后网络中最长的链会保留下来,其他较短的链将会被删除。如果我们网络中的链之间没有冲突,那么我们继续。手把手教你打造属于你自己的'比特币'(中)


日常深推公众号:
手把手教你打造属于你自己的'比特币'(中)