Skip to content

Latest commit

 

History

History
222 lines (136 loc) · 17.7 KB

以太坊测试网络Clique_PoA介绍.md

File metadata and controls

222 lines (136 loc) · 17.7 KB

ethereum/EIPs#225

Clique的模式下,用户是无法获取以太币的,因为无法挖矿,所以如果需要以太币, 需要通过特殊的途径来获取。

可以通过这个网站获取ether

https://faucet.rinkeby.io/

需要有google+账号,facebook或者twitter账号才能获取, 详细的获取办法参考上面的网站。

Clique 是以太坊的一个Power of authority 的实现, 现在主要在Rinkeby 测试网络使用。

背景

以太坊的第一个官方测试网是Morden。它从2015年7月到2016年11月,由于Geth和Parity之间累积的垃圾和一些testnet的共识问题,最终决定停止重新启动testnet。

Ropsten就这样诞生了,清理掉了所有的垃圾,从一个干净的石板开始。这一运行状况一直持续到2017年2月底,当时恶意行为者决定滥用Pow,并逐步将GasLimit从正常的470万提高到90亿,此时发送巨大的交易损害整个网络。甚至在此之前,攻击者尝试了多次非常长的区块链重组,导致不同客户端之间的网络分裂,甚至是不同的版本。

这些攻击的根本原因在于PoW网络的安全性与它背后的计算能力一样安全。从零开始重新启动一个新的测试网络并不能解决任何问题,因为攻击者可以反复安装相同的攻击。Parity 团队决定采取一个紧急的解决办法,回滚大量的区块,制定一个不允许GasLimit超过一定门槛的软交叉。

虽然这个解决方案可能在短期内工作:

这并不高雅:以太坊应该有动态的限制 这不是可移植的:其他客户需要自己实现新的fork逻辑 它与同步模式不兼容:fast sync和轻客户端都运气不佳 这只是延长了攻击的时间:垃圾依然可以在无尽的情况下稳步推进 Parity的解决方案虽然不完美,但仍然可行。我想提出一个更长期的替代解决方案,涉及更多,但应该足够简单,以便能够在合理的时间内推出。

标准化的PoA

如上所述,在没有价值的网络中,Pow不能安全地工作。 以太坊有以Casper为基础的长期PoS目标,但是这是一个繁琐的研究,所以我们不能很快依靠这个来解决今天的问题。 然而,一种解决方案很容易实施,而且足够有效地正确地修复测试网络,即权威证明方案(proof-of-authority scheme)。

注意,Parity确实有PoA的实现,虽然看起来比需要的更复杂,没有太多的协议文档,但是很难看到它可以和其他客户一起玩。 我欢迎他们基于他们的经验来给我的这个提案更多的反馈。

这里描述的PoA协议的主要设计目标是实现和嵌入任何现有的以太坊客户端应该是非常简单的,同时允许使用现有的同步技术(快速,轻松,扭曲),而不需要客户端开发者添加 定制逻辑到关键软件。

PoA101

对于那些没有意识到PoA如何运作的人来说,这是一个非常简单的协议,而不是矿工们为了解决一个困难的问题而竞相争夺,授权签署者可以随时自行决定是否创建新的块。

挑战围绕着如何控制挖矿频率,如何在不同的签名者之间分配负载(和机会)以及如何动态调整签名者列表。 下一节定义一个处理所有这些场景的建议协议。

Rinkeby proof-of-authority

总体来说,有两种同步区块链的方法:

  • 传统的方法是把所有的事务一个接一个地进行起始块和紧缩。这种方式尝试过而且已经被证明在以太坊这种复杂的网络中非常耗费计算资源。 另一种是只下载区块链头并验证它们的有效性,此后可以从网络上下载一个任意的最近的状态并检查最近的header。
  • PoA方案基于这样的想法,即块可能只能由可信签署人完成。 因此,客户端看到的每个块(或header)都可以与可信任的签名者列表进行匹配。 这里面临的挑战是如何维护一个可以及时更改的授权签名者列表? 明显的答案(将其存储在以太坊合同中)也是错误的答案:在快速同步期间是无法访问状态的。

维护授权签名者列表的协议必须完全包含在块头中。

下一个显而易见的想法是改变块标题的结构,这样就可以放弃PoW的概念,并引入新的字段来迎合投票机制。 这也是错误的答案:在多个实现中更改这样一个核心数据结构将是一个开发,维护和安全的噩梦。

维护授权签名者列表的协议必须完全适合当前的数据模型。

所以,根据以上所述,我们不能使用EVM进行投票,而是不得不求助于区块头。 而且我们不能改变区块头字段,而不得不求助于当前可用的字段。 没有太多的选择。

把区块头的一些其他字段用来实现投票和签名

当前仅用作有趣元数据的最明显的字段是块头中的32字节的ExtraData部分。 矿工们通常把他们的客户端和版本放在那里,但是有些人用另外的“信息”填充它们。 该协议将扩展此字段以增加65字节用来存放矿工的KEC签名。 这将允许任何获得一个区块的人员根据授权签名者的名单对其进行验证。 同时它也使得区块头中的矿工地址的字段作废。

请注意,更改区块头的长度是非侵入性操作,因为所有代码(例如RLP编码,哈希)都不可知,所以客户端不需要定制逻辑。

以上就足以验证一个链,但我们如何更新一个动态的签名者列表。 答案是,我们可以重新使用新近过时的矿工字段beneficiary和PoA废弃的nonce字段来创建投票协议:

  • 在常规块中,这两个字段都将被设置为零。
  • 如果签名者希望对授权签名人列表进行更改,则会:
    • 将矿工字段beneficiary设置为希望投票的签署者
    • nonce设置为0或0xff ... f来投票赞成添加或踢出

任何同步链的客户端都可以在数据块处理过程中“统计”选票,并通过普通投票保持授权签名者的动态变化列表。 初始的一组签名者通过创世区块的参数提供(以避免在起始状态中部署“最初选民名单”合同的复杂性)。

为了避免有一个无限的窗口来统计票数,并且允许定期清除陈旧的提议,我们可以重新使用ethash的概念 epoch,每个epoch 转换都会刷新所有未决的投票。 此外,这些epoch 转换还可以作为包含头部额外数据内的当前授权签名者列表的无状态检查点。 这允许客户端仅基于检查点散列进行同步,而不必重播在链上进行的所有投票。 它同样允许用包含了初始签名者的创世区块来完全定义区块链

攻击媒介:恶意签名者

可能发生恶意用户被添加到签名者列表中,或者签名者密钥/机器受到威胁。 在这种情况下,协议需要能够抵御重组和垃圾邮件。 所提出的解决方案是,给定N个授权签名者的列表,任何签名者可能只在每个K中填充1个块。这确保损害是有限的,其余的矿工可以投出恶意用户。

攻击媒介:审查签名者

另一个有趣的攻击媒介是如果一个签名者(或者一组签名者)试图检查出从授权列表中删除它们的块。 为了解决这个问题,我们限制了签名者允许的最小频率为N / 2。 这确保了恶意签名者需要控制至少51%的签名帐户,在这种情况下,游戏就是无论如何也无法进行下去了。

攻击媒介:垃圾邮件签名者

最后的小型攻击媒介就是恶意签署者在每一个块内注入新的投票建议。 由于节点需要统计所有投票来创建授权签名者的实际列表,所以他们需要通过时间跟踪所有投票。 没有限制投票窗口,这可能会慢慢增长,但却是无限的。 解决方法是放置一个W块的移动窗口,之后投票被认为是陈旧的。 一个理智的窗户可能是1-2个时代。 我们将这称为一个时代。

攻击媒介:并发块

如果授权签名者的数量是N,并且我们允许每个签名者在K中填充1个块,那么在任何时间N-K个矿工都被允许为Mint。 为了避免这些争夺块,每个签名者将添加一个小的随机“抵消”,以释放一个新的块。 这确保了小叉子是罕见的,但偶尔还会发生(如在主网上)。 如果一个签名者被滥用权威而引起混乱,那么这个签名就可以被投票出去。

注意

这是否表明建议我们使用一个被审查testnet?

该提议表明,考虑到某些行为者的恶意性质,并且鉴于“垄断资金”网络中PoW计划的弱点,最好是建立一个网络,使其具有一定的垃圾过滤功能,开发人员可以依靠它来测试其程序。

为什么规范PoA?

不同的客户在不同的情况下会更好。 Go可能在服务器端环境中很棒,但CPP可能更适合在RPI Zero上运行。

手动投票是不是很麻烦?

这是一个实现细节,但是签名者可以利用基于合同的投票策略,利用EVM的全部功能,只将结果推送到平均节点的头部进行验证。

