Ethereum Dencun 硬分叉内容介绍 - 01.jpg

Ethereum Dencun 硬分叉内容介绍

Dencun 是由 Deneb 及 Cancun 两个名称所组成,分别代表 Ethereum 共识层与执行层的硬分叉。Dencun 硬分叉已经在 Goerli、Sepolia 及 Holesky 测试网完成,主网将在 Epoch 269568(约为 2024.3.13 日)进行。

  • 作者:Nic @ imToken Labs

  • 校对:Members at imToken Labs
  • 封面来源:Cancun & Deneb by Midjourney

  • 先备知识:
    • 硬分叉
    • Ethereum 分为共识层(Consensus Layer)及执行层(Execution Layer)

Dencun 内容包含 9 个 EIP,分别是:

  • EIP-1153: Transient storage opcodes(执行层改动)
  • EIP-4788: Beacon block root in the EVM(执行层与共识层改动)
  • EIP-4844: Shard Blob Transactions(执行层与共识层改动)
  • EIP-5656: MCOPY - Memory copying instruction(执行层改动)
  • EIP-6780: SELFDESTRUCT only in same transaction(执行层改动)
  • EIP-7044: Perpetually Valid Signed Voluntary Exits(共识层改动)
  • EIP-7045: Increase Max Attestation Inclusion Slot(共识层改动)
  • EIP-7514: Add Max Epoch Churn Limit(共识层改动)
  • EIP-7516: BLOBBASEFEE opcode(执行层改动)

这篇文章将介绍这几个 EIP(不包含 4844)的改动与影响,4844 的介绍可以参考:

接下来介绍与顺序会大致区分为「执行层改动相关的 EIP」、「共识层改动相关的 EIP」及「4844 相关的 EIP」。

EIP-1153

1153 新增两个 Opcode:TSTORE 与 TLOAD,用来写入与读取「暂时的」Storage 数据。它们将可为许多合约开发者省下不少 Gas 成本。

背景

Storage 指的就是智能合约透过 SSTORE 这个 Opcode 将数据写入到该合约的储存空间中,数据写入后是永久存在的,直到合约主动移除该笔数据为止。而「暂时的」这个特质则是相对于「永久存在」,TSTORE 写入的数据有效期限只有到该笔交易结束为止,该笔交易执行完后 TSTORE 写入的值就会被丢弃。

运作细节

TSTORE 相比于 SSTORE 便宜非常多,而其有效期限又能横跨不同合约之间的呼叫(直到交易结束),不像 Memory 虽然便宜但 Memory 里的值只专属于每个合约自己,A 合约无法去读取 B 合约的 Memory。这对许多用途非常有帮助:

  1. Reentrancy Lock。目前 Reentrancy Lock 只能用 SSTORE 来仿真,虽然 SSTORE 的规则经过 EIP-2200 后有对 Reentrancy Lock 这样的用途减轻不少 Gas 成本,但 TSTORE 可以将成本再大幅降低:从 5000 降为 100

  2. 使用于单笔交易内的 ERC-20 approve。如果 A 合约和 B 合约进行交互,而 A 合约需要从 B 合约身上转走 ERC-20,此时 B 合约会先对 A 合约做 approve ERC-20 的动作然后才呼叫 A 合约。因为 ERC-20 的 approve 都是透过 SSTORE 所以成本不低,改成使用 TSTORE 后将能大幅降低成本
  3. 透过 CREATE2 部署合约时的部署参数。因为 Constructor 参数会影响 CREATE2 部署的合约地址,所以如果不想被 Constructor 参数影响的话,合约 Constructor 就会设计为去部署者合约的 Storage 读取参数,例如 Uniswap V3 的 Pool。透过 TSTORE,这样的模式就能省下许多成本

注意事项

  • 合约开发者在用 TSTORE 改写自己的 Reentrancy Lock 时,记得还是要在该清空 Lock 时清空,不要想说交易结束后它会自己清空所以可省下清空的 Gas 消耗,否则交易过程中如果有需要再次进入合约的话就有可能因为 Lock 没解锁(没清空)而无法进入
  • EIP-1153 已经在 Solidity 0.8.24 版中推出,开发者可以提前试用。这里有开发者实作的 Mutex 范例。仰赖 TSTORE 的 Uniswap V4 也将在 Dencun 后上线
  • 这个 EIP 新增新的 Opcode,所以开发者如果要部署合约到多链,要注意是否所有的链都有支持最新的 Opcode,否则将导致无法使用

