计算机竞赛python区块链实现 - proof of work工作量证明共识算法

文章目录

  • 0 前言
  • 1 区块链基础
    • 1.1 比特币内部结构
    • 1.2 实现的区块链数据结构
    • 1.3 注意点
    • 1.4 区块链的核心-工作量证明算法
      • 1.4.1 拜占庭将军问题
      • 1.4.2 解决办法
      • 1.4.3 代码实现
  • 2 快速实现一个区块链
    • 2.1 什么是区块链
    • 2.2 一个完整的快包含什么
    • 2.3 什么是挖矿
    • 2.4 工作量证明算法:
    • 2.5 实现代码
  • 3 最后

0 前言

🔥 优质竞赛项目系列,今天要分享的是

python区块链实现 - proof of work工作量证明共识算法

该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

在这里插入图片描述

1 区块链基础

学长以比特币的结构向大家详解区块链的组成部分

1.1 比特币内部结构

  • previous hash(前一个区块的hash)
  • merkle root(默克尔树根节点,内部存储交易数据)
  • timestamp(当前区块生成的时间)
  • nonce(旷工计算hash值次数)

在这里插入图片描述

1.2 实现的区块链数据结构

  • index 当前第几个区块
  • timestamp 该区块创建时的时间戳
  • data 交易信息
  • previousHash 前一个区块的hash
  • hash 当前区块的hash

1.3 注意点

第一个区块叫做创世区块(genesis block),区块链创建的时候默认生产的这里用的是单纯的链表,不是用默克尔树存储

示例代码

from hashlib import sha256//区块schemaclass Block:def __init__(self,index,timestamp,data,previousHash=""):self.index = indexself.timestamp = timestampself.data = dataself.previousHash = previousHashself.hash = self.calculateHash()//计算当前区块的hashdef calculateHash(self):plainData = str(self.index)+str(self.timestamp)+str(self.data)return sha256(plainData.encode('utf-8')).hexdigest()def __str__(self):return str(self.__dict__)//区块链schemaclass BlockChain://初始化的时候 创建 创世区块def __init__(self):self.chain = [self.createGenesisBlock()]//构建创世区块def createGenesisBlock(self):return Block(0,"01/01/2018","genesis block","0")//获取最后一个区块def getLatestBlock(self):return self.chain[len(self.chain)-1]//往区块链里面添加区块def addBlock(self,newBlock):newBlock.previousHash = self.getLatestBlock().hashnewBlock.hash = newBlock.calculateHash()self.chain.append(newBlock)def __str__(self):return str(self.__dict__)    //校验区块链是不是有效的 有没有人被篡改def chainIsValid(self):for index in range(1,len(self.chain)):currentBlock = self.chain[index]previousBlock = self.chain[index-1]if (currentBlock.hash != currentBlock.calculateHash()):return Falseif previousBlock.hash != currentBlock.previousHash:return Falsereturn TruemyCoin = BlockChain()
myCoin.addBlock(Block(1,"02/01/2018","{amount:4}"))
myCoin.addBlock(Block(2,"03/01/2018","{amount:5}"))#print block info 打印区块链信息
print("print block info ####:")
for block in myCoin.chain:print(block)
#check blockchain is valid 检查区块链是不是有效的
print("before tamper block,blockchain is valid ###")
print(myCoin.chainIsValid())
#tamper the blockinfo  篡改区块2的数据
myCoin.chain[1].data = "{amount:1002}"
print("after tamper block,blockchain is valid ###")
print(myCoin.chainIsValid())

输出结果

print block info ####:
{'index': 0, 'timestamp': '01/01/2018', 'data': 'genesis block', 'previousHash': '0', 'hash': 'd8d21e5ba33780d5eb77d09d3b407ceb8ade4e5545ef951de1997b209d91e264'}
{'index': 1, 'timestamp': '02/01/2018', 'data': '{amount:4}', 'previousHash': 'd8d21e5ba33780d5eb77d09d3b407ceb8ade4e5545ef951de1997b209d91e264', 'hash': '15426e32db30f4b26aa719ba5e573f372f41e27e4728eb9e9ab0bea8eae63a9d'}
{'index': 2, 'timestamp': '03/01/2018', 'data': '{amount:5}', 'previousHash': '15426e32db30f4b26aa719ba5e573f372f41e27e4728eb9e9ab0bea8eae63a9d', 'hash': '75119e897f21c769acee6e32abcefc5e88e250a1f35cc95946379436050ac2f0'}
before tamper block,blockchain is valid ###
True
after tamper block,blockchain is valid ###
False

