Ethereum POS实现概述
ETH POS算法已经在Ethereum2.0 共识协议Gasper分析 讨论过。 此处要结合ethereum consensus-specs, 分析Ethereum 共识层beacon chain是怎么实现的,以及beacon chain和执行层的关系,以及beacon chain最后如何跟eth1合并。 本文不讨论Ethereum POS对validator的奖惩策略,只关注工程结构。
参考文献为https://github.com/ethereum/consensus-specs 和 https://github.com/ethereum/annotated-spec。 后者是对前者部分spec的注解。 我们只关注已经实现的3个阶段的spec, 分别是phase 0、Altair、the merge。 每个阶段我们关注<Honest validator guide [changes]>和<The beacon chain [changes]>。
备注:
POW 到 POS 的迁移分为了三个阶段:
我们可以把blockchain看作一个不可篡改的历史数据库。 Beacon chain也是这样的, 它也有自己的状态和全部的历史数据。 不过在Phase0, Beacon chain中的状态和数据,仅与维持POS有关, beacon chain 中没有交易数据。具体地说,beacon chain block 中存储了时间片信息epoch/slot、validators列表、vote/attestation信息、奖惩信息、随机数信息。 在eth1中, 我们说state往往指accounts states; 在beacon chain中, 可以把state理解为validators states以及POS状态,记为BeaconState。 https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/validator.md https://kb.beaconcha.in/ethereum-2-keys https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md
Gasper 把时间分为slot和epoch, 在beacon chain, 1slot=12s, 1epoch=32*slot。根据当前时间与创世时间,确定当前所处的slot和epoch。
class BeaconState(Container):
# Versioning
genesis_time: uint64
genesis_validators_root: Root
slot: Slot
...
众所周知,validator要在eth1质押32eth, 才能进入共识层工作。 那么beacon chain是如何同步eth1中的质押数据,激活和组织validators工作的呢?
Eth1 上的deposits contract见: https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa#code 目前只可质押deposit,不能赎回withdraw。 调用合约的deposit方法时,传入了一些数据用于validator的验证工作,以及日后的赎回。
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) override external payable
以第一种撤销凭证为例,下图展示了质押与回撤过程中涉及的密钥关系: <img src="https://img.learnblockchain.cn/attachments/2022/10/QgOQTYYo63493b653d09b.png" alt="drawing" width="50%" /> withdraw功能将在shanghai升级中实现,相关spec见execution-specs/shanghai.md at master · ethereum/execution-specs。 从公布的进度看,还没达到准备上线的阶段。
Activation: From Eth1 to Beacon chain
eth1 中deposits数据由proposer validator引入beacon chain block。为了确保引入的eth1 block是不可篡改的, 通过延迟引入和投票的机制加载eth1的数据。每EPOCHS_PER_ETH1_VOTING_PERIOD (=32)个epoch为一个投票周期。 投票对象为位于投票周期开始slot之前 ETH1_FOLLOW_DISTANCE(=2048)个block之前的最后一个Eth1 block(在POW中, 一个block距离head block距离越远,则其确定性越强。 此处的距离基于eth1出块时间14s预估,而不是基于block number)。 每个proposer validator将对Eth1 block投票,投票信息记录在proposed beacon block中, 一个投票周期过后,获得超过半数票的eth1 block胜出,被更新在BeaconState中,从此刻,加载eth1 block中deposits信息到beacon chain, validator状态为pending。 平均来说,beacon chain每个epoch激活4个pending validators, 状态变为Active。 Active Validator并不立刻投入POS工作,而是提前4个epoch被告知自己被分配在哪个epoch, 提前一个epoch被确定validator所属的Committe, 以及角色(不包括proposer)。 所以一个eth1的staker从开始质押到产生收益,至少要经历12小时。
相关spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/validator.md#eth1-data https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#registry-updates https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#eth1-data https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#deposits
Randdo
我们已经知道validator信息如何从eh1加载到beacon chain。 那么validator又是如何被分配到committee呢? 这个分配过程,需要有几个特点:
如上图, 每个proposer会产生一个随机数randao mix, 其生产随机数的入参来源于parent slot randao mix以及当前slot block。 从而产生一个伪随机数列。 服务于未来某个epoch的validator set,将在4个epoch之前,根据当时的validator集合和rando mix确定。Epoch内的committee划分将被其前一个epoch的randao mix确定。
假设当前为epoch为N,在epoch N的第一个slot处,validator需要计算自己在epoch N+1中所属的角色(不包括proposer)。提前一个epoch确定角色的作用是,让validator完成子网的切换。为了减少attestation数据的广播, 同一个committe中的validator需要进入相同的子网,由agrregator把attestation数据聚合后广播。 https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#randao https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/validator.md#validator-assignments
接下来就是Gasper描述的validator行为了。 在slot开端, proposer打包和发送beacon chain block; 之后validator 验证和投票。 Block Proposal 在eth1中, block包含两部分数据:transactions 和 state。 Beacon block类似, 包含:
<img src="https://img.learnblockchain.cn/attachments/2022/10/TvJCzO6Y63493cc1465b0.png" alt="drawing" width="50%" align="center"/>
投票和验证过程分为2个阶段。 把slot分成INTERVALS_PER_SLOT段, 在1/3 slot处(或者在这之前收到slot block), validator 进行attesting (即vote for GHOST & vote for Casper), 签名后,构造 Attestation广播到subnet。 在2/3 slot处, aggregator 将收集到的attestation聚合,广播出去。
Proposer 在构建新的区块时和validator验证新的区块时,都需要基于收集到的validator行为进行state trasition。 有两个重要的state transiton的时间节点, epoch边界和新区块产生。 Epoch边界与Casper共识有关,此时调整validator集合, 对validator进行奖惩罚。 新区块 与Ghost fork choice有关并且对slot之间产生的validator行为进行奖惩处理。 状态更新包括: validator 的奖惩、validaor状态调整、 block finalization、 eth1 block投票与加载等。
<img src="https://img.learnblockchain.cn/attachments/2022/10/d9SKpPDI63493d03b179f.png" alt="drawing" width="50%"/>
此文只关注轻客户端同步协议sync protocal:https://github.com/ethereum/annotated-spec/blob/master/altair/sync-protocol.md
此协议的目的是: 轻客户端只需要下载部分block header, 即可证明block的有效性。 这里我们引入了Sync Committee, 相关参数:
<img src="https://img.learnblockchain.cn/attachments/2022/10/E8J23CKW63493d35add5f.png" alt="drawing" width="70%"/>
每个Sync Committee里有512个validator, 他们的责任是对他们认为正确的beacon chain head block签名, 对block N的签名,会合并记录在block N+1的sync_aggregate字段中。 每个Sync Committee负责256个epoch(称为 sync period), 即差不多一天的时间, 每256个epoch后Sync Comittee换届。 对于轻客户端Light Client, 它只要每256个epoch, 能有一个head block, 就能完成确定性证明(在一定安全级别下)。
我们来分析Light Client的证明过程。 BeaconState现在增加了两个字段,分别是current_sync_commitee 和 next_sync_committee, 分别为当前sync period的sync committee和下一个sync period的sync committee。 Sync commit中包含每个validator的公钥(以及所有公钥的和,用于优化验证速度)。 BeaconBlock 中新增sync_aggregate字段, 记录对parent block的聚合签名。 因此Light Client 可以使用至多512个validator的签名验证Block N的合法性 , 他需要两个信息:
由于一个BeaconState中包含了下一个sync period的sync_committee, 所以Light Client连续下载的两个Block header的距离最大可为256*2个epoch(第一个sync period的第一个block, 第二个sync period的最后一个block)。Light Client 通过一个block上签名的数量确定一个block的安全级别,如果一个block获得了2/3 sync committee成员的签名,则立刻作为light client本地block head; 如果在一个sync period只,始终没收到2/3 signed block, 则把这段时间(从确定上一个block head到现在)内具有最高签名数的节点作为本地block head。(还有对finalization的考虑,完整协议见:https://github.com/ethereum/annotated-spec/blob/master/altair/sync-protocol.md)
现在我们看sync protocal是如何嵌入到POS中的。其实与Attestation Committee是相似的。 在state transition的过程中新增 sync_committee_updates, 在每个sync_period的第一个slot, 基于randao更新BeaconState中的current_sync_commitee和next_sync_committee。为了减少数据广播,有sync committee subnet和sync agregators。 具体讲,512个validator中有16个aggregator,为了降低中心化,在每个slot, aggregator都会随机变化,详见is_sync_committee_aggregator。一共有4个sync committee subnet, 每个validator归属其中一个。beacon chain block的产生和签名过程为:
Phase 0 中attesting 的过程不受 sync committee的影响。 Proposer对签名数量不做要求(即使没有sync committeed signature),但是通过奖惩机制激励validator完成正确的签名。
https://github.com/ethereum/annotated-spec/blob/master/merge/beacon-chain.md https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/validator.md
所谓merge,即eth1停止自主出块,而是eth1在beacon chain的调用下出块。这个图存在一定问题,并不是从merge后, eth1 就不存储block chain了。eth1中仍然有完整的block chain, 只不过new block是被动产生的。
BeaconBlockBody中添加新字段excecution_payload。 execution_payload 中包含与当前的eth1 block头部等价的header信息以及 transactions列表。 BeaconState中添加新字段latest_execution_payload_header, 可以认为是execution_payload的指针。
Merge之后Beacon Chain中只有eth1的block header信息,以及每个eth1 block包含的transactions(用于新区块的广播), 合约和Account信息仍然存储在 eth1。
现在生产区块的流程是:
Beacon validator 会把finalization信息传递到eth1, eth1可以据此确定canonical chain。
Sharding将是The Merge之后的下一个以太坊重大更新。 由于POS的实现,以太坊可以进一步对集群参与者进行划分和约束, 这成为实现sharding的基础。 不过,目前还处在方案讨论阶段,2023年上线的计划不太可能实现。主要有两种方案:
Gasper 和 Randao 是Ethereum POS的基础。集群的参与者被划分为不同的角色以实现分布式一致。本文概述的就是角色是如何划分的,以及每个角色通常的行为是怎样的。 为了约束集群参与者的行为,Ethereum制定了它的法律,即 reward 和 penalty, 这是相当复杂和微妙的,本文并不涉及。 ETH POS并不是一个简单可证明理论的工程实现, 之后它会不会变得更复杂,它的“法律”能否无漏洞得维持系统运行,让我们拭目以待吧。 Beacon chain explorer: https://beaconcha.in/。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!