使用Python,结合Flask框架,创建一个可以处理交易、挖矿新区块、验证区块链有效性,并能在网络节点间同步的区块链网络。(持续更新)

目录

前言

二、代码注释

1.添加新交易到区块链

2.连接新节点

3、替换区块链为最长链

总结


前言

本篇文章将从一个实践者的角度出发,通过构建一个简单的区块链系统,揭开区块链技术的神秘面纱。我们将使用Python语言,结合Flask框架,创建一个可以处理交易、挖矿新区块、验证区块链有效性,并能在网络节点间同步的区块链网络。。


一、代码展示

python 复制代码
 # Module 1 -Create a Cryptocurrency
#To be installed:
#Flask==0.12.2:pip install Flask==0.12.2
#Postman HTrp Client:https://www.getpostman.com
#requests==2.18.4:pip install requests=-2.18.4
#时间戳
import datetime
import hashlib
import json
#Flask可以定义Web应用的路由(URL到Python函数的映射),并处理HTTP请求和响应。jsonify是一个函数,用于将Python对象转换为JSON格式的响应。当你在Flask路由函数中返回一个jsonify对象时,Flask会自动将该对象对应的数据转换为JSON格式,并设置合适的HTTP响应头,以便客户端可以正确解析响应内容。
from flask import Flask, jsonify,request
import requests
from uuid import uuid4
from urllib.parse import urlparse

#  1******Building a Blockchain
class Blockchain:
    def __init__(self):
        self.transactions=[]
        self.chain=[]
        self.create_block(proof=1,previous_hash='0')
        self.nodes=set()
    
    def create_block(self,proof,previous_hash):
        block={'index':len(self.chain)+1,
               'timestamp':str(datetime.datetime.now()),
               'proof':proof,
               'previous_hash':previous_hash,
               'transactions':self.transactions}
        self.transactions=[]
        self.chain.append(block) 
        return block
    def get_previous_block(self):
        return self.chain[-1] 
    
    def proof_of_work(self,previous_proof):
        new_proof=1
        check_proof=False
        while check_proof is False:
            hash_oparation=hashlib.sha256(str(new_proof**2-previous_proof**2).encode()).hexdigest()
            if hash_oparation[:4]=='0000':
                check_proof=True
            else:
                new_proof+=1
        return new_proof
    
    def hash(self, block):
        encode_block = json.dumps(block, sort_keys=True).encode()
        return hashlib.sha256(encode_block).hexdigest()

    def is_chain_valid(self,chain):
        previous_block=chain[0]
        block_index=1
        while block_index<len(chain):
          block=chain[block_index]
          if block['previous_hash'] !=self.hash(previous_block):
              return False
          previous_proof=previous_block['proof']
          proof=block['proof']
          hash_oparation=hashlib.sha256(str(proof**2-previous_proof**2).encode()).hexdigest()
          if hash_oparation[:4] !='0000':
              return False
          previous_block=block
          block_index+=1
        return True
    
    def add_transaction(self,sender,receiver,amount):
        self.transactions.append({'sender':sender,
                                  'receiver':receiver,
                                  'amount':amount})
        previous_block=self.get_previous_block()
        return previous_block['index']+1
            
    def add_node(self,address):
        parsed_url=urlparse(address)
        self.nodes.add(parsed_url.netloc)
        
    def replace_chain(self):
        network=self.nodes
        logest_chain=None
        max_length=len(self.chain)
        for nodes in network:
            response=request.get(f'http://127.0.0.1:5000/get_chain')
            if response.status_code==200:
                length=response.json()['length']
                chain=response.json()['chain']
                if length>max_length and self.is_chain_valid(chain):
                    max_length=length
                    logest_chain=chain
        if logest_chain:
            self.chain=logest_chain
            return True
        return False
#Part 2 -Mining our Blockchain

#Creating a Web App
app = Flask(__name__)

#Creating an address for the node on Port 5000
node_address=str(uuid4()).replace('-', '')

#Creating a Blockchain
blockchain=Blockchain()
#Mining a new block
@app.route('/mine_block',methods=['GET'])
def mine_block():
    previous_block=blockchain.get_previous_block()
    previous_proof=previous_block['proof']
    proof=blockchain.proof_of_work(previous_proof)
    previous_hash=blockchain.hash(previous_block)
    blockchain.add_transaction(sender=node_address,receiver='Lanzhile',amount=1)
    block=blockchain.create_block(proof, previous_hash)
    response={'message':'Congratulation,you just mined a block',
              'index':block['index'],
              'timestamp':block['timestamp'],
              'proof':block['proof'],
              'previous_hash':block['previous_hash'],
              'transactions':block['transactions']}
    return jsonify(response),200
            
#Getting the full Blockchain
@app.route('/get_chain',methods=['GET'])
def get_chain():
    response={'chain':blockchain.chain,
             'length':len(blockchain.chain)}
    return jsonify(response),200      
            
#Checking if the Blockchain is valid
@app.route('/is_valid',methods=['GET']) 
def get_valid():
    is_valid=blockchain.is_chain_valid(blockchain.chain)
    if is_valid:
        response={'message':'All good. The Blockchain is valid.'}
    else:
        response={'message':'Houston,we have a problem.The Blockchain is not valid.'}
    return jsonify(response),200

#Addling a new transaction to the Blockchain
@app.route('/add_transaction',methods=['POST']) 
def add_transaction():
    json =request.get_json()
    transaction_keys=['sender','receiver','amount']
    if not all(key in json for key in transaction_keys):
        return 'Some elements of the transaction are missing',400
    index=blockchain.add_transaction(json['sender'], json['receiver'],json['amount'])
    response={'message':f'This transaction will be added to Block {index}'}
    return jsonify(response),201

