本文主要是介绍联盟链系列 - 适用于联盟链的PoA共识,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Clique PoA技术原理
1.共识机制
决定哪个节点能获得当前区块的记账权
- PoW(Proof-of-Work): 工作量证明机制就是区块链网络中一堆计算机通过计算随机数的Hash值,谁先找到这个随机数谁就赢的当前区块的记账权。拼算力
- PoA(Proof of Authority): 授权证明机制就是由一组授权节点来负责新区块的产生和区块验证,按授权节点的地址升序排序后,按顺序轮流获得记账权。 人人平等
Ethereum存在两个PoA测试网,分别是Kovan(PoA算法,Parity专用,Rust 语言)和Rinkeby(Clique PoA共识算法,Geth专用(版本号>=1.6),Go语言)
Kovan
PoA (Immune to spam attacks)
Supported by parity only
Chaindata size 13 GB - Apr 2018
Rinkeby
PoA (Immune to spam attacks)
Supported by geth only
Chaindata size 6 GB - Apr 2018
2.PoA的特点
- PoW该有的功能PoA都有,使用方法也一样,包括交易,智能合约,发币,DAPP
- 节点分类
- 普通节点(node):
- 普通的以太坊节点,没有区块生成的权利。不能挖矿,无选举权,有被选举权
- 授权节点(signer):
- 具有区块生成权利的以太坊节点,即矿工。能挖矿,有选举权和被选举权
- 普通节点(node):
- 授权节点的职能
- 授权节点(signers)负责产生block。可以由已授权的signer选举(投票超过50%)加入新的signer,或者投票(超过50%)踢出某个signer。
- 创世块配置
- 指定出块时间,
- 预设默认的一批signers(至少一个),
- 给指定地址设置ETH余额(得预先配置好)
- ETH币
- 挖矿无奖励
3.挖矿
对于一个新区块被挖掘出的过程,代码实现上基本分为两个环节:
-
一是组装出一个新区块,这个区块的数据基本完整,包括成员Header的部分属性,和叔区块组uncles[],以及交易列表txs,并且所有交易已经执行完毕,所有收据(Receipt)也已收集完毕,这部分主要由worker完成;
-
二是填补该区块剩余的成员属性,比如Header.Difficulty,coinbase等,并完成授权,这些工作是由Agent调用接口实现体Prepare,Seal,利用共识算法来完成的。
第一步 收集数据 worker.commitNewWork()(miner/worker.go)
-
4种情况会调用到这个函数
-
程序启动时,执行newWorker方法初始化worker对象时,调用commitNewWork方法,开始组装新区块。
-
启动挖矿时,miner.start里会调用worker.start()和worker.commitNewWork()
-
网络接收到其他矿工广播过来的新区块,该区块验证有效插入到区块链后,会产生ChainHeadEvent事件,worker对象的update协程检测到该事件后,会调用commitNewWork方法,开始生成新的区块。
-
矿工自己生成新的区块并入链后,会向全网广播NewMinedBlockEvent,同时也会给自己发一个ChainHeadEvent,之后就跟上面的一样
- commitNewWork()做了什么?
- 准备新区块的Header属性,可确定的有Time,Number,ParentHash,其余留待之后共识算法中确定
- 调用engine.Prepare()函数,完成部分Header对象的准备
- 准备新区块的交易列表,并执行这些交易
- 准备新区块的叔块uncles[]
- 调用engine.Finalize()函数,对新区块“定型”,填充Header对象 Root(默克尔根),TxHash(默克尔根), ReceiptHash(默克尔根), UncleHash等属性。
- 把创建的Work对象,通过channel发送给每一个登记过的Agent,进行后续的挖掘。
worker.push() -> CpuAgent.update()
第二步 授权 CpuAgent(miner/agent.go)
- 和共识有关的主要是这几个函数Start(),update()和mine()
- CpuAgent.Start() 用来启动CpuAgent.update()协程
- miner.New() -> miner.Register(NewCpuAgent) -> (if Mining) agent.Start() -> go agent.update()
- miner.Start() -> worker.start() -> agent.Start() -> go agent.update()
- CpuAgent.update() 用来监听worker.commitNewWork()结束前通过worker.push()发出的channel
- worker.push() -> CpuAgent.update() -> CpuAgent.mine()
- CpuAgent.mine() 利用Engine实现体的共识算法对传入的Block进行最终的授权, 如果成功,就将Block同Work一起通过channel发还给worker,那边worker.wait()会接收并处理
- CpuAgent.mine() -> engine.Seal() -> worker.wait()
- CpuAgent.Start() 用来启动CpuAgent.update()协程
到此,形成一个大的消息循环, 产生出了新区块,哦也!!!
4.共识
不过真正的主角还未出场,注意到这三个函数engine.Prepare() , engine.Finalize() , engine.Seal() ,它们是共识算法对外暴露的接口.该接口有两种实现体,即PoW和PoA
5.Clique PoA的实现
POA 共识算法通过复用当前以太坊区块头中可用的 Extra 字段,将签名者列表(epoch块)和当前节点的签名者对该区块头的签名数据写入其中。更新一个动态的签名者列表的方法是复用区块头中的 Coinbase 和 Nonce 字段,以创建投票方案。
投票规则设定
- 投票方必须是已认证的
- 有效投票必须满足:被投票地址的新认证状态与其现状相反。
- 任意地值A只能给地址B投一张票
- 只有获得记账权时,才能将票投出去
- 不允许反复连续投 (由于有最近签名者的限制,在SIGNER_COUNT / 2 + 1个块内,签名者只能签署一个块)
共识的过程 也是 动态管理所有认证地址的过程
- 通过API提供的方法,插入或删除投票(未上链,只缓存在本地节点内存中)
- clique.Propose(address,bool)
- clique.Discard(address)
- 通过clique.Prepare() 方法,从本地众多未上链的有效投票中,随机出一张票,准备上链
- 遍历最近一次缓存快照之后的块(最多checkpointInterval=1024个块),更新票数和授权地址列表
- clique.Prepare() -> clique.snapshot() -> Snapshot.apply()
- 填充header对象的Coinbase,Nonce,Difficulty,Extra(预留后缀,用于Seal()存入当前块签名者的签名)
- 通过clique.Finalize() 方法,对新区块“定型”,计算header.Root的值(默克尔根),丢弃叔块,且不给挖矿奖励
- 通过clique.Seal()方法,生成签名到header.Extra的后缀中
- 更新票数和授权列表,保证即将充当公钥的地址在最新的Signers中
- clique.Seal() -> clique.snapshot() -> Snapshot.apply()
- 依据header.Difficulty的值,如果优先级低,则随机延迟 rand((SIGNER_COUNT / 2 + 1) * 500) ms 再签名
Snapshot.apply() 做了什么
遍历传入的所有Header对象,是一个遍历历史区块头的过程
- 首先从数字签名中恢复出签名所用公钥,转化为common.Address类型,作为signer地址。数字签名(signagure)长度65 bytes,存放在Header.Extra[]的末尾。
- 如果signer地址是尚未认证的,则直接退出本次迭代;如果是已认证的,则记名投票+1。所以一个父区块可添加一张记名投票,signer作为投票方地址,Header.Coinbase作为被投票地址,投票内容authorized可由Header.Nonce取值确定
- 更新投票统计信息。如果被投票地址的总投票次数达到已认证地址个数的一半,则通过之
- 该被投票地址的认证状态立即被更改,根据是何种更改,相应的更新缓存数据,并删除过时的投票信息
总结
Clique(PoA)利用数字签名算法完成Seal操作,签名所用公钥必须是已认证的。所有认证地址基于投票规则进行动态管理,记名投票由不记名投票和投票方地址随机组合而成,杜绝重复的不记名投票,严格限制外部代码恶意操纵投票数据。
参考文章
https://blog.csdn.net/teaspring/article/details/78050274
Clique联盟链搭建
https://blog.csdn.net/liuzhijun301/article/details/80784529
- 往期精彩回顾:
- 区块链知识系列
- 密码学系列
- 零知识证明系列
- 共识系列
- 公链调研系列
- 比特币系列
- 以太坊系列
- EOS系列
- 联盟链系列
- Fabric系列
- 智能合约系列
- Token系列
这篇关于联盟链系列 - 适用于联盟链的PoA共识的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!