python利用flask框架完成区块链小demo(实现转账,节点更新)

模仿用python flask 写了个小demo 这注释也花了我不少时间

import hashlib # 信息安全加密
import json 
import time 
from urllib.parse import urlparse #网络编码解码
from uuid import uuid4 # 生成唯一序列号
import requests #生成网络请求
from flask import Flask,jsonify,request #请求,网络请求
from typing import Any,Dict,List,Optional #数据结构

class DaDaCoinBlockChain:

    def __init__(self): #初始化
        self.current_transactions = []#交易列表
        self.chain=[]#区块链管理多个区块
        self.nodes=set()#保存网络中的多个节点
        self.new_block(previous_hash="1",proof=100)#创建创世区块

    def new_block(self,proof:int,#确定proof为int类型
                  previous_hash:Optional[str])->Dict[str,Any]: #创建一个区块,返回字典数据类型
        block={
            "index":len(self.chain)+1,#索引
            "timestamp":time.time(),#时间戳
            "teainsactions":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_transactions(self,sender:str,recipient:str,amount:int)->int: #创建一个交易
        self.current_transactions.append({
            "sender":sender,#付款方
            "recipient":recipient,#收款方
            "amount":amount#交易金额
        })
        return self.last_block["index"]+1#索引标记交易的数量

    @property
    def last_block(self)->Dict[str,any]:#取得最后一个区块
        return self.chain[-1]

    @staticmethod
    def hash(block:Dict[str,any])->str:# 哈希加密传递一个字典返回字符串
        blockstring=json.dumps(block,sort_keys=True).encode()#编码
        return hashlib.sha3_256(blockstring).hexdigest()#取出编码16进制的哈希

    def proof_of_work(self,last_proof:int)->int:#工作量证明,挖矿过程
        proof=0
        while self.valid_proof(last_proof,proof) is False: #验证求解
            proof+=1
        return proof

    @staticmethod #第N个区块依赖于N-1个区块
    def valid_proof(last_proof:int,proof:int)->bool:#验证证明
        guess=f'{last_proof*proof}'.encode()#二进制编码
        guess_hash=hashlib.sha3_256(guess).hexdigest()#取出哈希值
        return guess_hash[-4:]=="0000" #验证是否符合条件

    def register_node(self,addr:str)->None:#加入网络的其他节点,用于更新
        now_url=urlparse(addr)#解析网络
        self.nodes.add(now_url.netloc)#增加网络节点

    def valid_chain(self,chain:List[Dict[str,any]])->bool:#区块链校验
        #List[Dict[str,any]是一个列表,列表的每一个元素都是字典
        last_block=chain[0]#第一个区块
        curr_index=1#当前的第一个索引
        while curr_indexbool:#共识算法
        #网络中的多个节点,取出最长的
        neighbours=self.nodes#取得所有节点
        new_chain=None#新的区块链
        max_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_proof(chain):
                    max_length=length
                    new_chain=chain#保存长度与区块链
        if new_chain:
            self.chain=new_chain#替换区块链
            return True
        return False

dadacoin = DaDaCoinBlockChain()#创建一个网络节点
node_id=str(uuid4()).replace("-","")#生成秘钥
print("当前节点钱包地址",node_id)

app=Flask(__name__)#初始化Flask框架
@app.route("/")
def index_page():
    return "欢迎来到凹梗 你好"

@app.route("/chain")#查看所有的区块链
def index_chain():
    response={
        "chain":dadacoin.chain,#区块链
        "length":len(dadacoin.chain) #区块链的长度
    }
    return jsonify(response),200#展示区块链

@app.route("/mine")#挖矿
def index_mine():
    last_block=dadacoin.last_block#取得最后一个区块
    last_proof=last_block["proof"]#取得工作量证明
    proof=dadacoin.proof_of_work(last_proof)#挖矿计算

    #系统奖励比特币挖矿产生交易
    dadacoin.new_transactions(
        sender="0",#系统奖励
        recipient=node_id,#当前钱包
        amount=10,
    )
    block=dadacoin.new_block(proof,None)#增加一个区块
    response = {
        "message":"新的区块创建",
        "index":block["index"],#创建索引
        "teainsactions":block["teainsactions"],#交易
        "proof":block["proof"],#工作量证明
        "previous_hash":block["previous_hash"]#上一块的哈希
    }
    return jsonify(response),200

@app.route("/new_trainsactions",methods=["POST"])#实现交易
def new_trainsactions():
    values=request.get_json#抓取网络传输的信息
    required=["sender","recipient","amount"]
    if not all(key in values for key in required):
        return "数据不完整",400
    index=dadacoin.new_transactions(values["sender"],values["recipient"],values["amount"])

    response = {
        "message":f"交易加入到区块{index}"
    }
    return jsonify(response),200

@app.route("/new_node",methods=["POST"])#新注册节点
def new_node():
    values=requests.get_json()#获取json字符串
    nodes=values.get("nodes")#获取所有的节点
    if nodes is None:
        return "没有节点思密达",400
    for node in nodes:
        dadacoin.register_node(node)#增加网络节点
    response = {
        "message":f"网络节点已经被追加",
        "nodes":list(dadacoin.nodes),#查看所有节点
    }
    return jsonify(response),200

@app.route("/node_refresh", methods=["POST"])  # 更新节点
def node_refresh():
    replaced=dadacoin.resolve_conflicts()#共识算法进行替换
    if replaced:
        response={
            "message":"区块链已经被替换为最长",
            "new-chain":dadacoin.chain,
        }
    else:
        response={
            "message":"当前区块链已经是最长无需替换",
            "new-chain":dadacoin.chain
        }
    return jsonify(response),200

if __name__=="__main__":
    app.run("127.0.0.1",port=5000)

 

你可能感兴趣的:(区块链)