-
Notifications
You must be signed in to change notification settings - Fork 107
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) Precompile Checks #1120
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
// If the VS Code "Run and Debug" button, respecively launch selector are not visible, see this answer: | ||
// https://stackoverflow.com/a/74245823 | ||
// | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Launch fill --until choose fork", | ||
"type": "python", | ||
"request": "launch", | ||
"module": "pytest", | ||
"args": [ | ||
"-c", | ||
"pytest.ini", | ||
"--until", | ||
"${input:fork}", | ||
"--evm-bin", | ||
"${input:evmBinary}", | ||
"-v" | ||
], | ||
"cwd": "${workspaceFolder}" | ||
}, | ||
{ | ||
"name": "Launch fill -k choose test path", | ||
"type": "python", | ||
"request": "launch", | ||
"module": "pytest", | ||
"args": [ | ||
"-c", | ||
"pytest.ini", | ||
"--until", | ||
"Cancun", | ||
"--evm-bin", | ||
"${input:evmBinary}", | ||
"-v", | ||
"-k", | ||
"${input:testPathOrId}" | ||
], | ||
"cwd": "${workspaceFolder}" | ||
}, | ||
{ | ||
"name": "Launch fill --until Cancun", | ||
"type": "python", | ||
"request": "launch", | ||
"module": "pytest", | ||
"args": [ | ||
"-c", | ||
"pytest.ini", | ||
"--until", | ||
"Cancun", | ||
"--evm-bin", | ||
"${input:evmBinary}", | ||
"-v" | ||
], | ||
"cwd": "${workspaceFolder}" | ||
}, | ||
{ | ||
"name": "Launch fill --until Prague", | ||
"type": "python", | ||
"request": "launch", | ||
"module": "pytest", | ||
"args": [ | ||
"-c", | ||
"pytest.ini", | ||
"--until", | ||
"Prague", | ||
"--evm-bin", | ||
"${input:evmBinary}", | ||
"-v" | ||
], | ||
"cwd": "${workspaceFolder}" | ||
} | ||
], | ||
"inputs": [ | ||
{ | ||
"type": "pickString", | ||
"id": "evmBinary", | ||
"description": "Which evm binary to you want to run?", | ||
"options": [ | ||
{ | ||
"label": "First evm binary in PATH", | ||
"value": "evm", | ||
}, | ||
{ | ||
"label": "Geth, mario's repo", | ||
"value": "~/code/github/marioevz/go-ethereum/build/bin/evm", | ||
}, | ||
{ | ||
"label": "Geth, danceratopz's repo", | ||
"value": "~/code/github/danceratopz/go-ethereum/build/bin/evm", | ||
}, | ||
{ | ||
"label": "evmone", | ||
"value": "~/code/github/ethereum/evmone/build/bin/evmone-t8n", | ||
}, | ||
{ | ||
"label": "besu", | ||
"value": "~/code/github/danceratopz/besu/ethereum/evmtool/build/install/evmtool/bin/evm", | ||
} | ||
], | ||
"default": "evm" | ||
}, | ||
{ | ||
"type": "pickString", | ||
"id": "fork", | ||
"description": "Which fork do you want to use?", | ||
"options": [ | ||
"Frontier", | ||
"Homestead", | ||
"Byzantium", | ||
"Constantinople", | ||
"ConstantinopleFix", | ||
"Istanbul", | ||
"Berlin", | ||
"London", | ||
"Paris", | ||
"Shanghai", | ||
"Cancun", | ||
"Prague", | ||
], | ||
"default": "Cancun" | ||
}, | ||
{ | ||
"type": "promptString", | ||
"id": "testPathOrId", | ||
"description": "Enter a test path string or id to provide to pytest -k", | ||
"default": "test_" | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"_comment": [ | ||
"Dynamic python testing settings for the vscode testing extension." | ||
], | ||
"python.testing.promptToConfigure": false, | ||
"python.testing.unittestEnabled": false, | ||
"python.testing.pytestEnabled": true, | ||
"python.testing.pytestArgs": ["-c", "pytest.ini"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
"""Tests supported precompiled contracts.""" | ||
|
||
from typing import Iterator, Tuple | ||
|
||
import pytest | ||
|
||
from ethereum_test_forks import Fork | ||
from ethereum_test_tools import ( | ||
Account, | ||
Alloc, | ||
Environment, | ||
StateTestFiller, | ||
Transaction, | ||
) | ||
from ethereum_test_tools.code.generators import Conditional | ||
from ethereum_test_tools.vm.opcode import Opcodes as Op | ||
|
||
|
||
def precompile_addresses(fork: Fork) -> Iterator[Tuple[str, bool]]: | ||
""" | ||
Yield the addresses of precompiled contracts and their support status for a given fork. | ||
|
||
Args: | ||
fork (Fork): The fork instance containing precompiled contract information. | ||
|
||
Yields: | ||
Iterator[Tuple[str, bool]]: A tuple containing the address in hexadecimal format and a | ||
boolean indicating whether the address is a supported precompile. | ||
|
||
""" | ||
supported_precompiles = fork.precompiles() | ||
|
||
for address in range(1, len(supported_precompiles) + 2): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why +2 |
||
yield (hex(address), address in supported_precompiles) | ||
|
||
|
||
@pytest.mark.valid_from("Berlin") | ||
@pytest.mark.parametrize_by_fork("address,precompile_exists", precompile_addresses) | ||
def test_precompiles( | ||
state_test: StateTestFiller, address: str, precompile_exists: bool, pre: Alloc | ||
): | ||
""" | ||
Tests the behavior of precompiled contracts in the Ethereum state test. | ||
|
||
Args: | ||
state_test (StateTestFiller): The state test filler object used to run the test. | ||
address (str): The address of the precompiled contract to test. | ||
precompile_exists (bool): A flag indicating whether the precompiled contract exists at the | ||
given address. | ||
pre (Alloc): The allocation object used to deploy the contract and set up the initial | ||
state. | ||
|
||
This test deploys a contract that performs two CALL operations to the specified address and a | ||
fixed address (0x10000), measuring the gas used for each call. It then stores the difference | ||
in gas usage in storage slot 0. The test verifies the expected storage value based on | ||
whether the precompiled contract exists at the given address. | ||
|
||
""" | ||
env = Environment() | ||
|
||
args_offset = 0x1000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see you didn't want to copy, but then you can actually use default values of this args leaving it empty. |
||
args_size = 0x20 | ||
output_offset = 0x2000 | ||
output_size = 0x20 | ||
|
||
gas_test = 0x00 | ||
gas_10000 = 0x20 | ||
|
||
account = pre.deploy_contract( | ||
Op.MSTORE(gas_test, Op.GAS) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @marioevz it works |
||
+ Op.CALL( | ||
address=address, | ||
args_offset=args_offset, | ||
args_size=args_size, | ||
output_offset=output_offset, | ||
output_size=output_size, | ||
) | ||
+ Op.MSTORE(gas_test, Op.SUB(Op.GAS, Op.MLOAD(gas_test))) | ||
+ Op.MSTORE(gas_10000, Op.GAS) | ||
+ Op.CALL( | ||
address=0x10000, | ||
args_offset=args_offset, | ||
args_size=args_size, | ||
output_offset=output_offset, | ||
output_size=output_size, | ||
) | ||
+ Op.MSTORE(gas_10000, Op.SUB(Op.GAS, Op.MLOAD(gas_10000))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you get negative value here |
||
+ Op.SSTORE( | ||
0, | ||
Op.LT( | ||
Conditional( | ||
condition=Op.GT(Op.MLOAD(gas_test), Op.MLOAD(gas_10000)), | ||
if_true=Op.SUB(Op.MLOAD(gas_test), Op.MLOAD(gas_10000)), | ||
if_false=Op.SUB(Op.MLOAD(gas_10000), Op.MLOAD(gas_test)), | ||
), | ||
0x1A4, | ||
), | ||
) | ||
+ Op.STOP, | ||
storage={0: 0xDEADBEEF}, | ||
) | ||
|
||
tx = Transaction( | ||
to=account, | ||
sender=pre.fund_eoa(), | ||
gas_limit=1_000_000, | ||
protected=True, | ||
) | ||
|
||
# A high gas cost will result from calling a precompile | ||
# Expect 0x00 when a precompile exists at the address, 0x01 otherwise | ||
post = {account: Account(storage={0: "0x00" if precompile_exists else "0x01"})} | ||
|
||
state_test(env=env, pre=pre, post=post, tx=tx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the settings got exported?