refactor(spec-specs): add opcode gas constants#2396
refactor(spec-specs): add opcode gas constants#2396SamWilsn merged 63 commits intoethereum:forks/amsterdamfrom
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## forks/amsterdam #2396 +/- ##
===================================================
+ Coverage 86.26% 86.47% +0.21%
===================================================
Files 599 599
Lines 37038 37632 +594
Branches 3795 3795
===================================================
+ Hits 31949 32542 +593
- Misses 4525 4526 +1
Partials 564 564
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Awesome! cc @raxhvl, since this was directly mentioned in the gas-lighters call today. |
|
All failing tests are due to #2109, and unrelated to the changes in this PR: It should be ok for us to proceed to review -> merge. |
marioevz
left a comment
There was a problem hiding this comment.
Looks good to me, considering we are not touching opcodes that use GAS_BASE, which I'm guessing is because the amount of changes would grow even more, and it's not necessary for the gas repricings at the moment, we could leave it for a future PR if it becomes necessary IMO.
I just left a couple of comments and leave the approval to Sam when he returns.
SamWilsn
left a comment
There was a problem hiding this comment.
Looks good to me! Is the intent to make these constants modifiable at runtime? If so, there's some additional nonsense you need to do because Python.
bcf06ad to
4fb062e
Compare
Carsons-Eels
left a comment
There was a problem hiding this comment.
Regarding Louis' comment about constants in Frontier; I pushed a change that moves the 8 GAS_OPCODE_* fields that don't exist until after Frontier (SHL, SHR, SAR, RETURNDATACOPY, BLOBHASH, MCOPY, CLZ) to dataclass defaults and then initialize them via replace() where the fork introduces new terms. Frontier no longer references them.
I think we could do the same thing for the other 23 non-opcode constants that are zero-initialised in Frontier but aren't used until later forks:
Byzantium: GAS_PRECOMPILE_ECADD, GAS_PRECOMPILE_ECMUL, GAS_PRECOMPILE_ECPAIRING_BASE, GAS_PRECOMPILE_ECPAIRING_PER_POINT
Istanbul: GAS_PRECOMPILE_BLAKE2F_BASE, GAS_PRECOMPILE_BLAKE2F_PER_ROUND
Berlin: GAS_TX_ACCESS_LIST_ADDRESS, GAS_TX_ACCESS_LIST_STORAGE_KEY
Cancun: GAS_PRECOMPILE_POINT_EVALUATION
Prague: GAS_TX_DATA_TOKEN_STANDARD, GAS_TX_DATA_TOKEN_FLOOR, GAS_AUTH_PER_EMPTY_ACCOUNT, REFUND_AUTH_PER_EXISTING_ACCOUNT, GAS_PRECOMPILE_BLS_G1ADD, GAS_PRECOMPILE_BLS_G1MUL, GAS_PRECOMPILE_BLS_G1MAP, GAS_PRECOMPILE_BLS_G2ADD, GAS_PRECOMPILE_BLS_G2MUL, GAS_PRECOMPILE_BLS_G2MAP, GAS_PRECOMPILE_BLS_PAIRING_BASE, GAS_PRECOMPILE_BLS_PAIRING_PER_PAIR
Osaka: GAS_PRECOMPILE_P256VERIFY
Amsterdam: GAS_BLOCK_ACCESS_LIST_ITEM
None of these are referenced in Frontier, and they're already set by replace() by the fork that introduces them; they'd just also get = 0 defaults on the dataclass. Frontier doesn't need to mention them at all. This would follow along the same lines as the adjustment I made for Louis' comment, but that predates this PR, so I'd rather get feedback first. We're kind of already here though, so might as well if it feels right.
Thoughts? @LouisTsai-Csie @marioevz
9fa8094 to
1c9af18
Compare
|
opitonal nit: rename To ensure consistency with |
30525d8 to
e9f2c37
Compare
|
I updated |
SamWilsn
left a comment
There was a problem hiding this comment.
This is packages/** and src/ethereum/forks/amsterdam/**, and the occasional comment elsewhere.
SamWilsn
left a comment
There was a problem hiding this comment.
That's all of it, quickly read.
…CODE_EXP_PER_BYTE
…E_KECCAK256_PER_WORD
…E_KECCAK256_PER_WORD
…ACCOUNT=>OPCODE_SELF_DESTRUCT_NEW_ACCOUNT
… repricing mechanism.
24762c1 to
c612ae4
Compare
Looks like the change was made.
🗒️ Description
Currently, multiple opcodes share the same gas tier constant (e.g. DIV, SDIV, MOD, SMOD, MUL all reference
GAS_LOW = Uint(5)). This makes it impossible to reprice individual opcodes because changingGAS_LOWwould affect all of them at once. EIP-7904 - General Repricing requires per-opcode repricing (e.g. DIV=15, SDIV=20, MOD=12 while MUL stays at 5).This PR adds per-opcode gas constants (
OPCODE_*) to all 24 forkgas.pymodules and updates instruction files to use them instead of shared tier constants (VERY_LOW,LOW,MID,HIGH), and likewise makes the same changes to the test code by adding counterpart gas constants to the GasCosts dataclass.It introduces intermediate variables like
OPCODE_DIV = LOWin each fork'sgas.pyand updates instruction files to charge against the opcode-specific constant. The existingapply_spec_repricing()mechanism (from #2331) can then targetOPCODE_DIVdirectly in the JSON config, enabling per-opcode repricing without changing spec code.What changed:
Spec side:
OPCODE_*variable definitions (varying by fork based on available opcodes)OPCODE_*constants for BASE-tier opcodes (OPCODE_POP,OPCODE_MSIZE,OPCODE_ADDRESS,OPCODE_TIMESTAMP,OPCODE_GASLIMIT, etc.) plus fork-specific constants (OPCODE_DIFFICULTYpre-Paris,OPCODE_PREVRANDAOParis+,OPCODE_RETURNDATASIZEByzantium+,OPCODE_CHAINIDIstanbul+,OPCODE_BASEFEELondon+,OPCODE_BLOBBASEFEECancun+,OPCODE_PUSH0Shanghai+)charge_gas()calls to use opcode-specific constantsfork.pyfiles: movedGAS_LIMIT_ADJUSTMENT_FACTORandGAS_LIMIT_MINIMUMintoGasCosts(minusGAS_prefix); updatedcheck_gas_limit()referencestransactions.pyfiles: movedGAS_TX_BASE,GAS_TX_CREATE,GAS_TX_DATA_PER_*,GAS_TX_ACCESS_LIST_*intoGasCosts(minusGAS_prefix); removed module-level definitions and RST docstrings; used lazy imports where circular dependencies existvm/eoa_delegation.pyfiles (Prague+): movedGAS_AUTH_PER_EMPTY_ACCOUNTintoGasCostsasAUTH_PER_EMPTY_ACCOUNTcharge_gas(evm, GasCosts.BASE)calls with namedGasCosts.OPCODE_*constantsTesting side:
gas_costs.py: added 39OPCODE_*fields toGasCostsdataclassforks.py: updatedFrontier.gas_costs()initialization andopcode_gas_map()in Frontier + 4 fork overrides (Byzantium, Constantinople, Cancun, Osaka) to reference per-opcode fieldsNo behavioural changes — all variables default to their original tier constant values
Fork groups by opcode availability:
🔗 Related Issues or PRs
❓ Further Questions
OPCODE_BALANCE, post-Berlin they go from a static cost to a dynamic cost. I've left them in the dynamic section for now, but with the static naming. Treating them differently depending on the fork will cause ordering issues thatethereum-spec-lintwill complain about. Which to pick, or is there a better option?✅ Checklist
toxchecks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:uvx tox -e statictype(scope):.apply labels).
type(scope):.