1.4 区块链的核心-工作量证明算法

上面学长介绍了区块链的基本结构,我在之前的基础上来简单实现一下工作量证明算法(proof of
work),在介绍pow之前先思考一下为什么要工作量证明算法,或者再往前想一步为什么比特币如何解决信任的问题?

1.4.1 拜占庭将军问题

比特币出现之前就有了拜占庭将军问题,主要思想是,如何在分布式系统环境里去相信其他人发给你的信息?

一组拜占庭将军分别各率领一支军队共同围困一座城市。为了简化问题,将各支军队的行动策略限定为进攻或撤离两种。因为部分军队进攻部分军队撤离可能会造成灾难性后果,因此各位将军必须通过投票来达成一致策略,即所有军队一起进攻或所有军队一起撤离。因为各位将军分处城市不同方向,他
系统的问题在于,将军中可能出现叛徒,他们不仅可能向较为糟糕的策略投票,还可能选择性地发送投票信息。假设有9位将军投票,其中1名叛徒。8名忠诚的将军中出现了4人投进攻,4人投撤离的情况。这时候叛徒可能故意给4名投进攻的将领送信表示投票进攻,而给4名投撤离的将领送信表示投撤离。这样一来在4名投进攻的将领看来,投票结果是5人投进攻,从而发起进攻;而在4名投撤离的将军看来则是5人投撤离。这样各支军队的一致协同就遭到了破坏。

在这里插入图片描述

1.4.2 解决办法

拜占庭将军问题主要问题是,中间人可以拦截消息,进行修改;上述的那些士兵可以理解成比特币中的一些节点,不是所有节点拿到消息后都是可以直接处理的,先去解决一个数学问题,就是工作量证明,只有拥有特定的计算能力解决了问题之后才能去修改或者校验(验证,打包,上链)。

在这里插入图片描述
上图就是简单的工作量证明算法流程,一串数字后面有个x,x之前的数可以理解成交易数据,然后需要找到一个x,让整个数的hash值的开头有n个0,如果hash是很均匀的话,那么生成的hash值每一位为0或者1都是等可能的,所以前n个都为0的概率就是2的n次方/2的hash值位数,上图给出了如果hash值是5个bit的情况下的所有可能

1.4.3 代码实现

from hashlib import sha256import timeclass Block:def __init__(self,index,timestamp,data,previousHash=""):self.index = indexself.timestamp = timestampself.data = dataself.previousHash = previousHashself.nonce = 0 //代表当前计算了多少次hash计算self.hash = self.calculateHash()def calculateHash(self):plainData = str(self.index)+str(self.timestamp)+str(self.data)+str(self.nonce)return sha256(plainData.encode('utf-8')).hexdigest()#挖矿 difficulty代表复杂度 表示前difficulty位都为0才算成功def minerBlock(self,difficulty):while(self.hash[0:difficulty]!=str(0).zfill(difficulty)):self.nonce+=1self.hash = self.calculateHash()def __str__(self):return str(self.__dict__)class BlockChain:def __init__(self):self.chain = [self.createGenesisBlock()]self.difficulty = 5def createGenesisBlock(self):return Block(0,"01/01/2018","genesis block")def getLatestBlock(self):return self.chain[len(self.chain)-1]#添加区块前需要 做一道计算题😶,坐完后才能把区块加入到链上def addBlock(self,newBlock):newBlock.previousHash = self.getLatestBlock().hashnewBlock.minerBlock(self.difficulty)self.chain.append(newBlock)def __str__(self):return str(self.__dict__)    def chainIsValid(self):for index in range(1,len(self.chain)):currentBlock = self.chain[index]previousBlock = self.chain[index-1]if (currentBlock.hash != currentBlock.calculateHash()):return Falseif previousBlock.hash != currentBlock.previousHash:return Falsereturn TruemyCoin = BlockChain()# 下面打印了每个区块挖掘需要的时间 比特币通过一定的机制控制在10分钟出一个块 # 其实就是根据当前网络算力 调整我们上面difficulty值的大小,如果你在# 本地把上面代码difficulty的值调很大你可以看到很久都不会出计算结果startMinerFirstBlockTime = time.time()print("start to miner first block time :"+str(startMinerFirstBlockTime))myCoin.addBlock(Block(1,"02/01/2018","{amount:4}"))print("miner first block time completed" + ",used " +str(time.time()-startMinerFirstBlockTime) +"s")startMinerSecondBlockTime = time.time()print("start to miner first block time :"+str(startMinerSecondBlockTime))myCoin.addBlock(Block(2,"03/01/2018","{amount:5}"))print("miner second block time completed" + ",used " +str(time.time()-startMinerSecondBlockTime) +"s\n")#print block infoprint("print block info ####:\n")for block in myCoin.chain:print("\n")print(block)#check blockchain is validprint("before tamper block,blockchain is valid ###")print(myCoin.chainIsValid())#tamper the blockinfomyCoin.chain[1].data = "{amount:1002}"print("after tamper block,blockchain is valid ###")print(myCoin.chainIsValid())

