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

news/2024/5/6 2:01:45

目录

前言

二、代码注释

1.添加新交易到区块链

2.连接新节点

3、替换区块链为最长链

总结


前言

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


一、代码展示

 # 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 blockdef get_previous_block(self):return self.chain[-1] def proof_of_work(self,previous_proof):new_proof=1check_proof=Falsewhile check_proof is False:hash_oparation=hashlib.sha256(str(new_proof**2-previous_proof**2).encode()).hexdigest()if hash_oparation[:4]=='0000':check_proof=Trueelse:new_proof+=1return new_proofdef 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=1while block_index<len(chain):block=chain[block_index]if block['previous_hash'] !=self.hash(previous_block):return Falseprevious_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 Falseprevious_block=blockblock_index+=1return Truedef 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']+1def add_node(self,address):parsed_url=urlparse(address)self.nodes.add(parsed_url.netloc)def replace_chain(self):network = self.nodeslongest_chain = Nonemax_length = len(self.chain)for node in network:try:response = requests.get(f'http://{node}/get_chain')response.raise_for_status()  # 这将抛出异常,如果请求失败except requests.exceptions.RequestException as e:print(f"Failed to get the chain from {node}. Exception: {e}")continueif response.status_code == 200:length = response.json()['length']chain = response.json()['chain']if length > max_length and self.is_chain_valid(chain):max_length = lengthlongest_chain = chainif longest_chain:self.chain = longest_chainreturn Truereturn 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',400index=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", 400for 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_chain_replaced = blockchain.replace_chain()if is_chain_replaced: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}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.添加新交易到区块链

@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.连接新节点

@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、替换区块链为最长链

@app.route('/replace_chain', methods=['GET'])
def replace_chain():# 调用 Blockchain 类的 replace_chain 方法# 这个方法会遍历所有节点,并决定是否需要用更长的链替换当前链is_chain_replaced = blockchain.replace_chain()# 如果链被替换了if is_chain_replaced:# 构建一个包含替换信息的响应字典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}# 使用 jsonify 将 Python 字典转换成 JSON 格式的响应体# 返回 200 OK HTTP 状态码return jsonify(response), 200

总结

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


http://www.mrgr.cn/p/61803218

相关文章

如何在阿里云快速配置自动定时重启ECS云服务器?

背景 无论是电子商务、在线教育、游戏&#xff0c;还是流媒体等业务&#xff0c;服务器的稳定运行都是至关重要的。然而&#xff0c;在实际运行中&#xff0c;我们可能会遇到这样一些场景&#xff1a; 系统更新&#xff1a;一些操作系统或者软件的更新可能需要重启服务器才能…

buuctf-pwn-2.rip

先用checksec看一下保护情况红色表示没有保护,绿色则表示有相应的保护 关于每种保护会在之后的做题中遇到,也有相应的应对措施,这次就不过多深入 打开ida64分析附件发现高危函数gets,这个函数不会检查输入的长度 我们可以利用它修改函数的返回地址,从而执行后门函数找到后…

【draw.io的使用心得介绍】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

条件生成对抗网络(cGAN)在AI去衣技术中的应用探索

随着深度学习技术的飞速发展&#xff0c;生成对抗网络&#xff08;GAN&#xff09;作为其中的一个重要分支&#xff0c;在图像生成、图像修复等领域展现出了强大的能力。其中&#xff0c;条件生成对抗网络&#xff08;cGAN&#xff09;通过引入条件变量来控制生成模型的输出&am…

Redis系列5:深入分析Cluster 集群模式

1 背景 前面我们学习了Redis高可用的两种架构模式&#xff1a;主从模式、哨兵模式。 解决了我们在Redis实例发生故障时&#xff0c;具备主从自动切换、故障转移的能力&#xff0c;终保证服务的高可用。 但是这些其实远远不够&#xff0c;随着我们业务规模的不断扩展&#xff0…

Anaconda中安装pyecharts

学习Python的过程中发现conda无法使用pyecharts https://pypi.org/project/pyecharts/#files 下载后将whl文件复制到到本地conda\scripts目录下 随后打开conda 切换到script目录下,输入命令 pip install pyecharts-2.0.5-py3-none-any.whl 等待安装完成 在pycharm中配置Python…

【ZYNQ】zynq启动模式及程序固化

一、前言 由于zynq含有arm cpu ,其启动模式由ps主导&#xff0c;与纯逻辑的fpga不相同&#xff0c;此处做一个记录。 二、zynq启动模式 关于zynq的启动模式详细内容可以参考官方文档&#xff1a;ug585-Zynq 7000 SoC Technical Reference Manual&#xff0c;第六章。 2.1 启…

