来源:ECN以太坊中国
当我开始着手撰写一篇文章,意图详细介绍以太坊1.x研究的“路线图”,以及如何通向无状态以太坊,却意识到严格来说,这完全不能被定义为传统意义上的路线图。 虽然1.x团队有着共同的目标,但却是一个兼收并蓄的集体,开发者和研究者独立地进行着错综复杂的工作。因此,也不存在“官方”路线图一说,但这并不意味着混乱无序。团队工作遵循一种默认的“次序”,例如某些工作必须要优先进行,某些解决方案是互斥的,还有一些工作可能有所裨益但却不是必要的。
如果不用“路线图”来描述通向无状态以太坊的过程,那么是否有更好的比喻呢?要找到一个合适的比喻确实不容易,但我觉得无状态以太坊就像是科技树(tech tree)[1] 中的“全属性”。
有些读者可能会立即明白这个类比,那么接下来的几段可以跳过。有些读者可能不是游戏爱好者,我会稍作解释:科技树(tech tree)是游戏中的一种常见机制,玩家能够解锁和升级新的符咒、技术或技能,通常以松散的层次或树状结构展现分类。
通常来说,可以通过“耗费”某种XP(经验点)来获取树中的元素(属性),进而解锁更多高级元素。有时需要获取两个不相关的基本元素才能解锁第三个更高级的元素,有时解锁一个基本技能会为下次升级开放更多新的选择。对于玩家来说,游戏的乐趣有一半是来自于在科技树中选择了与自身角色能力、目标和偏好相匹配的正确路径。
以下是我自制的粗略科技树图。针对排列方式、每个升级及其与整体的关联性,我会稍作阐释。科技树中最终的“全属性”升级就是“无状态以太坊”。也即是指,一个功能齐备的以太坊主网将支持全状态、部分状态和零状态节点,将高效可靠地传递见证(witnesses)和状态信息,并且从原则上来说,对于后续的扩展性也要准备就绪,直到eth2的桥接建设完成且能够登陆eth1链。
注意:就像之前提到的,这不是“官方”的工作路线。这是我所整理和组织的1.x团队必须解决的关键难题、里程碑和决策,目标是最终实现无状态以太坊。欢迎提供反馈,随着研究的推进,该计划也会随之更新和修订。
阅读顺序是从左至右,左侧的紫色信息是“基本”要素,必须首先进行开发和确定,才能继续推进右侧的要素。绿色部分表明这些元素在某种意义上算是“增益”项目,尽管在过渡过程中不是必需,并且在研究方面还不够具体,但还是有可取之处。较大的粉色形状代表无状态以太坊的重要里程碑。要完全过渡到无状态以太坊,必须“解锁”图中所有四个主要里程碑。
上次的研究者会议中[2] ,转换为二叉树结构将需要保证以下两种互斥策略之一:
渐进式。如同忒修斯之船[3] ,当前的十六叉状态树将在很长一段时间内逐段进行转换。通过这种方式,任何涉及状态部分的事务或EVM执行都会自动将状态更改编码为新的二进制形式。这意味着采用“混合”树结构,休眠的状态部分依然保留当前的十六进制形式。该过程实际上永远不会完成,并且对于客户端开发者来说实施难度很大,但是在很大程度上将使用户和更高层的开发人员免受第0层幕后发生的更改的影响。
干净利落。也许这种策略更切合状态数变更的重要性,该策略将通过规划多次硬分叉为过渡过程制定清晰的时间线,计算状态的二进制树新表现形式,一旦新的状态计算完成就持续以二进制形式表示。尽管从实现的角度来看没那么复杂,但是需要协调所有节点运行者,并且几乎可以肯定会给网络带来一些(有限的)中断,这可能会影响过渡期间开发者和用户的体验。另一方面,对于更长远的eth2过渡计划来说,该过程具有一定的参考价值。
不管选择哪种过渡策略,二进制树都会是见证的基础结构,即构成状态树的哈希的顺序和层次。如果不进行优化,通过粗略计算(2020年1月),十六进制树结构中见证的大小将从约800—3400 kB减小到约300—1400 kB。
“静态”分块。将合约代码拆分为固定大小(约32个字节)。为了使分块后的代码正确运行,这种方法还需要在每个代码块中包含一些额外的元数据。
“动态”分块。根据代码本身的内容将合约代码拆分成多块,并按照其中包含的特定指令(JUMPDEST)进行分割。
乍一看,“静态”分块方式似乎更可取,以避免抽象泄漏,即防止拆分后的代码内容影响较低级别的代码块,这种情况在“动态”分块方式中也可能出现。话虽如此,这两种方式还尚待完全测试,因此都只是作为考虑选项。
然而实际上,协议的某些方面的确会直接影响EVM的内部运作。Gas成本就是一个明显的表现。智能合约(EVM抽象内)已通过GAS操作码暴露了各种堆栈操作(EVM抽象外)的gas成本。Gas调度的变动可能会直接影响某些合约的性能,但它取决于具体情况以及合约如何利用其可以访问的信息。
由于存在“泄漏”,因此必须谨慎变动gas调度和EVM执行,避免对智能合约产生意料之外的影响。这使我们必须面对和解决的现实问题,要设计零抽象泄漏的系统非常困难,并且1.x的研究者没有从头重新设计的时间和精力,他们需要在当前的以太坊协议范围内进行工作,目前的虚拟状态机抽象中只存在极少的泄漏现象。
回到我们的主题:见证的介绍将需要更改gas调度。见证需要在网络上生成和传播,并且该活动需要囊括在EVM操作中。EVM语义里程碑的相关主题都与这些成本和激励措施是什么有关,又要如何对其进行估算,以及如何在对其他较高layers影响最小的情况下实现。
由于多个交易可能涉及到状态的同一部分,因此尚不清楚如何最好地估算在广播交易时生成见证的gas成本。如果交易方支付了见证生成的全部费用,我们可以想象这种情况:交易重叠时,区块见证的同一部分可能会被多次支付。需要注意的是,这显然不是一件坏事,只是需要更好地理解这种情况如何为gas激励带来真正的改变。
无论相关的gas成本是多少,见证本身都将需要成为以太坊协议的一部分,并且可能需要并入每个区块成为标准组成部分,就像在每个区块头中加入witnessHash这一条信息。
以太坊核心文件[4] 中的建议之一,以弥补部分泄漏,使将来对gas调度的更改更易于实施,尤其是与见证和无状态以太坊有关的更改。
从某种意义上来说,现有的范例(例如快速同步)已经提供了此功能。但是零状态节点和部分状态节点的加入使新节点的速度问题变得更加复杂。目前,由于所有节点都保留了当前状态的副本,因此新节点可以从其连接的任何正常节点处下载状态。但是,如果某些节点是零状态节点或部分状态节点,该假设就不再成立。
达成状态可用性里程碑的前提条件与这些因素相关:节点如何相互告知对方拥有哪些状态;如何在持续变化的点对点网络中可靠地传递这些状态。
诸如EIP 2465[5] 之类的改进属于网络传播规则的一般类别:网络协议中的新消息类型,可表明节点拥有哪些信息,并定义如何将该信息传递给其他节点,而这些节点可能处于较差或有限的网络中。
数据传递是一个开放性问题,有许多潜在的解决方案。一个“主流”的解决方案就是通过云服务器的HTTP请求提供部分或全部状态。一个更有野心的解决方案是采用相关点对点数据传递方案中的功能,允许对部分状态的请求由连接的节点代理,并通过分布式
哈希表[6]查找正确的归属地。
这两个极端方案在本质上并非不兼容,所以鱼与熊掌为何不能兼得?
Geth团队对此进行了一些实验,实验表明状态切片有助于改进状态截图的可用性。
本文已经包含了很多背景知识,但图中还有一些细微之处需要解释:
优化Beam Sync、Red Queen’s Sync及其他状态同步方式
同步方式不是网络协议的关键部分,但却是影响有效节点如何执行协议的细节。Beam Sync和Red Queen’s Sync有助于创建来自见证的状态的本地副本。在决定并实施网络协议的最终版本时,我们需要改进同步方式,以使其适应网络协议。
目前,这还是科技树中的“增益”项目,因其可以独立于其他主题进行开发,并且其实现细节取决于更基础的因素,例如见证范式。值得注意的是,由于这些协议外的主题无关于“核心”更改,因此有助于实施和测试科技树左侧的根本改进项。
我希望能根据实际进展来更新科技树的结构。正如之前所说,这不是“官方”或“最终”的工作范围,只是目前最为准确的草图。如果您有任何改进意见,请与我联系。
如果您有疑问,希望提出新主题或加入无状态以太坊的研究工作,请在ethresear.ch上进行自我介绍,或在Twitter上联系@gichiba或@JHancock。
文内链接:
[1] https://en.wikipedia.org/wiki/Technology_tree
[2] https://blog.ethereum.org/2020/01/17/eth1x-files-digest-no-2/
[3] https://en.wikipedia.org/wiki/Ship_of_Theseus[4] https://corepaper.org/ethereum/#proposals
[5] https://github.com/ethereum/EIPs/issues/2465
[6] https://en.wikipedia.org/wiki/Distributed_hash_table
[7] https://gist.github.com/karalabe/60be7bef184c8ec286fc7ee2b35b0b5b