背景

从2017年11月启动至今,经过历时近一年的研究、开发与测试,初链主网Beta版于新加坡时间2018年09月28日08:00正式上线,在此之前,07:56分PBFT委员会第一次共识出块和TrueChain fPOW创世区块被挖出,为了让更多人从技术上去理解初链,初链社区发布了初链技术解读的任务,我也借这次任务开始我第一篇博客。

说明

初链本次上线体现了五大亮点,包括混合共识,FPow公链,TrueHash抗ASIC的挖矿算法,PBFT委员会的随机选举机制,高TPS。本文主要针对初链的混合共识进行解读。后续一一解读其它亮点。

名称解释

共识: 共识顾名思义,共同的认识,在区块链世界中早期的共识算法代表要算比特币的pow。pow简单来讲,就是前一个区块有一个随机数,大家都去猜,谁先猜出来谁就有记账权,记账好了后,就将区块广播给其它节点,如果要想从源码层解读,请参考文档“PoW挖矿算法原理及其在比特币、以太坊中的实现”。
混合共识: pow共识安全但不高效,转账效率低,为了解决这个问题,后面出现了pos dpos,虽然效率提高了但是已不再那么去中心化。为了找到效率和安全的平衡点,混合共识出现,一种共识解决记账,一种共识解决区中心化。本文主要解读初链,让我们来看看true链是怎么找到这个平衡点的。

技术架构

初链采用双链结构,如图所示。一条快链,一条慢链。快链是交易块,里面记录的是很多交易。慢链是水果块,里面记录的是很多水果,水果一次递增,每个水果映射一个交易块。

混合共识又是怎么一回事呢?
在初链中,采用改进拜赞庭(fbft)和工作量证明(pow)两种共识。fbft主要解决交易效率问题,如图所示,委员会由41个节点组成,相对于比特比节点而已,已经少之又少,当交易网络的交易提交到委员会网络以后,交易能够得到快速的确认,自然整个网络的交易效率也就提高了额。pow主要解决去中心化问题,每个水果和每个快区块一一对应,而每个水果又会被pow再次打包出块,如果想要篡改交易,首先要篡改pow里面的水果,就必须控制51%的算力。
这有点虚吧!没问题,下面就来点实际的。

从启动到运行bft有很深的调用链,如下可以找到node的NewNode方法
main-->>cmd:StartNode()
cmd-->>node:Start()
node-->>service:start()
service-->>backend-Truechain:Start()
truechain-->>pbft_agent:start()loop()
pbft_agent-->>commitee:PutNodes()
commitee-->>pbftserver:PutNodes()
pbftserver-->>proxy_server:NewServer()
proxy_server-->>node:NewNode()

有关pbft算法过程详情可以参考【链接5】,大概有5个过程1. Request 2. Pre-Prepare 3. Prepare 4. Commit 5.Reply。true链进行了改造。整个逻辑如图,重点是node的resolveMsg,该方法是true链委员会和fbft_impl起到核心关联作用。

相关代码如下

