Skip to content

feat(tests): Add flag to configure max_gas for fill command #1470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
May 5, 2025

Conversation

reedsa
Copy link
Contributor

@reedsa reedsa commented Apr 16, 2025

🗒️ Description

Add flag to configure max_gas for fill command with default of of 30_000_000.
Add fixture for max_gas to use in gas_limit of a Transaction.

🔗 Related Issues

#1434

✅ Checklist

  • All: Set appropriate labels for the changes.
  • All: Considered squashing commits to improve commit history.
  • All: Added an entry to CHANGELOG.md.
  • All: Considered updating the online docs in the ./docs/ directory.
  • Tests: All converted JSON/YML tests from ethereum/tests have been added to converted-ethereum-tests.txt.
  • Tests: A PR with removal of converted JSON/YML tests from ethereum/tests have been opened.
  • Tests: Included the type and version of evm t8n tool used to locally execute test cases: e.g., ref with commit hash or geth 1.13.1-stable-3f40e65.
  • Tests: Ran mkdocs serve locally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.

Add fixture for `max_gas` with default of 30_000_000
@reedsa reedsa self-assigned this Apr 16, 2025
@reedsa
Copy link
Contributor Author

reedsa commented Apr 21, 2025

Are tests that use more than 30_000_000 gas expected to be set to the enormous amounts like in this example. Some values of 50_000_000, etc. in various osaka tests as well.

Should these values remain or should they be set to the max_gas value from the configurable fixture?

Another question: There are gas limits used in the execution command. Are those to remain as is for now?

@reedsa reedsa requested review from marioevz and spencer-tb April 21, 2025 23:00
@reedsa reedsa added the scope:fill Scope: fill command label Apr 21, 2025
Update fill command output in docs
@reedsa reedsa force-pushed the configurable-max-gas branch from f279050 to 739ed53 Compare April 22, 2025 13:10
@reedsa reedsa marked this pull request as ready for review April 22, 2025 13:20
@reedsa
Copy link
Contributor Author

reedsa commented Apr 23, 2025

@marioevz I like the idea of setting the gas_limit as part of the Environment class. I assume the initial value should just use the flag value via the test fixture somehow? Perhaps a new method on the class similar to set_fork_requirements that is called from make_state_test_fixture?

I noticed there is a default value of 100_000_000_000_000_000 for the gas_limit. Should that value be lowered to the default configurable value of 30_000_000 and allow overrides with the --gas_limit flag?

Once it is in the environment, all tests will change and I'm not certain what effect lowering the value will have. Is this the right approach?

@marioevz
Copy link
Member

@marioevz I like the idea of setting the gas_limit as part of the Environment class. I assume the initial value should just use the flag value via the test fixture somehow? Perhaps a new method on the class similar to set_fork_requirements that is called from make_state_test_fixture?

I noticed there is a default value of 100_000_000_000_000_000 for the gas_limit. Should that value be lowered to the default configurable value of 30_000_000 and allow overrides with the --gas_limit flag?

Once it is in the environment, all tests will change and I'm not certain what effect lowering the value will have. Is this the right approach?

I think the default of 100_000_000_000_000_000 is way overblown, and we should be able to lower it and match it to the value we specify as the block limit, and not that many tests should fail.

Doing the environment-as-a-fixture would require some big changes, like the ones we did for the pre-as-a-fixture.
I.e. The environment changes from being something that gets instantiated by the test function (most tests just do Environment()) to something that is passed as a parameter and then read and potentially modified if necessary.

It might not even be necessary that the test function uses the parameter and we could simply pass it from the filler to the spec like we do for the pre here:

if "pre" not in kwargs:
kwargs["pre"] = pre

If the test function requires to know about its environment, it will be included in the test function as a parameter:

def test_something(pre: Alloc, env: Environment ...):

And the test could then:

  • Read values from its environment, like the gas_limit and adapt the test to only use that at most. If the test uses the environment as read-only, the test can be easily filled (uv run fill) and executed (uv run execute).
  • Write values to its environment, like increase the gas_limit to a minimum value because the test requires it as a minimum to execute its test logic, and in this case the test could be filled but not executed (because we cannot modify the environment we are running in when it's a live network).

One change I would do to the current implementation of this PR is rename max_gas to block_gas_limit.

@reedsa
Copy link
Contributor Author

reedsa commented May 1, 2025

@marioevz Pushed up my latest changes and had some follow up questions for what we've discussed.

  1. I was wondering if it would be useful to have the existing env.gas_limit only used for transactions and add a new env.block_gas_limit variable that is configurable?
  2. I am looking at the pytantic models, not totally certain about where validation happens to check that the env has the block_gas_limit value set? So far I have: block_gas_limit: NumberBoundTypeVar = Field(DEFAULT_BLOCK_GAS_LIMIT, alias="currentBlockGasLimit") as an attribute of EnvironmentGeneric with the default set.

@marioevz
Copy link
Member

marioevz commented May 1, 2025

1. I was wondering if it would be useful to have the existing `env.gas_limit` only used for transactions and add a new `env.block_gas_limit` variable that is configurable?

I normally see tx.gas_limit as the limit applied to the transaction and env.gas_limit as the total gas limit in the environment (block) where the transaction will execute. If you set tx.gas_limit=env.gas_limit it should (IMO) be seen as "the tx should consume all the gas that it can from the environment where it runs".

2. I am looking at the pytantic models, not totally certain about where validation happens to check that the env has the `block_gas_limit` value set? So far I have: `block_gas_limit: NumberBoundTypeVar = Field(DEFAULT_BLOCK_GAS_LIMIT, alias="currentBlockGasLimit")` as an attribute of `EnvironmentGeneric` with the default set.

I don't think this validation happens anywhere at the moment, it's simply set to a default max.

As an example, we do a hacky trick to alter the defaults of a transaction by using a TransactionDefaults class:

@dataclass
class TransactionDefaults:
"""Default values for transactions."""
chain_id: int = 1
gas_price = 10
max_fee_per_gas = 7
max_priority_fee_per_gas: int = 0

And then in the fill/execute plugins we import and modify the value to the new defaults for the given execution context:

@pytest.fixture(autouse=True, scope="session")
def modify_transaction_defaults(
default_gas_price: int, default_max_fee_per_gas: int, default_max_priority_fee_per_gas: int
):
"""Modify transaction defaults to values better suited for live networks."""
TransactionDefaults.gas_price = default_gas_price
TransactionDefaults.max_fee_per_gas = default_max_fee_per_gas
TransactionDefaults.max_priority_fee_per_gas = default_max_priority_fee_per_gas

Maybe this helps for environment too?

Copy link
Member

@marioevz marioevz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks very good!

After going through the code, I'm more convinced about the separation between gas_limit and block_gas_limit.

I'll try the changes today locally and potentially merge if it goes well :)

@reedsa
Copy link
Contributor Author

reedsa commented May 2, 2025

@marioevz Is it worth removing the env = Environment() setup that is in many of the tests?

I also haven't updated the execute command with a default value. Is that necessary?

@marioevz
Copy link
Member

marioevz commented May 2, 2025

@marioevz Is it worth removing the env = Environment() setup that is in many of the tests?

I was just thinking about that, it's maybe way too many tests using this pattern.

Maybe since it's simpler to just use the EnvironmentDefaults trick in this PR and focus on the ones that directly set Environment(gas_limit=...)?

I also haven't updated the execute command with a default value. Is that necessary?

If we go ahead and skip using a fixture then nothing needs to be changed for execute, but if we end up using the fixture route then we need to define it also in the execute plugin.

@marioevz
Copy link
Member

marioevz commented May 2, 2025

Just to summarize, the two options are:

env fixture

  • Tests would have to define the env parameter, and then pass it to state_test.
  • Basically all state tests are affected

EnvironmentDefaults

  • Only tests that modify gas limit would be affected, and they would need to do:
env = Environment()
...
tx.gas_limit = env.gas_limit  # <- env.gas_limit here automatically contains the --block-max-gas value
  • We could detect tests that go over this limit by checking tx.gas_limit > Environment().gas_limit, but for fill it's irrelevant, and we might only need to check this for execute.

@reedsa
Copy link
Contributor Author

reedsa commented May 2, 2025

I'm fine with using the EnvironmentFixture instead of the fixture. I'll update that shortly!

@reedsa
Copy link
Contributor Author

reedsa commented May 2, 2025

@marioevz I'm not seeing the flag in the help section when I put in the correct description for the flag group parser.getgroup("env", "Arguments defining the environment"). The flag had worked prior when I had it using the same description as the debug group. 😕

With the EnvironmentDefaults approach I am not sure if that's preventing the limit flag from propogating into the fill tests. Maybe I'm missing something or confused about how the flag should work without using a fixture.

@reedsa reedsa force-pushed the configurable-max-gas branch from cbac34c to bf70458 Compare May 2, 2025 20:14
@marioevz
Copy link
Member

marioevz commented May 2, 2025

@marioevz I'm not seeing the flag in the help section when I put in the correct description for the flag group parser.getgroup("env", "Arguments defining the environment"). The flag had worked prior when I had it using the same description as the debug group. 😕

With the EnvironmentDefaults approach I am not sure if that's preventing the limit flag from propogating into the fill tests. Maybe I'm missing something or confused about how the flag should work without using a fixture.

Have an idea on how to fix it: I think we should move the flag to the shared plugin.

I'll push a commit in a bit 👍

@marioevz
Copy link
Member

marioevz commented May 3, 2025

@reedsa Added the changes and it seems to be working now.

The nice thing is that with this change, since the default for Environment.gas_limit was drastically reduced, tests that were using excessive gas started failing, and I took the opportunity and reduced the gas limit of many tests where it was unnecessary.

Let me know what you think of the changes.

Copy link
Contributor Author

@reedsa reedsa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on these updates! I think the only update I would make is to the help text and I'll go ahead and push up that change.

Any test that currently just uses the default environment could also stop using env = Environment() to pass into state_test but isn't necessarily hurting anything as is. Looks good to go!

Copy link
Member

@marioevz marioevz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for this!

I'll apply my comments and merge :)

@marioevz marioevz merged commit 0c6f531 into ethereum:main May 5, 2025
12 checks passed
felix314159 pushed a commit to felix314159/execution-spec-tests that referenced this pull request May 16, 2025
…ethereum#1470)

* Add flag to configure `max_gas` for fill command

Add fixture for `max_gas` with default of 30_000_000

* Warnings for blockchain and state tests using gas_limit >= 30_000_000

* Set gas_limit from fixture for fill command

* Update CHANGELOG

Update fill command output in docs

* Add env fixture to pytest fill plugin and pass Environment to state tests directly

* Updates for using EnvironmentDefaults

* refactor(plugins/shared): Move block gas limit flag to shared

* refactor(tests): test fixes

* fix(specs): Unit tests

* fix(specs): More unit tests

* fix(types): Change semantics of max block gas limit

* refactor(plugins): Use different max gas defaults for execute/fill

* revert(pytest.ini): Remove filler.env

* fix(tests): Reduce amount of excessive-gas-usage tests

* fix(types): Fix unit tests take 3

* fix(tests): Mark tests timing out as slow

* Update docs for max gas flag

* fix(plugins): Move environment defaults modification in pytest_config

* fix tox

* Apply suggestions from code review

---------

Co-authored-by: Mario Vega <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
scope:fill Scope: fill command
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants