Gas 成本估算器项目是此 EIP 的经验基础。该项目在七个广泛使用的 EVM 实现中进行了广泛的测试,以测量各种操作码和操作所需的实际计算工作量。在受控环境中进行,以消除外部变量,这些测试产生了准确且可重现的结果。发现突出了当前 gas 成本计划与 EVM 操作的实际计算复杂度之间的不一致。通过根据这些测量结果重新校准 gas 成本,此 EIP 旨在使定价与计算现实保持一致,从而提高以太坊的性能和弹性。
此 EIP 基于 Gas 成本估算器项目的激进的提案。这意味着所有估算值都已额外重新调整,以便基本算术运算仅花费 1 个 gas 单位。使用的 rescale factor 是 Gas 成本估算器项目中定义的 0.217391304。将此提案与其他 EIP 或项目进行比较时,应使用此因子。
其他项目
一些计划已经探索了 EVM 操作的实际 gas 成本,为该 EIP 提供了有价值的背景信息。值得注意的例子包括:
降低计算 gas 成本旨在提高交易吞吐量,允许每个区块更多的交易。EIP-7783 和 EIP-7790 通过提高区块 gas 限制来追求类似的结果 - 一种影响可控的更简单方法。但是,它们不会解决定价错误的操作码和预编译。我们的提案通过纠正定价不准确来补充这些努力,并且应该一起实施这两种策略,以在确保成本准确性的同时最大化吞吐量。
两个存储操作码 SLOAD 和 STORE 已间接更新。它们的成本公式很复杂,并且仅修改了热/冷数据访问成本比率。CREATE 和 CREATE2 也是如此。仅修改了内存扩展成本因子,该因子是计算性的,并且与其他可能扩展内存的操作码一致。
预编译
对于 MODEXP 预编译,此提案假定采用 EIP-7883,并且其 gas 成本保持不变。对于 ECPAIRING,gas 成本降低了大约 5 倍,与此提案中的类似调整一致。ECRECOVER、IDENTITY、ECADD、ECMUL、BLAKE2F 和 POINTEVAL 等预编译要么保留其当前的 gas 成本,要么略有降低。
像 Nethermind 的 Gas 基准测试之类的项目强调了一个安全问题:降低 ECRECOVER 的 gas 成本可能会导致最坏的情况,即区块计算时间超过安全阈值。类似的问题适用于 MODEXP。因此,即使有进一步降低的空间,rescale factor 也不能低于提议的 0.217391304。请注意,区块中的最大操作数取决于 gas 成本计划和区块 gas 限制。
Gas 成本估算器项目建议略微增加 ECRECOVER 的 gas 成本,但此提案避免了该更改,以保持向后兼容性,并且因为影响很小。
由于提议的 gas 成本计划更改对其影响以太坊网络的操作机制,因此需要进行硬分叉。下面,我们概述了这些更改的主要后果,并重点介绍了需要进一步研究的领域,以确保平稳过渡。
这些变更具有以下后果:
Gas 成本调整:
将修改各种操作码、预编译和其他操作(例如内存扩展和访问成本)的 gas 成本。
这些调整旨在更好地使 gas 定价与操作的计算复杂度保持一致,但是它们将直接影响执行交易和智能合约的成本。
交易 Gas 成本变更:
调用合约的任何交易的 gas 成本都很可能会发生变化。
这是由于在智能合约代码中广泛使用了受影响的操作码和操作。
开发人员和用户应为硬分叉后交易费用的潜在变化做好准备,这可能需要更新 gas 限制估算和费用预算。
对具有硬编码 Gas 限制的合约的影响:
如果新的 gas 成本超过这些限制,则为子调用指定硬编码 gas 限制(例如,使用 call(gas, …))的合约可能会面临问题。
此类合约可能无法按预期执行,从而可能导致交易失败或意外行为。
可能需要进行进一步的研究,以确保不破坏使用硬编码限制的合约。
测试用例
测试 1
代码:
PUSH1 0x60
Gas 成本:1
测试 2
代码:
PUSH2 0x0202
PUSH2 0x1000
EXP
Gas 成本:1 + 1 + (2 + 4 * 2) = 12
TODO: 此 EIP 是一个相对简单的更改,但需要在许多测试(规范、执行 API 等)中进行更新。由于更新测试需要付出努力,因此只有在 EIP 被接受后才能提供
参考实现
Go-Ethereum 中的参考实现提供了新的指令集和新的 memoryGasCost 函数。此外,它还包含一组特定 gas 元素的替代项。实际的实现需要对替代项进行正确的版本控制。
const(RepricedGasBaseStepuint64=1RepricedGasFastStepuint64=2RepricedGasMidStepuint64=3//overridesWarmStorageReadCostuint64=100// WARM_STORAGE_READ_COSTExpGasuint64=2// Once per EXP instructionExpByteGasuint64=4// One per byte of the EXP exponentCopyGasuint64=1// One per word of the copied code// (CALLDATACOPY, CODECOPY, EXTCODECOPY,// RETURNDATACOPY, MCOPY))funcnewRepricedInstructionSet()JumpTable{instructionSet:=newPragueInstructionSet()// 重新定价的指令集instructionSet:=newPragueInstructionSet()for_,op:=rangeinstructionSet{ifop.isPush||op.isDup||op.isSwap||op.constantGas==GasFastestStep||op.constantGas==GasFastStep{op.constantGas=RepricedGasBaseStep}}instructionSet[ADDMOD].constantGas=RepricedGasFastStepinstructionSet[MULMOD].constantGas=RepricedGasMidStepinstructionSet[TLOAD].constantGas=WarmStorageReadCostinstructionSet[TSTORE].constantGas=WarmStorageReadCostvalidateAndFillMaxStack(&instructionSet)returninstructionSet}funcmemoryGasCost(mem*Memory,newMemSizeuint64)(uint64,error){ifnewMemSize==0{return0,nil}ifnewMemSize>0x1FFFFFFFE0{return0,ErrGasUintOverflow}newMemSizeWords:=ToWordSize(newMemSize)newMemSize=newMemSizeWords*32ifnewMemSize>uint64(mem.Len()){square:=newMemSizeWords*newMemSizeWordsnewTotalFee:=square/params.QuadCoeffDivfee:=newTotalFee-mem.lastGasCostmem.lastGasCost=newTotalFeereturnfee,nil}return0,nil}
安全考虑事项
与此提案相关的主要风险是潜在的 DoS 攻击。通过降低 gas 成本,该提案可能会无意中使某些操作更经济实惠,从而使攻击者可以出于恶意目的利用它们。为了缓解此风险,该提案侧重于降低定价过高的操作的 gas 成本,确保调整不会损害网络安全性。通过维持操作的相对成本,该提案确保即使在最坏的情况下,降低的价格也不会产生新的漏洞。