POS代码实现

news/2024/11/23 3:15:39/

本篇文章主要是POS共识的简单实现,其中有许多地方都做了简化。POS的原理已在上篇文章中描述过,如果对POS的原理不太清晰的可以进行查看。文章地址:共识算法学习总结。

代码实现的功能有:添加区块、查看区块链、添加验证者以及查看所有的验证者。代码使用bolt数据库进行数据持久化。

创建一条区块链

系统运行时,首先运行命令创建一条区块链。该函数主要的功能:创建一个创世块,并把创世块保存在bolt数据库中。

func create() {// 生成创世块genesisBlock := common.Block{}genesisBlock = common.Block{0,time.Now().String(),"",GenerateHashValue(genesisBlock),"",common.Validator{},}// 获取bolt数据库句柄db := common.GetDB()defer db.Close()// 把创世块添加进数据库文件中db.Update(func(tx *bolt.Tx) error {// 获取bucketbucket, err := tx.CreateBucketIfNotExists([]byte(common.BlocksBucket))if err != nil{fmt.Println(err)return err}// 获取最后一个区块的哈希lastHash := bucket.Get([]byte("lastHash"))if lastHash == nil {bucket.Put([]byte("lastHash"), []byte(genesisBlock.HashCode))bucket.Put([]byte(genesisBlock.HashCode), serializeBlock(genesisBlock))}return err})
}

添加一个区块

当创建一个区块链后就可以往区块链中添加区块。当添加区块时首先开启共识模块,共识模块会在后面讲解。开启共识模块后,把输入的数据打包成区块,然后把区块添加到候选区块通道中,等待共识模块的确认。最后等待共识模块的完成。

func addBlock(data string)  {// 开始共识go consensus.Start()// 把客户端输入的数据封装成区块。这里做了简化,直接生成了区块。// 实际上应由验证者进行打包区块。newBlock := generateBlock(data)// 把新生成的区块添加到候选区块通道中common.CandidateBlokcs <- newBlockselect {// 阻塞等待退出case <- common.ExitChan:return}
}

启动共识

在启动共识的函数中,首先开启一个协程,不断读取候选区块切片中的数据,如果读取到区块就把区块追加到临时区块切片中。协程启动完毕后就开始循环POS共识。

