Eth1.0 链的设计原理文档见:
https://github.com/ethereum/wiki/wiki/Design-Rationale
Serenity 设计原则
▲简洁性:特别是由于加密经济 PoS 和二次分片 (quadratic sharding) 在本质上很复杂,因此协议应该在其决策中尽可能地追求最大的简洁性。这是非常重要的,因为这将能够:(i) 最大限度地减少开发成本,
(ii) 减少发生意外安全问题的风险,且
(iii) 使得协议设计人员更容易让用户确信参数选择的合法性。
通过此链接[1]了解相关的背景信息。当我们为了实现特定级别的功能时,是无法避免一定的复杂性的。复杂性的优先级别是:Layer2 协议的复杂性 > 客户端实现的复杂性 > 协议规范的复杂性。
▲长期稳定性:理想情况下,应该构建较低级别的协议,这样就不需要在10年或更长时间内更改协议,并且任何需要的创新都可以在更高的级别 (客户端实现或 Layer2 协议) 上进行。
▲充裕性:在协议之上应能够构建尽可能多的应用程序类别。
▲深度防御性:协议应能够在各种可能的安全性假设 (例如有关网络延迟、故障数量、用户动机的假设) 的情况下继续运行。
▲轻客户端的可验证性:鉴于一些安全性假设 (例如网络延迟,攻击者预算界限,只存在1/n或少数诚实的验证者),验证 O© 数据 (理想情况是只验证信标链) 的客户端应该能够获得间接的保证,即整个系统的所有数据是可用且有效的,即使在受到51%攻击的情况下 (备注:这是“深度防御性”方面的其中一个目标)。
Layer1 与 Layer2 的折衷
读者可以先阅读我之前的两篇文章:Layer 1 Should Be Innovative in the Short Term but Less in the Long Term [2]和 Sidechains vs Plasma vs Sharding [3]。在任何区块链协议设计中,在 Layer1 (即共识层) 引入更多的特性,与构建一个更为简洁的 Layer1 协议并在 Layer2 (即应用层) 上允许构建这些特性,这两者之间各有折衷之处:
支持 Layer2 的论据:
减少共识层的复杂性 (参见上方提到的“简洁性”);
减少修改协议层的必要性 (参见上方提到的“长期稳定性”):
--降低无法达成共识的风险;--减少协议治理和政治风险方面的工作量
随着时间的推移,拥有更多的灵活性和实现新想法的能力
支持 Layer1的论据:
减少由于缺乏强制每个人升级到新协议 (即硬分叉) 的机制而导致进展停滞的风险;
可能会降低整个系统的复杂度;
如果 Layer1 不够强大,那么就不可能在 Layer1 上搭建具有所需性能的 Layer2 系统 (参见上方提到的“充裕性”)
以太坊2.0的设计在很大程度上都是要致力于谨慎地在 Layer1 和 Layer2 之间保持平衡。这包括 (i) 类似图灵完备的、包含丰富状态的代码执行,(ii) 在数据有效性和计算方面的扩展性,以及 (iii) 更快的区块确认时间,这对于协议实现【充裕性】都是非常必要的,因为:
如果不实现 (i),那就无法具有稳健的信任模型来搭建 Layer2 应用程序。
如果不实现 (ii),那扩展性将仅限于借助状态通道或者 Plasma 等技术实现,而这些技术在推广以及资金锁定和/或大规模退出方面存在挑战。
如果不实现 (iii),那就无法在不使用通道技术的情况下进行快速交易,而通道技术在推广以及资金锁定和/或大规模退出方面存在挑战。
但以太坊2.0也将一些其他的特性有意地留给了 Layer2 来实现:(i) 隐私性,(ii) 高级编程语言,(iii) 可扩展的状态存储,以及 (iv) 签名方案。这些特性留给 Layer2 来实现,是因为这些方面都是快速创新的领域,现有的许多方案具有不同的特性,并且不可避免地要进行权衡,以获得更好、更新的方案。比如:
隐私性:环签名 (Ring Signature) + 机密性值 (confidential values) vs. ZK-SNARKs 和 ZK-STARKs,Rollup vs. ZEXE 等等。
高级编程语言:声明式编程 vs. 命令式编程,语法,形式化验证特性,类型系统,保护性特征 (比如禁止在算术表达式中使用非纯函数),本地支持的隐私特征等等;
可扩展的状态存储:账户模型 vs. UTXO (未使用交易输出)模型、不同的租金方案、原始默克尔分支见证 (raw Merkle branch witnesses) vs. SNARK/STARK 压缩 vs. RSA 累加器,稀疏的默克尔树 vs. AVL树 vs. 基于使用情况的不平衡数等等 (除此之外,还有针对验证状态转换的不同方案)。
签名方案:Schnorr 签名、BLS 签名、Lamport 签名等等
为何使用权益证明?
参见:
https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ
https://medium.com/@VitalikButerin/a-proof-of-stake-design-philosophy-506585978d51
为何使用 Casper?
当前权益证明 (PoS) 共识算法主要要三个阵营:
受到中本聪启发的权益证明算法 (比如 Peercoin (点点币)、NXT (未来币)、Ouroboros (Cardano 的共识算法) 等实用的算法)
受到 PBFT (实用拜占庭容错) 启发的权益证明算法 (比如 Tendermint、Casper FFG、Hotstuff 等算法)
CBC Casper (解释详见 [4] 和 [5])
在后两个阵营存在一个问题,即是否使用以及如何使用保证金存款 (质押金) 和 Slashing (质押金罚没)。这三种权益证明机制都优于工作量证明 (PoW),但我们想在本文捍卫一下以太坊2.0使用的方法。
质押金罚没 (Slashing)
以太坊2.0 使用一种 Slashing (质押金罚没) 机制,即被检测到行为不端的验证者将会被惩罚,最轻微的惩罚是销毁~1%的质押金,最严重的惩罚是销毁验证者的所有质押金。我们通过以下几个方面来为 Slashing 机制的使用进行辩护:
增加攻击成本:我们想要确保的是,任何对 PoS 链发起的51%攻击都将导致攻击者消耗一笔非常大的费用 (比如价值数亿美元的加密货币),且系统能够快速地从任何攻击中恢复。这使得攻击/防御演算对于攻击者来说非常不利,并实际上可能使攻击适得其反。
克服验证者带来的困境:节点开始偏离“诚实”行为的最现实直接的方法就是疏忽职守 (比如验证者本该参与验证,但却不参与验证;或者在不该签名时进行签名等等)。验证者带来的困境详见[6],比特币 SPV 挖矿 [7] 就是这种情况发生的例子,这将导致非常严重的后果。对非诚实的验证者进行验证惩罚有助于缓解这些困境。
上方第2点的一个更为微妙的例子就是,在2019年7月 Cosmos 链上的一名验证者因对两个相互矛盾的区块进行签名而被罚没了 [8]。对此事件的调查结果显示,该验证者同时运行了一个主节点 (primary node) 和一个备份节点 (backup node),该验证者的目的是为了确保当其中一个节点下线时,该验证者依旧能够获得奖励,而这两个节点恰好同时启动了,导致这两个节点对两个相互矛盾的区块进行了签名。
如果同时拥有一个主节点和备份节点成为常态,那么攻击者就可以对区块链网络进行分区,并使所有验证者的主节点和备份节点提交不同的区块,从而导致两个相互矛盾的区块被敲定。slashing 惩罚有助于在很大程度上抑制这种操作,降低发生这种情况的风险。
共识算法的选择
在上文提及的 PoS 共识算法的三个阵营中,只有后两个阵营 (即受 PBFT 启发的共识算法和 CBC Casper) 这两种算法中存在 finality (确定性) 的概念,即某个区块是通过这种方式得以确认的:只有当很大一部分验证者 (受 PBFT 启发的算法要求至少有1/3的验证者,CBC Casper 算法要求至少有1/4的验证者) 行为不当并因此被罚没时,该区块才会被逆转;而第一个阵营--受中本聪启发的 (最长链规则) 共识算法无法实现这种意义上的确定性 (finality)。
需要注意的是,确定性要求大多数验证者在线,而这已经是 Sharding (分片) 机制中已经存在的要求,即 Sharding 机制要求每个由随机验证者组成的委员会中的2/3验证者对交联 (crosslink) 进行签名,只有这样,该交联才将被信标链接受。
我们选择 Casper FFG 只是因为它是协议在实现确定性时可用的最简单的算法。当前我们正在积极探索在以太坊2.0的阶段3将之切换为 CBC Casper。
Sharding,或者说我们为何讨厌超级节点?
对于 Layer1 扩展而言,sharding (分片) 方式的一个主要替代方法就是使用超级节点 (supernodes),超级节点要求每个共识节点都拥有一个强大的服务器,这样该节点就能单独地处理每一笔交易。基于超级节点的扩展方式很方便,因为很容易实现:这与当前很多区块链采取的方式一样,除了需要进行更多的软件设计工作来以一种更加并行化的方式进行构建。
我们不选择这种使用超级节点的方式,主要理由如下:
验证池中心化风险:在一个基于超级节点的系统中,运行一个节点将需要消耗一笔高昂的固定成本,这使得能够参与进来的用户数量受到限制。虽然有些人会反驳道“在大多数 PoW 和 PoS 加密货币中,共识是由 5-20 个池子 (矿池或验证池) 控制的,而这些池子可以很好地运行节点。”但这种观点的问题在于忽视了其中存在的中心化压力风险,即便是财力雄厚的池子之间也存在这种风险。如果运行验证者的固定成本相对于回报来说是非常高的,那更大的验证池就能够提供比小型验证池更低廉的手续费,这将可能导致那些小型的验证池被排挤并感受到进行合并的压力。而在分片系统中,质押更多 ETH 的验证者将需要验证更多的交易,因此成本并不是固定的。
云端中心化风险:在一个基于超级节点的系统中,用户在家里进行 staking 就变得不可行了,因此大多数 staking 更有可能发生在云计算环境中。这将创建一个单点故障。
抗审查性降低:如果没有达到高计算+带宽要求,用户就不可能参与共识,这使得检测和审查验证者变得更加容易。
扩展性:在一个基于超级节点的系统中,随着交易吞吐量的增加,上文提及的风险也会相应地增加,而分片系统能够更加轻松地处理交易量的增长。
上述这些中心化风险也是我们为何不会试图实现以太坊的超低延迟性 (低于1秒) 的原因,而是选择 (相对) 保守的延迟时间。在以太坊2.0系统中,使用尽可能少或尽可能多的 ETH 以及使用尽可能少或尽可能多的计算能力来参与是可能的 (尽管你需要在 ETH 和计算能力方面相一致,即你无法在仅拥有很少计算能力的情况下质押大量的 ETH,反之亦然),且固定成本是最小化的,尽管这种成本会随着你质押的 ETH 的数量的增长而增加 (一旦你质押的 ETH 数量超过了 32,768 ETH,那么大部分时间你将在验证所有的分片链 (备注:共计1024条分片链,每个验证者身份需要质押 32 ETH,因此 1024*32=32,768))。
安全模型
人们通常认为区块链的安全性依赖于“大多数参与者是诚实的”这一假设,即≥50%的参与者将会诚实地遵循既定的协议,会为了个人的利益放弃叛变的机会。事实上,(i) “大多数参与者是诚实的”这种假设并不切实际,因为参与者可能会“懒惰 (lazy)”,在不验证区块的情况下签署区块 (参见验证者带来的困境 [9] 和比特币SPV挖矿导致的分叉 [10]),这都是非常普遍的叛变情况;但幸运的是,(ii) 区块链通常会通过一些安全模型 (而非假定大多数参与者将保持诚实) 来维护自身的安全特性。
一种常见的较为严苛的安全模型就是非协同的理性多数模式 (uncoordinated rational majority),即参与者会按照自己的利益行事,但相互协同的参与者数量不会超过一定的比重 (在简单的 PoW 链中,这一比重为23.2% [11])。
另一个更为严苛的安全模式是应对最糟情况的模式,即当单个参与者控制了超过50%的算力或质押金时,此时的问题就变成了:
(1)在这种情况下,我们能保证验证者在试图破坏整条链时将付出非常高昂的成本吗?
(2)我们可以无条件地保持哪些保证?
在 PoS 链中,slashing (对质押金的罚没) 可以提供上方第一个问题的保证,即当攻击者试图破坏整条链时,将需要成大非常高昂的成本。在不存在分片的区块链 (比如当前的以太坊1.0链) 中,每个验证所有区块的节点都会通过提供以下两个保证来完成上方第二个问题的要求:(i) 最长的链是有效的,且 (ii) 最长的链也是可用的 (通过此链接 [12] 查看“数据可用性”的重要性的理论依据)。
在以太坊2.0中,我们通过 sharding (分片) 的方式来实现深度防御,即通过将随机选择的验证者委员会组合起来,基于大多数验证者将保持诚实的安全模式,以实现有效性和可用性保证,且通过托管证明 (proof of custody) 来防止懒惰的验证者(即如果验证者“懒惰”不参与验证将会面临惩罚),通过欺诈证明 (fraud proofs)和数据可用性证明 (data availability proofs) [9] 在无需下载和验证所有数据的情况下检测无效和不可用的链。这将允许客户端拒绝无效和不可用的链,即便当这条链是由大多数 PoS 验证者支持的链。
客户端可以通过某种保留共识的方式来检测交易的审查性 (详见 [13]),但这方面的研究还没有整合到以太坊路线图之中。
下表中展示了预计的安全特征:
Casper 设置的激励机制
基本奖励 (Basic rewards)在每个 epoch 期间 (在以太坊2.0中,每生成64个区块 (大约6.4分钟) 称为一个 epoch),每个验证者都要进行“证明(attestation)”,也即对链头 (head) 进行投票签名 (链头也就是顶端区块)。如果验证者的“证明”被包含在了链头中,那该验证者将获得奖励,这个奖励由五个部分组成:
因“证明”被包含在顶端区块中而获得的奖励;
因“证明”明确了正确的 epoch 检查点而获得的奖励 (备注:每个 epoch 期间的最后一个 slot 被称为 checkpoint (检查点),slot 为协议设定的生成一个区块所需的时间 (6秒));
因“证明”明确了正确的链头 (顶端区块) 而获得的奖励;
因“证明”被迅速地包含在链上而获得的奖励 (如果“证明”是在1个slot之后就被包含在链上,那验证者将获得全部奖励;如果在 n 个 slot 之后才被包含在链上,那获得的奖励将是全部奖励的 1/n);
因“证明”明确了正确的分片区块而获得的奖励。
在每种情况下,实际奖励的计算如下。如果 B 是基本的奖励,P 是执行所需“证明”操作的一部分验证者,那么任何执行了所需操作的验证者所获得的奖励将是 B*P,而任何本该执行相关操作但却未进行该操作的验证者将受到 -B 的惩罚。这种“集体奖励”机制的目标是“如果有人表现得更好,那每个人都表现得更好”,从而限制恶意破坏因素。(参见本文 [13] 查看有关恶意破坏因素的描述以及为何限制这些因素非常重要)
需要注意的是,上方第4点是一个例外;这种奖励取决于“证明”被采纳的延迟性,而不是取决于验证者的行为,而且没有惩罚的风险。
基本奖励 B 本身的计算方式是
,其中 D1...Dn 是验证者质押金的规模,k 是一个常量。这是两种常见模式的折中方案,这两种常见的模式是 (i) 设置固定的奖励率,也即 k*Di,(ii) 设置固定的总奖励,也即
。
反对 (i) 的主要论据是,这种模式给网络带来了两个方面的不确定性:币的发行总量不确定,以及参与质押的总数不确定 (因为如果固定的奖励率太低,那基本没人会参与进来,这威胁了整个网络;而如果固定的奖励率太高,那将有太多的人参与进来,使得币的发行量出乎意料的高)。
反对(ii)的的主要论据是,这种模式将会使网络更容易遭受“discouragement attacks”攻击,详见 [13]。
采取基本奖励的方式折衷了这两种方法,并避免了每种方法的最坏结果。
区块提议者将“证明”包含在区块中之后获得的奖励是基本奖励的 1/8,这样的目的是鼓励区块提议者尽可能地监听信息并接受尽可能多的信息。
达到收支平衡的在线时间假设存在两种验证者:(i) 发挥作用的在线验证者,和 (ii) 离线的验证者,如果前一类验证者部分是 P,基本的奖励是 B,那么在线验证者预计将获得的奖励是:上方第1、2、3、5种情况下的奖励 B*4P + 上方第4种情况的奖励7/8*B*(P+(P*(1-P))/2+(P*(1-P)^2)/3+...) (因为“证明”有可能会因为验证者缺席而延迟被包含在链头中) +区块提议者奖励1/8*B*P。验证者缺席 (即本该参与验证而实际上并未进行验证) 将受到的惩罚是 B*4。因此,如果所有其他验证者都在线,那验证者在线时将会获得 B*5 的奖励,而离线时将会受到 B*4 的惩罚,因此如果验证者在线的时长为≥4/(4+5)≈44.44%,那验证者将能够处于不赔不赚 (收支平衡) 的状态。如果P=2/3 (即在线的验证者占所有验证者总数的2/3),那验证者将会因为在线而获得的奖励是≈B*(2/3*4.125+7/8*0.81)≈B*3.46,或者将为因为在线时长≥53.6%而达到收支平衡的状态。
但是,如果 P 低于 2/3 (即在线验证者的数量低于总数的2/3),那针对离线的验证者将会受到称为“inactivity leak”的惩罚。
Inacivity leak如果以太坊2.0链在超过4个epoch的期间都未能实现确定性 (finality),那将会增加额外的惩罚,使得最大可能的奖励是零 (未能正确执行操作的验证者受到惩罚),且还会增加第二个惩罚,此惩罚将会根据在多少个epoch期间未能实现 finality 而成比例地增长。这是为了确保如果超过 1/3 的验证者下线,那这些离线的验证者将会受到更为严重的惩罚,且这种惩罚会随着时间的推移而成倍地增长。这将带来三个影响:
离线验证者将会受到更严重的惩罚,因为此时验证者的离线实际上会阻止区块被敲定;
服务于“反相关性惩罚”的目标 (下文将进一步解释)
确保如果超过1/3的验证者同时离线时,最终上线的验证者数量将恢复至总数的2/3,因为离线验证者不断减少的质押金将会导致他们被驱逐出验证者行列。
基于当前这种参数化,如果区块停止了被 finalize (敲定) 的进程,那验证者将会在2.6天之后损失1%的质押金,在8.4天后损失10%的质押金,在21天后损失50%的质押金。
这意味着,如果50%的验证者离线了,那区块会在21天之后重新开始被 finalize,因为21天之后,所有离线的验证者已经损失了50%的质押金 (16 ETH),而如果验证者的质押金低于16 ETH 将被驱逐出验证者行列。
Slashing & 反相关性惩罚如果验证者被发现违反了 Casper FFG 的 slashing (罚没) 条件,那该验证者将受到惩罚 (损失一部分质押金);如果大约在同一时间还有其他验证者受到 slashing 惩罚 (具体来说,就是从该验证者被惩罚的前18天到该验证者退出验证者行列的这段时间),那这种惩罚将是之前的三倍。这样做有几个目的:
只有当某个验证者同时与很多其他验证者一起行为不当时,该验证者的行为才会对网络造成真正的损害,因此这种情况下的惩罚会更加严重;
这会对实际的攻击行为进行严重地惩罚,但对可能并非恶意的单个独立失误采取非常轻微的惩罚;
这确保了小型验证者将比大型验证者承担更少的风险 (因为在正常情况下,只有大型验证者才会在同一时间失效);
这抑制了所有人都加入最大的验证池中。
BLS 签名
我们将使用 BLS 签名,因为 BLS 签名是聚合友好型的:由密钥 k1和 k2 (对应的公钥 K1=G*k1,K2=G*k2,其中G是椭圆曲线的基点) 对消息 M 进行的任意两个签名 S1 和 S2 都可以简单地通过椭圆曲线点加法聚合起来:S1+S2。这允许生成数千个签名,每个签名的边际成本就是一个数据位 (用于表示在该聚合签名中存在一个特定的公钥) 和一个用于计算的椭圆曲线加法。需要注意的是,这种形式的 BLS 签名易遭受流氓密钥攻击 (rogue key attackes):如果你看到其他验证者已经公布了公钥 K1...Kn,那你可以生成私钥 r 并公布一个公钥 G*r-K1-...-Kn。聚合的公钥将是 G*r,这样将能够自己对聚合的公钥进行签名验证。解决这个问题的标准方法是需要一个所有权证明 (proof of possession):基本上就是某条针对私钥k和公钥k对公钥进行验证的签名。这确保了你控制了与你公布的公钥相连接的私钥。
我们使用验证者抵押消息的签名作为所有权证明,该签名明确了签名的密钥以及其他重要的信息,比如取款密钥。
随机选择验证者
用于实现随机性的种子 (seed) 会通过对区块提议者必须揭露的一个值进行“mixing in” (即 seed <- hash(seed, new_data)) 从而在每个区块中进行更新。就像托管证明子密钥 (subkey) 一样,验证者的值 (values) 是在验证者进行质押之后就立即确定好的,第三方无法计算出子密钥,但是当子密钥被资源揭露时对其进行验证 (这种机制有时叫做 RANDAO)。这确保了每个区块提议者都对随机性种子有“位操作”:提议者可以提议区块,也可以不提议。如果提议者不提议区块,那将错过很多的奖励。此外,由于长期委员会 (persistent committee) 和交联委员会 (crosslink committee) 的规模很大,因此对随机性的操控几乎肯定是无法让少数攻击者控制任何一个委员会中的2/3的验证者。
未来我们计划使用 VDF (可验证延迟函数) 来进一步增加随机性种子抵御操控的鲁棒性。
打乱验证者 (Shuffle)在每个 epoch 期间,我们使用 swap-or-not shuffle [13] 的方式来打乱验证者并分配职责。这种算法确保了:由于打乱验证者 (shuffle) 就是一种置换,在每个 epoch 期间,每个验证者都会被指定为一个交联委员会的成员 (从而使验证者的工作量稳定,并减少随机性操控带来盈利的可能性);
由于打乱验证者 (shuffle) 就是一种置换,在每个 epoch 期间,每个验证者都会被指定为一个长期委员会的成员;
交联委员会在每个 epoch 期间,每个分片都会进行一次交联 (crosslink),即从分片委员会中随机选择2/3的验证者 (每个分片委员会的验证者数量约为128名) 对自上一次交联以来在该分片中包含的所有数据的哈希进行签名 (由于分片中的交联可能失败,因此该哈希最多可以代表前64个 epoch 的数据;如果分片中连续好多次的交联失败,那可能需要实现多次成功的交联才能赶上)。每个分片委员会的验证者数量被设定为128名,因为这是一个抵御攻击者在控制少于1/3的所有验证者的情况下偶然地控制2/3的委员会成员的最低数量,通过二项式定理,攻击者控制2/3的委员会成员的几率是5.55*10^(-15)
由于以太坊2.0系统中将有1024条分片链,这意味着要想每个分片链在每个 epoch 期间进行一次交联,那我们将需要131072名验证者 (备注:1024*128=131072),或者说,以太坊2.0系统中需要质押大约440万 ETH (实际上,如果质押的 ETH 少于这个数,那分片链的交联发生的次数就会更少)。而如果将最低的质押限制提高 (比如提高至1024 ETH,当前确定的是32 ETH),那意味着我们将无法获得足够多的验证者数量来实现在每个 epoch 期间在每个分片链上进行交联,除非所有的 ETH 都质押了进来。
每个 epoch (64个区块,约6.4分钟) 之后,信标链都会重新为每个分片链重组一个分片委员会 (也即打乱验证者)。对验证者进行快速打乱,是为了确保如果攻击者想要攻击某条分片链,那该攻击者将需要快速地破坏 (控制) 该分片委员会。
长期委员会在每个27小时左右的时间段内,系统将会为每条分片链选择一个长期委员会 (persistent committee)。在任何时间,以太坊2.0系统中的每个验证者都是其中某个长期委员会的成员。长期委员会负责提议分片区块、为用户提供某种程度的有关分片区块的保证 (直到分片区块包含在了某次交联中),且轻客户端可以借助长期委员会。为了保持P2P网络的稳定性和轻客户端的效率,长期委员会的变更相对较少 (而分片委员会每隔约6分钟就更换一次)。每个长期委员会的验证者数量上限是128,因此如果系统中的验证者数量超过了131072,那任何时候都会有验证者不被选中进入任何一个长期委员会中;这减少了不必要的验证浪费。
为了进一步维护网络的稳定性,并不是所有的验证者都会同时从 n 时间段的长期委员会中轮换为 n+1 时间段的长期委员会;而是每个验证者的轮换都会有所延迟,直到下个时间段的某个随机时间点再进行轮换。
LMD GHOST 分叉选择规则
信标链使用 LMD GHOST 分叉选择规则,相关描述参见 [15]。LMD GHOST 分叉选择规则会合并来自所有验证者的信息,确保在正常情况下任何一个区块都不可能会被逆转。由于该分叉选择规则依赖于所有的验证者,这也确保了除非攻击者控制了50%以上的验证者,否则无法逆转区块,因为这种情况下攻击者无法通过操控随机性来获得很大的优势。信标链/分片链结构以太坊2.0分片系统的结构包含一个协调所有活动的中心“信标链”,以及1024条分片链。每条分片链都会定期地通过交联 (crosslink) 的方式与信标链相连接。这种分片结构的替代方案:
(1)通过委员会对分片区块进行签名,将所有分片区块都直接地放入信标链中;
(2)不存在信标链,而是通过某种结构将所有的分片链连接起来。
上述第(1)种结构被舍弃的原因是:对分片链区块设置一个6秒的时间 (slot) 是可取的,但是每6秒在信标链上进行1024次交联将会导致信标链承受非常高的负荷。
上诉第(2)中结构被舍弃的原因是:中心辐射型的信标链结构比任何复杂的构造都更容易实现和理解。
分片链的设计每个分片都是一条半独立的链,它可以比交联聚合区块更快递处理区块 (目标是3-6秒)。这使得交易在被信标链 (通过交联的方式) 确认之前,能够通过分片长期委员会快速地获得一定程度的确认。分片链结构是这样的,每个区块都由分片委员会的每个验证者进行证明 (attest),这保证了验证的简单性,并确保分片区块获得了程度相当高的确认;大多数处理较低价值的应用应该都可以依赖于单次确认。
在每个 epoch 开启时,每个分片区块都包含了一个指向其父块的 pointer 和一个指向信标区块的 pointer。信标链和分片链之间的这种半紧密耦合是为了 (i) 确保分片链知道有关其长期委员会的信息 (因为此信息是由信标链生成的),同时 (ii) 使验证分片链区块称为一个决定哪条链才是规范信标链的可行方式。
分片链状态 (奖励、惩罚、历史累加器) 被故意设计成小于区块大小,目的是确保如果欺诈证明有需要,分片链状态可以完全被放入信标链之中 (虽然这可能只会在阶段2放宽限制,在阶段2,每个单独的执行环境的状态将受到此大小的限制,但所有状态合并起来将非常大,因此欺诈证明将需要默克尔证明)。
交联数据交联包含了data_root,即自上次交联以来,包含了某条分片中所有分片区块的数据结构的默克尔根 (Merkle root)。这种交联数据结构+根有多重目标:
使信标链知道哪些才是规范的分片链区块;
创建一个简单的字节数组,可以通过不同的方法 (托管证明、数据可用性证明) 来验证其可用性,并保证可以通多交联来对分片区块进行完全恢复。
创建一个简单的字节数组,可以对欺诈证明进行评估。
验证者生命周期
质押验证者通过发送一笔交易来进行 ETH 质押 (这笔交易会调用部署在 Eth1.0 链上的抵押合约 (deposit contract) 的一个函数) ,最终我们会在 Eth2.0链上加入进行质押的方式。验证者的这一操作明确了:
与用于对消息签名的私钥相对应的公钥;
取款凭证 (即公钥哈希,当验证者在完成验证之后,公钥哈希将用于提取资金)
质押金额
这些值都是由签名密钥进行签名的。将签名密钥 (signing key) 和取款密钥 (withdrawal key) 分开,目的是让更具安全风险的取款密钥得更加安全 (取款密钥处于离线状态,不会与任何质押池进行共享等等),而签名密钥则用于在每个 epoch 期间对消息进行签名。
抵押合约 (deposit contract) 中保留着所有质押的默克尔根 (Merkle root)。一旦验证者质押的默克尔根被包含在了 Eth2.0 链中 (通过Eth1.0 数据投票机制),Eth2.0 区块提议者就可以提交一个该质押的默克尔证明,并启动质押过程。
激活当某个验证者往抵押合约中发送了一笔交易之后,就立即加入了验证者登记表中,但该验证者一开始处于未激活状态。只有当至少4个 epoch 之后,该验证者才会被激活;验证者之所以需要等待至少4个 epoch (每个 epoch 大约6.4分钟),是为了确保 RANDAO 没有被操纵,且如果很多验证者同时加入进来,那 N 可能会超过4。如果Eth2.0中已经存在的验证者总数是|V|,那每个 epoch 期间能够新加入的最大验证者数量将是max(4, |V|/65536);如果更多的验证者想要加入进来,那他们将需要排队,系统将尽可能快地进行处理。退出当某个验证者从 Eth2.0 系统中退出时 (无论是通过发布一个自愿退出消息,还是由于被罚没而退出),那该验证者也将需要进行排队才能从系统中退出,每个epoch期间能够退出的最大验证者数量与上文所述的能够新加入的最大验证者数量一样。之所以设置这种新加入/退出排队的限制,是为了确保系统中的验证者总数不会在任何两个时间点之间变化太快,这确保了只要验证者足够频繁地登入 (如果验证者总数≥262144,那验证者保证能够每1-2个月登入一次),那就能保证以太坊新旧两条链之间依旧存在确定性。相关原理参考 [17]和[18]。取款一旦验证者成功地通过排队退出了,还需要等待大约27小时的时间才能进行取款。这一等待时间有几个作用:
这确保了如果该验证者有不当行为,将有时间抓获该不当行为,并对该验证者进行罚没 (slashing);
这给予系统时间将最后一段时间的分片奖励发放给该验证者;
这为对托管证明发起挑战提供了时间。
如果验证者被罚没了,那取款时间还将进一步延迟约36天。这是对验证者的进一步惩罚 (并强迫他们持有 ETH;相比于那些想要支持以太坊但只是不小心犯错的验证者受到的惩罚,这使得那些想要破坏以太坊区块链的恶意验证者受到的惩罚将要更严重),同时也给系统预留了时间,用于计算在此期间也被罚没的其他验证者的数量。
在阶段0期间,想要“取款”的验证者实际上是还不能进行取款的;在之后的阶段,将能够把验证者取出的资金转移至某个执行环境中。
有效余额大多数基于验证者余额的计算都使用验证者的“有效余额 (effective balance,EB)”;唯一的例外就是有关增加或减少验证者余额的计算。只有当验证者的余额 B 低于 EB 或者高于 EB+1.5 时,EB 才会调整为等于 floor(B)。这是为了确保有效余额不会经常改变,减少每个 epoch 期间重新计算状态所需的 hashing 量;平均而言,只需要更新余额,而每个验证者只需相对更少地对有效余额进行更新。
分叉机制
Fork数据结构包含了 (i) 当前的 “fork ID”,(ii) 前一个“fork ID” 和 (iii) 切换这两个分叉的 slot。当前区块高度的 fork ID 影响着所有消息的有效签名;因此,使用一个 fork ID 签名的消息对于使用任何其他 fork ID 的验证函数无效。通过在某个 “fork slot” 增加一个状态转换就可以进行分叉。签名验证函数将使用消息所在的 slot 的 fork ID 来验证该消息,这个 fork ID 有可能是前一个 fork ID,也有可能是当前的 fork ID。
如果任何用户不想要加入某个分叉,只需继续留在那条没有在 fork slot 改变 fork ID 的链上。这两条链都可以继续存在,验证者可以自由地对这两条链进行验证,且不会受到罚没惩罚。