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

Tools: Update framework tests to run with solc 0.8.21 #228

Merged
merged 5 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
matrix:
python: ['3.10', '3.11']
golang: ['1.20.5']
solc: ['0.8.20']
solc: ['0.8.20', '0.8.21']
steps:
- uses: actions/checkout@v2
with:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ The following requires a Python 3.10 or Python 3.11 installation.

This guide installs stable versions of the required external `evm` and `solc` executables and will only enable generation of test fixtures for features deployed to mainnet. In order to generate fixtures for features under active development, you can follow the steps below and then follow the [additional steps in the online doc](https://ethereum.github.io/execution-spec-tests/getting_started/executing_tests_dev_fork/).

1. Ensure go-ethereum's `evm` tool and `solc` are in your path. Either build the required versions, or alternatively:
1. Ensure go-ethereum's `evm` tool and `solc` ([0.8.20](https://github.com/ethereum/solidity/releases/tag/v0.8.20) or [0.8.21](https://github.com/ethereum/solidity/releases/tag/v0.8.21)) are in your path. Either build the required versions, or alternatively:

```console
sudo add-apt-repository -y ppa:ethereum/ethereum
Expand All @@ -77,7 +77,7 @@ This guide installs stable versions of the required external `evm` and `solc` ex

Help for other platforms is available in the [online doc](https://ethereum.github.io/execution-spec-tests/getting_started/quick_start/).

2. Clone the [execution-spec-tests](https://github.com/ethereum/execution-spec-tests) repo and install its and dependencies (it's recommended to use a virtual environment for the installation):
2. Clone the [execution-spec-tests](https://github.com/ethereum/execution-spec-tests) repo and install its dependencies (it's recommended to use a virtual environment for the installation):

```console
git clone https://github.com/ethereum/execution-spec-tests
Expand Down
2 changes: 1 addition & 1 deletion docs/getting_started/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

The following requires a Python 3.10 or Python 3.11 installation.

1. Ensure `go-ethereum`'s `evm` tool and `solc` are in your path. Either build the required versions, or alternatively:
1. Ensure `go-ethereum`'s `evm` tool and `solc` ([0.8.20](https://github.com/ethereum/solidity/releases/tag/v0.8.20) or [0.8.21](https://github.com/ethereum/solidity/releases/tag/v0.8.21)) are in your path. Either build the required versions, or alternatively:

=== "Ubuntu"

Expand Down
25 changes: 25 additions & 0 deletions src/ethereum_test_tools/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Common pytest fixtures for ethereum_test_tools tests.
"""

import pytest
from packaging import version

from ..code import Yul

SUPPORTED_SOLC_VERSIONS = [
version.parse(v)
for v in [
"0.8.20",
"0.8.21",
]
]


@pytest.fixture(scope="session")
def solc_version() -> version.Version:
"""Return the version of solc being used for tests."""
solc_version = version.parse(Yul("").version().split("+")[0])
if solc_version not in SUPPORTED_SOLC_VERSIONS:
raise Exception("Unsupported solc version: {}".format(solc_version))
return solc_version
141 changes: 100 additions & 41 deletions src/ethereum_test_tools/tests/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
Test suite for `ethereum_test.code` module.
"""

from string import Template
from typing import SupportsBytes

import pytest
from packaging import version

from ethereum_test_forks import Merge
from ethereum_test_forks import Fork, Homestead, Shanghai, forks_from_until, get_deployed_forks

from ..code import Code, Initcode, Yul

Expand Down Expand Up @@ -42,77 +44,134 @@ def test_code_operations(code: Code, expected_bytes: bytes):
assert bytes(code) == expected_bytes


@pytest.fixture(params=forks_from_until(get_deployed_forks()[1], get_deployed_forks()[-1]))
def fork(request: pytest.FixtureRequest):
"""
Return the target evm-version (fork) for solc compilation.

Note:
- get_deployed_forks()[1] (Homestead) is the first fork that solc supports.
- forks_from_util: Used to remove the Glacier forks
"""
return request.param


@pytest.fixture()
def yul_code(request: pytest.FixtureRequest, fork: Fork, padding_before: str, padding_after: str):
"""Return the Yul code for the test."""
yul_code_snippets = request.param
if padding_before is not None:
compiled_yul_code = Code(padding_before)
else:
compiled_yul_code = Code("")
for yul_code in yul_code_snippets:
compiled_yul_code += Yul(yul_code, fork=fork)
if padding_after is not None:
compiled_yul_code += Code(padding_after)
return compiled_yul_code


SOLC_PADDING_VERSION = version.parse("0.8.21")


@pytest.fixture()
def expected_bytes(request: pytest.FixtureRequest, solc_version: version.Version, fork: Fork):
"""Return the expected bytes for the test."""
expected_bytes = request.param
if isinstance(expected_bytes, Template):
if solc_version < SOLC_PADDING_VERSION or fork == Homestead:
solc_padding = ""
elif solc_version == SOLC_PADDING_VERSION:
solc_padding = "00"
else:
raise Exception("Unsupported solc version: {}".format(solc_version))
return bytes.fromhex(expected_bytes.substitute(solc_padding=solc_padding))
if isinstance(expected_bytes, bytes):
if fork == Shanghai:
expected_bytes = b"\x5f" + expected_bytes[2:]
if solc_version < SOLC_PADDING_VERSION or fork == Homestead:
return expected_bytes
elif solc_version == SOLC_PADDING_VERSION:
return expected_bytes + b"\x00"
else:
raise Exception("Unsupported solc version: {}".format(solc_version))
raise Exception("Unsupported expected_bytes type: {}".format(type(expected_bytes)))


@pytest.mark.parametrize(
"yul_code,expected_bytes",
["yul_code", "padding_before", "padding_after", "expected_bytes"],
[
(
Yul(
pytest.param(
(
"""
{
sstore(1, 2)
}
"""
{
sstore(1, 2)
}
""",
),
bytes.fromhex("6002600155"),
None,
None,
Template("6002600155${solc_padding}"),
id="simple",
),
(
Yul(
pytest.param(
(
"""
{
sstore(1, 2)
}
"""
)
+ "0x00",
bytes.fromhex("600260015500"),
""",
),
None,
"0x00",
Template("6002600155${solc_padding}00"),
id="simple-with-padding",
),
(
"0x00"
+ Yul(
pytest.param(
(
"""
{
sstore(1, 2)
}
"""
""",
),
bytes.fromhex("006002600155"),
"0x00",
None,
Template("006002600155${solc_padding}"),
id="simple-with-padding-2",
),
(
Yul(
pytest.param(
(
"""
{
sstore(1, 2)
}
"""
)
+ Yul(
""",
"""
{
sstore(3, 4)
}
"""
""",
),
bytes.fromhex("60026001556004600355"),
None,
None,
Template("6002600155${solc_padding}6004600355${solc_padding}"),
id="multiple",
),
(
Yul(
"{\n" + "\n".join(["sstore({0}, {0})".format(i) for i in range(5000)]) + "\n}",
# TODO(dan): workaround until it's understood why Shanghai takes so long to compile
fork=Merge,
),
pytest.param(
("{\n" + "\n".join(["sstore({0}, {0})".format(i) for i in range(5000)]) + "\n}",),
None,
None,
b"".join([b"\x60" + i.to_bytes(1, "big") + b"\x80\x55" for i in range(256)])
+ b"".join([b"\x61" + i.to_bytes(2, "big") + b"\x80\x55" for i in range(256, 5000)]),
id="large",
),
],
ids=[
"simple",
"simple with padding",
"simple with padding 2",
"multiple",
"large",
],
indirect=["yul_code", "expected_bytes"],
)
def test_yul(yul_code: SupportsBytes, expected_bytes: bytes):
def test_yul(
yul_code: SupportsBytes, expected_bytes: bytes, padding_before: str, padding_after: str
):
assert bytes(yul_code) == expected_bytes


Expand Down
41 changes: 29 additions & 12 deletions src/ethereum_test_tools/tests/test_filler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Any, Dict, List

import pytest
from packaging import version

from ethereum_test_forks import Berlin, Fork, Istanbul, London
from evm_transition_tool import GethTransitionTool
Expand All @@ -23,18 +24,32 @@ def remove_info(fixture_json: Dict[str, Any]):
del fixture_json[t]["_info"]


@pytest.fixture()
def hash(request: pytest.FixtureRequest, solc_version: version.Version):
"""
Set the hash based on the fork and solc version.
"""
if solc_version == version.parse("0.8.20"):
if request.node.funcargs["fork"] == Berlin:
return bytes.fromhex("193e550de3")
elif request.node.funcargs["fork"] == London:
return bytes.fromhex("b053deac0e")
elif solc_version == version.parse("0.8.21"):
if request.node.funcargs["fork"] == Berlin:
return bytes.fromhex("f3a35d34f6")
elif request.node.funcargs["fork"] == London:
return bytes.fromhex("c5fa75d7f6")
else:
raise Exception("Unsupported solc version: {}".format(solc_version))


@pytest.mark.parametrize(
"fork,hash",
[
(
Berlin,
bytes.fromhex("193e550de3"),
),
(
London,
bytes.fromhex("b053deac0e"),
),
(Berlin, "set using indirect & hash fixture"),
(London, "set using indirect & hash fixture"),
],
indirect=["hash"],
)
def test_make_genesis(fork: Fork, hash: bytes):
env = Environment()
Expand Down Expand Up @@ -138,7 +153,7 @@ def test_fill_state_test(fork: Fork, expected_json_file: str):


@pytest.mark.parametrize("fork", [London])
def test_fill_london_blockchain_test_valid_txs(fork: Fork):
def test_fill_london_blockchain_test_valid_txs(fork: Fork, solc_version: str):
"""
Test `ethereum_test.filler.fill_fixtures` with `BlockchainTest`.
"""
Expand Down Expand Up @@ -423,11 +438,12 @@ def test_fill_london_blockchain_test_valid_txs(fork: Fork):

fixture_json = to_json(fixture)
remove_info(fixture_json)
assert fixture_json == expected

assert fixture_json == expected[f"solc={solc_version}"]


@pytest.mark.parametrize("fork", [London])
def test_fill_london_blockchain_test_invalid_txs(fork: Fork):
def test_fill_london_blockchain_test_invalid_txs(fork: Fork, solc_version: str):
"""
Test `ethereum_test.filler.fill_fixtures` with `BlockchainTest`.
"""
Expand Down Expand Up @@ -758,4 +774,5 @@ def test_fill_london_blockchain_test_invalid_txs(fork: Fork):

fixture_json = to_json(fixture)
remove_info(fixture_json)
assert fixture_json == expected

assert fixture_json == expected[f"solc={solc_version}"]
Loading
Loading