Rumah > Artikel > pembangunan bahagian belakang > Bagaimana Python membina rantaian blok
Blockchain ialah lejar (pangkalan data teragih) yang berkongsi data antara nod dalam rangkaian komputer. Sebagai pangkalan data, blockchain menyimpan maklumat dalam format elektronik. Inovasi blockchain ialah ia menjamin keselamatan, ketulenan dan kredibiliti rekod data (tanpa memerlukan pihak ketiga yang dipercayai).
Perbezaan antara blockchain dan pangkalan data biasa ialah struktur data. Blockchain mengumpul maklumat dengan cara block
.
block
ialah struktur data yang boleh merekodkan data transaksi mata wang kripto (atau tujuan lain) secara kekal. Sama seperti senarai terpaut. A block
merekodkan beberapa transaksi terbaharu kebakaran yang masih belum disahkan. Setelah data telah disahkan, block
akan ditutup dan block
baharu akan dibuat untuk memasuki dan mengesahkan transaksi baharu. Oleh itu, apabila ditulis, ia tidak boleh diubah atau dipadamkan secara kekal.
block
ialah tempat maklumat disimpan dan disulitkan dalam rantaian blok
block
dikenal pasti dengan nombor panjang yang termasuk yang sebelumnya penyulitan Maklumat transaksi yang disulitkan bagi blok dan maklumat transaksi baharu
sebelum dibuat, block
dan maklumat di dalamnya mesti disahkan oleh rangkaian
di bawah ialah contoh mudah:
block = { 'index': 1, 'timestamp': 1506057125.900785, 'transactions': [ { 'sender': "8527147fe1f5426f9dd545de4b27ee00", 'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f", 'amount': 5, } ], 'proof': 324984774000, 'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" }
Matlamat blockchain adalah untuk membenarkan maklumat digital direkodkan dan diedarkan, tetapi tidak diedit. Dengan cara ini, blockchain menjadi asas untuk lejar tidak berubah, atau rekod transaksi yang tidak boleh diubah, dipadam dan dimusnahkan.
Bayangkan sebuah syarikat dengan 10,000 pelayan mengekalkan pangkalan data yang mengandungi semua maklumat pelanggan. Semua pelayan syarikat berada dalam satu gudang, dengan kawalan penuh ke atas setiap pelayan. Ini memberikan satu titik kegagalan. Bagaimana jika kuasa padam di tempat itu? Bagaimana jika sambungan internetnya terputus? Walau apa pun, data boleh hilang atau rosak.
Kami akan mencipta kelas BlockChain
, pembina mencipta senarai kosong untuk menyimpan blokchain, dan kemudian mencipta senarai kosong untuk Simpan transaksi . Cipta 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
Kami memerlukan cara untuk menambah transaksi pada blok. new_transaction
bertanggungjawab untuk ini
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
Selepas new_transaction
menambah urus niaga pada senarai, ia mengembalikan indeks blok urus niaga akan ditambah kepada - blok seterusnya untuk dilombong. Ini akan berguna kemudian kepada pengguna yang menyerahkan transaksi.
Apabila blockchain kami diwujudkan, kami perlu menyemainya dengan blok genesis - blok tanpa pendahulu. Kami juga perlu menambah "bukti" pada blok genesis kami, yang merupakan hasil perlombongan (atau bukti kerja). Selain mencipta blok genesis dalam pembina kami, kami juga akan menyempurnakan kaedah new_block(), new_transaction(), dan 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()
Pada ketika ini, kami hampir selesai mewakili Blockchain kawasan kami . Tetapi pada ketika ini, anda mesti tertanya-tanya bagaimana blok baharu dicipta, dipalsukan atau dilombong.
Proof of Work (PoW) ialah satu cara untuk mencipta atau melombong blok baharu pada blockchain dengan matlamat untuk menemui nombor yang menyelesaikan masalah. Nombor ini mesti sukar dicari tetapi mudah disahkan oleh sesiapa sahaja di web. PoW digunakan secara meluas dalam perlombongan mata wang kripto untuk mengesahkan transaksi dan melombong syiling baharu. Terima kasih kepada PoW, Bitcoin dan urus niaga mata wang kripto lain boleh diproses peer-to-peer dengan cara yang selamat tanpa memerlukan pihak ketiga yang dipercayai.
Mari kita laksanakan algoritma yang serupa:
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'
Untuk membolehkan blockchain berinteraksi, kami memerlukan pelayan web untuk mengehoskannya. Di sini kami menggunakan bingkai Flask
.
Jika tidak dipasang, anda perlu memasangnyaflask
pip install flask
Pelayan kami akan membentuk satu unit dalam rangkaian blockchain kami Nod, buat 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)
dalam direktori tahap yang sama dan kemudian jalankan
flask run
melalui perisian api (menggunakan ini masa adalah api fox) untuk menghantar permintaan:
Inti utama blockchain ialah mereka harus Desentralisasi. Jika anda ingin mempunyai berbilang nod dalam rangkaian, anda mesti menggunakan algoritma konsensus. Sebelum kita boleh melaksanakan algoritma konsensus, kita memerlukan cara untuk nod mengetahui nod jiran mereka pada rangkaian. Setiap nod pada rangkaian kami harus mengekalkan pendaftaran nod lain pada rangkaian. Oleh itu, kita memerlukan lebih banyak titik akhir:
... 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)
Konflik ialah apabila satu nod mempunyai rantaian yang berbeza daripada nod yang lain. Untuk menyelesaikan masalah ini, kami akan membangunkan peraturan bahawa rantaian sah terpanjang ialah pihak berkuasa. Menggunakan algoritma ini, kami mencapai konsensus antara nod dalam rangkaian.
... 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来进行尝试。
Atas ialah kandungan terperinci Bagaimana Python membina rantaian blok. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!