澄清和反馈

  • 这个建议并不排除客户端运行基于PoW的测试网络,无论是Ropsten还是基于它的新的测试网络。理想的情况是客户提供一种连接PoW以及基于PoA的测试网络的方法(#225(评论))。

  • 协议参数尽管可以在客户端实施者的破坏中进行配置,但Rinkeby网络应该尽可能地靠近主网络。这包括动态GasLimit,15秒左右的可变区块时间,GasPrice等(#225(评论))。

  • 该方案要求至少有K个签名者随时上网,因为这是确保“最小化”多样性所需的最少人数。这意味着如果超过K,则网络停止。这应该通过确保签名者是高运行时间的机器来解决,并且在发生太多故障之前及时地将失败的机器投票出去(#225(评论))。

  • 该提案并没有解决“合法的”垃圾邮件问题,就像在攻击者有效地使用testnet以创建垃圾一样,但是如果没有PoW挖掘,攻击者可能无法获得无限的ether来攻击。一种可能性是以有限的方式(例如每天10次)(#225(评论)),以GitHub(或其他任何方式)帐户为基础提供一个获取ether的途径。

  • 有人建议为当时包含授权签名者列表的每个epoch创建checkpoint block。这将允许稍后的轻客户说“从这里同步”,而不需要从起源开始。这可以在签名之前作为前缀添加到extradata字段(#225(comment))。

Clique PoA 一致性协议 (Clique proof-of-authority consensus protocol )

我们定义下面的常量:

  • EPOCH_LENGTH:检查点并重置未决投票的块数。
    • 建议30000,以便和主网络的ethhash epoch类似
  • BLOCK_PERIOD:两个连续块的时间戳之间的最小差异。
    • 建议15,以便和主网络的ethhash epoch类似
  • EXTRA_VANITY:固定数量的ExtraData前缀字节为签名者vanity保留。
    • 建议的32个字节以便和当前的ExtraData的长度相同。
  • EXTRA_SEAL:为签名者印章保留的固定数量的额外数据后缀字节。
    • 保存签名的65个字节,基于标准secp256k1曲线。
  • NONCE_AUTH:魔术随机数字0xffffffffffffffff投票添加一个新的签名者。
  • NONCE_DROP:魔术随机数字0x0000000000000000对移除签名者进行投票。
  • UNCLE_HASH:始终Keccak256(RLP([]))作为Uncles在PoW之外没有任何意义。
  • DIFF_NOTURN:如果当前没有轮到你签名,那么你签名的区块的难度就是这个难度。
    • 建议1,因为它只需要是一个任意的基线常数。
  • DIFF_INTURN:如果当前轮到你签名,那么你签名的难度。
    • 建议2, 这样就比没有轮到的签名者难度要高。

我们还定义了以下每块的常量:

  • BLOCK_NUMBER:链中的块高度,创世区块的高度是0。
  • SIGNER_COUNT:在区块链中中特定实例上有效的授权签名者的数量。
  • SIGNER_INDEX:当前授权签名者的排序列表中的索引。
  • SIGNER_LIMIT:每隔这么多块,签名者只能签署一块。
    • 必须有floor(SIGNER_COUNT / 2)+1 这么多签名者同意才能达成某项决议。

我们重新调整区块头字段的用途,如下所示:

  • beneficiary:建议修改授权签名人名单的地址。
    • 应该正常填写零,只有投票时修改。
    • 尽管如此,仍然允许任意值(甚至是无意义的值,例如投出非签名者),以避免增加围绕投票机制的额外复杂性。
    • 必须在检查点(即epoch转换)块填充零。
  • nonce:Signer关于受益人字段中定义的账户的建议。
    • NONCE_DROP 提议取消授权受益人作为现有签名者。
    • NONCE_AUTH 提出授权受益人作为新的签名者。
    • 必须在检查点块填充零。
    • 除了上述两者(现在)之外,不得采用任何其他值。
  • extraData: vanity, checkpointing and signer signatures的组合字段。
    • 第一个EXTRA_VANITY字节(固定长度)可以包含任意签名者vanity data。
    • 最后一个EXTRA_SEAL字节(固定长度)是密封标题的签名者签名。
    • 检查点块必须包含一个签名者列表(N * 20字节),否则省略。
    • 检查点块附加数据部分中的签署者列表必须按升序排序。
  • mixHash:为了分叉保留。类似于Dao的额外数据
    • 在正常操作期间必须填入零。
  • ommersHash:必须是UNCLE_HASH,因为在PoW之外,Uncles叔没有任何意义。
  • timestamp:必须至少为父区块的时间戳 + BLOCK_PERIOD。
  • difficulty:包含块的独立得分 来推导链的质量。
    • 如果BLOCK_NUMBER%SIGNER_COUNT!= SIGNER_INDEX,则必须为DIFF_NOTURN
    • 如果BLOCK_NUMBER%SIGNER_COUNT == SIGNER_INDEX,则必须为DIFF_INTURN

Authorizing a block

为了给网络授权一个块,签名者需要签署包含除签名本身以外的所有内容。 这意味着哈希包含区块头的每个字段(包括nonce和mixDigest),还有除了65字节签名后缀外的extraData。 这些字段按照其在黄皮书中定义的顺序进行hash。

该散列使用标准的secp256k1曲线进行签名,得到的65字节签名(R,S,V,其中V为0或1)作为尾随的65字节后缀嵌入到extraData中。

为了确保恶意签名者(签名密钥丢失)不能在网络上受到破坏,每位签名者都可以在SIGNER_LIMIT连续块中签最多一个。 顺序不是固定的,不过(DIFF_INTURN)的签名者签出的区块难度要比(DIFF_NOTURN)高

授权策略

只要签名者符合上述规范,他们可以授权和分配他们认为合适的块, 下面的建议策略会减少网络流量和分叉,所以这是一个建议的功能:

  • 如果签署者被允许签署一个区块(在授权清单上并且最近没有签署)。
    • 计算下一个块的最佳签名时间(父+ BLOCK_PERIOD)。
    • 如果轮到了,等待准确的时间到达,立即签字和播放。
    • 如果没有轮到,则延迟 rand(SIGNER_COUNT * 500ms)这么久的时间签名。 这个小小的策略将确保当前轮到的签名者(谁的块更重)对签名和传播与外转签名者有稍微的优势。 此外,该方案允许随着签名者数目的增加而具有一定规模。

投票签署者

每个epoch转换(包括创世区块)作为一个无状态的检查点,有能力的客户端应该能够同步而不需要任何以前的状态。 这意味着新epoch header不得包含投票,所有未落实的投票都将被丢弃,并从头开始计数。

对于所有非epoch 转换块:

  • 签名者可以使用自己签署的区块投一票,以提出对授权列表的更改。
  • 对每一个提案只保留最新的一个投票。
  • 随着链条的进展,投票也会生效(允许同时提交提案)。
  • 达成多数人意见的提案SIGNER_LIMIT立即生效。
  • 对于客户端实现的简单性,无效的提议不会受到惩罚。

生效的提案意味着放弃对该提案的所有未决投票(无论是赞成还是反对),并从一个清晰的名单开始。

级联投票

签名者取消授权期间可能会出现复杂的案例。如果先前授权的签署者被撤销,则批准提案所需的签名者数量可能会减少一个。这可能会导致一个或多个未决的提案达成共识,执行这些提案可能会进一步影响新的提案。

当多个相冲突的提议同时通过时(例如,添加新的签名者vs删除现有的提案者),处理这种情况并不明显,评估顺序可能会彻底改变最终授权列表的结果。由于签名者可能会在他们自己的每一个区块中反转他们自己的投票,所以哪一个提案将是“第一”并不那么明显。

为了避免级联执行所带来的缺陷,解决的办法是明确禁止级联效应。换句话说:只有当前标题/投票的受益人可以被添加到授权列表或从授权列表中删除。如果这导致其他建议达成共识,那么当他们各自的受益者再次“触发”时,这些建议将被执行(因为大多数人的共识仍然在这一点上)。

投票策略

由于区块链可以有很小的reorgs,所以“cast-and-forget”的天真投票机制可能不是最优的,因为包含singleton投票的区块可能不会在最终的链中结束。

一个简单但工作的策略是允许用户在签名者上配置“提案”(例如“add 0x ...”,“drop 0x ...”)。 签署的代码,然后可以选择一个随机的建议,每块它签署和注入。 这确保了多个并发提案以及reorgs最终在链上被注意到。

这个列表可能在一定数量的块/epoch后过期,但重要的是要认识到“看”一个提案通过并不意味着它不会被重新组合,所以当提案通过时不应该立即放弃。