万向区块链技术研究报告 | EOS.IO技术调研

区块链技术迅猛发展,新想法、新概念、新名词层出不穷。万向区块链因此推出“技术研究报告”专栏,定期与大家分享在区块链行业创新及热门技术方面的研究成果,带领大家第一时间研究学习新技术,紧跟技术发展趋势,探索发掘技术的应用价值。

在《EOS.IO技术调研》一文中,我们分享关于EOS.IO概况、共识、出块、验证等方面的研究结果。

本文作者:万向区块链通用架构技术部 吴超尘

简介

技术组成 EOS.IO
背景 开发团队 BM
成功项目 BitShare(基于区块链技术的去中心化交易所), Steemit(基于区块链技术的社交和内容平台), EOS
主打功能 TPS+WASM
技术 模块化开发 插件机制 (plugin
共识 DPoS + Pipelined BFT
存储系统 ChainBase / RocksDB
外部DB插件 MongoDB, PG, Mysql
密码算法 哈希算法 SHA2 - SHA256
私钥 32个字节的随机数,然后Base58编码
公钥 由私钥通过ECDSA-secp256k1/r1 计算出对应的公钥 65个字节(未压缩)
签名算法 SHA256 + ECDSA-secp256k1/r1 sign
验签算法 ECDSA-secp256k1/r1 recove
应用 虚拟机 WASM
SDK js, go
开发 开发语言 C++ (11/14/17)
智能合约语言 C++ (11/14/17)
社区活跃度 Github Starred 11.3k, Fork 3.7k

共识

0.共识大概过程

DPoS (21个生产节点轮流出块,每轮出12个块, 0.5秒出1个块), 流程大概:

  1. 散户抵押之后进行投票

  2. 每轮按投票权重选出21个超级节点(BP)

  3. BP按schedule轮流出块

  4. 区块的验证: Pipelined BFT (基于流水线的拜占庭容错机制)

  5. 成为不可逆区块: LIB(Last Irreversible Block)

  6. 链头高度和BFT共识高度之间有325个块的差距 12*(14+13)+1=325

1.选出共识节点的机制 - DPoS

  • 将账户注册为候选人

  • 从候选人中投票选出21位区块记账者,组成超级节点列表(BP列表) (类似于选人大代表)

    • 投票的权重会随着时间越来越小

  • 节点定时更新BP列表的流程:

    步骤一: nodeos出块时调合约内的方法onblock:

    • nodeos

    on_block_act.name = N(onblock);
    ​
    eos_abi.structs.emplace_back( struct_def {
    "onblock", "", {
    {"header", "block_header"}
    }
    });
    ​
    eos_abi.actions.push_back( action_def{name("onblock"), "onblock",""} );
    • contract

    [[eosio::action]]
    void onblock( ignore<block_header> header );

    步骤二: BP合约内容更新时 回调nodeos本地函数接口

    onblock合约方法内限制间隔1分钟才会调此方法进行统计选票

    update_elected_producers

    决定出最新的21个BP后, 再设置回nodeos(节点)的接口 set_proposed_producers, 发出 promoting proposed schedule

    set_proposed_producers

    步骤三: 从promoting proposed schedulepending schedule再到active schedule

    • 当包含promoting proposed schedule的块进入LIB后,BP会陆续更新自己block header中的pending schedule

    • 等到2/3 +1个BP节点都已经更新block header后,pending schedule达成共识。BP会陆续将active schedule更新为此时pending schedule的值,并按照新的BP组合开始出块,整个过程需要至少经过两轮完整的出块。

    • 每一次新的BP组合,一定要能够达成共识才能真正生效。换句话说,如果网络中7个或更多节点无法正常通信,那么无论如何不能通过投票的方式产生新的BP。网络的LIB会一直停留在节点崩溃的那个共识点。

2.出块机制

  • 出块间隔 0.5 秒

  • 每个超级节点每轮连续出12个块,21*12个块算一轮,每轮结束,重新计算选票,选出新的超级节点列表

    Block Producing Explained | EOSIO Developer Docs

    一个BP连续出12个块, 相对而言在此6秒内能比较稳定的出块, 只在2个BP交替的第13个块, 后一个BP可能会有跟不上的风险

  • 如果在某个时间内没有成功出块,则跳过该块 (在最近24小时内没有产生任何块,则这个出块者将被删除)

  • 出块流程

    在这里插入图片描述

    image-20211231000609458

3.区块验证机制 - Pipelined BFT

EOS的特殊BFT (采用的是基于流水线的拜占庭容错机制)

常规的PBFT是生产一个区块,等待共识,然后再生产一个区块。21个共识节点时, 由于PBFT共识两轮投票需要较长的时间,因而不容易满足0.5s出块需求。因而EOS的BFT采取了不同的实现方式,出块和共识是流水并行工作的,区块生产完成后,不等待BFT共识,继续生产同时参与并处理上一个区块的BFT共识,当BFT共识完成后即修改为不可逆状态。

假设: 共4个BP, 一次生产一个块

image-20220107102659108

EOS中,21个生产节点轮流出块。一个区块是通过后续节点基于该区块的生产行为来间接确认的,为了实现BFT级别的不可逆,需要得到两轮2/3+1的节点确认。区块的确认分为两个阶段:

  1. 第一个阶段是prepare阶段,该阶段需要接受2/3+1个节点的确认。由于每个节点生产12个区块,所以需要12*(2/3*21+1)=12*15=180个区块确认。

  2. 第二个阶段是commit阶段, 也需要2/3+1个节点的签名确认。因为经过prepare阶段之后, 还不能确定绝大多数节点都已经了解到这轮2/3的确认信息。因而还需要一轮2/3的确认, 好180个块。

  3. 然而,如果大家在EOS区块链上查询区块的实时信息,就会发现一个区块需要经过的是325个区块, 之后会被标识为不可逆状态。块数: 12*14 + (12*13 + 1) = 12*(14+13)+1 = 325

    解释: 整个网络共21个超级节点, 那么需要15个人(BP)确认才能达成一轮共识。每个人默认会对自己出的块进行确认,所以每个块需要14个人的确认就能完成一轮共识。同理第二轮也需要14个BP, 但最后第14个BP出第一个块时,共识共识即可完结, 而不用等它出完自己连续的12个块. 所以一个块从它产生后,要到之后的第28个BP所产出的第一个块时才能得到全网共识,进入LIB。因此有以上计算。

4.比较

POA 与 DPoS 的比较

POA DPoS
适用场景 私链或者联盟链 公链
候选节点 作为提案直接指定 任何链上账户都可以注册为候选节点
票哪里来 一个共识节点一票 抵押原生兑换物, 获得票数
票的权重 无/或者认为是不变的 选票的权重会随着时间而衰退*,除非重新投票 (可以确保更积极的治理 DAO)
成为共识节点 得到大多数现有共识节点的同意 获得选票最高的前21个节点
共识节点数量 没有限制 最多21个
移除共识节点组 得到大多数现有共识节点的同意 每轮都会重新计票

*权重衰退的发生率约为每周1%。这意味着,在一年的过程中,如果不更新投票,账户的投票权重将减少约一半

PBFT 与 DPoS - Pipelined BFT 的比较

PBFT DPoS - Pipelined BFT
适用场景 联盟链 公链
view change 更换primary节点的过程 BP schedule发生变更
pre-prepare primary节点收到请求,广播给网络里的所有replica BP出块并广播至全网
prepare replica收到pre-prepare请求后向全网广播将要对此请求进行执行 所有节点收到块并验证成功后广播已收到的信息
commit replica收到足够多的对同一请求的prepare消息,向全网广播执行此请求 节点收到足够多基于某一个块之后出的块, 提出proposed lib消息
committed-local replica收到足够多对同一请求的commit消息, 完成了验证工作 LIB Number 变更
checkpoint 固定k个请求后生成 BP schedule发生变更的块(至少两轮完整的出块过程)

checkpoint: 指在某一个块高度记录共识证据, 以此来提供安全性证明. 当足够多的replica的checkpoint相同时, 这个checkpoint被认为是stable的. 可以清理stable checkpoint之前的共识数据, 避免内存占用过大

5.避免分叉

  • 区块创造过程对分叉的检测

    1. 检查区块生产者的合法性

    2. 如果当前主干已经不是最长链,需要切换到最长的分叉链上切换过程如下

      1. 弹出一定数量的区块,直到碰到分叉处

      2. 将分叉中的新区块写入主干数据库

      3. 切换后的分叉成为主干

      4. 如果上述过程失败,则恢复状态

    3. 如果不需要切换分支,则往主干数据库中写入区块

    4. 返回结果,以表明这次写入是否造成了分支切换

  • 还未成为不可逆的区块,可能会分叉, 共识将自动切换到最长的链条。具有更多生产者的区块链长度将比具有较少生产者的区块链增长速度更快。

  • 经过Pipelined BFT共识验证过的区块不会再分叉

  • 块生产者不应该同时在两条分叉链上都生产块。一旦被发现,就可能被投票出局

6.共识协议升级机制 (DAO)

  • 投票率达到15%,激活DPoS共识

  • 需要获得绝大多数区块生产者的批准, 才能激活新的协议

    cleos push transaction '{"delay_sec":0,"max_cpu_usage_ms":0,"actions":[{"account":"eosio","name":"activate","data":{"feature_digest":"299dcb6af692324b899b39f16d5a530a33062804e41f09dc97e9f156b4476707"},"authorization":[{"actor":"eosio","permission":"active"}]}]}'
  • 链激活后

    • eosio将owner和active权限转移给eosio.prods(这是个权限由21个超级节点控制的多签账户)

      image-20211226235040817

    • 所有eosio.*账户将owner和active权限转移给eosio

7.出块奖励机制

image-20211231000038002

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>