Skip to content
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

feat(tests): port ethereum/tests swap opcode tests #1163

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

bomanaps
Copy link

πŸ—’οΈ Description

Port test for swap opcode ported from ethereum/tests.

πŸ”— Related Issues

Closes #1012

βœ… 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.

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.

Thanks so much for implementing this.

There's a couple of comments I think should be addressed before merging, but overall it's a very good PR!

@@ -590,7 +590,7 @@ requires-dist = [
{ name = "pytest-metadata", specifier = ">=3,<4" },
{ name = "pytest-xdist", specifier = ">=3.3.1,<4" },
{ name = "pyyaml", specifier = ">=6.0.2,<7" },
{ name = "questionary", git = "/~https://github.com/tmbo/questionary?rev=ff22aeae1cd9c1c734f14329934e349bec7873bc#ff22aeae1cd9c1c734f14329934e349bec7873bc" },
Copy link
Member

Choose a reason for hiding this comment

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

I think we can leave this file out of the PR for the time being πŸ‘

Copy link
Member

Choose a reason for hiding this comment

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

Looks like @bomanaps is using uv>=0.8.22 - this is due to:

Copy link
Member

@danceratopz danceratopz Feb 5, 2025

Choose a reason for hiding this comment

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

@bomanaps no action required regarding your uv version at the moment, I think everyone else needs to upgrade their uv.

Copy link
Author

Choose a reason for hiding this comment

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

Okay

from ethereum_test_forks import Fork, Frontier, Homestead
from ethereum_test_tools import Account, Alloc, Environment
from ethereum_test_tools import Opcodes as Op
from ethereum_test_tools import StateTestFiller, Storage, Transaction, Bytecode
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
from ethereum_test_tools import StateTestFiller, Storage, Transaction, Bytecode
from ethereum_test_tools import StateTestFiller, Transaction, Bytecode

Storage is unused.

contract_code += swap_opcode

# Store the top of the stack in storage slot 0
contract_code += Op.PUSH1(0) + Op.SSTORE
Copy link
Member

Choose a reason for hiding this comment

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

We could change the approach a bit here:

  • SSTORE(0,1) at the start of the execution, just to have something that will revert when the underflow happens.
  • Fill the stack up to the SWAP* opcode's required minimum minus one.
  • Perform the SWAP* that should abort the execution because there's not enough values in the stack for it to operate.
  • Verify that the storage is empty since the SSTORE(0,1) reverts with the execution abort caused by the underflow.

Copy link
Member

Choose a reason for hiding this comment

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

The test as it is right now is producing an overflow that is accomplished by the opcode PUSH1, and in that case, the SWAPn opcode is not really used.

This is the last executed opcode in the trace:

Step 1025:
{ 'depth': 1,
  'error': 'StackOverflowError',
  'gas': '0x74315',
  'gasCost': '0x3',
  'memSize': 0,
  'op': 96,
  'opName': 'PUSH1',
  'pc': 2049,
  'refund': 0,
  'returnData': '0x',
  'stack': [ '0x0',
             '0x1',
             '0x2',
...
             '0xfe',
             '0xef']}

Step 1026:
{'error': 'StackOverflowError', 'gasUsed': '0x74f18', 'output': ''}

So we don't really need to push this many items into the stack for an underflow, the key is not having enough items for the SWAPn opcode to try to fetch outside of the bounds of the stack.

For example, for SWAP1, it requires at least two elements in the stack to work properly (see the min_stack_height property of the opcode https://ethereum.github.io/execution-spec-tests/main/library/ethereum_test_vm/#ethereum_test_vm.Opcodes.SWAP1), because it swaps the first item for the second. Therefore, to create a stack underflow, we place a single item in the stack and then execute the SWAP1.

sender=pre.fund_eoa(),
to=contract,
gas_limit=500_000,
protected=False if fork in [Frontier, Homestead] else True,
Copy link
Contributor

Choose a reason for hiding this comment

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

@marioevz can we automate this thing? unless we specificly want to test this

Copy link
Member

@danceratopz danceratopz Feb 5, 2025

Choose a reason for hiding this comment

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

One potential solution for this would be:

Copy link
Contributor

@winsvega winsvega left a comment

Choose a reason for hiding this comment

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

why uv.lock is deleted?

@danceratopz danceratopz added scope:tests Scope: Changes EL client test cases in `./tests` type:feat type: Feature labels Feb 5, 2025
@danceratopz danceratopz changed the title Port test for swap opcode feat(tests): port ethereum/tests swap opcode tests Feb 5, 2025
@danceratopz danceratopz added the port Related to porting ethereum/tests to EEST label Feb 7, 2025
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.

More comments.

contract_code += swap_opcode

# Store the top of the stack in storage slot 0
contract_code += Op.PUSH1(0) + Op.SSTORE
Copy link
Member

Choose a reason for hiding this comment

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

The test as it is right now is producing an overflow that is accomplished by the opcode PUSH1, and in that case, the SWAPn opcode is not really used.

This is the last executed opcode in the trace:

Step 1025:
{ 'depth': 1,
  'error': 'StackOverflowError',
  'gas': '0x74315',
  'gasCost': '0x3',
  'memSize': 0,
  'op': 96,
  'opName': 'PUSH1',
  'pc': 2049,
  'refund': 0,
  'returnData': '0x',
  'stack': [ '0x0',
             '0x1',
             '0x2',
...
             '0xfe',
             '0xef']}

Step 1026:
{'error': 'StackOverflowError', 'gasUsed': '0x74f18', 'output': ''}

So we don't really need to push this many items into the stack for an underflow, the key is not having enough items for the SWAPn opcode to try to fetch outside of the bounds of the stack.

For example, for SWAP1, it requires at least two elements in the stack to work properly (see the min_stack_height property of the opcode https://ethereum.github.io/execution-spec-tests/main/library/ethereum_test_vm/#ethereum_test_vm.Opcodes.SWAP1), because it swaps the first item for the second. Therefore, to create a stack underflow, we place a single item in the stack and then execute the SWAP1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
port Related to porting ethereum/tests to EEST scope:tests Scope: Changes EL client test cases in `./tests` type:feat type: Feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(tests): SwapFiller.yml
4 participants