从构建区块链理解区块链概念

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 = []# 共识机制的节点setself.nodes = set()# Create the genesis block# 创建创世区块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")# Check that the hash of the block is correctif block["previous_hash"] != self.hash(last_block):return False# Check that the Proof of Work is correctif 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 = None# We're only looking for chains longer than oursmax_length = len(self.chain)# Grab and verify the chains from all the nodes in our networkfor 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 validif length > max_length and self.valid_chain(chain):max_length = lengthnew_chain = chain# Replace our chain if we discovered a new, valid chain longer than oursif 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]),}# Reset the current list of transactions# 重置交易列表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: """# We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashesblock_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"# Instantiate our Nodeapp = Flask(__name__)# Generate a globally unique address for this nodenode_identifier = str(uuid4()).replace("-", "")# Instantiate the Blockchainblockchain = 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()# Check that the required fields are in the POST'ed datarequired = ["sender", "recipient", "amount"]if not all(k in values for k in required):return "Missing values", 400# Create a new Transactionindex = 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():# We run the proof of work algorithm to get the next proof...last_block = blockchain.last_blocklast_proof = last_block["proof"]proof = blockchain.proof_of_work(last_proof)# 给工作量证明的节点提供奖励.# 发送者为 "0" 表明是新挖出的币blockchain.new_transaction(sender="0", recipient=node_identifier, amount=1,)# Forge the new Block by adding it to the chainblock = 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)