EIP-4788

EIP-4788 新增一个 BEACON_ROOTS_ADDRESS 合约来让人读取共识层区块的数据,也就是执行层将能读取到共识层的数据。透过这个合约,Staking 及 Restaking 协议可以在不信任任何第三方的前提下读取并使用共识层的数据,例如读取某个验证者的状态。

运作细节

使用者或合约可以透过呼叫合约的方式去查询某个时间点的共识层区块根(Beacon Block Root)。区块根如同区块内容的哈希值(Beacon Block Hash),是区块内容透过 SSZ 编码的方式所得到的 Merkle Tree 的树根(Merkle Tree Root)。呼叫者将时间戳(timestamp)编码成 uint256 的值并当作呼叫内容, 合约会以时间戳去 Storage 寻找相对应的共识层区块根并回传。

开发者如果要使用共识层的信息,则他的合约会透过 BEACON_ROOTS_ADDRESS 合约查询他要读取的共识层区块的区块根,然后再搭配该共识层区块的信息(例如某个验证者的余额)及 Merkle Proof 来验证该信息是否属于该区块根。(SSZ 因为将内容都做成 Merkle Tree,所以内容里任何信息都可以产生相对应的 Merkle Proof 来验证该信息存在于该内容里。)

Ethereum Dencun 硬分叉内容介绍 - 02.png

使用者提供 Merkle Proof 与共识层区块的时间戳

Ethereum Dencun 硬分叉内容介绍 - 03.png

Merkle Proof 搭配询问区块根来验证某个时间点的验证者余额

不过 BEACON_ROOTS_ADDRESS 合约里存的共识层区块根其实是「母」区块(也就是前一个区块)的区块根,而不是和执行层同一个区块的区块根。

Ethereum Dencun 硬分叉内容介绍 - 04.png

Block 11001 的时间戳(1234567)对应的是 Block 11000 的区块根;同样地,Block 11000 的时间戳(1234555)对应的是 Block 10999 的区块根

注意事项

BEACON_ROOTS_ADDRESS 合约里储存最多 8191 个共识层区块根,8191 个以前的区块根会被覆写。例如假设现在是 Block 18191,则当下能存取到区块根范围会是 Block 10000 到 Block 18190 的区块根。

EIP-5656

EIP-5656 新增一个 MCOPY Opcode,专门用来复制合约执行过程中 Memory 里储存的值。合约将可受益于这个 Opcode 节省的 Gas 成本。

合约开发者若要使用 MCOPY Opcode,需要将编译程序版本指定为 0.8.24(或以上)以及 EVM 版本指定为 Cancun:

Ethereum Dencun 硬分叉内容介绍 - 05.png

要使用 MCOPY 需要设定编译程序版本及 EVM 版本

注:0.8.24 版的编译程序只开放透过 Assembly 的方式来使用 MCOPY(mcopy(),link),未来的版本才会自动由编译程序来在需要复制 Memory 的地方套用 MCOPY。

注意事项

  • 这个 EIP 新增新的 Opcode,所以开发者如果要部署合约到多链,要注意是否所有的链都有支持最新的 Opcode,否则将导致无法使用

EIP-6780

EIP-6780 修改了 SELFDESTRUCT Opcode 的行为,为 Verkle Tree 及淘汰 SELFDESTRUCT Opcode 做准备。合约有使用到 SELFDESTRUCT Opcode 的开发者需要特别注意。

背景

SELFDESTRUCT Opcode 目前的行为是:(1) 删除该合约的代码及 Storage,并 (2) 将身上的 ETH 全都转给指定的地址。

一开始设计 SELFDESTRUCT Opcode 搭配 Refund 机制来激励开发者移除用不到的合约及储存空间,协助维持 Ethereum 状态在一个适合的大小。但真的这么做的人不多,反倒是出现像 Parity Multisig 这样因为 SELFDESTRUCT 导致数十万 ETH 冻结的意外,因此 Ethereum 社群希望能逐渐淘汰掉 SELFDESTRUCT Opcode。过去有不少修改或移除 SELFDESTRUCT Opcode 的提案,EIP-6780 是其中一个并且最终被收入进 Dencun 硬分叉中。

