Python构建区块链的方法详解

2023-02-27 08:56:36
目录
区块链block目标去中心化构建区块链类添加交易创建新blocksPOWAPI注册新节点冲突

区块链

区块链是在计算机网络的节点之间共享数据的分类账(分布式数据库)。作为数据库,区块链以电子格式储存信息。区块链的创新之处在于它保证了数据记录的安全性和真实性,可信性(不需要没有可信任的第三方)。

区块链和典型数据库的区别是数据结构。区块链以block的方式收集信息。

block

block是一种能永久记录加密货币交易数据(或其他用途)的一种数据结构。类似于链表。一个block记录了一些火所有尚未被验证的最新交易。验证数据后,block将关闭,之后会创建一个新的block来输入和验证新的交易。因此,一旦写入,永久不能更改和删除。

    block是区块链中存储和加密信息的地方block由长数字标识,其中包括先前加密块的加密交易信息和新的交易信息在创建之前,block以及其中的信息必须由网络验证

    以下是一个简单的例子:

    block = {
        'index': 1,
        'timestamp': 1506057125.900785,
        'transactions': [
            {
                'sender': "8527147fe1f5426f9dd545de4b27ee00",
                'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",
                'amount': 5,
            }
        ],
        'proof': 324984774000,
        'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
    }
    

    目标

    区块链的目标是允许数字信息被记录和分发,但不能编辑。通过这种方式,区块链成为了不可变分类账或无法更改、删除和销毁的交易记录的基础。

    去中心化

    想象一下,一家公司拥有10000台服务器,用于维护一个包含所有客户信息的数据库。公司的所有服务器都在一个仓库中,可以完全控制每台服务器。这就提供了单点故障。如果那个地方停电了怎么办?如果他的网络连接被切断了怎么办?在任何情况下,数据都会丢失或损坏。

    构建

    区块链类

    我们将创建一个BlockChain类,构造函数创建一个空列表来存储区块链,再创建一个空列表来存储交易。创建block_chain.py

    # block_chain.py
    class Blockchain:
        def __init__(self) -> None:
            self.chain = []
            self.current_transactions = []
        def new_block(self):
            # Creates a new Block and adds it to the chain
            pass
        def new_transaction(self):
            # Adds a new transaction to the list of transactions
            pass
        @staticmethod
        def hash(block):
            # Hashes a Block
            pass
        @property
        def last_block(self):
            # Returns the last Block in the chain
            pass
    

    添加交易

    我们需要一种将交易添加到区块的方法。new_transaction负责这个

    class Blockchain(object):
        ...
        def new_transaction(self, sender, recipient, amount) -> int:
            self.current_transactions.append({
                'sender': sender,
                'recipient': recipient,
                'amount': amount,
            })
            return self.last_block['index'] + 1
    

    new_transaction 将交易添加到列表后,它返回交易将被添加到的块的索引——下一个要挖掘的块。这将在以后对提交交易的用户有用。

    创建新blocks

    当我们的区块链被实例化时,我们需要为它播种一个创世块——一个没有前辈的块。我们还需要向我们的创世块添加一个“证明”,这是挖掘的结果(或工作量证明)。除了在我们的构造函数中创建创世块之外,我们还将充实>

    import hashlib
    import json
    from time import time
    class Blockchain:
        def __init__(self) -> None:
            self.chain = []
            self.current_transactions = []
            # Create the genesis block
            self.new_block(previous_hash=1, proof=100)
        def new_block(self, proof, previous_hash=None) -> dict:
            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) -> int:
            self.current_transactions.append(
                {
                    'sender': sender,
                    'recipient': recipient,
                    'amount': amount,
                }
            )
            return self.last_block['index'] + 1
        @property
        def last_block(self) -> dict:
            # Returns the last Block in the chain
            return self.chain[-1]
        @staticmethod
        def hash(block) -> str:       
            block_string = json.dumps(block, sort_keys=True).encode()
            return hashlib.sha256(block_string).hexdigest()
    

    到这里,我们几乎完成了代表我们的区块链。但此时,你一定想知道新区块是如何创建、锻造或开采的。

    POW

    工作量证明算法>

    让我们实现一个类似的算法:

    class Blockchain(object):
        def proof_of_work(self, last_proof) -> int:
            proof = 0
            while self.valid_proof(last_proof, proof) is False:
                proof += 1
            return proof
        @staticmethod
        def valid_proof(last_proof, proof) -> bool:
            guess = f'{last_proof}{proof}'.encode()
            guess_hash = hashlib.sha256(guess).hexdigest()
            return guess_hash[:4] == '0000'
    

    API

    为了使区块链能够交互,我们需要一个将其置于web服务器上。这里我们是用Flask框架。

    如果没有安装,需要安装flask

    pip>

    我们的服务器将在我们的区块链网络中形成单一节点,在同级目录下创建一个app.py:

    from uuid import uuid4
    from time import time
    from textwrap import dedent
    from flask import Flask, jsonify, request
    from block_chain import Blockchain
    # 实例化应用
    app = Flask(__name__)
    # 创建随机节点名称
    node_identifier = str(uuid4()).replace('_', '')
    # 实例化block_chain类
    block_chain = Blockchain()
    # 创建/mine端点
    @app.route('/mine', methods=['GET'])
    def mine():
        block_chain.new_transaction(
            sender="0",
            recipient=node_identifier,
            amount=1,
        )
        last_block = block_chain.last_block
        last_proof = last_block['proof']
        proof = block_chain.proof_of_work(last_proof)
        previous_hash = block_chain.hash(last_block)
        block = block_chain.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), 200
    @app.route('/transactions/new', methods=['POST'])
    def new_transaction():
        return "We'll add a new transaction"
    @app.route('/chain', methods=['GET'])
    def full_chain():
        response = {
            'chain': block_chain.chain,
            'length': len(block_chain.chain),
        }
        return jsonify(response), 200
    # 修改端口号
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=5000)
    

    然后运行

    flask run

    通过api软件(本次使用的是api fox)来发送请求:

    注册新节点

    区块链的全部意义在于它们应该去中心化。如果想要网络中有多个节点,必须采用共识算法。在我们可以实施共识算法之前,我们需要一种方法让节点知道网络上的相邻节点。我们网络上的每个节点都应该保留网络上其他节点的注册表。因此,我们需要更多的端点:

    ...
    from urllib.parse import urlparse
    ...
    class Blockchain:
        def __init__(self) -> None:
            ...
            self.nodes = set()
            ...
        def register_node(self, address) -> None:    
            parsed_url = urlparse(address)
            self.nodes.add(parsed_url.netloc)
    

    冲突

    冲突是指一个节点与另一个节点有不同的链。为了解决这个问题,我们将制定最长有效链为权威的规则。使用此算法,我们在网络中的节点之间达成共识。

    ...
    import requests
    class Blockchain:
        ...
        def valid_chain(self, chain):
            last_block = chain[0]
            current_index = 1
            while current_index < len(chain):
                block = chain[current_index]
                print(f'{last_block}')
                print(f'{block}')
                print("\n-----------\n")
                # Check that the hash of the block is correct
                if block['previous_hash'] != self.hash(last_block):
                    return False
                # Check that the Proof of Work is correct
                if not self.valid_proof(last_block['proof'], block['proof']):
                    return False
                last_block = block
                current_index += 1
            return True
        def resolve_conflicts(self):
            """
            This is our Consensus Algorithm, it resolves conflicts
            by replacing our chain with the longest one in the network.
            :return: <bool> True if our chain was replaced, False if not
            """
            neighbours = self.nodes
            new_chain = None
            # We're only looking for chains longer than ours
            max_length = len(self.chain)
            # Grab and verify the chains from all the nodes in our network
            for node in neighbours:
                response = requests.get(f'http://{node}/chain')
                if response.status_code == 200:
                    length = response.json()['length']
                    chain = response.json()['chain']
                    # Check if the length is longer and the chain is valid
                    if length > max_length and self.valid_chain(chain):
                        max_length = length
                        new_chain = chain
            # Replace our chain if we discovered a new, valid chain longer than ours
            if new_chain:
                self.chain = new_chain
                return True
            return False
    

    第一个方法 valid_chain() 负责通过遍历每个块并验证哈希和证明来检查链是否有效。resolve_conflicts() 是一种循环遍历我们所有相邻节点、下载它们的链并使用上述方法验证它们的方法。如果找到一个有效的链,其长度大于我们的,我们将替换我们的。

    让我们将两个端点注册到我们的 API,一个用于添加相邻节点,另一个用于解决冲突:

    @app.route('/nodes/register', methods=['POST'])
    def register_nodes():
        values = request.get_json()
        nodes = values.get('nodes')
        if nodes is None:
            return "Error: Please supply a valid list of nodes", 400
        for node in nodes:
            blockchain.register_node(node)
        response = {
            'message': 'New nodes have been added',
            'total_nodes': list(blockchain.nodes),
        }
        return jsonify(response), 201
    @app.route('/nodes/resolve', methods=['GET'])
    def consensus():
        replaced = blockchain.resolve_conflicts()
        if replaced:
            response = {
                'message': 'Our chain was replaced',
                'new_chain': blockchain.chain
            }
        else:
            response = {
                'message': 'Our chain is authoritative',
                'chain': blockchain.chain
            }
        return jsonify(response), 200
    

    在这一点上,如果你愿意,你可以拿一台不同的机器,并在你的网络上启动不同的节点。或者在同一台机器上使用不同的端口启动进程。比如创建两个端口5000和6000来进行尝试。

    到此这篇关于Python构建区块链的方法详解的文章就介绍到这了,更多相关Python构建区块链内容请搜索易采站长站以前的文章或继续浏览下面的相关文章希望大家以后多多支持易采站长站!