输出

在这里插入图片描述

2 快速实现一个区块链

2.1 什么是区块链

区块链是一个不可变得,有序的被称之为块的记录链,它们可以包含交易、文件或者任何你喜欢的数据,但最重要的是,它们用hash连接在一起。

2.2 一个完整的快包含什么

一个索引,一个时间戳,一个事物列表,一个校验, 一个前快的散链表

2.3 什么是挖矿

挖矿其实非常简单就做了以下三件事:

1、计算工作量证明poW
2、通过新增一个交易赋予矿工(自已)一个币
3、构造新区块并将其添加到链中

2.4 工作量证明算法:

使用该算法来证明是如何在区块上创建和挖掘新的区块,pow的目标是计算出一个符合特定条件的数字,这个数字对于所有人而言必须在计算上非常困难,但易于验证,这就是工作证明背后的核心思想计算难度与目标字符串需要满足的特定字符串成正比。

2.5 实现代码

import hashlibimport jsonimport requestsfrom textwrap import dedentfrom time import timefrom uuid import uuid4from urllib.parse import urlparsefrom flask import Flask, jsonify, requestclass Blockchain(object):def __init__(self):...self.nodes = set()# 用 set 来储存节点,避免重复添加节点....self.chain = []self.current_transactions = []#创建创世区块self.new_block(previous_hash=1,proof=100)def reister_node(self,address):"""在节点列表中添加一个新节点:param address::return:"""prsed_url = urlparse(address)self.nodes.add(prsed_url.netloc)def valid_chain(self,chain):"""确定一个给定的区块链是否有效:param chain::return:"""last_block = chain[0]current_index = 1while current_index<len(chain):block = chain[current_index]print(f'{last_block}')print(f'{block}')print("\n______\n")# 检查block的散列是否正确if block['previous_hash'] != self.hash(last_block):return False# 检查工作证明是否正确if not self.valid_proof(last_block['proof'], block['proof']):return Falselast_block = blockcurrent_index += 1return Truedef ressolve_conflicts(self):"""共识算法:return:"""neighbours = self.nodesnew_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_chain(chain):max_length = lengthnew_chain = chain# 如果发现一个新的有效链比当前的长,就替换当前的链if new_chain:self.chain = new_chainreturn Truereturn Falsedef new_block(self,proof,previous_hash=None):"""创建一个新的块并将其添加到链中:param proof: 由工作证明算法生成证明:param previous_hash: 前一个区块的hash值:return: 新区块"""block = {'index':len(self.chain)+1,'timestamp':time(),'transactions':self.current_transactions,'proof':proof,'previous_hash':previous_hash or self.hash(self.chain[-1]),}# 重置当前交易记录self.current_transactions = []self.chain.append(block)return blockdef new_transaction(self,sender,recipient,amount):# 将新事务添加到事务列表中"""Creates a new transaction to go into the next mined Block:param sender:发送方的地址:param recipient:收信人地址:param amount:数量:return:保存该事务的块的索引"""self.current_transactions.append({'sender':sender,'recipient':recipient,'amount':amount,})return  self.last_block['index'] + 1@staticmethoddef hash(block):"""给一个区块生成 SHA-256 值:param block::return:"""# 必须确保这个字典(区块)是经过排序的,否则将会得到不一致的散列block_string = json.dumps(block,sort_keys=True).encode()return hashlib.sha256(block_string).hexdigest()@propertydef last_block(self):# 返回链中的最后一个块return self.chain[-1]def proof_of_work(self,last_proof):# 工作算法的简单证明proof = 0while self.valid_proof(last_proof,proof)is False:proof +=1return proof@staticmethoddef valid_proof(last_proof,proof):# 验证证明guess =  f'{last_proof}{proof}'.encode()guess_hash = hashlib.sha256(guess).hexdigest()return guess_hash[:4] =="0000"# 实例化节点app = Flask(__name__)# 为该节点生成一个全局惟一的地址node_identifier = str(uuid4()).replace('-','')# 实例化Blockchain类blockchain = Blockchain()# 进行挖矿请求@app.route('/mine',methods=['GET'])def mine():# 运行工作算法的证明来获得下一个证明。last_block = blockchain.last_blocklast_proof = last_block['proof']proof = blockchain.proof_of_work(last_proof)# 必须得到一份寻找证据的奖赏。blockchain.new_transaction(sender="0",recipient=node_identifier,amount=1,)# 通过将其添加到链中来构建新的块previous_hash = blockchain.hash(last_block)block = blockchain.new_block(proof,previous_hash)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_transactions():values = request.get_json()# 检查所需要的字段是否位于POST的data中required = ['seder','recipient','amount']if not all(k in values for k in request):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", 400for 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), 200if __name__ == '__main__':app.run(host='0.0.0.0',port=5000)

