原文标题:《Possible futures of the Ethereum protocol, part 5: The Purge》 原文作者:Vitalik Buterin 原文编译:Odaily星球日报 夫如何 自 10 月 14 日起,以太坊创始人 Vitalik Buterin 陆续发布对以太坊可能的未来的讨论,从《The Merge》、《The Surge》、《The Scourge》、《The Verge》到最新发布的《The Purge》彰显了 Vitalik 对以太坊主网的未来发展的畅想和如何解决目前所面临问题的解决方案。 《The Merge》:探讨了以太坊在转向 PoS 后需改进单槽最终性和降低质押门槛,以提高参与度和交易确认速度。 《The Surge》:探讨了以太坊扩容的不同策略,尤其是以 Rollup 为中心的路线图,及其在可扩展性、去中心化和安全性方面的挑战与解决方案。 《The Scourge》:探讨了以太坊在向 PoS 转型中面临中心化和价值提取风险,开发了多种机制以增强去中心化和公平性,同时进行质押经济改革以保障用户利益。 《The Verge》:探讨了以太坊无状态验证的挑战与解决方案,重点介绍了 Verkle 树和 STARK 等技术如何增强区块链的去中心化和效率。 10 月 26 日,Vitalik Buterin 发布关于《The Purge》文章,文章中探讨了以太坊面临的挑战是如何在长期内降低复杂性和存储需求,同时保持链的持久性和去中心化,关键措施包括通过“历史过期”和“状态过期”减少客户端存储负担,并通过“特征清理”简化协议,以确保网络的可持续性和可扩展性。 以下为原文内容,由Odaily星球日报编译。 特别感谢 Justin Drake、Tim Beiko、Matt Garnett、Piper Merriam、Marius van der Wijden 和 Tomasz Stanczak 的反馈和审查。 以太坊面临的挑战之一是,默认情况下,任何区块链协议的膨胀和复杂性都会随着时间的推移而增加。这发生在两个地方: 历史数据:历史上任何时刻进行的任何交易和创建的任何帐户都需要由所有客户端永久存储,并由任何新客户端下载,从而完全同步到网络。这会导致客户端负载和同步时间随着时间的推移不断增加,即使链的容量保持不变。 协议功能:添加新功能比删除旧功能容易得多,导致代码复杂性随着时间的推移而增加。 为了使以太坊能够长期维持下去,我们需要对这两种趋势施加强大的反压力,随着时间的推移降低复杂性和膨胀。但与此同时,我们需要保留使区块链变得伟大的关键属性之一:持久性。你可以把一张 NFT、一封交易通话数据中的情书、或者一份包含 100 万美元的智能合约放在链上,进入一个洞穴十年,出来时发现它仍然在那里等待你阅读和交互。为了让 DApp 放心地完全去中心化并删除升级密钥,他们需要确信他们的依赖项不会以破坏他们的方式升级 - 特别是 L1 本身。 如果我们下定决心,在这两种需求之间取得平衡,并在保持连续性的同时最大限度地减少或扭转臃肿、复杂性和衰退,这是绝对可能的。生物体可以做到这一点:虽然大多数生物体都会随着时间的推移而衰老,但少数幸运儿却不会。即使是社会系统也可以有极长的寿命。在某些情况下,以太坊已经取得了成功:工作证明消失了, SELFDESTRUCT 操作码大部分消失了,信标链节点已经存储了最多六个月的旧数据。以更通用的方式为以太坊找出这条道路,并走向长期稳定的最终结果,是以太坊长期可扩展性、技术可持续性甚至安全性的终极挑战。 The Purge:主要目标。 通过减少或消除每个节点永久存储所有历史记录甚至最终状态的需要来降低客户端存储要求。 通过消除不需要的功能来降低协议复杂性。 文章目录: History expiry(历史记录到期) State expiry(状态到期) Feature cleanup(特征清理) 截至撰写本文时,完全同步的以太坊节点需要大约 1.1 TB的磁盘空间用于执行客户端,另外还需要数百 GB 的磁盘空间用于共识客户端。其中绝大多数是历史:有关历史区块、交易和收据的数据,其中大部分已有多年历史。这意味着即使 Gas 限制根本没有增加,节点的大小每年也会持续增加数百 GB。 历史存储问题的一个关键简化特征是,因为每个块通过哈希链接(和其他结构)指向前一个块,所以对当前达成共识就足以对历史达成共识。只要网络对最新区块达成共识,任何历史区块或交易或状态(账户余额、随机数、代码、存储)都可以由任何单个参与者提供以及 Merkle 证明,并且该证明允许其他任何人验证它的正确性。共识是 N/2-of-N 信任模型,而历史是N-of-N 信任模型。 这为我们如何存储历史记录提供了很多选择。一种自然的选择是每个节点仅存储一小部分数据的网络。这就是种子网络几十年来的运作方式:虽然网络总共存储和分发了数百万个文件,但每个参与者仅存储和分发其中的几个文件。也许与直觉相反,这种方法甚至不一定会降低数据的稳健性。如果通过让节点运行更加经济实惠,我们可以建立一个拥有 100, 000 个节点的网络,其中每个节点存储随机 10% 的历史记录,那么每条数据将被复制 10, 000 次 - 与 10, 000 个节点的复制因子完全相同-节点网络,每个节点都存储所有内容。 如今,以太坊已经开始摆脱所有节点永久存储所有历史的模型。共识区块(即与权益证明共识相关的部分)仅存储约 6 个月。 Blob 仅存储约 18 天。 EIP-4444 旨在为历史区块和收据引入一年的存储期。长期目标是建立一个统一的时期(可能约为 18 天),在此期间每个节点负责存储所有内容,然后建立一个由以太坊节点组成的点对点网络,将旧数据存储在分布式网络方式。 Erasure codes 可用于提高 robustness,同时保持复制因子相同。事实上,Blob 已经进行了纠删码,以支持数据可用性采样。最简单的解决方案很可能是重新使用这种 Erasure codes,并将执行和共识块数据也放入 blob 中。 EIP-4444 ; Torrents and EIP-4444 ; 门户网络; 门户网络和 EIP-4444 ; Portal 中 SSZ 对象的分布式存储和检索; 如何提高 gas 限制(Paradigm)。 剩下的主要工作包括构建和集成一个具体的分布式解决方案来存储历史记录——至少是执行历史记录,但最终还包括共识和 blob。最简单的解决方案是 (i) 简单地引入现有的 torrent 库,以及 (ii) 称为Portal 网络的以太坊原生解决方案。一旦引入其中任何一个,我们就可以打开 EIP-4444 。 EIP-4444 本身不需要硬分叉,但它确实需要新的网络协议版本。因此,同时为所有客户端启用它是有价值的,否则存在客户端因连接到其他节点期望下载完整历史记录但实际上并未获取而发生故障的风险。 主要的权衡涉及我们如何努力提供“古代”历史数据。最简单的解决方案是明天停止存储古代历史,并依赖现有的存档节点和各种集中式提供程序进行复制。这很容易,但这削弱了以太坊作为永久记录场所的地位。更困难但更安全的途径是首先构建并集成 torrent 网络,以分布式方式存储历史记录。在这里,“我们有多努力”有两个维度: 我们如何努力确保最大的节点集确实存储了所有数据? 我们将历史存储集成到协议中的深度有多深? 对于(1)的一种极端偏执的方法将涉及托管证明:实际上要求每个权益证明验证器存储一定比例的历史记录,并定期以加密方式检查它们是否这样做。更温和的方法是为每个客户端存储的历史百分比设置一个自愿标准。 对于 ( 2),基本实现只涉及今天已经完成的工作:Portal 已经存储了包含整个以太坊历史的 ERA 文件。更彻底的实现将涉及实际将其连接到同步过程,这样,如果有人想要同步完整历史记录存储节点或存档节点,即使没有其他存档节点在线存在,他们也可以通过直接同步来实现来自门户网络。 如果我们想让节点运行或启动变得极其容易,那么减少历史存储需求可以说比无状态性更重要:在节点需要的 1.1 TB 中,约 300 GB 是状态,剩余的约 800 GB GB 已成为历史。只有实现无状态性和 EIP-4444 ,才能实现在智能手表上运行以太坊节点并且只需几分钟即可设置的愿景。 即使我们消除了客户端存储历史记录的需要,客户端的存储需求也将继续增长,每年约 50 GB,因为状态持续增长:账户余额和随机数、合约代码和合约存储。用户可以支付一次性费用,从而永远给现在和未来的以太坊客户带来负担。 状态比历史更难“过期”,因为 EVM 从根本上来说是围绕这样一个假设而设计的:一旦创建了状态对象,它就会始终存在,并且可以随时被任何事务读取。如果我们引入无状态性,有人认为这个问题也许并没有那么糟糕:只有专门的区块构建器类需要实际存储状态,而所有其他节点(甚至包含列表生成!)都可以无状态运行。然而,有一种观点认为,我们不想过多依赖无状态性,最终我们可能希望使状态过期以保持以太坊的去中心化。 今天,当您创建一个新的状态对象时(可以通过以下三种方式之一发生:(i)将 ETH 发送到新帐户,(ii)使用代码创建新帐户,(iii)设置以前未触及的存储槽) ,该状态对象永远处于该状态。相反,我们想要的是对象随着时间的推移自动过期。关键的挑战是以实现三个目标的方式做到这一点: 效率:不需要大量的额外计算来运行到期过程。 用户友好性:如果有人进入洞穴五年并回来,他们不应该失去对 ETH、ERC 20、NFT、CDP 头寸的访问权…… 开发人员友好性:开发人员不必切换到完全不熟悉的思维模型。此外,目前已经僵化且不更新的应用程序应该可以继续正常运行。 不满足这些目标就很容易解决问题。例如,您可以让每个状态对象还存储一个过期日期计数器(可以通过燃烧 ETH 来延长过期日期,这可能在任何时候读取或写入时自动发生),并有一个循环遍历状态以删除过期日期的过程状态对象。然而,这引入了额外的计算(甚至存储需求),并且它肯定不能满足用户友好性的要求。开发人员也很难推理涉及存储值有时重置为零的边缘情况。如果你在合同范围内设置到期计时器,这在技术上会让开发者的生活变得更容易,但它会让经济变得更加困难:开发者必须考虑如何将持续的存储成本“转嫁”给用户。 这些都是以太坊核心开发社区多年来一直在努力解决的问题,包括“区块链租金”和“再生”等提案。最终,我们结合了提案中最好的部分,并集中在两类“已知最不糟糕的解决方案”上: 部分状态过期解决方案 基于地址周期的状态到期建议。 部分状态到期提案都遵循相同的原则。我们将状态分成块。每个人都永久存储“顶级映射”,其中块为空或非空。仅当最近访问过该数据时才会存储每个块中的数据。有一种“复活”机制,如果不再存储 这些提案之间的主要区别是:(i)我们如何定义“最近”,以及(ii)我们如何定义“块”?一个具体的提案是EIP-7736 ,它建立在为 Verkle 树引入的“茎叶”设计之上(尽管与任何形式的无状态状态兼容,例如二叉树)。在这种设计中,彼此相邻的标头、代码和存储槽存储在同一个“主干”下。一个茎下存储的数据最多可以是 256 * 31 = 7, 936 字节。在许多情况下,帐户的整个标头和代码以及许多密钥存储槽都将存储在同一个主干下。如果给定主干下的数据在 6 个月内没有被读取或写入,则不再存储该数据,而是仅存储该数据的 32 字节承诺(“存根”)。未来访问该数据的交易将需要“复活”数据,并提供根据存根进行检查的证明。 还有其他方法可以实现类似的想法。例如,如果帐户级别的粒度不够,我们可以制定一个方案,其中树的每个 1/2 32 部分都由类似的茎叶机制控制。 由于激励因素,这变得更加棘手:攻击者可以通过将大量数据放入单个子树并每年发送单个交易来“更新树”,从而迫使客户端永久存储大量状态。如果您使续订成本与树大小成正比(或续订持续时间成反比),那么有人可能会通过将大量数据放入与他们相同的子树中来伤害其他用户。人们可以尝试通过根据子树大小使粒度动态化来限制这两个问题:例如,每个连续的 2 16 = 65536 个状态对象可以被视为一个“组”。然而,这些想法更为复杂;基于茎的方法很简单,并且可以调整激励措施,因为通常茎下的所有数据都与同一应用程序或用户相关。 如果我们想完全避免任何永久状态增长,甚至是 32 字节存根,该怎么办?由于复活冲突,这是一个难题:如果一个状态对象被删除,稍后 EVM 执行会将另一个状态对象置于完全相同的位置,但之后关心原始状态对象的人回来并尝试恢复它,该怎么办?当部分状态到期时,“存根”会阻止创建新数据。随着状态完全到期,我们甚至无法存储存根。 基于地址周期的设计是解决这个问题的最著名的想法。我们不是用一棵状态树存储整个状态,而是有一个不断增长的状态树列表,并且任何读取或写入的状态都会保存在最新的状态树中。每个时期(例如: 1 年)添加一次新的空状态树。老树都冻得严严实实的。完整节点仅存储最近的两棵树。如果一个状态对象在两个周期内没有被触及,从而落入过期树中,它仍然可以被读取或写入,但交易需要证明它的 Merkle 证明 - 一旦证明,就会保存一个副本再次在最新的树中。 使这对用户和开发人员都友好的一个关键思想是地址周期的概念。地址周期是属于地址一部分的数字。关键规则是具有地址周期 N 的地址只能在周期 N 期间或之后(即,当状态树列表达到长度 N 时)被读取或写入。如果你要保存一个新的状态对象(例如,一个新的合约,或者一个新的 ERC 20 余额),如果你确保将状态对象放入地址周期为 N 或 N-1 的合约中,那么你可以保存立即进行,无需提供证据证明之前什么都没有。另一方面,在旧地址期间进行的任何添加或编辑都需要证明。 这种设计保留了以太坊当前的大部分属性,不需要额外的计算,允许几乎像现在一样编写应用程序(ERC 20 需要重写,以确保地址周期为 N 的地址余额存储在子合约中,本身有地址周期 N),解决了“用户进山洞五年”的问题。然而,它有一个大问题:地址需要扩展到 20 字节以上才能适应地址周期。 一项建议是引入一种新的 32 字节地址格式,其中包括版本号、地址周期号和扩展散列。 0x01 (红色) 0000 (橙色) 000001 (绿色) 57 aE408398 dF7 E5 f4552091 A69125 d5dFcb7B8C2659029395bdF(蓝色)。 红色的是版本号。这里橙色的四个零旨在作为空白空间,将来可以容纳分片编号。绿色是地址周期号。蓝色是 26 字节的哈希值。 这里的关键挑战是向后兼容性。现有合约是围绕 20 字节地址设计的,并且通常使用严格的字节打包技术,明确假设地址正好是 20 字节长。解决这个问题的一个想法涉及转换映射,其中与新式地址交互的旧式合约将看到新式地址的 20 字节哈希值。然而,确保其安全性存在很大的复杂性。 另一种方法采取相反的方向:我们立即禁止一些 2 128 大小的地址子范围(例如,所有以0x ffffffff 开头的地址),然后使用该范围引入具有地址周期和 14 字节哈希值的地址。 0xffffffff000169125 d5dFcb7B8C2659029395bdF 这种方法做出的主要牺牲是引入了反事实地址的安全风险:持有资产或权限的地址,但其代码尚未发布到链上。风险涉及有人创建一个地址,该地址声称拥有一段(尚未发布)代码,但也有另一段有效的代码散列到同一地址。今天计算这样的碰撞需要 2 80 个哈希;地址空间收缩会将这个数字减少到易于访问的 2 56 个哈希值。 关键风险领域,即非单一所有者持有的钱包的反事实地址,在今天相对罕见,但随着我们进入多 L2 世界,可能会变得更加常见。唯一的解决方案是简单地接受这种风险,但要确定可能出现问题的所有常见用例,并提出有效的解决方法。 早期提案 区块链清洁; 再生; 以太坊状态大小管理理论; 无状态和状态过期的一些可能路径; 部分状态到期提案 EIP-7736 ; 地址空间扩展文档 原始提案; Ipsilon 评论; 博客文章评论; 如果我们失去碰撞抵抗力会破坏什么。 我认为未来有四种可行的道路: 我们做到无状态,并且从不引入状态过期。状态正在不断增长(尽管缓慢:我们可能看不到它 超过 8 TB 数十年),但只需要由相对 特殊类别的用户:甚至 PoS 验证器也不需要 状态。 我们进行部分状态到期,并接受一个低得多但仍然非零的永久状态大小增长率。这个结果可以说类似于涉及对等网络的历史过期提案如何接受每个客户端必须存储较低但固定百分比的历史数据的低得多但仍然非零的永久历史存储增长率。 我们通过地址空间扩展来进行状态过期。这将涉及一个多年的过程,以确保地址格式转换方法有效且安全,包括现有应用程序。 我们通过地址空间收缩来进行状态过期。这将涉及一个多年的过程,以确保所有涉及地址冲突的安全风险(包括跨链情况)都得到处理。 重要的一点是,无论是否实施依赖于地址格式更改的状态到期方案,最终都必须解决有关地址空间扩展和收缩的难题。如今,生成地址冲突大约需要 2 80 个哈希值,对于资源极其丰富的参与者来说,这种计算负载已经是可行的:GPU 可以执行大约 2 27 个哈希值,因此运行一年可以计算 2 52 ,因此所有世界上约 2 30 个 GPU可以在约 1/4 年内计算一次碰撞,而 FPGA 和 ASIC 可以进一步加速这一过程。未来,此类攻击将会向越来越多的人开放。因此,实施完全状态到期的实际成本可能不像看起来那么高,因为无论如何我们都必须解决这个非常具有挑战性的地址问题。 进行状态过期可能会使从一种状态树格式到另一种状态树格式的转换变得更容易,因为不需要转换过程:您可以简单地开始使用新格式创建新树,然后进行硬分叉来转换旧树。因此,虽然状态到期很复杂,但它确实有利于简化路线图的其他方面。History expiry
解决什么问题?
它是什么,它是如何工作的?
与现有研究有哪些联系?
还需要做什么,需要权衡什么?
它如何与路线图的其他部分交互?
限制历史存储还使得较新的以太坊节点实现更可行,仅支持协议的最新版本,这使它们变得更加简单。例如,现在可以安全地删除许多代码行,因为 2016 年 DoS 攻击期间创建的空存储槽已全部删除。既然转向权益证明已经成为历史,客户可以安全地删除所有与工作量证明相关的代码。State expiry
解决什么问题?
它是什么,它是如何工作的
Partial state expiry 部分状态到期
基于地址周期的状态到期建议
Address space extension 地址空间扩展
地址空间收缩
与现有研究有哪些联系?
还需要做什么,需要权衡什么?
需要访问部分状态的一个功能是包含列表生成,但我们可以以分散的方式完成此操作:每个用户负责维护状态树中包含其自己帐户的部分。当他们广播交易时,他们会广播交易并附带验证步骤期间访问的状态对象的证明(这适用于 EOA 和 ERC-4337 帐户)。然后,无状态验证器可以将这些证明组合成整个包含列表的证明。它如何与路线图的其他部分交互?
Feature cleanup