弱无状态性 以及/或者 状态保质期机制:即将到来

2021-03-12 18:47:51 作者:金色财经

以太坊基础层接下来面临的一大挑战就是处理日渐增加的状态数据:当前以太坊区块链的状态数据约有 100 GB(其中就包括状态树节点数据),而且每年大约会增加 50GB。日益膨胀的状态会让同步以太坊区块链、担当区块链的验证者变得越来越困难,还有使网络陷入中心化的风险;尤其,状态数据的增长还有可能变得更快(因为区块 Gas 上限可能进一步提高)。

现在,人们提出了两类技术作为短期内的解决方案:

状态保质期(State expiry):从状态中移除那些近期(比如过去一年)没有被访问的状态对象,并且,在 “复活” 这些过期的状态对象时需要提供(证明其存在性的)见证数据(witness)。这将使 每个节点 都要存储的状态数据限制在 20~50 GB。

弱无状态性(Weak Statelessness):仅要求区块生产者(block proposer)存储状态,而所有其他节点都无需存储状态即可验证区块。

当然,也有更长期的选择如 “完全无状态性(full statelessness)”:可以认为是上述两种方案的极端形式(你既可以把它当成是保质时长为 0 的状态保质期方案,也可以当成是连区块生产者也无需存储任何状态的弱无状态性方案),但更具有挑战性,因此可以认为在短期内没有投入太多时间的必要。

当然,状态保质期方案和弱无状态性也面临许多挑战(见我最近的一篇文章(中文译本)),不过,不论哪一种方案,近来都有可观的进步,可以大大缓解我们面临的困难。

关于状态保质期方案,关键难点在于:

如何组织状态的结构,使得不用的部分就会过期?(我们是在状态树上存储 “存根”,还是把过期的状态对象移到一个单独的树状结构中,还是完全放到别的结构中?)我们是在账户层实现它,还是在存储槽层面实现它(我更倾向于在存储槽层面实现状态保质期方案(中文译本))

灭活状态对象时应采取什么样的流程?尤其是,我们是接连不断地灭活状态对象,还是每隔一段时间(比如 1 年)实施一次灭活行动?“ReGenesis”就是后面这种策略的代称(中文译本)。

如何处理 “复活冲突(resurrection conflicts)” 问题?复活冲突是一个重要的概念。假设某些账户或存储槽在某些 地址/位置 创建好之后过期了;然后,该账户/存储槽又在相同的位置被重新写入;最后,有些人又尝试复活最初那个已经过期的对象。我们该如何解决 这个过期又复活的状态 与 那个新创建的状态 之间的冲突?我的文章有专门的一节详细描述了这个问题。

至于弱无状态性,关键难点在于:

如何使用 Gas 重定价来限制见证数据的上限?(EIP 2929 解决了大部分问题;然而一旦我们引入代码默克尔化(中文译本),就仍然需要为访问每一个合约代码块施加成本)

见证数据的大小:见证数据即向无状态的客户端提供的、用于验证区块有效性的额外数据;这部分数据,即使有了合适的重定价措施,也有约 4 MB,对于我们这个每 13 秒就要广播一次区块的网络来说,还是太大了。

事务的广播:如果客户端并不能直接访问状态来验证事务本身的有效性(nonce 对不对、够不够 ETH 支付手续费),那事务要怎么在网络间传播、验证呢?(译者注:如果客户端无法验证自己收到的事务的有效性,将无论有效无效的事务都一视同仁地转播,则这会变成一个阻塞 P2P 网络的拒绝服务攻击因素。)

幸运的是,近来两种方法都取得了许多进展,这些进展似乎能解决绝大多数困扰:

一些技术能让 ReGenesis 类型的(基于 epoch)的状态保质期方案最小化复活冲突

Piper Merriam 研究了如何在事务广播网络中添加见证消息使之适合无状态客户端;以及分布式的状态存储和按需可得性

Verkle tree,可以将最糟糕情况下的见证数据大小从约 4 MB 降低到约 800 kB(这已经足够小了,因为当前最糟糕情况下(全部是 calldata)的区块可达到约 780 kB,而我们也不得不处理)。看 幻灯片、文档 和 代码。

从理论到实际

两种解决方案都在开发中,可能现在是时候要改观、把它们当成是可行的路径而非研究领域的概念了。至少有一个(可能最终是两个)需要在以太坊上实现。

那这就产生了一个优先级问题:如果我们不得不在两者中挑一个,哪一个更重要一些?Dankrad 分析了弱无状态性;如果有详细讲解状态保质期的工作,那对照起来必定会很有趣(我还没发现有这样的文档;但也许有)。

另一个挑战是,让整个生态准备好付出转变的代价。举些例子:

弱无状态性需要用 verkle tree 来替代二进制树(译者注:原文如此。疑应为 “十六进制树”,即当前的以太坊状态树所用的格式),这会使现今所有的默克尔分支验证器(不论是客户端和还是智能合约)失效

Verkle tree 也要求改变客户端的同步协议

我们还需要添加按代码块计算的 Gas 成本(例如,每访问 32 字节的代码块就需要消耗 500 Gas),这会让某些应用的 Gas 开销比当前的更大

状态保质期方案需要应用重新设计自己的合约,以高效地使用新状态(意思是,当前用于解决复活冲突问题的方案引入了 “旧状态区域” 和 “新状态区域” 的概念,在旧状态区域创建一个新对象需要提交证明,且证明会随时间推移而增大;而在新状态区域创建对象则不需要证明,所以合约(例如 token 合约)需要新的版本和架构来处理这一点,虽然不更新也能继续用,但这样会更不便利,Gas 开销也会更高)

依赖历史数据访问权的 dApp 需要切换到一些 另外的协议/L2 机制 (比如 The Graph?)中,以访问 1 年以前的数据

好处

解决上述问题需要极大的毅力。但回报是丰厚的:

让更多人能够运行以太坊节点,帮助以太坊去中心化以及降低 “Infura 依赖风险”

启用以太坊的无状态验证,大幅降低成为 PoS 验证者的开销:实现之后,节点甚至可以选择性地验证以太坊应用的数据,例如:仅验证自己参与了见证(attesting)的区块。这将使我们更接近我们梦寐以求的目标:保证用户使用容易买到的消费级硬件(甚至是手机!)就能成为 PoS 验证者并且长期不变

提高区块 Gas 上限:缩减客户端的状态数据规模使我们能安全地大幅提高区块 Gas 上线,为用户提供更低的交易手续费。更小的状态数据意味着这些数据甚至可以放到内存中,因此每次访问状态的实际开销都会更小,因此我们有望安全地提高区块 Gas 上限。

让应用开发者更为确信,此番转变之后,协议的经济模型可以更坚固,而且未来不会再有太大改变,因为协议中主要的经济激励不兼容问题(用户只需支付一次费用就可以永久存储一个状态对象)已经终结。

希望对该主题我们有更多的讨论,尽快开始开发必要的准备工作,为解决我们的状态问题、为更高的 L1 效率和可扩展性铺平道路!

原文链接:

https://ethereum-magicians.org/t/weak-statelessness-and-or-state-expiry-coming-soon/5453

作者:  Vitalik

翻译: 阿剑

相关推荐

图文推荐