注:在 2023 年初的 Shanghai 硬分叉中,EIP-6049 已经正式宣告 SELFDESTRUCT 将会被淘汰。

Verkle Tree 是 Ethereum 社群目前正在积极研究与开发的状态储存结构,将用来取代目前的 Merkle Patricia Tree。Verkle Tree 将会让 Ethereum 状态的证明大小变得更小,因此也是 Stateless Client 设计中的关键。有了 Stateless Client,节点的硬件将会降低,让更多人可以以更轻量、便宜的硬件来运行节点,提升网络的去中心化程度。

运作细节

在 EIP-6780 后,SELFDESTRUCT Opcode 将会移除 (1) 的行为,只保留 (2)「将身上的 ETH 全都转给指定的地址」的功能。合约的代码及 Storage 都将维持不动,除非该合约是在同一笔交易创建然后又进行 SELFDESTRUCT。

所以当 SELFDESTRUCT 被触发时

  • 如果合约不是在同一笔交易被创建,则合约的代码及 Storage 都维持不动,但把身上的 ETH 全都转给指定的地址
  • 如果合约是在同一笔交易被创建,则行为和原本(EIP-6780 以前)一样:合约的代码及 Storage 都会被移除,ETH 也会被转给指定地址

为了 Verkle Tree,必须移除 (1) 的行为

在 Verkle Tree 的设计中,其储存状态的方式和 Merkle Patricia Tree 不一样。Merkle Patricia Tree 储存状态可以想象成是两层(树中树)的结构:第一层是所有地址集合成的一棵树,第二层是每个地址所有 Storage 及合成的一棵树;而 Verkle Tree 则可以想象是一层、完全打平的结构。因此在 Merkle Patricia Tree 中我们可以很轻松定位一个地址的 Storage 并将其移除,但在 Verkle Tree 中则几乎无法定位一个地址的 Storage,因为所有地址及地址的每个 Storage 值都被打平分散在同一棵树中,无法轻易知道哪个值是属于哪个地址的 Storage,所以我们没办法在 Verkle Tree 中移除合约代码及它的所有 Storage。

Ethereum Dencun 硬分叉内容介绍 - 06.png

目前的状态树设计(Merkle Patricia Tree)是两层结构:State Root 对应所有地址集合成的一棵树,Storage Root 对应一个地址底下所有 Storage 及合成的一棵树。source: https://fisco-bcos-documentation.readthedocs.io/en/latest/docs/design/storage/mpt.html

Ethereum Dencun 硬分叉内容介绍 - 07.png

Verkle Tree 状态树则是一层、完全打平的树,图中红色节点是地址,绿色节点是该地址的 Storage 值。source: https://youtu.be/s7fm6Zz_G0I?t=572

Ethereum Dencun 硬分叉内容介绍 - 08.png

如果我们只移除红色节点但没移除 Storage(绿色节点们),则要是合约重新部署至同一个地址,它就会直接继承旧的、没有被删除的 Storage,这会成为潜在的高风险漏洞。source: https://youtu.be/s7fm6Zz_G0I?t=572

所以为了迎接 Verkle Tree,我们势必得禁止 SELFDESTRUCT Opcode 可以移除合约代码及 Storage 的行为。

注意事项

  • 如果开发者使用 CREATE2 + SELFDESTRUCT 来重复部署到同一个地址,在 Dencun 后这将只会在同一笔交易内同时发生才能完成
  • 如果开发者使用 CREATE2 + SELFDESTRUCT 来达成合约升级的效用(因此 CREATE2 + SELFDESTRUCT 不会是在同一笔交易完成),在 Dencun 后将无法继续,请改用一般不会 SELFDESTRUCT 的升级模式

EIP-7044

EIP-7044 让验证者用来退出 PoS 的签章变为永久有效,避免签章因为网络硬分叉而导致无效。委托给非托管质押服务(例如 Lido)的验证者们的使用体验与保障将可以提升:不必每次硬分叉就要请第三方重新签名。

背景

Ethereum PoS 的验证者需要有两把私钥:一把用于日常参与验证(例如产区块并签名),称作 Validator Key;另一把则是在退出 PoS 时领回质押资产及手续费的地址的私钥,称作 Withdrawal Key。当验证者要退出 PoS 时,他会用 Validator Key 签名,签名的内容包含当前的网络(硬分叉)版本。

在目前的非托管质押服务中,服务提供商手上会握有 Validator Key,使用者则是握有 Withdrawal Key,因此服务提供商只能执行日常的验证相关的工作内容,不能领走使用者的质押资产及手续费,达到非托管的目的。而为了避免服务提供商以「不退出 PoS」来威胁敲诈使用者,服务提供商在一开始就会先签好退出 PoS 证明并将此证明交给使用者,如此使用者就随时都可以选择退出 PoS,不受服务提供商影响。

运作细节

但因为退出 PoS 的签名内容包含当前网络(硬分叉)版本,例如当前的 Shanghai 或前一版的 Capella。而网络会比对「退出证明里的硬分叉版本」和「网络当前的版本」,如果版本差异在两个版本以上就会视为无效。也就是说随着网络不断更新,进行硬分叉、升级到新版本后,太旧的退出证明就会无效。

例如目前共识层的硬分叉版本从旧到新分别是 Altair、Bellatrix 及(目前的)Capella。那在 Altair 那时签的退出证明在现在就会变成无效;如果接下来更新至下一个版本 Deneb,那在 Altair、Bellatrix 那时签的退出证明就会变成无效。为了应付这种状况,使用者每次硬分叉时就要向服务提供商重新索取一次退出证明,如果使用者没有提前拿到退出证明,那硬分叉后服务提供商就可能可以以「不退出 PoS」威胁敲诈使用者。

注:不过因为「退出 PoS」是在 Capella 之后才开放,所以可能没有什么人提前在 Altair 或 Bellatrix 就签退出证明。

所以 EIP-7044 将退出证明里的硬分叉版本固定在 Capella,如此在当前这个版本所签的所有退出证明都将永久有效。而未来不管更新几次,退出证明里也都是签 Capella,不会再受硬分叉版本所影响。

注意事项

  • 因为退出证明的硬分叉版本已经固定在 Capella,所以如果有验证者或服务提供商提前就签了 Deneb 版的退出证明,在 Deneb 后反而会变成无效

EIP-7045

EIP-7045 延长验证者们的投票(Attestation)有效期,让投票有更充足的时间能被收入,增加网络的稳定性。对一般使用者或验证者无影响。

背景

原本验证者的投票(Attestation)有一个 Epoch(32 个 Slot)的时间可以被收入,例如假设验证者 Alice 被分派在 Slot 10000 进行投票,而她因为网络等待时间问题可能到了 Slot 10010 才完成投票或到了 Slot 10020 投票才成功广播到 p2p 网络中,但她的投票都还是会被收入。不过如果她的投票到 10033 Slot 才出现,那就没办法收录她的投票,视同没有投票。

运作细节

EIP-7045 将投票收录的有效期限延长至最晚「投票的下一个 Epoch 结束前」都有效。例如假设验证者 Alice 被分派在 Epoch 100 的 Slot 3205 进行投票,在 EIP-7045 之前,她的投票有效期限最晚是到 Slot 3237 (3237 = 3205 + 32);在 EIP-7045 之后,她的投票最晚到 Epoch 101 结束前(也就是 Slot 3263)都可以被收录。

注:Epoch 0 包含的 Slot 是 0 到 31;Epoch 100 包含的 Slot 是 3200 到 3231;Epoch 101 包含的 Slot 是 3232 到 3263。

EIP-7514

背景

从 2023 年上海升级开放验证者退出 PoS 后,反倒吸引更多使用者加入成为验证者,导致验证者等待序列(Entry Queue)总是处于爆满状态,总验证者数量也不断高速上升。

Ethereum Dencun 硬分叉内容介绍 - 09.png

Entry Queue 从开放退出 PoS 后反而激增。source: https://www.validatorqueue.com/

如果验证者等待序列持续维持满载的状态,则从 2023 年 9 月(EIP 提出时)到 2024 年 5 月,约八个月的时间,就会有 50% 的 ETH 都将质押进 PoS;到了 2024 年 9 月就会有 75% ETH 质押。这么多 ETH 质押有几个缺点,例如验证者数量太多,造成验证者投票及聚合签章数量太多,增加验证者 p2p 网络的负担及共识链的状态膨胀。另外也有人觉得 Ethereum 所需要的安全性并不需要这么多 ETH 质押,多质押的 ETH 从安全性的角度是浪费。

而为什么会持续有这么多 ETH 涌入呢?因为即便到了 100% ETH 都质押,年化率仍然有约 1.6%,而且 Liquid Staking Token(LST)的出现近一步的提高资本利用效率,再加上 MEV 的收益,种种因素都让质押变成一个非常吸引人的选项。

所幸质押热潮在 2023 年下半年逐渐退去,减缓了验证者数量成长的速度。

Ethereum Dencun 硬分叉内容介绍 - 10.png

2023 年下半年验证者数量成长放缓,在 2024 年 2 月时约有 25% 左右 ETH 质押。source: https://www.validatorqueue.com/

运作细节

原本 Entry Queue 的数量上限是随着当前验证者人数而变动,每增加或减少 65536 个验证者,Entry Queue 的数量上限就会增加或减少 1。2024 年 2 月的 Entry Queue 数量上限是 14 个(当前验证者数量约为 95 万)。

EIP-7514 会将 Entry Queue 数量上限固定在 8,不再随着当前验证者人数增加而提高,藉此减缓验证者数量成长的速度,让社群有更多时间能想出长期的解法,例如下一个硬分叉可能会收入的 EIP-7251

EIP-4844 与 EIP-7516

EIP-4844 新增新的交易种类,一个专门用来放 Blob 数据的交易。透过将数据放在 Blob 里,Rollup 将可以进一步降低交易手续费。

EIP-4844 并非作为进行扩容升级的改动,而更像是「提升区块 Gas Limit」并「降低成本」,让区块可以放入更多(Rollup)交易的一种提升交易量的改动。但 EIP-4844 同时也是为真正的扩容方案 – Danksharding 在进行铺路。

另外 Blob 交易会和一般交易会是分开独立的手续费市场,各自有各自的 Base Fee 及 Priority Fee,所以 EIP-7516 为 Blob 交易的手续费市场新增一个 BLOBBASEFEE Opcode(作用等同于一般交易的 BASEFEE Opcode),让 Rollup 合约可以透过这个 Opcode 得知该 Blob 的 Base Fee 是多少。

总结与重点

  • Dencun 硬分叉由共识层的 Deneb 硬分叉及执行层的 Cancun 硬分叉所组成
  • 本次升级的主角是 EIP-4844,引入 Blob 交易格式让 Rollup 能进一步降低交易成本,并同时为 Danksharding 铺路
  • 共识层的改动包含 EIP-7044、EIP-7045 与 EIP-7514
  • EIP-7044 让使用非托管质押服务的验证者在选择退出 PoS 时能不受未来硬分叉所影响
  • EIP-7045 及 EIP-7514 可视为增加 PoS 网络稳定性的更新
  • 执行层改动包含 EIP-1153、EIP-4788、EIP-5656、EIP-6780 与 EIP-7516
  • EIP-1153 让许多合约设计模式上能节省不少 Gas;EIP-5656 也是让 Gas 成本能稍微降低
  • EIP-4788 让执行层能以不需信任第三方的方式读取到共识层的信息,开启更多质押相关服务的可能性
  • EIP-6780 则是进一步淘汰 SELFDESTRUCT,拿掉它「移除合约代码及状态」的能力
  • 开发者需要注意使用 EIP-1153 时不要仰赖「暂时 Storage 在交易后会被清空」的假设,以及如果有使用到 SELFDESTRUCT,务必留意自己的合约会不会受影响
  • 一般使用者不需特别留意,只要等到 Rollup 采用 Blob 交易后就能享受到更低的交易成本

参考数据与推荐延伸阅读

EIP-1153

EIP-4788

EIP-5656

EIP-6780

EIP-7044

EIP-7514

EIP-4844 & EIP-7516