网络拓扑—FTP服务搭建

均使用Windows Server 2003进行搭建目录FTP服务搭建网络拓扑配置网络FTPPC安装FTP服务配置FTP服务FTP用户配置—1PC机访问FTP站点IE浏览器访问终端访问FTP用户配置—2PC机访问ftp站点IE浏览器访问终端访问 FTP服务搭建 网络拓扑//交换机忽略不计 FTP服务IP:192.168.1.1 PC机IP…

【研发管理】产品经理知识体系-产品创新中的市场调研

导读&#xff1a;在产品创新过程中&#xff0c;市场调研的重要性不言而喻。它不仅是产品创新的起点&#xff0c;也是确保产品成功推向市场的关键步骤。对于产品经理系统学习和掌握产品创新中的市场调研相关知识体系十分重要。 目录 概述&#xff1a;市场调研重要性 1、相关概…

10:00面试,10:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

【Java--数据结构】链表经典OJ题详解(上)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 谈谈头插、头删、尾插、头插的时间复杂度 反转一个单链表 链表的中间结点 返回倒数第k个结点 合并两个链表 谈谈头插、头删、尾插、头插的时间复杂度 头插和头删的时…

顺序栈--代码题

数据结构 顺序栈代码题设计一个进制转换程序,使用顺序栈设计一个把十进制转化为十六进制的接口,实现当键盘输入一个非负的十进制时,可以在终端输出对应的十六进制数。 /***************************************************************************************** file n…

完美运营版商城/拼团/团购/秒杀/积分/砍价/实物商品/虚拟商品等全功能商城

源码下载地址&#xff1a;完美运营版商城.zip 后台可以自由拖曳修改前端UI页面 还支持虚拟商品自动发货等功能 挺不错的一套源码 前端UNIAPP 后端PHP 一键部署版本

aws安装jenkins步骤

一、aws安装jdk11 1.1 aws安装jdk11 1、切换root,更新yum, sudo su yum update exist 2、安装JDK1.8版本 yum -y list java-1.8.0* #(安装jdk11,yum -y list java-11*) yum install java-1.8.0-openjdk-devel.x86_64 #(安装jdk11,yum -y list java-11-openjdk-deve…

嵌入式4-24

作业&#xff1a; 整理思维导图 定义一个矩形类Rec&#xff0c;包含私有属性length&#xff0c;width&#xff0c;有以下成员函数&#xff1a; void set_length(int l); //设置长度 void set_width(int w); //设置宽度 int get_length(); //获取长度 int get_width(); //获取宽…

【GIS教程】ArcGIS做日照分析(附练习数据下载)

我国对住宅日照标准的规定是:冬至日住宅底层日照不少于1小时或大寒日住宅层日照不少于2小时(通常以当地冬至日正午12时的太阳高度角作为依据)。因冬至日太阳高度角最低&#xff0c;照射范围最小&#xff0c;如果冬至日12&#xff1a;00建筑物底层能够接收到阳光&#xff0c;那么…

Golang | Leetcode Golang题解之第42题接雨水

题目&#xff1a; 题解: func trap(height []int) (ans int) {n : len(height)if n 0 {return}leftMax : make([]int, n)leftMax[0] height[0]for i : 1; i < n; i {leftMax[i] max(leftMax[i-1], height[i])}rightMax : make([]int, n)rightMax[n-1] height[n-1]for i…

详解MySQL C API 相关接口(大白话就是:MySQL的c语言怎么写)

文章目录 1、C API 官方文档2、初始化 MYSQL3、连接 MySQL设置连接字符集&#xff08;使得客户端编码方式匹配&#xff09; 4、下发 mysql 指令5、获取 mysql 查询结果(保存起来)获取行与列遍历存储结果 6、释放 MYSQL\_RES 对象7、关闭 MySQL 连接8、总结 1、C API 官方文档 …

vue3 删除对象中的属性,可以使用js里的delete,但需注意ts定义对象类型!

如上如&#xff0c;当使用delete 删除stateData中的属性时&#xff0c; 报错&#xff0c;意思为 TypeScript 错误“‘delete’ 运算符的操作数必须是可选的 什么原因呢&#xff1f;是因为我偷懒 缺少了ts定义类型 方法一&#xff1a; &#xff08;不推荐&#xff09; delete …

嵌入式笔记4.1 GPIO 功能复用

目录一、了解 MCU(GPIO)具有的所有复用功能通过查看 MCU 的数据手册可以知道 MCU 的所有引脚的功能:例 STM32L431:例 stm32f103:复用、重映射、多路复用(多功能引脚)GPIO复用(AF - Alternate Function)重映射(Remapping)多路复用(Multi-function)常见引脚功能一览…