从构建区块链理解区块链概念
import hashlibimport jsonfrom datetime import timefrom urllib.parse import urlparsefrom uuid import uuid4import requestsfrom flask import Flask, jsonify, requestclass Blockchain(object):def __init__(self):self.current_transactions = []self.chain = []self.nodes = set()self.new_block(previous_hash=1, proof=100)def register_node(self, address):"""Add a new node to the list of nodesresolve_conflicts:param address: Address of node. Eg. 'http://192.168.0.5:5000':return: None"""parsed_url = urlparse(address)self.nodes.add(parsed_url.netloc)def valid_chain(self, chain):"""Determine if a given blockchain is valid:param chain: A blockchain:return: True if valid, False if not"""last_block = chain[0]current_index = 1while current_index < len(chain):block = chain[current_index]print(f"{last_block}")print(f"{block}")print("\n-----------\n")if block["previous_hash"] != self.hash(last_block):return Falseif not self.valid_proof(last_block["proof"], block["proof"]):return Falselast_block = blockcurrent_index += 1return Truedef resolve_conflicts(self):"""共识算法解决冲突使用网络中最长的链.:return: True 如果链被取代, 否则为False"""neighbours = self.nodesnew_chain = Nonemax_length = len(self.chain)for node in neighbours: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):max_length = lengthnew_chain = chainif new_chain:self.chain = new_chainreturn Truereturn Falsedef new_block(self, proof, previous_hash=None):"""生成新块:param proof: The proof given by the Proof of Work algorithm:param previous_hash: (Optional) Hash of previous Block:return: New Block"""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 blockdef new_transaction(self, sender, recipient, amount):"""生成新交易信息,信息将加入到下一个待挖的区块中:param sender: Address of the Sender:param recipient: Address of the Recipient:param amount: Amount:return: The index of the Block that will hold this transaction"""self.current_transactions.append({"sender": sender, "recipient": recipient, "amount": amount,})return self.last_block["index"] + 1@propertydef last_block(self):return self.chain[-1]@staticmethoddef hash(block):"""生成块的 SHA-256 hash值:param block: Block:return: """block_string = json.dumps(block, sort_keys=True).encode()return hashlib.sha256(block_string).hexdigest()def proof_of_work(self, last_proof):"""简单的工作量证明: - 查找一个 p' 使得 hash(pp') 以4个0开头 - p 是上一个块的证明,p' 是当前的证明:param last_proof: :return: """proof = 0while self.valid_proof(last_proof, proof) is False:proof += 1return proof@staticmethoddef valid_proof(last_proof, proof):"""验证证明: 是否hash(last_proof, proof)以4个0开头?:param last_proof: Previous Proof:param proof: Current Proof:return: True if correct, False if not."""guess = f"{last_proof}{proof}".encode()guess_hash = hashlib.sha256(guess).hexdigest()return guess_hash[:4] == "0000"app = Flask(__name__)node_identifier = str(uuid4()).replace("-", "")blockchain = Blockchain()@app.route("/chain", methods=["GET"])def full_chain():response = {"chain": blockchain.chain,"length": len(blockchain.chain),}return jsonify(response), 200@app.route("/transactions/new", methods=["POST"])def new_transaction():values = request.get_json()required = ["sender", "recipient", "amount"]if not all(k in values for k in required):return "Missing values", 400index = blockchain.new_transaction(values["sender"], values["recipient"], values["amount"])response = {"message": f"Transaction will be added to Block {index}"}return jsonify(response), 201@app.route("/mine", methods=["GET"])def mine():last_block = blockchain.last_blocklast_proof = last_block["proof"]proof = blockchain.proof_of_work(last_proof)blockchain.new_transaction(sender="0", recipient=node_identifier, amount=1,)block = blockchain.new_block(proof)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("/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", 400for 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), 200if __name__ == "__main__":app.run(host="0.0.0.0", port=5000)