zoukankan      html  css  js  c++  java
  • 区块链python演示

    # -*- 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("
    -----------
    ")
                # 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)
  • 相关阅读:
    POI导出word
    idea 右键无java class选项
    从接口输出日志中提取用例
    Java 注解
    从输出日志中提取接口的入参和返回做为用例导入到excel中
    苹果绿RGB值
    YAML详解
    Linux grep命令
    MySQL DATE_FORMAT() 函数
    sql server 备份还原
  • 原文地址:https://www.cnblogs.com/x0216u/p/8386166.html
Copyright © 2011-2022 走看看