# -*- coding: utf-8 -*- """ Created on Tue Jan 30 08:46:36 2018 block:每个区块包含属性:索引(index),Unix时间戳(timestamp),交易列表(transactions),工作量证明(稍后解释)以及前一个区块的Hash值。 @author: Administrator """ import hashlib import json import requests from time import time from uuid import uuid4 from flask import Flask, jsonify, request from textwrap import dedent from urllib.parse import urlparse class Blockchain(object): #初始化变量 def __init__(self): self.chain = [] #当前链长度为0 self.current_transactions = [] #当前交易量为空 self.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 nodes :param address: <str> Address of node. Eg. ‘http://192.168.0.5:5000‘ :return: None """ parsed_url = urlparse(address) self.nodes.add(parsed_url.netloc) #创建新块 def new_block(self, proof, previous_hash=None): 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 block #创建新交易 并返回该记录将被添加到的区块(下一个待挖掘的区块)的索引 def new_transaction(self, sender, recipient, amount): self.current_transactions.append({ ‘sender‘: sender, ‘recipient‘: recipient, ‘amount‘: amount, }) return self.last_block[‘index‘] + 1 #静态哈希方法 @staticmethod def hash(block): block_string = json.dumps(block, sort_keys=True).encode() return hashlib.sha256(block_string).hexdigest() #上一区块 @property def last_block(self): return self.chain[-1] """ 简单的工作量证明: - 查找一个 p‘ 使得 hash(pp‘) 以4个0开头 - p 是上一个块的证明, p‘ 是当前的证明 :param last_proof: <int> :return: <int> """ #工作量验证工作 def proof_of_work(self, last_proof): proof = 0 while self.valid_proof(last_proof, proof) is False: proof += 1 return proof @staticmethod def valid_proof(last_proof, proof): """ 验证证明: 是否hash(last_proof, proof)以4个0开头? :param last_proof: <int> Previous Proof :param proof: <int> Current Proof :return: <bool> True if correct, False if not. """ #F-string 提高效率 guess = f‘{last_proof}{proof}‘.encode() guess_hash = hashlib.sha256(guess).hexdigest() return guess_hash[:4] == "0000" def valid_chain(self, chain): """ Determine if a given blockchain is valid :param chain: <list> A blockchain :return: <bool> True if valid, False if not """ 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): """ 共识算法解决冲突 使用网络中最长的链. :return: <bool> True 如果链被取代, 否则为False """ 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 # Instantiate our Node #s实例化Flask app = Flask(__name__) # Generate a globally unique address for this node #创建地址 node_identifier = str(uuid4()).replace(‘-‘, ‘‘) # 初始化区块链 创建创世快 blockchain = Blockchain() #开始挖矿 @app.route(‘/mine‘, methods=[‘GET‘]) def mine(): # 获取上一个区块 的proof 得到下一个区块的proof last_block = blockchain.last_block #上一个证明 last_proof = last_block[‘proof‘] #工作量证明 proof = blockchain.proof_of_work(last_proof) #添加交易 # 给工作量证明的节点提供奖励. # 发送者为 "0" 表明是新挖出的币 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(‘/transactions/new‘, methods=[‘POST‘]) def new_transaction(): #获取传送过来的json参数 values = request.get_json() # Check that the required fields are in the POST‘ed data required = [‘sender‘, ‘recipient‘, ‘amount‘] if not all(k in values for k in required): return ‘Missing values‘, 400 #创建一个新交易 返回当前交易所引 (发送方 接收方 数量..) index = 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(‘/chain‘, methods=[‘GET‘]) def full_chain(): #返回全部区块链 response = { ‘chain‘: blockchain.chain, ‘length‘: len(blockchain.chain), #链长度 } 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", 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 if __name__ == ‘__main__‘: app.run(host=‘0.0.0.0‘, port=5000)
原文地址:https://www.cnblogs.com/x0216u/p/8386166.html
时间: 2024-10-07 18:31:20