Maison  >  Article  >  développement back-end  >  Comment Python construit une blockchain

Comment Python construit une blockchain

WBOY
WBOYavant
2023-05-12 17:55:061687parcourir

Blockchain

Blockchain est un grand livre (base de données distribuée) qui partage des données entre les nœuds d'un réseau informatique. En tant que base de données, la blockchain stocke les informations sous format électronique. L’innovation de la blockchain est qu’elle garantit la sécurité, l’authenticité et la crédibilité des enregistrements de données (sans avoir recours à un tiers de confiance).

La différence entre la blockchain et les bases de données classiques réside dans la structure des données. La blockchain collecte des informations sous forme de bloc. 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

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

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

工作量证明算法 (PoW) 是在区块链上创建或挖掘新块的方式,它的目标是发现一个解决问题的数字。这个数字必须很难找到但很容易被网络上的任何人验证。PoW广泛用于加密货币挖掘,用于验证交易和挖掘新代币。由于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 install flask

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

block

block est une structure de données qui peut enregistrer en permanence les données de transaction de crypto-monnaie (ou à d'autres fins). Semblable à une liste chaînée. Un bloc enregistre toutes les dernières transactions qui n'ont pas encore été vérifiées. Après avoir vérifié les données, le bloc sera fermé et un nouveau bloc sera créé pour saisir et vérifier de nouvelles transactions. Par conséquent, une fois rédigé, il ne peut être modifié ou supprimé définitivement.
  • block est l'endroit où les informations sont stockées et cryptées dans la blockchain

block code> Identifié par un numéro long qui comprend les informations de transaction cryptées du bloc précédemment crypté et les informations de la nouvelle transaction

  • Avant la création, le bloc et les informations qu'il contient doivent être déterminé par le réseau Vérification

  • Comment Python construit une blockchainVoici un exemple simple :
    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)

    Objectif Comment Python construit une blockchain

    Le but de la blockchain est de permettre l'enregistrement et la distribution d'informations numériques, mais non modifiables. De cette manière, la blockchain devient la base d’un grand livre immuable, ou d’un enregistrement de transactions qui ne peut être modifié, supprimé ou détruit.

    Décentralisation

    Imaginez une entreprise avec 10 000 serveurs gérant une base de données contenant toutes les informations client. Tous les serveurs de l'entreprise se trouvent dans un seul entrepôt, avec un contrôle total sur chaque serveur. Cela fournit un point de défaillance unique. Et si le courant était coupé à cet endroit ? Et si sa connexion internet est coupée ? Dans tous les cas, les données peuvent être perdues ou corrompues.

    Building

    Classe Blockchain🎜🎜Nous allons créer une classe BlockChain, le constructeur crée une liste vide pour stocker la blockchain, puis crée une liste vide pour stocker les transactions. Créez block_chain.py🎜
    ...
    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)
    🎜Ajouter des transactions🎜🎜Nous avons besoin d'un moyen d'ajouter des transactions au bloc. new_transaction en est responsable 🎜
    ...
    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&#39;{last_block}&#39;)
                print(f&#39;{block}&#39;)
                print("\n-----------\n")
                # Check that the hash of the block is correct
                if block[&#39;previous_hash&#39;] != self.hash(last_block):
                    return False
                # Check that the Proof of Work is correct
                if not self.valid_proof(last_block[&#39;proof&#39;], block[&#39;proof&#39;]):
                    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&#39;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&#39;http://{node}/chain&#39;)
                if response.status_code == 200:
                    length = response.json()[&#39;length&#39;]
                    chain = response.json()[&#39;chain&#39;]
                    # 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
    🎜Après que new_transaction ait ajouté la transaction à la liste, il renvoie l'index du bloc auquel la transaction sera ajoutée - le prochain bloc à être extrait. Cela sera utile plus tard à l'utilisateur qui a soumis la transaction. 🎜🎜Créer de nouveaux blocs🎜🎜Lorsque notre blockchain est instanciée, nous devons l'ensemencer avec un bloc Genesis - un bloc sans prédécesseurs. Nous devons également ajouter une « preuve » à notre bloc Genesis, qui est le résultat du minage (ou preuve de travail). En plus de créer le bloc Genesis dans notre constructeur, nous étofferons également les méthodes new_block(), new_transaction() et hash() : 🎜
    @app.route(&#39;/nodes/register&#39;, methods=[&#39;POST&#39;])
    def register_nodes():
        values = request.get_json()
        nodes = values.get(&#39;nodes&#39;)
        if nodes is None:
            return "Error: Please supply a valid list of nodes", 400
        for node in nodes:
            blockchain.register_node(node)
        response = {
            &#39;message&#39;: &#39;New nodes have been added&#39;,
            &#39;total_nodes&#39;: list(blockchain.nodes),
        }
        return jsonify(response), 201
    @app.route(&#39;/nodes/resolve&#39;, methods=[&#39;GET&#39;])
    def consensus():
        replaced = blockchain.resolve_conflicts()
        if replaced:
            response = {
                &#39;message&#39;: &#39;Our chain was replaced&#39;,
                &#39;new_chain&#39;: blockchain.chain
            }
        else:
            response = {
                &#39;message&#39;: &#39;Our chain is authoritative&#39;,
                &#39;chain&#39;: blockchain.chain
            }
        return jsonify(response), 200
    🎜À ce stade, nous avons presque fini de représenter notre blockchain. Mais à ce stade, vous devez vous demander comment les nouveaux blocs sont créés, forgés ou extraits. 🎜🎜POW🎜🎜Proof-of-Work (PoW) est un moyen de créer ou d'exploiter de nouveaux blocs sur une blockchain dans le but de découvrir un nombre qui résout un problème. Ce numéro doit être difficile à trouver mais facilement vérifiable par n'importe qui sur le Web. PoW est largement utilisé dans l’extraction de crypto-monnaie pour valider les transactions et extraire de nouvelles pièces. Grâce à PoW, les transactions Bitcoin et autres cryptomonnaies peuvent être traitées en peer-to-peer de manière sécurisée sans avoir recours à un tiers de confiance. 🎜🎜Implémentons un algorithme similaire : 🎜rrreee🎜API🎜🎜Pour que la blockchain puisse interagir, nous avons besoin d'un moyen de la mettre sur un serveur Web. Ici, nous utilisons le framework Flask. 🎜🎜S'il n'est pas installé, vous devez installer flask🎜🎜🎜pip install flask🎜🎜🎜Notre serveur formera un nœud unique dans notre réseau blockchain, créera un dans le même répertoire >app.py :🎜rrreee🎜Ensuite, exécutez🎜🎜🎜flask run🎜🎜🎜Envoyez la demande via le logiciel API (cette fois en utilisant api fox) :🎜🎜🎜🎜🎜🎜🎜🎜Enregistrez un nouveau nœud🎜 🎜Tout l’intérêt des blockchains est qu’elles doivent être décentralisées. Si vous souhaitez avoir plusieurs nœuds dans le réseau, vous devez utiliser un algorithme de consensus. Avant de pouvoir implémenter un algorithme de consensus, nous avons besoin d’un moyen permettant aux nœuds de connaître leurs nœuds voisins sur le réseau. Chaque nœud de notre réseau doit maintenir un registre des autres nœuds du réseau. Par conséquent, nous avons besoin de plus de points de terminaison : 🎜rrreee🎜Conflits🎜🎜Un conflit se produit lorsqu'un nœud a une chaîne différente de celle d'un autre nœud. Pour résoudre ce problème, nous développerons la règle selon laquelle la chaîne valide la plus longue est l’autorité. Grâce à cet algorithme, nous parvenons à un consensus entre les nœuds du réseau. 🎜
    ...
    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&#39;{last_block}&#39;)
                print(f&#39;{block}&#39;)
                print("\n-----------\n")
                # Check that the hash of the block is correct
                if block[&#39;previous_hash&#39;] != self.hash(last_block):
                    return False
                # Check that the Proof of Work is correct
                if not self.valid_proof(last_block[&#39;proof&#39;], block[&#39;proof&#39;]):
                    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&#39;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&#39;http://{node}/chain&#39;)
                if response.status_code == 200:
                    length = response.json()[&#39;length&#39;]
                    chain = response.json()[&#39;chain&#39;]
                    # 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(&#39;/nodes/register&#39;, methods=[&#39;POST&#39;])
    def register_nodes():
        values = request.get_json()
        nodes = values.get(&#39;nodes&#39;)
        if nodes is None:
            return "Error: Please supply a valid list of nodes", 400
        for node in nodes:
            blockchain.register_node(node)
        response = {
            &#39;message&#39;: &#39;New nodes have been added&#39;,
            &#39;total_nodes&#39;: list(blockchain.nodes),
        }
        return jsonify(response), 201
    @app.route(&#39;/nodes/resolve&#39;, methods=[&#39;GET&#39;])
    def consensus():
        replaced = blockchain.resolve_conflicts()
        if replaced:
            response = {
                &#39;message&#39;: &#39;Our chain was replaced&#39;,
                &#39;new_chain&#39;: blockchain.chain
            }
        else:
            response = {
                &#39;message&#39;: &#39;Our chain is authoritative&#39;,
                &#39;chain&#39;: blockchain.chain
            }
        return jsonify(response), 200

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

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer