首页 > 中国比特币 > 柏林硬分叉如何影响以太坊交易的 Gas 费开销?
2024
08-23

柏林硬分叉如何影响以太坊交易的 Gas 费开销?

私募比特币

以及 EIP-2930 引进的拜访清单(Access List)功用应坐山观虎斗运用?

原文标题:《干货 | 搞懂 “柏林” 之后的合约 Gas 开支》 撰文:Franco Victorio 翻译 AMPL 校正:阿剑「柏林」硬分叉已于 4 月 15 日激活,该硬分叉所包括 EIP 中的两个(EIP-2929 和 EIP-2930)都会影响业务的 Gas 开支。本文会解说 “柏林” 激活之前,一些操作码的 Gas 耗费量是坐山观虎斗核算的,而 EIP-2929 对此有何影响,以及,2930 引进的拜访清单(Access List)功用应坐山观虎斗运用。 摘要 这篇文章很长,你要是只想知道定论,看完这部分就能够把网页关掉了:

  • 柏林硬分叉改动了某些操作码的 Gas 开支。假定你在自己的运用中硬编码了一些操作可运用的 Gas 数量,这些操作或许会卡死。假定真的呈现了这种状况,而你的智能合约又是无法晋级的,用户就需求运用 “拜访清单” 功用来运用你的运用。
  • 拜访清单功用可稍微削减 Gas 开支,但有些时分也或许会进步总的 Gas 耗费量。
  • geth 客户端引进了一种新的 RPC 办法,叫做 eth_createAccessList 来简化拜访清单的生成。

「柏林」晋级曾经的 Gas 开支 EVM 所履行的每一个操作码都有一个对应的 Gas 耗费量。大部分操作码的耗费量都是固定的:PUSH1 总是耗费 3 gas,而 MUL 耗费 5 gas,等等。有一些操作码的耗费量是可变的:举个比方,SHA3 操作码的开支由输入值的长度决议。咱们先了解 SLOADSSTORE 操作码,由于这两个操作码受 “柏林” 影响最大。后边咱们会再谈谈那些以地址为方针的操作,比方一切的 EXT* 类操作码和 CALL* 类操作码,由于它们的 Gas 开支也被改动了。 「柏林」 曾经的SLOAD 在 EIP-2929 施行前,SLOAD 开支的核算办法很简单:总是耗费 800 gas。所以,也没啥可打开的。 「柏林」曾经的SSTORE** 要讲到 Gas 耗费量的核算,SSTORE 操作码或许是最杂乱的了。由于耗费多少取决于该存储项槽当时的值、要写入的新值、该存储项是否现已修正正。咱们只会剖析少量几种场景,了解个大约。假定你想了解更多,请阅览本文结尾所附的 EIP 链接。

  • 假定存储项的值从 0 改为 1 (或许恣意非零的值),Gas 耗费量是 20000
  • 假定存储项的值从 1 改为 2 (或许恣意非零的值),Gas 耗费量是 5000
  • 假定存储项的值从 1 (或恣意非零的值) 改为 0,耗费量也是 5000,但你会在业务履行完毕后取得 gas 补助。咱们这儿也不评论 gas 返还机制,由于它不会遭到柏林的影响
  • 在一笔业务中,假定存储项已不是第一次修正,则后续每一次 SSTORE 都耗费 800 gas

细节在这儿并不重要,重要的是,SSTORE 是贵重的,详细耗费多少 gas 则依赖于多个要素。 EIP-2929 之后的 Gas 耗费量 EIP-2929 改动了一切这些数值。但在打开之前,咱们要先谈谈该 EIP 引进的一个重要概念:被拜访过的地址被拜访过的存储项的键(storage key)。当一个地址或许一个存储项的键,在一笔业务中被 “运用过” 之后,在该笔买卖余下的履行进程中,这个地址(或许这个键)都会被当成 “已被拜访过的”。举个比方,假定你在一笔业务中 CALL (调用)另一个合约,那么该合约的地址就会被标记为 “拜访过的”。类似地,假定你 SLOAD 或许 SSTORE 过一些存储项槽 ,在该笔业务余下的履行进程里,这些槽也会被当成现已拜访过的。究竟用的哪个操作码是没有关系的,即便你只 SLOAD 过某个槽,接下来运用 SSTORE 时该槽也会被当成已拜访过的。留意:存储项的键是 “内在于” 某些地址中的,一如该 EIP 所解说的:

履行业务时,坚持一个调集:accessed_addresses: Set[Address] 以及 accessed_storage_keys: Set[Tuple[Address, Bytes32]]

也便是说,当咱们说某个存储槽已被拜访过了,咱们的实践意思是:(address, storageKey) 已被拜访过了。搞清楚了这个概念,咱们来谈谈新的 Gas 耗费量核算方式。 「柏林」今后的SLOAD 晋级前,SLOAD 的 Gas 耗费量是固定的 800。但晋级后,Gas 耗费量要看这个存储槽是否现已被拜访过。还没拜访过的,耗费量便是 2100 gas;拜访过的,便是 100 gas。所以,假定某个存储项槽现已在 “已拜访过的存储项键 ` 的调集里了,就能够 掉 2000 gas。 「柏林」今后的SSTORE 咱们逐一逐一对比下,在 EIP-2929 施行后,上面的几个比方会产生什么样的改动:

  • 假定存储项的值从 0 改为 1 (或许恣意非零的值),Gas 耗费量是 20000
    • 假定该存储项键还未拜访过,耗费 22100 gas
    • 若已拜访过,耗费 20000 gas
  • 假定存储项的值从 1 改为 2 (或许恣意非零的值),Gas 耗费量是 5000
    • 假定该存储项键还未拜访过,耗费 5000 gas
    • 若已拜访过,耗费 2900 gas
  • 假定存储项的值从 1 (或恣意非零的值) 改为 0,耗费量坚持不变,gas 返还机制也不变
  • 在一笔业务中,假定存储项已不是第一次修正,则后续每一次 SSTORE 都耗费 100 gas

由此可见,假定某个槽此前已拜访过,则对它的第一次 SSTORE 操作会节约 2100 gas (比较于从未拜访过)。 汇总一下 上面的文字真实烦琐,咱们就直接做一张表,把上面说到的值都汇总一下:柏林硬分叉如何影响以太坊交易的 Gas 费开销? - 第1张  | 比特币-比特币价格-比特币行情交易交流平台留意看最终一行:此刻已不再需求区别它究竟有没有被拜访过,由于,假定此前已写入,则必定已被拜访过。 EIP-2930:可选 「拜访清单」的业务类 另一个 “柏林” 晋级包括的 EIP 是 2930。该 EIP 参加了一种新的类的业务,能够在业务的负载中包括一个 “拜访清单”,意思是,你能够在业务履行前就声明哪些地址和存储槽应被认为是 “拜访过的”。举个比方,对一个未拜访过的槽履行 SLOAD 需求耗费 2100 gas,但假定该存储槽被包括在了业务的 “拜访清单” 中,则操作的耗费量时机降为 100 gas。但假定只需地址和槽被当成 “已拜访过的” 就能够下降操作的 Gas 耗费量;而拜访清单能够把地址和槽标记为 “已拜访过的”;那岂不是说咱们能够把这些东西都放在拜访清单中,来取得 Gas 耗费量的减免?真棒,天赐 Gas!额,并不彻底如此,由于你每增加一个地址或存储项键,都要付出额定的 Gas。举个比方。假定咱们要向合约 A 发送了一条业务。咱们编写了一条这样的拜访清单:柏林硬分叉如何影响以太坊交易的 Gas 费开销? - 第2张  | 比特币-比特币价格-比特币行情交易交流平台假定咱们发送了一条带有这条拜访清单的业务,而运用 0x0 存储槽的第一个操作码便是 SLOAD,则 Gas 耗费量会是 100 而非 2100,也便是减免了 2000 gas。可是,在拜访列表中声明一个存储项键需求额定付出 1900 gas,所以咱们只节约了 100 gas。(假定对该存储槽的第一个操作是 SSTROE,咱们在单个操作中就 下了 2100 gas,也便是一共 下了 200 gas,由于拜访清单本身需求耗费 gas)。这是不是说,每次运用拜访清单咱们都能节 gas 呢?很惋惜,也不是,由于在拜访清单中填入地址也需求付出 gas。(也便是咱们示例中的 "") 拜访过的地址 迄今为止,咱们只评论了 SLOADSSTORE 操作码,但 “柏林” 晋级还改动了其他操作码。举个比方,CALL 操作码本来的 Gas 耗费量为固定的 700,但 2929 施行后,假定所调用的地址不在拜访清单中,耗费量将进步到 2600;假定在,则下降为 100。并且,就像拜访过的存储键相同,究竟哪个操作码拜访过那个地址并不重要(比方,假定用户最早调用的是 EXTCODESIZE,这一个操作的耗费量是 2600,但后续的调用,只需是对同一个地址的,无论是 EXTCODESIZECALL 仍是 STATICCALL ,都只耗费 100 gas。那个这个规划对带有拜访清单的业务有何影响?假定咱们向合约 A 发送一条买卖,而合约 A 调用了合约 B,而咱们在拜访清单中写入这样的内容:柏林硬分叉如何影响以太坊交易的 Gas 费开销? - 第3张  | 比特币-比特币价格-比特币行情交易交流平台咱们首要需求为在这条业务的拜访清单中参加这个地址付出 2400 gas,但对 B 运用的第一个操作码就只需求耗费 100 gas 而不是 2600 gas,这就剩下了 100 gas。假定 B 也需求运用其存储项,咱们又知道它将运用哪个键,咱们也能够把这些键包括在拜访列表中,然后为每个键的操作 下 100 或 200 gas (取决于第一个操作码是 SLOAD 仍是 SSTORE)。但为啥咱们要加多一个合约来举比方?咱们不是能够这样写吗?柏林硬分叉如何影响以太坊交易的 Gas 费开销? - 第4张  | 比特币-比特币价格-比特币行情交易交流平台你当然能够这样做,但不值得,由于 EIP-2929 指明晰你一开端调用的合约(也便是 tx.to 的意图地)必定会被包括在 accessed_addresses 列表中,所以你便是额定花了 2400 gas,什么优点都没得到。所以,回头看咱们上面举的比方:柏林硬分叉如何影响以太坊交易的 Gas 费开销? - 第5张  | 比特币-比特币价格-比特币行情交易交流平台这样做其实是糟蹋,除非你在里面加多几个存储项键。假定咱们假定一切的存储项键的第一个操作都是 SLOAD,那你要至少 24 个键,才干赚回来。并且,如你所见,自己如数家珍地剖析这些要素、手动生成拜访清单,显然是极端繁琐而令人溃散的事。好在,还有更好的办法。eth_createAccessList RPC 办法 Geth 客户端(从 1.10.2)开端将包括一个新的 eth_createAccessList RPC 办法,你能够用它来生成拜访清单,就像运用 eth_estimateGas 相同,只不过回来的不是 Gas 耗费量估量,而是形如这样的数据:柏林硬分叉如何影响以太坊交易的 Gas 费开销? - 第6张  | 比特币-比特币价格-比特币行情交易交流平台也便是告知你一笔业务将会用到的地址和存储项键的清单,以及,_假定归入这份拜访清单_将耗用多少 gas。跟 eth_estimateGas 相同,这也是估量出来的,该笔业务真正上链时,会拜访到哪些数据仍有或许改动。可是,再说一遍,这绝不意味着你只需运用了拜访清单,所用的 Gas 就会比不必清单更少!我估量跟着时间推移,咱们会越来越知道怎样运用这个功用,但我个人估量,办法的伪代码方式会像这样:柏林硬分叉如何影响以太坊交易的 Gas 费开销? - 第7张  | 比特币-比特币价格-比特币行情交易交流平台 避免合约变砖 值得提示,拜访清单功用的首要意图不是节 Gas。如该 EIP 本身所述:

缓解由 EIP-2929 带来的合约变砖危险,由于业务能够预先指定、预先付出本身测验范文的账户和存储槽,因而,在实践的履行中,SLOAD 和 EXT* 操作码都只会耗费 100 gas:这个值低到既足以避免 2929 打破某些合约,也能够 “解封” 被 EIP-1884 封印的合约。

本来,只需一个合约预设了履行的 Gas 开支,操作码的 Gas 耗费量变化就有或许导致它变砖。比方,假定一个合约预设另一个合约的 someFunction 只会用到 34500 gas,因而总是用 someOtherContract.someFunction{gas: 34500}() 调用那个合约,这个合约就有或许变砖。但只需你在业务中增加适宜的拜访清单,这个合约就还能作业。自己验证 假定你想自己测验一下,克隆这个库房,这儿面有许多比方,能够运用 Hardhat 和 Geth 客户端来运转。请仔细阅览 README。

参阅文献

  • EIP-2929 和 EIP-2930 是两个跟本文有关的 “柏林” EIP。
  • EIP-2930 依赖于 “柏林” 晋级归入的另一个 EIP:EIP-2718,也叫标准化的业务信封。
  • EIP-2929 很多参阅了 EIP-2200,假定你想更深化地了解 Gas 耗费量,你应该从那里开端。

来历链接:hackmd.io

最后编辑:
作者:币云谷
头像
这个作者貌似有点懒,什么都没有留下。

柏林硬分叉如何影响以太坊交易的 Gas 费开销?》有 0 条评论

留下一个回复

你的email不会被公开。