使用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数据,然后根据不同的路由执行相应的操作,最后返回响应消息和状态码。

相关推荐
HsuHeinrich28 分钟前
流程图(二)利用python绘制网络图
python·数据可视化
爱学习的Allan37 分钟前
使用 pyreqs 快速创建 requirements.txt & PyCharm 中 UnicodeDecodeError 问题
ide·python·pycharm·pip
HackKong1 小时前
高校网络安全_网络安全之道
java·网络·c++·python·学习·web安全·黑客技术
yangjiwei02071 小时前
数据结构-排序
数据结构·python
秋天下着雨2 小时前
apifox调用jar程序
java·python·jar
bs_1012 小时前
【保姆式】python调用api通过机器人发送文件到飞书指定群聊
python·机器人·飞书
Redamancy_Xun2 小时前
软件老化分析
python·程序人生·安全威胁分析·可信计算技术·安全架构
geovindu2 小时前
python: Oracle Stored Procedure query table
数据库·python·mysql·postgresql·oracle·sqlserver·mssql
NiNg_1_2343 小时前
Python中SKlearn的K-means使用详解
python·kmeans·sklearn
葡萄架子3 小时前
Python中的logger作用(from loguru import logger)
java·前端·python