func Start(){// 不断读取候选区块通道,如果有新的区块,就追加到临时区块切片中go func() {for candidate := range common.CandidateBlokcs{fmt.Println("有新的临时区块")common.TempBlocks = append(common.TempBlocks, candidate)}}()for  {// 循环pos共识算法pos()}}

POS共识

进入共识算法后,首先获取临时区块中的区块,接着获取所有的验证者并根据验证者的权重创建一个新的切片。在这个切片中,验证者的权重越高,重复的次数也就越多,也就越容易被选为出块节点。接着通过一个随机数挑选验证者并打包区块。

func pos()  {// 复制临时区块temp := common.TempBlocks// 根据temp的长度判断是否存在临时区块if len(temp) > 0{var tempValidators []common.Validator// 获取所有的验证者validators := getAllValidators()// 根据验证者拥有的token数量及时间得出权重,权重越高,被选取为出块节点的概率越大for i := 0; i < len(validators) - 1; i++{for j := 0; j < validators[i].Tokens * validators[i].Days; j++{tempValidators = append(tempValidators, validators[i])}}// 获取数据库句柄db := common.GetDB()defer db.Close()for _, block := range temp{// 挑选验证者rand.Seed(time.Now().Unix())var rd =rand.Intn(len(tempValidators))block.Validator = validators[rd % len(validators)]// 持久化db.Update(func(tx *bolt.Tx) error {bucket := tx.Bucket([]byte(common.BlocksBucket))err := bucket.Put([]byte(block.HashCode), serializeBlock(block))if err != nil {log.Fatal(err)}err = bucket.Put([]byte("lastHash"), []byte(block.HashCode))if err != nil {log.Fatal(err)}return nil})}mutex.Lock()common.ExitChan <- truecommon.TempBlocks = []common.Block{}temp = []common.Block{}mutex.Unlock()}
}

添加验证者

添加验证者时,需要指定验证者的token数量。验证者的地址用时间来模拟。最后把验证者持久化到数据库中,键为验证者的地址,值为序列化后的验证者。

func addValidator(token int)  {// 验证者的地址用当前时间的sha256值代替address := calculateHash(time.Now().String())// 创建一个验证者validator := common.Validator{token,time.Now().Second(),address,}// 添加到数据库中db := common.GetDB()defer db.Close()db.Update(func(tx *bolt.Tx) error {bucket := tx.Bucket([]byte(common.PeerBucket))err := bucket.Put([]byte(validator.Address), serializeValidator(validator))if err != nil {log.Fatal(err)return err}return nil})
}

查看验证者

查看验证者比较简单,只是查询一下数据库并进行打印。

func view()  {var validators []common.Validatordb := common.GetDB()defer db.Close()db.View(func(tx *bolt.Tx) error {bucket := tx.Bucket([]byte(common.PeerBucket))cursor := bucket.Cursor()for k, v := cursor.First(); k != nil; k, v = cursor.Next(){if string(k) == "lastHash"{continue}block := deserializeValidator(v)validators = append(validators, block)}return nil})spew.Dump(validators)
}

运行结果

在这里插入图片描述

最后

项目中做了很多简化并且有很多设计不合理的地方,以后会继续进行改进。源码:https://github.com/blockchainGuide/Consensus_Algorithm


http://www.ppmy.cn/news/465694.html

相关文章

android 控制POS机图文打印(一)

因为公司业务的需要&#xff0c;要用android客户端控制pos机打印票据&#xff0c;不单只是中文的&#xff0c;而且还要包括二维码的打印的&#xff01;经过两天的努力&#xff01;终于搞定了&#xff01;&#xff01;&#xff01;&#xff01;我真是&#xff01; 首先&#xf…

pos机相关概念

pos机终端 一、管理功能&#xff1a; 1.系统管理&#xff1a; 自检&#xff1a;开机后pos机对自身硬件的检测&#xff0c;【操作员也可以在功能设置中手动对其自检】 程序下载管理&#xff1a;对终端是使用的一些程序进行管理。 a.串口程序下载&#xff1a;使用串口通讯方式 …

为什么Eth转向Pos?

1.更加安全性。 什么是区块链的安全性&#xff1f; 如果攻击者掌握了超过诚实用户的计算资源&#xff0c;则攻击者所生成的新的分叉增长速度就会快于公开的区块链的增长速度&#xff0c;他很容易形成一个新的更长的区块链分支取代公开的最长区块链。当攻击者掌握了51%以上的计…

POS机 示例代码

POS机的基本要求与解释如下&#xff1a; 需求描述 商店里进行购物结算时会使用收银机&#xff08;POS&#xff09;系统&#xff0c;这台收银机会在结算时根据客户的购物车&#xff08;Cart&#xff09;中的商品&#xff08;Item&#xff09;和商店正在进行的优惠活动&#xff0…

银汇通支付解析固定pos机与移动pos机的优缺对比

银汇通支付解析固定pos机的优点是&#xff1a; 1、软件升级和维护比较容易; 2、网络和电话拨号方式; 3、POS 交易清算比较容易; 银汇通支付解析固定pos机的缺点是&#xff1a;固定在吧台&#xff0c;要不与电话线连接&#xff0c;要不就是和电脑连接。 银汇通支付解析无线pos机…

mybatisplus连接sqlserver配置

目录 前言&#xff1a; 一&#xff1a;所需依赖&#xff1a; 二&#xff1a;application.yml 三:分页插件 前言&#xff1a; 本文主要讲解连接sqlserver的配置 一&#xff1a;所需依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> &l…

高性能网络 SIG 月度动态:联合 IBM 就 SMC v2.1 协议升级达成一致,ANCK 率先完成支持

高性能网络 SIG&#xff08;Special Interest Group&#xff09; &#xff1a;在云计算时代&#xff0c;软硬件高速发展&#xff0c;云原生、微服务等新的应用形态兴起&#xff0c;让更多的数据在进程之间流动&#xff0c;而网络则成为了这些数据流的载体&#xff0c;在整个云时…

1229

/* 字符串题 奇数偶数分开处理会方便一些 以下贴出核心代码 */ for(i0;i<m;i) { for(j0;i-j>0 && ij<m;j)//对奇数的处理 { if(a[i-j]!a[ij]) break;//检查字符串 if(2*j1>max) max 2*j1;//更新…