#Connecting new nodes
@@app.route('/connect_node', methods=['POST'])
def connect_node():
    json = request.get_json()
    nodes = json.get('nodes')
    if nodes is None:
        return "No nodes provided", 400
    for node in nodes:
        blockchain.add_node(node)
    # 将响应构建移到循环外,并在所有节点添加后才返回
    response = {
        'message': 'All the nodes are now connected. The Lancoin Blockchain now contains the following nodes:',
        'total_nodes': list(blockchain.nodes)
    }
    return jsonify(response), 201
        
#Replacing the chain by the longest chain if needed
@app.route('/replace_chain',methods=['GET']) 
def replace_chain():
    is_replace_chain=blockchain.replace_chain()
    if is_replace_chain:
        response={'message':'The nodes had different chains so the chain was replaced by the logest one.',
                  'new_chain':blockchain.chain}
    else:
        response={'message':'All good.the chain is the largest one.',
                  'actual_chain':blockchain.chain}
    return jsonify(response),200
    
        
app.run(host='0.0.0.0',port=5000)         
            

二、代码注释

注:下面对/add_transaction、/connect_node、/replace_chain路由和对应的视图函数进行讲解,其他函数的详解在我的另外两篇我的文章里"创建一个简单的区块链,并使用 Flask 框架提供一个简单的 Web 接口来与区块链交互。-CSDN博客""使用了Python语言和Flask框架。创建一个区块链网络,允许用户通过HTTP请求进行交互,如包括创建区块链、挖矿、验证区块链等功能。-CSDN博客"

1.添加新交易到区块链

python 复制代码
@app.route('/add_transaction', methods=['POST'])
def add_transaction():
    # 获取请求的JSON数据
    json = request.get_json()
    # 定义交易必须包含的键
    transaction_keys = ['sender', 'receiver', 'amount']
    # 检查JSON数据中是否包含所有必要的交易键
    if not all(key in json for key in transaction_keys):
        # 如果缺少任何一个键,返回错误信息和400状态码
        return 'Some elements of the transaction are missing', 400
    # 添加交易到区块链,并获取返回的区块索引
    index = blockchain.add_transaction(json['sender'], json['receiver'], json['amount'])
    # 构建响应消息,告知交易将被添加到的区块索引
    response = {'message': f'This transaction will be added to Block {index}'}
    # 返回JSON格式的响应和201状态码,表示交易已成功创建
    return jsonify(response), 201

2.连接新节点

python 复制代码
@app.route('/connect_node', methods=['POST'])
def connect_node():
# 获取请求的JSON数据
    json = request.get_json()
# 尝试从JSON数据中获取节点列表
    nodes = json.get('nodes')
# 如果节点列表不存在,返回错误信息和400状态码
    if nodes is None:
        return "No nodes provided", 400
# 遍历节点列表,并将每个节点添加到区块链网络中
    for node in nodes:
        blockchain.add_node(node)
    # 构建响应消息,列出所有已连接的节点
    response = {
        'message': 'All the nodes are now connected. The Lancoin Blockchain now contains the following nodes:',
        'total_nodes': list(blockchain.nodes)
    }
    # 返回JSON格式的响应和201状态码,表示节点已成功连接
    return jsonify(response), 201

3、替换区块链为最长链

python 复制代码
@app.route('/replace_chain', methods=['GET'])
def replace_chain():
    # 调用区块链的replace_chain方法尝试替换当前链为最长的链
    is_replace_chain = blockchain.replace_chain()
    # 如果替换成功
    if is_replace_chain:
        # 构建响应消息,告知链已被替换,并提供新的链数据
        response = {
            'message': 'The nodes had different chains so the chain was replaced by the longest one.',
            'new_chain': blockchain.chain
        }
    else:
        # 如果当前链已经是最长的链,则告知用户无需替换
        response = {
            'message': 'All good. the chain is the largest one.',
            'actual_chain': blockchain.chain
        }
    # 返回JSON格式的响应和200状态码,表示链替换操作已完成
    return jsonify(response), 200

总结

这纸片文章主要介绍三个路由:/add_transaction/connect_node/replace_chain,分别用于添加交易、连接新节点和替换链。在处理请求时,代码首先获取请求中的JSON数据,然后根据不同的路由执行相应的操作,最后返回响应消息和状态码。

相关推荐
UR的出不克8 小时前
使用 Python 爬取 Bilibili 弹幕数据并导出 Excel
java·python·excel
数说星榆1818 小时前
模型即服务(MaaS)生态的去中心化探索
去中心化·区块链
Arms2068 小时前
python时区库学习
开发语言·python·学习
与光同尘 大道至简8 小时前
ESP32 小智 AI 机器人入门教程从原理到实现(自己云端部署)
人工智能·python·单片机·机器人·github·人机交互·visual studio
清水白石0088 小时前
深入 Python 对象模型:PyObject 与 PyVarObject 全解析
开发语言·python
tjjucheng8 小时前
小程序定制开发服务商推荐
python
囊中之锥.8 小时前
《从零到实战:基于 PyTorch 的手写数字识别完整流程解析》
人工智能·pytorch·python
子云之风9 小时前
LSPosed 项目编译问题解决方案
java·开发语言·python·学习·android studio
小北方城市网9 小时前
SpringBoot 全局异常处理与接口规范实战:打造健壮可维护接口
java·spring boot·redis·后端·python·spring·缓存
SunnyRivers9 小时前
打包 Python 项目
python·打包