Python 区块链学习(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Clannad_niu/article/details/88079363

0x01 链扩展

继续上一篇,由于区块链是建立在互联网上的各个节点之间的协议,所以我们需要将之前的单链扩展到各个节点之间。首先我们需要对init()函数追加一个属性node,用一个set()来存放。node用来存放当前节点获取到的周围节点的ip地址,通过这种方式使得各个节点可以知道相互的存在,最终各个节点都可以连接起来。

tips:python中的set()数据结构用来存放一组数据,其中的每一项都不相同。且set()不能用序号来访问,且不能排序。

例子如下:

>>> set('hello')
{'o', 'e', 'l', 'h'}

首先更改init()函数结构,追加node属性

    def __init__(self):
        self.chain = []
        self.current_transactions = []
        self.node = set()

        self.new_block(previous_hash=1, proof=100)

  以及添加node节点的函数

    def register_node(self, address):
        parsed_url = urlparse(address)
        self.node.add(parsed_url.netloc)

0x02 共识体系

我们已经有了一个基本的区块链可以接受交易和挖矿。但是区块链系统应该是分布式的。既然是分布式的,那么我们究竟拿什么保证所有节点有同样的链呢?这就是一致性问题,我们要想在网络上有多个节点,就必须实现一个一致性的算法

在实现一致性算法之前,我们需要找到一种方式让一个节点知道它相邻的节点。每个节点都需要保存一份包含网络中其它节点的记录。因此让我们新增几个接口:

/nodes/register 接收 URL 形式的新节点列表.
/nodes/resolve 执行一致性算法,解决任何冲突,确保节点拥有正确的链.
 

 @app.route('/register/node', methods=['POST']) #注册节点
    def register_node():
        values = request.get_json()
        nodes = values.get('nodes')    

        if nodes is None:
            return 'Error:nodes err', 400

        for node in nodes:
            blockchain.register_node(node)

        response = {
            'message': 'Nodes have been added',
            'total_nodes': list(blockchain.node)
        }

        return jsonify(response), 200

    @app.route('/nodes/resolve', methods=['GET'])   #判断链是否正确 正确返回True
    def consensus():
        result = blockchain.resolve_conflicts()

        if result:
            response = {
                'message': 'The chain has been updated.',
                'new_chain': blockchain.chain,
            }

        else:
            response = {
                'message': 'Our chain is authoritative',
                'chain': blockchain.chain,
            }

        return jsonify(response), 200

就像先前讲的那样,当一个节点与另一个节点有不同的链时,就会产生冲突。 为了解决这个问题,我们将制定最长的有效链条是最权威的规则。换句话说就是:在这个网络里最长的链就是最权威的。 我们将使用这个算法,在网络中的节点之间达成共识。其中判别是否合法的函数valid_chain() 以及更新自己的链的函数resolve_conflicts()的实现如下:

    def valid_chain(self, chain):    #验证链是否正确
        current_index = 1
        last_block = chain[0]

        while current_index < len(chain):
            block = chain[current_index]
            print(f'block:{block}, last_block:{last_block}')

            if block['previous_hash'] != self.hash(last_block): #判断块的hash是否正确
                return False
            if not self.valid_proof(block['proof'],last_block['proof']): #判断proof正确
                return False

            last_block = block
            current_index +=1

        return True

    def resolve_conflicts(self):  #判别是否和自己的链相同 相同返回FALSE
        neighbors = self.node
        new_chain = None

        max_length = len(self.chain)

        for node in neighbors:
            response = requests.get(f'http://{node}/chain')

            if response.status_code == 200:
                length = response.json()['length']
                chain = response.json()['chain']

                if length > max_length and self.valid_chain(chain):
                    new_chain = chain
                    max_length = length

        if new_chain:
            self.chain = new_chain
            return True

        return False

到此我们的节点就已经完成了。接下来进入到测试阶段。

猜你喜欢

转载自blog.csdn.net/Clannad_niu/article/details/88079363