feat(test-specs): Allow automatic transaction gas-limit - #2969
Conversation
kclowes
left a comment
There was a problem hiding this comment.
Berlin-Frontier look good to me. This is such a nice change!
|
@marioevz I think there are places where we are setting Transaction(gas_limit=None) but setting it to a variable that can be |
|
|
I think there are no unit tests for with_gas_limit, _calculate_implicit_gas_limit, calculate_max_gas_limit and state_gas_reservoir. Perhaps we don't need it because they are called from other tests. |
Co-authored-by: Leo Lara <leolara@users.noreply.github.com>
Nice catch, uploaded a new commit a2e13fb. Just as a side note, I think this specific tests need an update because they are no longer really accurate (they hard-code assumed gas costs for the system contracts, which no longer hold). |
|
Once @spencer-tb signs off we can proceed to merge. |
spencer-tb
left a comment
There was a problem hiding this comment.
Did a final check this morning! All LGTM :)
#2984 feels appropriate to me too. Lets merge!
`test_code_deposit_oog_preserves_parent_reservoir` forwards a fixed `child_gas` to the factory via `Op.CALL`. After the factory's CREATE takes 63/64, the retained 1/64 (~15k from 1M) no longer covers its repriced post-CREATE SSTOREs (~21k), so the factory halted before its `parent_sstore` and the expected storage write disappeared. Raise the in-bytecode `child_gas` 1000000 -> 1500000; the factory then retains ~23k. The code-deposit OOG premise (deploy size 4096, deposit state gas 6.27M) is unaffected. PR ethereum#2969 auto-sizes the transaction gas limit but not a `CALL` gas argument inside contract code, so this budget is re-tuned by hand.
PR ethereum#2969 computes the transaction gas limit automatically and adds a state-gas reservoir on EIP-8037 forks. These 71 files set an explicit transaction gas_limit that was incidental: it sufficed on older forks, but on Amsterdam the state-gas component pushed the transaction over its budget and broke the test. Leaving the gas limit unset gives each transaction the implicit limit plus reservoir, which restores the recorded full-execution behaviour. Drop the transaction gas_limit from these files, together with the helpers it orphaned (tx_gas lists, an intrinsic-gas computation) and three now-unused fork-conditional bumps that the unset limit supersedes. Filling them on Amsterdam passes every variant with no residual failures, so remove their 123 entries from amsterdam_skip_list.txt. Total 437 down to 314.
PR ethereum#2969 computes the transaction gas limit automatically and adds a state-gas reservoir on EIP-8037 forks. These 69 files set an explicit transaction gas_limit that was incidental: it sufficed on older forks, but on Amsterdam the state-gas component pushed the transaction over its budget and broke the test. Leaving the gas limit unset gives each transaction the implicit limit plus reservoir, which restores the recorded full-execution behaviour. Drop the transaction gas_limit from these files, together with the helpers it orphaned (tx_gas lists, an intrinsic-gas computation) and three now-unused fork-conditional bumps that the unset limit supersedes. Filling them across every valid fork passes all variants with no residual failures, so remove their 116 entries from amsterdam_skip_list.txt. Total 437 down to 321.
`test_code_deposit_oog_preserves_parent_reservoir` forwards a fixed `child_gas` to the factory via `Op.CALL`. After the factory's CREATE takes 63/64, the retained 1/64 (~15k from 1M) no longer covers its repriced post-CREATE SSTOREs (~21k), so the factory halted before its `parent_sstore` and the expected storage write disappeared. Raise the in-bytecode `child_gas` 1000000 -> 1500000; the factory then retains ~23k. The code-deposit OOG premise (deploy size 4096, deposit state gas 6.27M) is unaffected. PR ethereum#2969 auto-sizes the transaction gas limit but not a `CALL` gas argument inside contract code, so this budget is re-tuned by hand.
`test_code_deposit_oog_preserves_parent_reservoir` forwards a fixed `child_gas` to the factory via `Op.CALL`. After the factory's CREATE takes 63/64, the retained 1/64 (~15k from 1M) no longer covers its repriced post-CREATE SSTOREs (~21k), so the factory halted before its `parent_sstore` and the expected storage write disappeared. Raise the in-bytecode `child_gas` 1000000 -> 1500000; the factory then retains ~23k. The code-deposit OOG premise (deploy size 4096, deposit state gas 6.27M) is unaffected. PR ethereum#2969 auto-sizes the transaction gas limit but not a `CALL` gas argument inside contract code, so this budget is re-tuned by hand.
PR ethereum#2969 made the transaction gas limit automatic. On EIP-8037 forks the implicit limit now carries a state-gas reservoir, so tests that leave the transaction gas limit unset receive enough headroom and stop running out of gas under the two-dimensional gas model. Filling tests/ported_static/ for Amsterdam without the skip list shows 33 of these entries pass across all fixture variants. Remove them from amsterdam_skip_list.txt and recompute the per-section counts and the total, from 480 down to 447. Two sections become empty and are dropped, stCallDelegateCodesHomestead and stRecursiveCreate. Most of the cleared cases are the _suicide_end family. They set only the environment gas limit and rely on the implicit transaction gas limit, so the reservoir restores their pre-Amsterdam behaviour.
PR ethereum#2969 computes the transaction gas limit automatically and adds a state-gas reservoir on EIP-8037 forks. These 69 files set an explicit transaction gas_limit that was incidental: it sufficed on older forks, but on Amsterdam the state-gas component pushed the transaction over its budget and broke the test. Leaving the gas limit unset gives each transaction the implicit limit plus reservoir, which restores the recorded full-execution behaviour. Drop the transaction gas_limit from these files, together with the helpers it orphaned (tx_gas lists, an intrinsic-gas computation) and three now-unused fork-conditional bumps that the unset limit supersedes. Filling them across every valid fork passes all variants with no residual failures, so remove their 116 entries from amsterdam_skip_list.txt. Total 437 down to 321.
…2996) * chore(tests): unskip ported_static cases now passing on Amsterdam PR #2969 made the transaction gas limit automatic. On EIP-8037 forks the implicit limit now carries a state-gas reservoir, so tests that leave the transaction gas limit unset receive enough headroom and stop running out of gas under the two-dimensional gas model. Filling tests/ported_static/ for Amsterdam without the skip list shows 33 of these entries pass across all fixture variants. Remove them from amsterdam_skip_list.txt and recompute the per-section counts and the total, from 480 down to 447. Two sections become empty and are dropped, stCallDelegateCodesHomestead and stRecursiveCreate. Most of the cleared cases are the _suicide_end family. They set only the environment gas limit and rely on the implicit transaction gas limit, so the reservoir restores their pre-Amsterdam behaviour. * chore(tests): drop obsolete ported_static skip entries on Amsterdam These 10 entries match no test collected on Amsterdam, so the conftest never skips anything for them. They are dead weight in the list. Eight are size-limit tests under stCodeSizeLimit and stEIP3860_limitmeterinitcode. They carry valid_before("EIP7954"), and Amsterdam includes EIP-7954, so pytest deselects them and they never reach the skip step. Both sections empty out and are dropped. Two are stCreateTest/test_create_address_warm_after_fail cases pinned to a create-code-too-big-v1 parametrization that no longer exists after the test was reparametrized. Recompute the section counts and the total, from 447 down to 437. * chore(tests): unset incidental tx gas_limit on 69 ported_static files PR #2969 computes the transaction gas limit automatically and adds a state-gas reservoir on EIP-8037 forks. These 69 files set an explicit transaction gas_limit that was incidental: it sufficed on older forks, but on Amsterdam the state-gas component pushed the transaction over its budget and broke the test. Leaving the gas limit unset gives each transaction the implicit limit plus reservoir, which restores the recorded full-execution behaviour. Drop the transaction gas_limit from these files, together with the helpers it orphaned (tx_gas lists, an intrinsic-gas computation) and three now-unused fork-conditional bumps that the unset limit supersedes. Filling them across every valid fork passes all variants with no residual failures, so remove their 116 entries from amsterdam_skip_list.txt. Total 437 down to 321. * chore(tests): unset g1 gas_limit on Amsterdam for no_src_account_create test_no_src_account_create and its 1559 variant assert an INSUFFICIENT_ACCOUNT_FUNDS rejection at gas index g1 (210000). On Amsterdam EIP-8037 raises the creation intrinsic gas above that budget, so the transaction is rejected for gas before the funds check and the assertion fails. Make the g1 budget fork-conditional: leave the gas limit unset on EIP-8037 forks, where the implicit limit plus reservoir clears the intrinsic and the intended funds rejection fires again. Earlier forks keep the original 210000. Filling across every valid fork passes all variants, so remove the 16 g1 entries from amsterdam_skip_list.txt. Total 321 down to 305. * chore(tests): fork-conditional gas unset for 8 more ported_static files Extend the per-parametrization fix from no_src_account_create to eight more mixed files. Each sets the skip-listed gas slot to None on EIP-8037, so that parametrization gets the implicit limit plus reservoir, while the other slots and earlier forks keep their explicit gas. These slots recorded a full-execution result that broke on Amsterdam when the state-gas component pushed the transaction over its budget. The stZeroKnowledge point_mul tests run out of gas because they SSTORE the precompile result, which EIP-8037 makes more expensive; the precompile call itself is unchanged, so unsetting restores the recorded success state. Filling across every valid fork passes all variants with no failures, so remove the 47 entries from amsterdam_skip_list.txt. Total 305 down to 258. * chore(tests): Port and remove failing stZeroKnowledge tests --------- Co-authored-by: marioevz <marioevz@gmail.com>
Co-authored-by: Leo Lara <leolara@users.noreply.github.com> Co-authored-by: danceratopz <danceratopz@gmail.com> Co-authored-by: spencer-tb <spencer.tb@ethereum.org>
🗒️ Description
Summary
While reviewing #2901 I noticed that the bulk of its test changes were simply bumping the
gas_limitof transactions in tests that don't actually care about the exact gas limit — they only care that the transaction executes in full without running out of gas.This PR makes the transaction
gas_limitoptional. When a test omits it, the filling/execution tooling calculates it automatically based on fork properties.Review Plan
Tests
Testing Framework
Tooling changes
Transaction.gas_limitnow defaults toNoneinstead ofHexNumber(21_000).Transaction.set_gas_limit()resolves an unset limit in place, and signing now raisesValueError("gas_limit must be set to sign a transaction")if the limit is still unset by the time the transaction is signed.This lead to many typing issues that have now been resolved, but it can be argued that a better choice is to leave
HexNumberas the type forTransaction.gas_limitand rely instead onmodel_fields_setto determine whether the gas limit has been set by the tester.BlockchainTestandStateTestFillersFor State tests (
StateTest), an unsetgas_limitis filled with the fork'stransaction_gas_limit_cap(), falling back to the environmentgas_limitwhen there is no cap.For Blockchain tests (
BlockchainTest), the block's remaining gas (env.gas_limitminus the gas already claimed by transactions with explicit limits) is split evenly across the transactions that leavegas_limitunset, clamped to the fork's transaction gas-limit cap. It raises a clear "test correctness" error if no gas remains.Execute Tests
The same logic is implemented for the execute path (
calculate_max_transaction_gas_limitinexecution/base.py, applied intransaction_post.pyandblob_transaction.py), so implicit gas limits work when running against a live client, not just during filling.It can be argued that there's a better path to resolve the transaction gas limit in the case of execute, such as:
eth_estimateGasand use the value returned, with the minor caveat that the contracts that the transaction requires have to be already on chain before calling this RPC method.Both methods require more work and could be implemented in a future PR.
State gas reservoir (EIP-8037)
Rather than special-casing EIP-8037 (
fork.is_eip_enabled(8037)), this PR introduces a fork-level concept:Fork.state_gas_reservoir_enabled()(alongside the existingtransaction_gas_limit_cap()), defaulting to False and turned on by EIP-8037, currently in Amsterdam.Transaction.state_gas_reservoirfield. When a fork enables the reservoir, the transaction gas-limit cap is treated as removed andset_gas_limit()accounts for the requested reservoir (transaction_gas_limit_cap + state_gas_reservoir) when sizing the implicit limit.tx.state_gas_reservoir = state_gas_reservoirinstead oftx.gas_limit = gas_limit_cap + state_gas_reservoir).Test cleanup
The implicit gas limit was applied across the test suite, removing explicit
gas_limitassignments from transactions wherever the precise limit was irrelevant to what the test exercises. This touches ~509 test files (net ~7,200 lines removed) spanning Frontier through Amsterdam and many individual EIPs (1153, 4844, 5656, 6780, 7516, 7708, 7843, 7928, 8024, Blake2, etc.).Tests that should rely on the implicit gas limit are those that only need the transaction to execute fully without running out of gas. Tests that intentionally probe gas-limit behavior continue to set it explicitly.
Incidental fixes surfaced while porting tests
pre.fund_eoadefault bumped from10**21to10**27to fix deposit tests that were under-funded.🔗 Related Issues or PRs
Closes #2248:
✅ Checklist
just statictype(scope):.mkdocs servelocally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.@ported_frommarker.Cute Animal Picture