代码弄好启动你的项目以后打开Postman 完成以下操作

在这里插入图片描述

学长通过请求 http://localhost:5000/mine进行采矿

在这里插入图片描述

3 最后

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/157454.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 基于SpringBoot的某家乡美食系统

1 简介 《Java 基于SpringBoot的某家乡美食系统》该项目含有源码、文档等资料、配套开发软件、软件安装教程等。系统功能完整&#xff0c;适合作为毕业设计、课程设计、数据库大作业学习使用。 功能介绍 这个项目是基于 SpringBoot和 Vue 开发的地方美食系统&#xff0c;包括…

竞赛选题 深度学习 机器视觉 人脸识别系统 - opencv python

文章目录 0 前言1 机器学习-人脸识别过程人脸检测人脸对其人脸特征向量化人脸识别 2 深度学习-人脸识别过程人脸检测人脸识别Metric Larning 3 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 人脸识别系统 该项目…

小谈设计模式(25)—职责链模式

小谈设计模式&#xff08;25&#xff09;—职责链模式 专栏介绍专栏地址专栏介绍 职责链模式分析角色分析抽象处理者&#xff08;Handler&#xff09;具体处理者&#xff08;ConcreteHandler&#xff09;客户端&#xff08;Client&#xff09; 优缺点分析优点123 缺点12 应用场…

当下测试行业中UI自动化面临的难点及如何解决

经常有人会问&#xff0c;什么样的项目才适合进行UI自动化测试呢&#xff1f;UI自动化测试相当于模拟手工测试&#xff0c;通过程序去操作页面上的控件。而在实际测试过程中&#xff0c;经常会遇到无法找到控件&#xff0c;或者因控件定义变更而带来的维护成本等问题。 哪些场…

深度学习基础知识 给模型的不同层 设置不同学习率

深度学习基础知识 给模型的不同层 设置不同学习率 1、使用预训练模型时&#xff0c;可能需要将2、学习率设置方式&#xff1a; 1、使用预训练模型时&#xff0c;可能需要将 &#xff08;1&#xff09;预训练好的 backbone 的 参数学习率设置为较小值&#xff0c; &#xff08;2…

Fastjson历史版本记录

1.2.24 TemplatesImpl&#xff0c;利用条件苛刻&#xff0c;需要开启Feature.SupportNonPublicField {"type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes": ["yv66vgAAADQA...CJAAk"],"_name…

LeetCode刷题总结 - LeetCode 热题 100 - 持续更新

LeetCode 热题 100 其他系列哈希1. 两数之和49. 字母异位词分组128. 最长连续序列 双指针27. 移除元素283. 移动零11. 盛最多水的容器剑指 Offer II 007. 数组中和为 0 的三个数42. 接雨水 滑动窗口438. 找到字符串中所有字母异位词3. 无重复字符的最长子串 字串560. 和为 K 的…

PerformanceRunner国产化性能测试工具

