本文深入探讨了以太坊的状态管理和EIP-2935提案,提出通过引入无状态执行来解决因状态增长带来的问题。文章详细介绍了以太坊的区块结构、Merkle树、Gas机制,以及状态和数据的过期管理,通过对比现有EIP,强调EIP-2935在实现无状态以太坊中的重要性与潜在益处,促进了以太坊的去中心化和可扩展性。
4 April 2025
区块链在处理交易时存储和引用的内容称为 状态。在以太坊上,状态是促进节点共识的属性。每个完整节点在每个有效区块期间都需要存储和更新这个状态。状态对区块链如此重要,但它也有一个缺点;随着时间的推移,它们会不断增长。它们在比特币和以太坊等区块链中是一个主要问题,因为大小的增加伴随着节点硬件要求的相应增加。空间阈值会随着时间推移而淘汰一些节点,导致中心化。 EIP-2935 提出了将无状态性引入以太坊,减轻节点的 大小 负担。EIP-2935 是一个改进提议,试图通过存储和提供无状态执行所需的最后 8192 个区块哈希来实现无状态性。
区块是一组交易,并在链中包含前一个区块的引用(哈希)。每个区块的哈希是根据该区块的数据通过加密方式导出的。这一包含将链通过哈希链接在一起,批量处理意味着网络中所有参与者同时同意并同步状态。此外,对批块的达成共识会通知以太坊在网络中每个参与者作为节点更新其全球状态。
替代文本: 以太坊中的状态变化
一旦新的区块被处理并与网络中的验证者广播,其余参与者会将其添加到存储中并更新全球状态。每个区块的验证者是通过 随机化去中心化自治组织 (RANDAO) 参数随机选择的。区块结构是严格排列的,区块创建和共识流程在以太坊的权益证明协议下被指定。
一个区块在其头部和主体中包含多个字段。例如,区块头包括 slot
,proposer_index
,parent_root
,state_root
和 body
字段。区块主体包括 randao_reveal
,eth1_data
,graffiti
,proposer_slashings
,attester_slashings
,attestations
,deposits
,voluntary_exits
,sync_aggregate
和 execution_payload
。每个字段具有不同的参数,并处理不同的需求。
以太坊的 12 秒 区块创建周期,亦称为“时隙”,为网络参与者提供足够的时间以同步新块并达成共识。在这一期间:
区块和交易的最终性意味着在分布式网络中没有重大 ETH 焚烧的情况下无法更改。以太坊采用 “检查点块” 方法来管理最终性。每个周期的第一个区块被视为该时隙的检查点。验证者为这个假设投票,以使其成为有效的检查点。如果三分之二的总抵押 ETH 投票选举出一对检查点,则这些检查点将升级为 有根据。在下一个检查点升级后,之前的有根据检查点也会被升级并最终确认。如果恶意用户想要撤销一个最终确认的区块,他们需要承诺损失至少三分之一的总抵押 ETH。虽然存在一个称为 不活动泄露 的机制,通过对验证者资金施加巨大惩罚,并在大量验证者的永久故障情况下减少验证者奖励,从而恢复最终性。
在处理区块时,以太坊应用哈希函数来获取区块数据并将其缩减为唯一字符串。在哈希函数中,所有输入产生唯一的输出。区块中的哈希值是唯一的不变部分。通过焚烧三分之一的总抵押 ETH,可以更改它。然而,该金额来自重新计算Merkle树的哈希,直到一个检查点。每个区块的哈希过程输出与 blockHash
参数一起返回。blockHash
参数包括区块中的所有数据。
区块的哈希值和其他所需参数存储在Merkle树中。以太坊使用Merkle树架构的不同版本,例如Merkle帕特里夏树。
树状结构,尤其是Merkle树,对于区块链存储至关重要。没有Merkle树,区块链每次会变成难以处理的单个区块。借助Merkle树,或者一般的树状架构,区块链通过基本片段实现了完整性。这使得它们成为具有低硬件要求的网络参与者。
Merkle树是一种将大量数据块哈希化并拆分成部分的结构化方式。通过Merkle化,数据成对组织;每一对一起哈希。Merkle化过程重复进行,直到获得一个单一的Merkle根。
以太坊更倾向于Merkle帕特里夏树,这是一种双重Merkle树结构。它使用二叉树进行基本数据处理,如交易数据,因为这种方法在此情况下更有效。然而,在处理状态等复杂情况时,以太坊使用更复杂的Merkle帕特里夏树。
在状态树数据存储方案中,以太坊利用键值映射。键表示地址,值表示账户声明。状态树比二叉树更动态。因此,可以频繁插入新账户,并且可以频繁插入和删除键。这一过程中需要一个快速可更新的数据结构,而不是重新计算整个数据集。
树根只依赖于数据,而不是顺序。以不同顺序对数据进行更新不会改变根本身。
替代文本: 二叉Merkle树
以太坊使用了改进的Merkle帕特里夏树,这具有 PATRICIA (用以检索以字母和数字编码的信息的实际算法) 和经过修改的Merkle树的一些特性。这一架构是确定性的和密码学可验证的。生成此结构的状态根的唯一方法是通过从每个独立状态片段计算得到。两个相同的状态可以通过比较根哈希和导致它的哈希来轻松证明。
最终,使用不同的值修改状态是不可能的,因为这会导致不同的状态根哈希。以太坊执行层中所有树状结构都使用Merkle帕特里夏树。网络有三个树:状态树、存储树和交易树。此外,每个区块都有自己的收据树。虽然Merkle帕特里夏树在许多方面都是高效的,但以太坊希望用 Verkle 树替代它们以实现无状态性。
替代文本: Merkle帕特里夏树
Gas是执行 EVM 所需的属性。由于 EVM 使用并需要计算资源来执行,这些努力的回报以Gas的形式支付,以确保 EVM 的安全。Gas费用是所需Gas量与每单位费用的乘积。这是一个动态值,并依赖于操作类型。
替代文本: https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf
EIP-1559 对交易费用机制引入了一些重要的变化。过去,支付Gas以将交易包括在区块中采用拍卖式的方法。随着 EIP-1559 的出台,出现了一种称为基本费用的最低限制和一种称为优先费用的提示。提议的区块首先从优先费用最高的交易开始。区块处理后,基本费用会被焚烧,优先费用则用于激励验证者。
区块链状态可以被定义为在特定时刻描述某系统的一组数据(或变量)。互联网几乎从一开始就有状态,但它存储在单一服务器上。随着 Web3 的出现,一个通过去中心化方法维护的开放和分布式网络上的全球状态被引入。每个人都可以在任何时候查看和验证分布式网络的状态。
以太坊的全球状态包括账户、余额、部署的智能合约和相关的存储。随着这些参数的增加和变化,以太坊的状态不断增长。当托管完整节点的硬件成本变得高不可攀时,状态增长就变得成问题。在这种挑战下,Vitalik Buterin 在2017年提出 无状态以太坊的概念。提出的解决以太坊状态增长的方法包括数据和状态过期。
数据或历史过期意味着在一定时间后从客户端中修剪掉不需要的数据。通过 “弱主观性检查点”,客户端可以从创世块进行同步并修剪历史废数据。
主观性是指网络节点依赖社会信息对当前状态达成共识。在这种情况下,弱主观性 是指一个可以根据一些通过社交获取的初始信息客观进展的链。然而,弱主观性检查点意味着网络中所有负责共识的节点属于规范链。弱主观性检查点帮助以太坊 PoS 从一个受信源处获取最近的状态(弱主观性检查点)以同步。
EIP-4444 提供了通过弱主观性达成数据过期的实际路径。该提案并不旨在改变以太坊节点处理状态数据的方式;而是修改了对历史数据的访问。
状态过期试图消除未被近期访问的节点上的状态。过期可能通过租金或时间来实施。按租金过期 是指对存储状态的账户施加额外费用。另一方面,按时间过期 意味着在一定时间内未被激活的账户将被置为不活动。
数据过期和状态过期都是开放的研究领域。目前实现这些提议状态的方法涉及通过中心化网络/提供者。迄今为止,弱无状态性和状态过期在以太坊中已部分实现。
无状态以太坊向核心协议引入了新概念。从理想上讲,无状态性并不意味着状态不存在。而是,客户端可以选择他们想要维持的状态。当客户端收到经过验证的区块时,他们也接收与该区块相关的见证。每个区块的见证由执行该区块中包含的交易所需的所有数据组成。
EIP-161 提出了第一个减少状态的方法。以太坊曾遭受过拒绝服务 (DoS) 攻击,这个脆弱性使其能够创建增加了以太坊全球状态的空账户。EIP-161 提出了以较低的成本删除这些由于这次攻击而产生的在其nonce上价值为零(0)的空账户。该提案被执行,导致状态撤销。
通过 EIP-4788 提出的另一个无状态性努力。这项提案试图在 EVM 中暴露信标链区块的根。与连接信标链(共识层)和执行层的 Eth1-Eth2 桥 的方法相似,该提案允许 EVM 和共识层之间进行信任最小化访问。
因为每个执行区块都包含父信标区块的根,所以错过的时隙事件不需要改变前一个区块根。因此,执行的前提条件缩小为在每个执行区块中保留一个小空间用于信任最小化的预言机。该提案建议在一个根合约中存储一小段块根的历史信息,以提高预言机的效率。
以太坊中的无状态性可以是弱无状态性或强无状态性。
弱无状态性是一种并不消除所有节点存储状态数据需要的状态。相反,它表现为节点如何验证以太坊状态的变化。它将状态存储的责任置于区块提议者身上,并要求其他节点在不存储完整状态数据的情况下验证区块。
区块提议者需要存储完整的状态数据。然而,验证器客户端不需要在网络中存储状态数据。相反,他们可以存储状态根(整个状态的哈希)。弱无状态性的实现需要 提议者-构建者分离 (PBS) 和 Verkle 尝试 的实现。
提议者使用状态数据生成见证来证明状态变化,而验证者则根据状态根哈希验证这些证明。
强无状态性消除了任何节点存储状态数据的需要。它通过将已发送的交易和由区块提议者聚合的见证结合在一起。区块提议者仅存储他们正在处理的状态,为相关账户生成见证。该提案仍需进一步开发,并包括 访问列表 或 EIP-2930 等要求。
然而,可以使用某些更改和属性实现无状态性。EIP-2935 提议从状态中为无状态执行提供历史区块哈希。
EIP-2935 旨在将历史区块哈希保存在区块链的状态中,存储在称为 HISTORY_STORAGE_ADDRESS
的特殊存储插槽中。此过程将通过便利无状态客户端对所需历史信息的便捷访问来实现无状态执行。
EIP-2935 提议将在系统合约中存储最后 8192 个历史区块哈希,作为区块处理逻辑的一部分。该提案旨在解决 EVM 假设客户端拥有最近区块哈希的问题。这种假设性的做法不适用于未来的以太坊,尤其是无状态客户端。
将先前的区块哈希包含在状态中将允许将这些哈希与哈希函数捆绑在一起,从而形成证据。随后,会向无状态客户端提供见证以验证执行并实现无状态执行。此提案被称为预 Verkle 规范,因为它可以在核心协议适应 Verkle 尝试之前进行实现,并支持部分无状态性。
将 blockHash
服务的区块范围扩展到 8192 个区块将允许向执行方法的平滑过渡。Rollups 可以通过直接查询此合约从这一更长的历史窗口中获益,因为 blockHash
数据存储在此合约中。此外,这一 EIP 将便于验证与当前状态相关联的 8192 区块量的 HISTORY_SERVE_WINDOW
。
EIP-2935 允许以太坊客户端,特别是无状态的客户端,轻松访问最近的区块哈希。为了实现这一点,它引入了四个新参数:
BLOCKHASH_SERVE_WINDOW
: 告诉客户端应该保留多少过去的区块哈希。默认值为 256。HISTORY_SERVE_WINDOW
: 此参数定义存储多少区块哈希。默认值为 8191。SYSTEM_ADDRESS
: 一个特殊地址(最初在 EIP-4788 中引入),作为将区块哈希写入存储的“调用者”。HISTORY_STORAGE_ADDRESS
: 存储这些区块哈希的合约地址。该提案的规范指示将最后 HISTORY_SERVE_WINDOW
个区块哈希存储在长度为 HISTORY_SERVE_WINDOW
的环形缓冲存储中。
EIP-2935 使用了一种称为环形缓冲区的附加特性进行临时存储。环形缓冲区是允许网络重用相同存储用于不同数据的特性。环形缓冲区的存储限制为每次相同的存储位置。EIP-2935 中的环形缓冲区仅用于服务所需的 HISTORY_SERVE_WINDOW
,因为 EIP-4788 和信标状态累加器允许对任何祖先进行证明。
在分叉后,当网络开始考虑这些 EIP 时,HISTORY_STORAGE_ADDRESS
参数将被称为 SYSTEM_ADDRESS
,其输入为 block.parent.hash
(默认 32 字节),Gas限制为 30,000,000,值为 0。该过程将触发历史合约的 set()
函数。
提案后的分叉过程与常规分叉过程有所不同。此 set()
操作是一个通用系统操作,但调用遵循以下约定:
HISTORY_STORAGE_ADDRESS
中没有代码,则调用必须在没有致命错误的情况下失败。该过程必须填满区块周期 HISTORY_SERVE_WINDOW
以便满足环形缓冲区触发周期。历史合约将仅包含分叉区块的父哈希,作为参考哈希和新的哈希起始点。
一个区块哈希历史合约将有两个操作:get()
和 set()
。set()
操作在合同的调用者在交易中等于 EIP-4788 引入的 SYSTEM_ADDRESS
时被激活。如果调用者与 SYSTEM_ADDRESS
不相等或不满足条件,则激活 get()
操作。
get()
操作在 EVM 中用于找到区块哈希。它允许调用者提供他们查询的区块号,如果 calldata
输入不是 32 字节(这意味着这是一个有效的 block.parent.hash
),并且请求超出了范围 ([block.number-HISTORY_SERVE_WINDOW, block.number-1]
),则它会撤销交易。
当调用者通过交易调用合约时,set()
将以 calldata
中的 block.parent.hash
作为输入。它还在 block.number-1 % HISTORY_SERVE_WINDOW
处将存储值设置为 calldata[0:32]
。
HISTORY_STORAGE_ADDRESS
将通过 EIP-4788 部署,以上述方式直接从共识层访问区块哈希。HISTORY_STORAGE_ADDRESS
的 nonce 值为 1,并免于 EIP-161 的零 nonce 清理标准。
关于这个 EIP 的一个担忧是如何最好地在分叉后转换 BLOCKHASH
解析逻辑。目前考虑了两种主要方法:
HISTORY_SERVE_WINDOW
区块使整个相关历史得以保留,HISTORY_SERVE_WINDOW
区块哈希。开发者们选择了第一个选项。它更为实际,因为这不需要任何临时更改。
之前提出过类似的 EIP 以实现无状态执行。EIP-2935 与这些早期提议的不同之处在于其定向的复杂性,主要体现在以下几个方面。
由于 EIP-2935 使用智能合约,其面临分支中毒攻击的风险。然而,状态根的大小使得尝试任何更新缓慢且中毒攻击的成本大大增加。
blockHash
支持最多 256 个区块。利用 EIP-2935,此过程通过允许访问较旧的区块哈希得到改善,意味着证明可以更长时间得到验证。EIP-2935 代表了实现无状态以太坊长期目标的关键一步。在状态中存储最后 8192 个区块哈希的专用合约,解决了当前设计的一项根本限制。以太坊假设客户端固有地能够访问最近的区块哈希。在无状态执行的背景下,客户端不再维护完整状态,这一假设变得过时。EIP-2935 通过引入一种轻量、高效且不具侵入性的机制,解决了这一问题,使无状态客户端能够在不修改 EVM 或依赖复杂数据结构如 Verkle 树的情况下访问所需的历史数据。
除了无状态执行,这一提案还解锁了以太坊生态系统中的更广泛好处。它增强了无信任预言机的能力,扩展了轻客户端的可用性,并通过实现对较旧状态数据的可靠验证来加强 Layer 1 和 Layer 2 解决方案之间的互操作性。它的实施依靠一种干净且节能的设计,采用环形缓冲存储和系统级合约,从而无需对 EVM 进行硬编码,提供了简便和可扩展性。
随着以太坊继续朝着更大去中心化、可扩展性和可访问性的发展,EIP-2935 成为了一项基础性改进。它弥合了当前有状态架构与预想的无状态未来之间的鸿沟,并为整个区块链生态系统铺平了建立更稳健、高效、无许可基础设施的基础。
我们真诚感谢 Daniel Ayuko 审阅了这篇文章。
2077 研究所提供的内容仅供信息参考,并不构成财务、法律或税务建议。所表达的观点仅代表作者,并不一定反映 2077 研究所或其附属机构的意见。读者应自行进行研究,并在解读所提供的信息时运用独立判断。
- 原文链接: research.2077.xyz/eip-29...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!