type PBFT interface {StartConsensus(request *RequestMsg) (*PrePrepareMsg, error)PrePrepare(prePrepareMsg *PrePrepareMsg) (*VoteMsg, error)Prepare(prepareMsg *VoteMsg) (*VoteMsg, error)Commit(commitMsg *VoteMsg) (*ReplyMsg, *RequestMsg, error)
}实现类在pbft_impl.go中,这里只展示一段,其它方法感兴趣的同学可以自行查看
func (state *State) PrePrepare(prePrepareMsg *PrePrepareMsg) (*VoteMsg, error) {// Get ReqMsgs and save it to its logs like the primary.state.MsgLogs.ReqMsg = prePrepareMsg.RequestMsg// Verify if v, n(a.k.a. sequenceID), d are correct.if !state.verifyMsg(prePrepareMsg.ViewID, prePrepareMsg.SequenceID, prePrepareMsg.Digest) {return nil, errors.New("pre-prepare message is corrupted")}// Change the stage to pre-prepared.state.CurrentStage = PrePreparedreturn &VoteMsg{ViewID:     state.ViewID,SequenceID: prePrepareMsg.SequenceID,Digest:     prePrepareMsg.Digest,MsgType:    PrepareMsg,Height:     prePrepareMsg.Height,}, nil
}
而上文提到的node.NewNode中有这么一段,其中resolveMsg就是处理各种fbft过程传统msg,对msg校验,然后发起下一阶段的请求。
// Start message dispatchergo node.dispatchMsg()// Start alarm triggergo node.alarmToDispatcher()// Start message resolvergo node.resolveMsg()//start backward message dispatchergo node.dispatchMsgBackward()//start Process message commit waitgo node.processCommitWaitMessage()resolveMsg代码如下
func (node *Node) resolveMsg() {for {// Get buffered messages from the dispatcher.msgs := <-node.MsgDeliveryswitch msgs.(type) {case []*consensus.RequestMsg:errs := node.resolveRequestMsg(msgs.([]*consensus.RequestMsg))if len(errs) != 0 {for _, err := range errs {fmt.Println(err)}// TODO: send err to ErrorChannel}case []*consensus.PrePrepareMsg:errs := node.resolvePrePrepareMsg(msgs.([]*consensus.PrePrepareMsg))if len(errs) != 0 {for _, err := range errs {fmt.Println(err)}// TODO: send err to ErrorChannel}case []*consensus.VoteMsg:voteMsgs := msgs.([]*consensus.VoteMsg)if len(voteMsgs) == 0 {break}if voteMsgs[0].MsgType == consensus.PrepareMsg {errs := node.resolvePrepareMsg(voteMsgs)if len(errs) != 0 {for _, err := range errs {fmt.Println(err)}// TODO: send err to ErrorChannel}} else if voteMsgs[0].MsgType == consensus.CommitMsg {errs := node.resolveCommitMsg(voteMsgs)if len(errs) != 0 {for _, err := range errs {fmt.Println(err)}// TODO: send err to ErrorChannel}}}}
}

还有一个重要的问题必须要回答,因为现在fbft调用链找到了额,fbft过程消息处理机制也找到了额,但是共识的是什么?这个问题一直没回答。其实fbft共识的是leader和fastblock。代码如下,中间省去部分细节。

app启动是会开启维护员leader选举
pbft_agent.gocase types.CommitteeStart:log.Info("CommitteeStart...")self.committeeMu.Lock()self.setCommitteeInfo(self.NextCommitteeInfo, CurrentCommittee)self.committeeMu.Unlock()if self.IsCommitteeMember(self.CommitteeInfo) {go self.server.Notify(self.CommitteeInfo.Id, int(ch.Option))//发送选举通知  Notify为调用pbftserver.work}
pbftserver.go work代码如下
func (ss *PbftServerMgr) work(cid *big.Int, acChan <-chan *consensus.ActionIn) {for {select {case ac := <-acChan:if ac.AC == consensus.ActionFecth {req, err := ss.GetRequest(cid)if err == nil && req != nil {if server, ok := ss.servers[cid.Uint64()]; ok {server.Height = big.NewInt(req.Height)server.server.PutRequest(req) //发起共识} else {fmt.Println(err.Error())}} else {lock.PSLog(err.Error())}} else if ac.AC == consensus.ActionBroadcast {ss.Broadcast(ac.Height)} else if ac.AC == consensus.ActionFinish {return}}}选举完成之后将自己设置为leader
func (ss *PbftServerMgr) PutCommittee(committeeInfo *types.CommitteeInfo) error {lock.PSLog("PutCommittee", committeeInfo.Id, committeeInfo.Members)id := committeeInfo.Idmembers := committeeInfo.Membersif id == nil || len(members) <= 0 {return errors.New("wrong params...")}if _, ok := ss.servers[id.Uint64()]; ok {return errors.New("repeat ID:" + id.String())}leader := members[0].Publickeyinfos := make([]*types.CommitteeNode, 0)server := serverInfo{   //第一次共识完成,选出leaderleader: leader,nodeid: common.ToHex(crypto.FromECDSAPub(ss.pk)),info:   infos,Height: new(big.Int).Set(common.Big0),clear:  false,}for _, v := range members {server.insertMember(v)}ss.servers[id.Uint64()] = &serverreturn nil
}
在fb出块的时候有一个leader判断动作
func (ss *PbftServerMgr) GetRequest(id *big.Int) (*consensus.RequestMsg, error) {// get new fastblock 产出一个fastblockserver, ok := ss.servers[id.Uint64()]if !ok {return nil, errors.New("wrong conmmitt ID:" + id.String())}// the node must be leaderif !bytes.Equal(crypto.FromECDSAPub(server.leader), crypto.FromECDSAPub(ss.pk)) { //leader判断return nil, errors.New("local node must be leader...")}lock.PSLog("AGENT", "FetchFastBlock", "start")fb, err := ss.Agent.FetchFastBlock()lock.PSLog("AGENT", "FetchFastBlock", err == nil, "end")if err != nil {return nil, err}if fb := ss.getBlock(fb.NumberU64()); fb != nil {return nil, errors.New("same height:" + fb.Number().String())}fmt.Println(len(ss.blocks))sum := ss.getBlockLen()if sum > 0 {last := ss.getLastBlock()if last != nil {cur := last.Number()cur.Add(cur, common.Big1)if cur.Cmp(fb.Number()) != 0 {return nil, errors.New("wrong fastblock,lastheight:" + cur.String() + " cur:" + fb.Number().String())}}}ss.putBlock(fb.NumberU64(), fb)data, err := rlp.EncodeToBytes(fb)if err != nil {return nil, err}msg := hex.EncodeToString(data)val := &consensus.RequestMsg{ //返回一个fastblock共识消息ClientID:  server.nodeid,Timestamp: time.Now().Unix(),Operation: msg,Height:    fb.Number().Int64(),}return val, nil
}

本来想对pow在解析一下,发现有童鞋写的非常好了额,感兴趣的可以移步链接【6】

运行状况

再来看看true链运行情况。
总体运行情况如下图:图中可以看出目前委员会为6个,FB69758个,SB982个。委员会6据了解是前期为了主网稳定,但6个节点那么允许作恶容忍6*0.25=1.2个,作恶风险还是比较高,如果出现2台机器作恶,将会产生混乱,还是希望官网引起重视。

再来看混合共识的结果
快链:初略看了一下大部分block的共识委员会都是6个,说明目前没有分岔,但有一个疑问,为什么第一个的block高度不是1?

慢链:初略看了一下大部分挖矿地址比较分散,说明pow效果还是很明显真正做到了去中心化。但是大部分区块没有交易数,很多空块会占用大量的存储空间,而且毫无意义,因为没有交易。我想一种采用一种压缩技术,对连续空块进行压缩;一种方式降低出块速率让速率和交易量挂钩。这两种思路都可以解决空块暂用磁盘问题,我的一点拙见。

Snail Blocks:进入SnailBlocks发现没有水果,不知是我理解的问题,还是浏览器的bug,没有发现水果。按照逻辑应该水果能被查询出来才算正常,水果作为Fast Block再次打包的凭证,如果没有水果很难说pow发挥作用,希望是浏览器的bug。

结论

节点启动以后会先发起一轮fbft的共识选举,选举leader有记账权,记账的表现形式为fastblock。如果想研究pow机制请参考链接【6】。这两种共识一种保障效率,一种保障安全,在去中心化和效率选进行了一个折中的选择。从上线的运行效果来看,两种共识能够完美配合,但是仍存在一些不足,比如空块暂用磁盘可以进行优化,水果在区块链浏览器中无法查看,委员会只有6个安全有待进一步提升。最后,初链做出的努力和结果可喜可贺,为投资者和社区交了一份满意的答卷。

参考资料

[1]:https://www.8btc.com/article/106800 论比特币系统的共识规则
[2]:http://blog.51cto.com/11821908/2059711 PoW挖矿算法原理及其在比特币、以太坊中的实现
[3]:http://www.sohu.com/a/239677141_100092199 POW+POS混合共识机制有多牛?区块链大佬揭秘!
[4]:https://blog.csdn.net/qq_22269733/article/details/83025225 Truechain主网Beta版交易流程解析
[5]:https://blog.csdn.net/jerry81333/article/details/74303194/ 区块链共识算法 PBFT(拜占庭容错)、PAXOS、RAFT简述
[6]:https://blog.csdn.net/sinat_27935057/article/details/83193018 初链主网Beta版慢链挖矿解析

初链主网上线技术解读之-混合共识相关推荐

  1. “初链”主网上线解析之“初始化”

    从2017年11月启动至今,经过历时近一年的研究.开发与测试,初链主网Beta版于新加坡时间2018年09月28日08:00正式上线,在此之前,07:56分PBFT委员会第一次共识出块和TrueCha ...

  2. 北京链安:火币生态链Heco主网上线一月,已达到以太坊峰值5倍处理能力

    陀螺财经消息,1月20日,北京链安监测发现,自火币生态链Heco主网上线以来,其处理能力最高已达到以太坊峰值5倍并经过链上验证. 1月19日,Heco主网吞吐量TPS大于70,并承载链上十万级以上服务 ...

  3. 一块听听:Mixin 主网上线语音直播文字稿

    本文是在一块听听上的语音直播的文字精简版. Mixin Network的成绩,主网和展望 大家好,我是Mixin Network 的李林.非常高兴能在这里跟大家分享一下Mixin Network.第一 ...

  4. EOS主网上线只是开始,如何运营决定未来

    相比前段时间大佬力挺,交易所争相竞选超级节点的利好,EOS近来的日子真是不太平.先是被360公司Vulcan(伏尔甘)团队爆出"百亿美金"的致命漏洞,日前又被V神侧击,这个6月,E ...

  5. Filecoin主网上线只是鸣枪开跑,完美落地需要成长的过程

    作为搅动全球的热点,主网上线的运行情况和FIL的后续进展成为市场焦点.Filecoin不同于国内的小项目,这是一个长期的项目,有着可以实现落地的愿景和使命,也有着巨大的体量和簇拥. 这样的一个项目,对 ...

  6. EOS主网上线世界庆典完美收官|荣耀将至!一个伟大时代即将开启

    30秒的临时起意 30个小时的不眠不休 两天6个小时的实时直播 来自10个以上国家的重量级嘉宾 全球数十个竞选节点的现身参与 EOS开发者BM的现身问好 70万以上在线人次的观看 为期两天的EOS主网 ...

  7. 主网已经上线的币有哪些_什么是主网币圈主网上线意味着什么?

    本文来自网络抓取,如果侵权请联系删除 作者:区块链学习 来源:区块链百科 简介:本文内容由区块链分析师整理编辑 主要讲解的内容是:什么是主网币圈主网上线意味着什么? ......的相关信息,具体详情阅 ...

  8. 主网已经上线的币有哪些_主要币种主网上线时间(超全)

    导语 主网一般是底层基础链. 主网的上线节点(是否上线.什么时候上线)是判断该项目真假的关键依据. 以下为社长整理的较详细的主网上线时间清单. Nebulas 代币简称:NAS 主网上线时间:2018 ...

  9. Sui Builder House首尔站|主网上线后首次亮相

    Sui Builder House提供与全球Sui构建者会面.合作并学习Sui平台前沿技术的机会.Sui基金会计划将于2023年在全球12个城市举办Sui Builder House.截止目前,已成功 ...

最新文章

  1. javascript--------this探险
  2. Git使用出错:Couldn‘t reserve space for cygwin‘s heap, Win32
  3. linux中iconv函数,Linux下编码转换(iconv函数族)
  4. (二)stm32之中断配置
  5. 【kafka】Kafka消息压缩与解压与相关实验
  6. 从 SGD 到 Adam —— 深度学习优化算法概览(一) 重点
  7. 用于主题检测的临时日志(861e8353-61d5-43a9-b1b4-e055dac9cf39 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)...
  8. 构造Linux流媒体服务器收藏
  9. oracle 表或视图不存在
  10. 生产车间仿真软件flexSIM
  11. 人人都是产品经理面试题
  12. 产品原型工具 AXURE9 Mac汉化
  13. gis怎么改鼠标滚轮缩放_鼠标滚轮缩放工具-MAPGIS滚轮助手下载V1.3免费版-西西软件下载...
  14. php 获取ipad,利用PHP判断iPhone、iPad、Android、PC设备
  15. 凑微分公式_高等数学–求积分的一些方法(IV 凑微分法)
  16. 无限法则服务器维护中,维护内容
  17. 【论文笔记】Deep Learning on Graphs: A Survey
  18. excel 文件加密
  19. matlab 显示程序进度条,matlab学习---------------进度条waitbar
  20. 图鉴|春节怼亲戚指南(2020版)

热门文章

  1. pp-vehicle简介
  2. 【C语言】计算含多种运算符的表达式
  3. Android Studio修改grade版本
  4. 九州云出席全球人工智能开发者先锋大会,圆桌论道开源未来
  5. 逻辑运算符号“”、“||”和“!=”的相对优先级是怎样的,代码解释。
  6. H5和PC端开发差异对比
  7. 好消息!2021大数据独角兽企业榜单出炉!智领云再上榜!
  8. Python之Request模块学习
  9. 校招----纷享销客面经
  10. zmq 基本使用方法