国产化性能测试工具PerformanceRunner&#xff08;简称PR&#xff09;通过模拟海量用户并发测试整个系统的承受能力&#xff0c;实现压力测试、性能测试、配置测试、峰值测试等。大限度地缩短测试时间&#xff0c;优化性能和加速应用系统的发布周期。 泽众PR性能测试工具是国内…

基于Linux上MySQL8.*版本的安装-参考官网

本地hadoop环境安装好,并安装好mysql mysql下载地址及选择包 MySQL :: Download MyS的QL Community Server (Archived Versions) mysql安装步骤 下载与上传解压给权限 #mysql安装包上传到/opt下 cd /usr/local/ #解压到此目录 tar -xvf /opt/mysql-8.0.33-linux-glibc2.12-…

C# 使用 RSA 加密算法生成证书签名产生“The system cannot find the file specified”异常

使用 C# 中 RSA&#xff08;System.Security.Cryptography.RSA&#xff09; 加密算法生成证书签名进行身份验证&#xff0c;在 VS2022 开发工具本地运行应用程序一切正常。 但将应用程序部署到远程服务器&#xff08;如&#xff1a;Azure App Services&#xff09;&#xff0c…

基于PLC的机械手控制系统设计

目录 摘 要......................................................................................................................... 1 第一章 绪论.............................................................................................................…

计算机毕业设计选什么题目好?springboot 高校就业管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

git的基础操作

https://blog.csdn.net/a18307096730/article/details/124586216?spm1001.2014.3001.5502 1&#xff1a;使用场景 SVN&#xff0c;如果服务器里面的东西坏掉了&#xff0c;那么就全线崩盘了。 1:基本配置 git config --global user.name “luka” (自己的名字就行) git co…

opencv dnn模块 示例(18) 目标检测 object_detection 之 pp-yolo、pp-yolov2和pp-yolo tiny

文章目录 1、PP-YOLO1.1、网络架构1.1.1、BackBone骨干网络1.1.2、DetectionNeck1.1.3、DetectionHead 1.2、Tricks的选择1.2.1、更大的batchsize1.2.2、滑动平均1.2.3、DropBlock1.2.4、IOU Loss1.2.5、IOU Aware1.2.6、GRID Sensitive1.2.7、Matrix NMS1.2.8、CoordConv1.2.9…

基于Labview的噪声采集分析系

目录 摘 要......................................................................................................................... 3 第一章 绪论.............................................................................................................…

iPhone手机上使用的定时提醒APP是哪个

在日常喧闹的生活和工作中&#xff0c;琐碎的任务会像喷泉一样突涌而至&#xff0c;如不及时规划&#xff0c;我们将陷入手足无措的境地。而想要让各项工作任务按时完成&#xff0c;我们可以借助一些比较好用的时间提醒软件来督促各项任务。 就拿常用的iPhone手机来讲&#xf…

CCF CSP认证 历年题目自练Day29

题目一 试题编号&#xff1a; 202112-1 试题名称&#xff1a; 序列查询 时间限制&#xff1a; 300ms 内存限制&#xff1a; 512.0MB 样例1输入 3 10 2 5 8 样例1输出 15 样例2输入 9 10 1 2 3 4 5 6 7 8 9 样例2输出 45 题目分析&#xff08;个人理解&#xff09; 还是…

解读提示工程(Prompt Engineering)

提示工程&#xff08;Prompt Engineering&#xff09;&#xff0c;也称为上下文提示&#xff0c;是一种通过不更新模型的权重/参数来引导LLM行为朝着特定结果的方法。这是与AI有效交流所需结果的过程。提示工程可以用于各种任务&#xff0c;从回答问题到算术推理乃至各种应用领…

json库的基本使用

目录 1 将python变量转变为json变量 dumps() 2 将json变量转换为python变量 loads() 3 将键值对存储为json文件 dump() 4 读取json文件 前后端常用json进行信息的交互&#xff0c;不转json会有收不到的情况 我们先看一下转换成json的服务 发现该有的信息都有&#x…

Spring Boot中的Redis自动配置与使用

Spring Boot中的Redis自动配置与使用 Redis是一种高性能的开源内存数据库&#xff0c;常用于缓存、会话管理和消息队列等场景。Spring Boot提供了自动配置来简化在Spring应用程序中使用Redis的过程。本文将介绍Spring Boot中的Redis自动配置是什么以及如何使用它来轻松集成Red…