diff --git a/.gitignore b/.gitignore
index fd08eaf32b..68ffdb4860 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ __pycache__
__pycache__/
*.py[cod]
*$py.class
+.mypy_cache/
# C extensions
*.so
diff --git a/packages/tests/pyproject.toml b/packages/tests/pyproject.toml
new file mode 100644
index 0000000000..2779e50270
--- /dev/null
+++ b/packages/tests/pyproject.toml
@@ -0,0 +1,216 @@
+[build-system]
+requires = [
+ "setuptools==78.0.2",
+ "wheel==0.45.1",
+] # the setuptools version here should match that of setuptools below in docs in optional-dependencies
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "ethereum-execution-tests"
+version = "1.0.0"
+description = "Ethereum execution client test authoring framework"
+readme = "README.md"
+requires-python = ">=3.11"
+license = "MIT"
+license-files = [ "LICENSE" ]
+keywords = ["ethereum", "testing", "blockchain"]
+classifiers = [
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+]
+dependencies = [
+ "click>=8.1.0,<9",
+ "ethereum-hive>=0.1.0a1,<1.0.0",
+ "ethereum-execution",
+ "gitpython>=3.1.31,<4",
+ "PyJWT>=2.3.0,<3",
+ "requests>=2.31.0,<3",
+ "requests_unixsocket2>=0.4.0",
+ "colorlog>=6.7.0,<7",
+ "pytest>=8,<9",
+ "pytest-custom-report>=1.0.1,<2",
+ "pytest-html>=4.1.0,<5",
+ "pytest-metadata>=3,<4",
+ "pytest-xdist>=3.3.1,<4",
+ "coincurve>=20.0.0,<21",
+ "trie>=3.1.0,<4",
+ "semver>=3.0.1,<4",
+ "pydantic>=2.11.0,<3",
+ "rich>=13.7.0,<14",
+ "filelock>=3.15.1,<4",
+ "ethereum-types>=0.2.1,<0.3",
+ "pyyaml>=6.0.2,<7",
+ "types-pyyaml>=6.0.12.20240917,<7",
+ "pytest-json-report>=1.5.0,<2",
+ "typing-extensions>=4.12.2,<5",
+ "questionary>=2.1.0,<3",
+ "ethereum-rlp>=0.1.3,<0.2",
+ "pytest-regex>=0.2.0,<0.3",
+ "eth-abi>=5.2.0",
+ "joblib>=1.4.2",
+ "ckzg>=2.1.3,<3",
+ "tenacity>=9.0.0,<10",
+]
+
+[project.urls]
+Homepage = "https://github.com/ethereum/execution-specs"
+Documentation = "https://eest.ethereum.org"
+Repository = "https://github.com/ethereum/execution-specs"
+Issues = "https://github.com/ethereum/execution-specs/issues"
+Changelog = "https://eest.ethereum.org/main/CHANGELOG/"
+
+[project.optional-dependencies]
+test = ["pytest-cov>=4.1.0,<5"]
+lint = [
+ "ruff==0.13.2",
+ "mypy==1.17.0",
+ "types-requests>=2.31,<2.33",
+]
+docs = [
+ "cairosvg>=2.7.0,<3",
+ "codespell>=2.4.1,<3",
+ "markdown==3.8",
+ "mike>=1.1.2,<2",
+ "mkdocs>=1.4.3,<2",
+ "mkdocs-click>=0.8,<1",
+ "mkdocs-gen-files>=0.5.0,<1",
+ "mkdocs-git-authors-plugin>=0.7.1,<1",
+ "mkdocs-glightbox>=0.3.4,<1",
+ "mkdocs-literate-nav>=0.6.0,<1",
+ "mkdocs-material>=9.1.14,<10",
+ "mkdocs-material-extensions>=1.1.1,<2",
+ "mkdocstrings>=0.21.2,<1",
+ "mkdocstrings-python>=1.0.0,<2",
+ "pillow>=10.0.1,<11",
+ "pyspelling>=2.8.2,<3",
+ "lxml>=6.0.0,<7", # needs to be >= 6.0 for pypy
+ "setuptools==78.0.2",
+]
+
+[project.scripts]
+fill = "cli.pytest_commands.fill:fill"
+phil = "cli.pytest_commands.fill:phil"
+execute = "cli.pytest_commands.execute:execute"
+attac = "cli.pytest_commands.execute:execute"
+checkfixtures = "cli.check_fixtures:check_fixtures"
+check_eip_versions = "cli.pytest_commands.check_eip_versions:check_eip_versions"
+consume = "cli.pytest_commands.consume:consume"
+protec = "cli.pytest_commands.consume:consume"
+checklist = "cli.pytest_commands.checklist:checklist"
+generate_checklist_stubs = "cli.generate_checklist_stubs:generate_checklist_stubs"
+genindex = "cli.gen_index:generate_fixtures_index_cli"
+gentest = "cli.gentest:generate"
+eofwrap = "cli.eofwrap:eof_wrap"
+pyspelling_soft_fail = "cli.tox_helpers:pyspelling"
+markdownlintcli2_soft_fail = "cli.tox_helpers:markdownlint"
+order_fixtures = "cli.order_fixtures:order_fixtures"
+evm_bytes = "cli.evm_bytes:evm_bytes"
+hasher = "cli.hasher:main"
+eest = "cli.eest.cli:eest"
+fillerconvert = "cli.fillerconvert.fillerconvert:main"
+groupstats = "cli.show_pre_alloc_group_stats:main"
+extract_config = "cli.extract_config:extract_config"
+compare_fixtures = "cli.compare_fixtures:main"
+modify_static_test_gas_limits = "cli.modify_static_test_gas_limits:main"
+
+[tool.setuptools.packages.find]
+where = ["src"]
+exclude = ["*tests*"]
+
+[tool.pyright]
+exclude = ["tests/static/**"]
+
+[tool.setuptools.package-data]
+ethereum_test_forks = ["forks/contracts/*.bin"]
+"pytest_plugins.execute" = ["eth_config/networks.yml"]
+"pytest_plugins" = ["eels_resolutions.json"]
+"cli.eest.make" = ["templates/*.j2"]
+"cli.pytest_commands" = ["pytest_ini_files/*.ini"]
+"ethereum_test_types" = ["kzg_trusted_setup.txt"]
+
+[tool.ruff]
+line-length = 99
+
+[tool.ruff.lint]
+select = [
+ "E", # pycodestyle errors
+ "F", # Pyflakes
+ "B", # flake8-bugbear
+ "W", # pycodestyle warnings
+ "I", # isort
+ "A", # flake8-builtins
+ "N", # pep8-naming
+ "D", # pydocstyle
+ "C4", # flake8-comprehensions
+ "ARG", # flake8-unused-arguments
+]
+fixable = [
+ "E", # pycodestyle errors
+ "F", # Pyflakes
+ "B", # flake8-bugbear
+ "W", # pycodestyle warnings
+ "I", # isort
+ "D", # pydocstyle
+]
+ignore = [
+ "C401", # Unnecessary generator set
+ "C408", # Unnecessary collection call
+ "D107", # Missing docstring in __init__
+ "D200", # One-line docstring should fit on one line with quotes
+ "D203", # 1 blank line required before class docstring
+ "D205", # Missing blank line after summary
+ "D212", # Multi-line docstring summary should start at the first line
+ "D401", # First line should be in imperative mood ("Do", not "Does")
+ # TODO: ethereum/execution-spec-tests#2176
+ "ARG002", # unused-method-argument
+ "ARG003", # unused-class-method-argument
+ "ARG005", # unused-lambda-argument
+]
+
+[tool.ruff.lint.per-file-ignores]
+"tests/*" = ["ARG001"] # TODO: ethereum/execution-spec-tests#2188
+
+[tool.mypy]
+disable_error_code = ["import-untyped"]
+mypy_path = ["src", "$MYPY_CONFIG_FILE_DIR/stubs"]
+files = ["src", "tests"]
+exclude = [
+ '^\.cache/',
+ '^\.git/',
+ '^\.pytest_cache/',
+ '^\.ruff_cache/',
+ '^\.tox/',
+ '^\.venv/',
+ '^\.vscode/',
+ '^fixtures/',
+ '^logs/',
+ '^site/',
+]
+plugins = ["pydantic.mypy"]
+
+[tool.codespell]
+skip = ".venv,__pycache__,.git,build,dist,*.pyc,*.lock"
+check-filenames = true
+ignore-words-list = "ingenuous"
+
+[tool.pytest.ini_options]
+console_output_style = "count"
+minversion = "7.0"
+python_files = [
+ "test_*.py"
+]
+testpaths = [
+ "src"
+]
+addopts = [
+ "-p", "pytester",
+ "--ignore=src/pytest_plugins/consume/test_cache.py",
+ "--ignore=src/pytest_plugins/consume/direct/",
+ "--ignore=src/pytest_plugins/consume/simulators/",
+]
+
+[tool.uv]
+required-version = ">=0.7.0"
+
+[tool.uv.sources]
+ethereum-execution = { workspace = true }
diff --git a/src/ethereum_spec_tests/cli/__init__.py b/packages/tests/src/cli/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/__init__.py
rename to packages/tests/src/cli/__init__.py
diff --git a/src/ethereum_spec_tests/cli/check_fixtures.py b/packages/tests/src/cli/check_fixtures.py
similarity index 95%
rename from src/ethereum_spec_tests/cli/check_fixtures.py
rename to packages/tests/src/cli/check_fixtures.py
index 6660bceab7..1497d5b281 100644
--- a/src/ethereum_spec_tests/cli/check_fixtures.py
+++ b/packages/tests/src/cli/check_fixtures.py
@@ -27,14 +27,15 @@ def check_json(json_file_path: Path):
"""
Check all fixtures in the specified json file:
1. Load the json file into a pydantic model. This checks there are no
- Validation errors when loading fixtures into EEST models.
+ Validation errors when loading fixtures into EEST models.
2. Serialize the loaded pydantic model to "json" (actually python data
- structures, ready to written as json).
+ structures, ready to written as json).
3. Load the serialized data back into a pydantic model (to get an updated
- hash) from step 2.
+ hash) from step 2.
4. Compare hashes:
a. Compare the newly calculated hashes from step 2. and 3. and
- b. If present, compare info["hash"] with the calculated hash from step 2.
+ b. If present, compare info["hash"] with the calculated hash from
+ step 2.
"""
fixtures: Fixtures = Fixtures.model_validate_json(json_file_path.read_text())
fixtures_json = to_json(fixtures)
@@ -86,7 +87,9 @@ def check_json(json_file_path: Path):
help="Stop and raise any exceptions encountered while checking fixtures.",
)
def check_fixtures(input_str: str, quiet_mode: bool, stop_on_error: bool):
- """Perform some checks on the fixtures contained in the specified directory."""
+ """
+ Perform some checks on the fixtures contained in the specified directory.
+ """
input_path = Path(input_str)
success = True
file_count = 0
diff --git a/src/ethereum_spec_tests/cli/compare_fixtures.py b/packages/tests/src/cli/compare_fixtures.py
similarity index 95%
rename from src/ethereum_spec_tests/cli/compare_fixtures.py
rename to packages/tests/src/cli/compare_fixtures.py
index 787e0f9f07..bd7a5b9673 100644
--- a/src/ethereum_spec_tests/cli/compare_fixtures.py
+++ b/packages/tests/src/cli/compare_fixtures.py
@@ -1,9 +1,9 @@
"""
Compare two fixture folders and remove duplicates based on fixture hashes.
-This tool reads the .meta/index.json files from two fixture directories and identifies
-fixtures with identical hashes on a test case basis, then removes the duplicates from
-both of the folders. Used within the coverage workflow.
+This tool reads the .meta/index.json files from two fixture directories and
+identifies fixtures with identical hashes on a test case basis, then removes
+the duplicates from both of the folders. Used within the coverage workflow.
"""
import json
@@ -95,8 +95,8 @@ def batch_remove_fixtures_from_files(removals_by_file):
def rewrite_index(folder: Path, index: IndexFile, dry_run: bool):
"""
- Rewrite the index to the correct index file, or if the test count was reduced to zero,
- the entire directory is deleted.
+ Rewrite the index to the correct index file, or if the test count was
+ reduced to zero, the entire directory is deleted.
"""
if len(index.test_cases) > 0:
# Just rewrite the index
@@ -130,7 +130,9 @@ def main(
dry_run: bool,
abort_on_empty_patch: bool,
):
- """Compare two fixture folders and remove duplicates based on fixture hashes."""
+ """
+ Compare two fixture folders and remove duplicates based on fixture hashes.
+ """
try:
# Load indices
base_index = load_index(base)
diff --git a/packages/tests/src/cli/diff_opcode_counts.py b/packages/tests/src/cli/diff_opcode_counts.py
new file mode 100644
index 0000000000..d33ce9f4bd
--- /dev/null
+++ b/packages/tests/src/cli/diff_opcode_counts.py
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+"""
+Compare opcode counts between two folders of JSON fixtures.
+
+This script crawls two folders for JSON files, parses them using the Fixtures
+model, and compares the opcode_count field from the info section between
+fixtures with the same name.
+"""
+
+import sys
+from pathlib import Path
+from typing import Dict, List, Optional
+
+import click
+
+from ethereum_clis.cli_types import OpcodeCount
+from ethereum_test_fixtures.file import Fixtures
+
+
+def find_json_files(directory: Path) -> List[Path]:
+ """Find all JSON files in a directory, excluding index.json files."""
+ json_files = []
+ if directory.is_dir():
+ for file_path in directory.rglob("*.json"):
+ if file_path.name != "index.json":
+ json_files.append(file_path)
+ return json_files
+
+
+def load_fixtures_from_file(
+ file_path: Path, remove_from_fixture_names: List[str]
+) -> Optional[Fixtures]:
+ """Load fixtures from a JSON file using the Fixtures model."""
+ try:
+ fixtures = Fixtures.model_validate_json(file_path.read_text())
+ renames = []
+ for k in fixtures.root:
+ new_name = None
+ for s in remove_from_fixture_names:
+ if s in k:
+ if new_name is None:
+ new_name = k.replace(s, "")
+ else:
+ new_name = new_name.replace(s, "")
+ if new_name is not None:
+ renames.append((k, new_name))
+ for old_name, new_name in renames:
+ fixtures.root[new_name] = fixtures.root.pop(old_name)
+ return fixtures
+ except Exception as e:
+ print(f"Error loading {file_path}: {e}", file=sys.stderr)
+ return None
+
+
+def extract_opcode_counts_from_fixtures(fixtures: Fixtures) -> Dict[str, OpcodeCount]:
+ """Extract opcode_count from info field for each fixture."""
+ opcode_counts = {}
+ for fixture_name, fixture in fixtures.items():
+ if hasattr(fixture, "info") and fixture.info and "opcode_count" in fixture.info:
+ try:
+ opcode_count = OpcodeCount.model_validate(fixture.info["opcode_count"])
+ opcode_counts[fixture_name] = opcode_count
+ except Exception as e:
+ print(f"Error parsing opcode_count for {fixture_name}: {e}", file=sys.stderr)
+ return opcode_counts
+
+
+def load_all_opcode_counts(
+ directory: Path, remove_from_fixture_names: List[str]
+) -> Dict[str, OpcodeCount]:
+ """Load all opcode counts from all JSON files in a directory."""
+ all_opcode_counts = {}
+ json_files = find_json_files(directory)
+
+ for json_file in json_files:
+ fixtures = load_fixtures_from_file(
+ json_file, remove_from_fixture_names=remove_from_fixture_names
+ )
+ if fixtures:
+ file_opcode_counts = extract_opcode_counts_from_fixtures(fixtures)
+ # Use fixture name as key, if there are conflicts, choose the last
+ all_opcode_counts.update(file_opcode_counts)
+
+ return all_opcode_counts
+
+
+def compare_opcode_counts(count1: OpcodeCount, count2: OpcodeCount) -> Dict[str, int]:
+ """Compare two opcode counts and return the differences."""
+ differences = {}
+
+ # Get all unique opcodes from both counts
+ all_opcodes = set(count1.root.keys()) | set(count2.root.keys())
+
+ for opcode in all_opcodes:
+ val1 = count1.root.get(opcode, 0)
+ val2 = count2.root.get(opcode, 0)
+ diff = val2 - val1
+ if diff != 0:
+ differences[str(opcode)] = diff
+
+ return differences
+
+
+@click.command()
+@click.argument("base", type=click.Path(exists=True, file_okay=False, path_type=Path))
+@click.argument("patch", type=click.Path(exists=True, file_okay=False, path_type=Path))
+@click.option(
+ "--show-common",
+ is_flag=True,
+ help="Print fixtures that contain identical opcode counts.",
+)
+@click.option(
+ "--show-missing",
+ is_flag=True,
+ help="Print fixtures only found in one of the folders.",
+)
+@click.option(
+ "--remove-from-fixture-names",
+ "-r",
+ multiple=True,
+ help="String to be removed from the fixture name, in case the fixture names have changed, "
+ "in order to make the comparison easier. "
+ "Can be specified multiple times.",
+)
+def main(
+ base: Path,
+ patch: Path,
+ show_common: bool,
+ show_missing: bool,
+ remove_from_fixture_names: List[str],
+):
+ """Crawl two folders, compare and print the opcode count diffs."""
+ print(f"Loading opcode counts from {base}...")
+ opcode_counts1 = load_all_opcode_counts(base, remove_from_fixture_names)
+ print(f"Found {len(opcode_counts1)} fixtures with opcode counts")
+
+ print(f"Loading opcode counts from {patch}...")
+ opcode_counts2 = load_all_opcode_counts(patch, remove_from_fixture_names)
+ print(f"Found {len(opcode_counts2)} fixtures with opcode counts")
+
+ # Find common fixture names
+ common_names = set(opcode_counts1.keys()) & set(opcode_counts2.keys())
+ only_in_1 = set(opcode_counts1.keys()) - set(opcode_counts2.keys())
+ only_in_2 = set(opcode_counts2.keys()) - set(opcode_counts1.keys())
+
+ print("\nSummary:")
+ print(f" Common fixtures: {len(common_names)}")
+ print(f" Only in {base.name}: {len(only_in_1)}")
+ print(f" Only in {patch.name}: {len(only_in_2)}")
+
+ # Show missing fixtures if requested
+ if show_missing:
+ if only_in_1:
+ print(f"\nFixtures only in {base.name}:")
+ for name in sorted(only_in_1):
+ print(f" {name}")
+
+ if only_in_2:
+ print(f"\nFixtures only in {patch.name}:")
+ for name in sorted(only_in_2):
+ print(f" {name}")
+
+ # Compare common fixtures
+ differences_found = False
+ common_with_same_counts = 0
+
+ for fixture_name in sorted(common_names):
+ count1 = opcode_counts1[fixture_name]
+ count2 = opcode_counts2[fixture_name]
+
+ differences = compare_opcode_counts(count1, count2)
+
+ if differences:
+ differences_found = True
+ print(f"\n{fixture_name}:")
+ for opcode, diff in sorted(differences.items()):
+ if diff > 0:
+ print(f" +{diff} {opcode}")
+ else:
+ print(f" {diff} {opcode}")
+ elif show_common:
+ print(f"\n{fixture_name}: No differences")
+ common_with_same_counts += 1
+
+ if not differences_found:
+ print("\nNo differences found in opcode counts between common fixtures!")
+ elif show_common:
+ print(f"\n{common_with_same_counts} fixtures have identical opcode counts")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/ethereum_spec_tests/cli/eest/__init__.py b/packages/tests/src/cli/eest/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/eest/__init__.py
rename to packages/tests/src/cli/eest/__init__.py
diff --git a/src/ethereum_spec_tests/cli/eest/cli.py b/packages/tests/src/cli/eest/cli.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/eest/cli.py
rename to packages/tests/src/cli/eest/cli.py
diff --git a/src/ethereum_spec_tests/cli/eest/commands/__init__.py b/packages/tests/src/cli/eest/commands/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/eest/commands/__init__.py
rename to packages/tests/src/cli/eest/commands/__init__.py
diff --git a/src/ethereum_spec_tests/cli/eest/commands/clean.py b/packages/tests/src/cli/eest/commands/clean.py
similarity index 95%
rename from src/ethereum_spec_tests/cli/eest/commands/clean.py
rename to packages/tests/src/cli/eest/commands/clean.py
index a0a65ab743..58f7b93dac 100644
--- a/src/ethereum_spec_tests/cli/eest/commands/clean.py
+++ b/packages/tests/src/cli/eest/commands/clean.py
@@ -19,18 +19,23 @@
def clean(all_files: bool, dry_run: bool, verbose: bool):
"""
Remove all generated files and directories from the repository.
- If `--all` is specified, the virtual environment and .tox directory will also be removed.
+
+ If `--all` is specified, the virtual environment and .tox directory will
+ also be removed.
Args:
- all_files (bool): Remove the virtual environment and .tox directory as well.
+ all_files (bool): Remove the virtual environment and .tox directory
+ as well.
dry_run (bool): Simulate the cleanup without removing files.
verbose (bool): Show verbose output.
- Note: The virtual environment and .tox directory are not removed by default.
+ Note: The virtual environment and .tox directory are not removed by
+ default.
- Example: Cleaning all generated files and directories and show the deleted items.
+ Example: Cleaning all generated files and directories and show the deleted
+ items.
uv run eest clean --all -v
diff --git a/src/ethereum_spec_tests/cli/eest/commands/info.py b/packages/tests/src/cli/eest/commands/info.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/eest/commands/info.py
rename to packages/tests/src/cli/eest/commands/info.py
diff --git a/src/ethereum_spec_tests/cli/eest/make/__init__.py b/packages/tests/src/cli/eest/make/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/eest/make/__init__.py
rename to packages/tests/src/cli/eest/make/__init__.py
diff --git a/src/ethereum_spec_tests/cli/eest/make/cli.py b/packages/tests/src/cli/eest/make/cli.py
similarity index 71%
rename from src/ethereum_spec_tests/cli/eest/make/cli.py
rename to packages/tests/src/cli/eest/make/cli.py
index 413050d7a7..ae0c75ba8a 100644
--- a/src/ethereum_spec_tests/cli/eest/make/cli.py
+++ b/packages/tests/src/cli/eest/make/cli.py
@@ -1,11 +1,14 @@
"""
-The `make` CLI streamlines the process of scaffolding tasks, such as generating new test files,
-enabling developers to concentrate on the core aspects of specification testing.
+The `make` CLI streamlines the process of scaffolding tasks, such as generating
+new test files, enabling developers to concentrate on the core aspects of
+specification testing.
-The module calls the appropriate function for the subcommand. If an invalid subcommand
-is chosen, it throws an error and shows a list of valid subcommands. If no subcommand
-is present, it shows a list of valid subcommands to choose from.
+
+The module calls the appropriate function for the subcommand. If an invalid
+subcommand is chosen, it throws an error and shows a list of valid subcommands.
+If no subcommand is present, it shows a list of valid subcommands to choose
+from.
"""
import click
diff --git a/packages/tests/src/cli/eest/make/commands/__init__.py b/packages/tests/src/cli/eest/make/commands/__init__.py
new file mode 100644
index 0000000000..64234b3000
--- /dev/null
+++ b/packages/tests/src/cli/eest/make/commands/__init__.py
@@ -0,0 +1,11 @@
+"""
+Holds subcommands for the make command.
+
+New subcommands must be created as modules and exported from this package,
+then registered under the make command in `cli.py`.
+"""
+
+from .env import create_default_env
+from .test import test
+
+__all__ = ["test", "create_default_env"]
diff --git a/src/ethereum_spec_tests/cli/eest/make/commands/env.py b/packages/tests/src/cli/eest/make/commands/env.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/eest/make/commands/env.py
rename to packages/tests/src/cli/eest/make/commands/env.py
diff --git a/src/ethereum_spec_tests/cli/eest/make/commands/test.py b/packages/tests/src/cli/eest/make/commands/test.py
similarity index 90%
rename from src/ethereum_spec_tests/cli/eest/make/commands/test.py
rename to packages/tests/src/cli/eest/make/commands/test.py
index 0eb6e49141..2d30ee195b 100644
--- a/src/ethereum_spec_tests/cli/eest/make/commands/test.py
+++ b/packages/tests/src/cli/eest/make/commands/test.py
@@ -1,9 +1,10 @@
"""
Provides a CLI command to scaffold a test file.
-The `test` command guides the user through a series of prompts to generate a test file
-based on the selected test type, fork, EIP number, and EIP name. The generated test file
-is saved in the appropriate directory with a rendered template using Jinja2.
+The `test` command guides the user through a series of prompts to generate a
+test file based on the selected test type, fork, EIP number, and EIP name. The
+generated test file is saved in the appropriate directory with a rendered
+template using Jinja2.
"""
import os
@@ -38,10 +39,11 @@ def test():
"""
Generate a new test file for an EIP.
- This function guides the user through a series of prompts to generate a test file
- for Ethereum execution specifications. The user is prompted to select the type of test,
- the fork to use, and to provide the EIP number and name. Based on the inputs, a test file
- is created in the appropriate directory with a rendered template.
+ This function guides the user through a series of prompts to generate a
+ test file for Ethereum execution specifications. The user is prompted to
+ select the type of test, the fork to use, and to provide the EIP number and
+ name. Based on the inputs, a test file is created in the appropriate
+ directory with a rendered template.
Example:
uv run eest make test
diff --git a/src/ethereum_spec_tests/cli/eest/make/templates/blockchain_test.py.j2 b/packages/tests/src/cli/eest/make/templates/blockchain_test.py.j2
similarity index 97%
rename from src/ethereum_spec_tests/cli/eest/make/templates/blockchain_test.py.j2
rename to packages/tests/src/cli/eest/make/templates/blockchain_test.py.j2
index beb6bdd4d8..7cb2c14aad 100644
--- a/src/ethereum_spec_tests/cli/eest/make/templates/blockchain_test.py.j2
+++ b/packages/tests/src/cli/eest/make/templates/blockchain_test.py.j2
@@ -14,7 +14,7 @@ from ethereum_test_tools import (
Environment,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "DUMMY/eip-DUMMY.md"
REFERENCE_SPEC_VERSION = "DUMMY_VERSION"
diff --git a/src/ethereum_spec_tests/cli/eest/make/templates/state_test.py.j2 b/packages/tests/src/cli/eest/make/templates/state_test.py.j2
similarity index 97%
rename from src/ethereum_spec_tests/cli/eest/make/templates/state_test.py.j2
rename to packages/tests/src/cli/eest/make/templates/state_test.py.j2
index 35d845ca27..ad5c12a7a6 100644
--- a/src/ethereum_spec_tests/cli/eest/make/templates/state_test.py.j2
+++ b/packages/tests/src/cli/eest/make/templates/state_test.py.j2
@@ -7,7 +7,7 @@ import pytest
from ethereum_test_forks import Fork
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "DUMMY/eip-DUMMY.md"
REFERENCE_SPEC_VERSION = "DUMMY_VERSION"
diff --git a/src/ethereum_spec_tests/cli/eest/quotes.py b/packages/tests/src/cli/eest/quotes.py
similarity index 96%
rename from src/ethereum_spec_tests/cli/eest/quotes.py
rename to packages/tests/src/cli/eest/quotes.py
index dfd8353072..e097a31b9f 100644
--- a/src/ethereum_spec_tests/cli/eest/quotes.py
+++ b/packages/tests/src/cli/eest/quotes.py
@@ -51,5 +51,7 @@ def box_quote(quote):
def get_quote():
- """Return random inspirational quote related to system design formatted in a box."""
+ """
+ Return random inspirational quote formatted in a box.
+ """
return box_quote(random.choice(make_something_great))
diff --git a/src/ethereum_spec_tests/cli/eofwrap.py b/packages/tests/src/cli/eofwrap.py
similarity index 93%
rename from src/ethereum_spec_tests/cli/eofwrap.py
rename to packages/tests/src/cli/eofwrap.py
index 479eb045fd..9d8382a74c 100644
--- a/src/ethereum_spec_tests/cli/eofwrap.py
+++ b/packages/tests/src/cli/eofwrap.py
@@ -1,6 +1,6 @@
"""
-Generate a JSON blockchain test from an existing JSON blockchain test by wrapping its pre-state
-code in EOF wherever possible.
+Generate a JSON blockchain test from an existing JSON blockchain test by
+wrapping its pre-state code in EOF wherever possible.
Example Usage:
@@ -33,7 +33,7 @@
from ethereum_test_types import Transaction
from ethereum_test_types.block_types import Environment
from ethereum_test_types.eof.v1 import Container
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
from .evm_bytes import OpcodeWithOperands, process_evm_bytes
@@ -44,8 +44,8 @@
@click.option("--traces", is_flag=True, type=bool)
def eof_wrap(input_path: str, output_dir: str, traces: bool):
"""
- Wrap JSON blockchain test file(s) found at `input_path` and
- outputs them to the `output_dir`.
+ Wrap JSON blockchain test file(s) found at `input_path` and outputs them to
+ the `output_dir`.
"""
eof_wrapper = EofWrapper()
@@ -116,7 +116,9 @@ class EofWrapper:
GENERATION_ERRORS = "generation_errors"
def __init__(self):
- """Initialize the EofWrapper with metrics tracking and a unique EOF set."""
+ """
+ Initialize the EofWrapper with metrics tracking and a unique EOF set.
+ """
self.metrics = {
self.FILES_GENERATED: 0,
self.FILES_SKIPPED: 0,
@@ -135,7 +137,8 @@ def __init__(self):
file_skip_list = [
"Pyspecs",
- # EXTCODE* opcodes return different results for EOF targets and that is tested elsewhere
+ # EXTCODE* opcodes return different results for EOF targets and that is
+ # tested elsewhere
"stExtCodeHash",
# bigint syntax
"ValueOverflowParis",
@@ -168,10 +171,11 @@ def __init__(self):
def wrap_file(self, in_path: str, out_path: str, traces: bool):
"""
- Wrap code from a blockchain test JSON file from `in_path` into EOF containers,
- wherever possible. If not possible - skips and tracks that in metrics. Possible means
- at least one account's code can be wrapped in a valid EOF container and the assertions
- on post state are satisfied.
+ Wrap code from a blockchain test JSON file from `in_path` into EOF
+ containers, wherever possible. If not possible - skips and tracks that
+ in metrics. Possible means at least one account's code can be wrapped
+ in a valid EOF container and the assertions on post state are
+ satisfied.
"""
for skip in self.file_skip_list:
if skip in in_path:
@@ -301,9 +305,9 @@ def _wrap_fixture(self, fixture: BlockchainFixture, traces: bool):
test.blocks.append(block)
elif isinstance(fixture_block, InvalidFixtureBlock):
- # Skip - invalid blocks are not supported. Reason: FixtureTransaction doesn't
- # support expected exception. But we can continue and test the remaining
- # blocks.
+ # Skip - invalid blocks are not supported. Reason:
+ # FixtureTransaction doesn't support expected exception. But we
+ # can continue and test the remaining blocks.
self.metrics[self.INVALID_BLOCKS_SKIPPED] += 1
else:
raise TypeError("not a FixtureBlock")
@@ -331,13 +335,13 @@ def _validate_eof(self, container: Container, metrics: bool = True) -> bool:
return True
-# `no_type_check` required because OpcodeWithOperand.opcode can be `None` when formatting as a
-# string, but here it can never be `None`.
+# `no_type_check` required because OpcodeWithOperand.opcode can be `None` when
+# formatting as a string, but here it can never be `None`.
@no_type_check
def wrap_code(account_code: Bytes) -> Container:
"""
- Wrap `account_code` into a simplest EOF container, applying some simple heuristics in
- order to obtain a valid code section termination.
+ Wrap `account_code` into a simplest EOF container, applying some simple
+ heuristics in order to obtain a valid code section termination.
"""
assert len(account_code) > 0
diff --git a/src/ethereum_spec_tests/cli/evm_bytes.py b/packages/tests/src/cli/evm_bytes.py
similarity index 96%
rename from src/ethereum_spec_tests/cli/evm_bytes.py
rename to packages/tests/src/cli/evm_bytes.py
index cfe3c6283f..7f4a73f096 100644
--- a/src/ethereum_spec_tests/cli/evm_bytes.py
+++ b/packages/tests/src/cli/evm_bytes.py
@@ -6,9 +6,8 @@
import click
from ethereum_test_base_types import ZeroPaddedHexNumber
-from ethereum_test_vm import Macro
+from ethereum_test_vm import Bytecode, Macro
from ethereum_test_vm import Opcodes as Op
-from ethereum_test_vm.bytecode import Bytecode
OPCODES_WITH_EMPTY_LINES_AFTER = {
Op.STOP,
@@ -63,7 +62,8 @@ def terminating(self) -> bool:
@property
def bytecode(self) -> Bytecode:
"""Opcode as bytecode with its operands if any."""
- # opcode.opcode[*opcode.operands] crashes `black` formatter and doesn't work.
+ # opcode.opcode[*opcode.operands] crashes `black` formatter and doesn't
+ # work.
if self.opcode:
return self.opcode.__getitem__(*self.operands) if self.operands else self.opcode
else:
@@ -182,7 +182,8 @@ def hex_string(hex_string: str, assembly: bool):
Output 1:
\b
- Op.PUSH1[0x42] + Op.PUSH1[0x0] + Op.MSTORE + Op.PUSH1[0x20] + Op.PUSH1[0x0] + Op.RETURN
+ Op.PUSH1[0x42] + Op.PUSH1[0x0] + Op.MSTORE + Op.PUSH1[0x20] +
+ Op.PUSH1[0x0] + Op.RETURN
Example 2: Convert a hex string to assembly
uv run evm_bytes hex-string --assembly 604260005260206000F3
@@ -208,14 +209,16 @@ def binary_file(binary_file, assembly: bool):
"""
Convert the BINARY_FILE containing EVM bytes to Python Opcodes or assembly.
- BINARY_FILE is a binary file containing EVM bytes, use `-` to read from stdin.
+ BINARY_FILE is a binary file containing EVM bytes, use `-` to read from
+ stdin.
Returns:
(str): The processed EVM opcodes in Python or assembly format.
Example: Convert the Withdrawal Request contract to assembly
\b
- uv run evm_bytes binary-file ./src/ethereum_test_forks/forks/contracts/withdrawal_request.bin --assembly
+ uv run evm_bytes binary-file ./src/ethereum_test_forks/forks/
+ contracts/withdrawal_request.bin --assembly
Output:
\b
@@ -226,6 +229,6 @@ def binary_file(binary_file, assembly: bool):
jumpi
...
- """ # noqa: E501,D301
+ """ # noqa: D301
processed_output = format_opcodes(process_evm_bytes(binary_file.read()), assembly=assembly)
click.echo(processed_output)
diff --git a/src/ethereum_spec_tests/cli/extract_config.py b/packages/tests/src/cli/extract_config.py
similarity index 97%
rename from src/ethereum_spec_tests/cli/extract_config.py
rename to packages/tests/src/cli/extract_config.py
index 503c352eb1..bf0e1f717c 100755
--- a/src/ethereum_spec_tests/cli/extract_config.py
+++ b/packages/tests/src/cli/extract_config.py
@@ -1,9 +1,11 @@
#!/usr/bin/env python
"""
-CLI tool to extract client configuration files (chainspec/genesis.json) from Ethereum clients.
+CLI tool to extract client configuration files (chainspec/genesis.json) from
+Ethereum clients.
-This tool spawns an Ethereum client using Hive and extracts the generated configuration
-files such as /chainspec/test.json, /configs/test.cfg, or /genesis.json from the Docker container.
+This tool spawns an Ethereum client using Hive and extracts the generated
+configuration files such as /chainspec/test.json, /configs/test.cfg, or
+/genesis.json from the Docker container.
"""
import io
@@ -119,7 +121,9 @@ def create_genesis_from_fixture(fixture_path: Path) -> Tuple[FixtureHeader, Allo
def get_client_environment_for_fixture(fork: Fork, chain_id: int) -> dict:
- """Get the environment variables for starting a client with the given fixture."""
+ """
+ Get the environment variables for starting a client with the given fixture.
+ """
if fork not in ruleset:
raise ValueError(f"Fork '{fork}' not found in hive ruleset")
@@ -176,8 +180,8 @@ def extract_config(
Extract client configuration files from Ethereum clients.
This tool spawns an Ethereum client using Hive and extracts the generated
- configuration files such as /chainspec/test.json, /configs/test.cfg, or /genesis.json
- from the Docker container.
+ configuration files such as /chainspec/test.json, /configs/test.cfg, or
+ /genesis.json from the Docker container.
"""
if not fixture:
raise click.UsageError("No fixture provided, use --fixture to specify a fixture")
diff --git a/src/ethereum_spec_tests/cli/fillerconvert/fillerconvert.py b/packages/tests/src/cli/fillerconvert/fillerconvert.py
similarity index 95%
rename from src/ethereum_spec_tests/cli/fillerconvert/fillerconvert.py
rename to packages/tests/src/cli/fillerconvert/fillerconvert.py
index 6cb7a5f3b5..c7392fd420 100644
--- a/src/ethereum_spec_tests/cli/fillerconvert/fillerconvert.py
+++ b/packages/tests/src/cli/fillerconvert/fillerconvert.py
@@ -44,5 +44,6 @@ def main() -> None:
# or file.endswith("vmPerformance/performanceTesterFiller.yml")
# or file.endswith("vmPerformance/loopExpFiller.yml")
# or file.endswith("vmPerformance/loopMulFiller.yml")
- # or file.endswith("stRevertTest/RevertRemoteSubCallStorageOOGFiller.yml")
+ # or
+ # file.endswith("stRevertTest/RevertRemoteSubCallStorageOOGFiller.yml")
# or file.endswith("stSolidityTest/SelfDestructFiller.yml")
diff --git a/src/ethereum_spec_tests/cli/fillerconvert/verify_filled.py b/packages/tests/src/cli/fillerconvert/verify_filled.py
similarity index 92%
rename from src/ethereum_spec_tests/cli/fillerconvert/verify_filled.py
rename to packages/tests/src/cli/fillerconvert/verify_filled.py
index 706d62ac3e..3c3302342e 100644
--- a/src/ethereum_spec_tests/cli/fillerconvert/verify_filled.py
+++ b/packages/tests/src/cli/fillerconvert/verify_filled.py
@@ -34,10 +34,9 @@ class FilledStateTest(RootModel[dict[str, StateTest]]):
def verify_refilled(refilled: Path, original: Path) -> int:
"""
- Verify post hash of the refilled test against original:
- Regex the original d,g,v from the refilled test name.
- Find the post record for this d,g,v and the fork of refilled test.
- Compare the post hash.
+ Verify post hash of the refilled test against original: Regex the original
+ d,g,v from the refilled test name. Find the post record for this d,g,v and
+ the fork of refilled test. Compare the post hash.
"""
verified_vectors = 0
json_str = refilled.read_text(encoding="utf-8")
@@ -46,7 +45,8 @@ def verify_refilled(refilled: Path, original: Path) -> int:
json_str = original.read_text(encoding="utf-8")
original_test_wrapper = FilledStateTest.model_validate_json(json_str)
- # Each original test has only 1 test with many posts for each fork and many txs
+ # Each original test has only 1 test with many posts for each fork and many
+ # txs
original_test_name, test_original = list(original_test_wrapper.root.items())[0]
for refilled_test_name, refilled_test in refilled_test_wrapper.root.items():
diff --git a/packages/tests/src/cli/fuzzer_bridge/README.md b/packages/tests/src/cli/fuzzer_bridge/README.md
new file mode 100644
index 0000000000..6f54cce908
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/README.md
@@ -0,0 +1,301 @@
+# Fuzzer Bridge for Execution Spec Tests
+
+This module provides a bridge between blocktest fuzzers (like `blocktest-fuzzer`) and the Ethereum execution-spec-tests framework, enabling automatic generation of valid blockchain test fixtures from fuzzer output.
+
+## Overview
+
+The fuzzer bridge solves a critical problem: fuzzers can generate transactions and pre-state, but creating valid blockchain tests requires complex calculations (state roots, RLP encoding, block headers, etc.). This bridge leverages the execution-spec-tests framework to handle all these complexities.
+
+## Architecture
+
+```mermaid
+graph LR
+ A[Blocktest
Fuzzer] -->|JSON
v2 format| B[Fuzzer
Bridge]
+ B -->|Blockchain Test
Fixtures| C[Ethereum
Clients]
+```
+
+## Fuzzer Output Format (v2)
+
+The fuzzer must output JSON in the following format:
+
+```json
+{
+ "version": "2.0",
+ "fork": "Prague",
+ "chainId": 1,
+ "accounts": {
+ "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf": {
+ "balance": "0x1000000000000000000",
+ "nonce": "0x0",
+ "code": "",
+ "storage": {},
+ "privateKey": "0x0000000000000000000000000000000000000000000000000000000000000001"
+ },
+ "0x2b5ad5c4795c026514f8317c7a215e218dccd6cf": {
+ "balance": "0x100000000000000000",
+ "nonce": "0x0",
+ "code": "0x600160005260206000f3",
+ "storage": {}
+ }
+ },
+ "transactions": [
+ {
+ "from": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf",
+ "to": "0x2b5ad5c4795c026514f8317c7a215e218dccd6cf",
+ "value": "0x100",
+ "gas": "0x5208",
+ "gasPrice": "0x7",
+ "nonce": "0x0",
+ "data": "0x"
+ }
+ ],
+ "env": {
+ "currentCoinbase": "0xc014ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x0",
+ "currentGasLimit": "0x1000000",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x1000",
+ "currentBaseFee": "0x7",
+ "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000000000"
+ }
+}
+```
+
+### Key Requirements
+
+1. **Private Keys**: Any account that sends transactions MUST include a `privateKey` field.
+2. **Address-Key Match**: Private keys must generate the corresponding addresses.
+3. **Environment**: Describes the environment for block 1 (genesis is automatically derived).
+4. **Version**: Use "2.0" for this format.
+
+## Architecture: DTO Pattern
+
+The fuzzer bridge uses a **Data Transfer Object (DTO) pattern** for clean separation between external data format and internal domain logic.
+
+### Design Flow
+
+```mermaid
+graph TD
+ A["Fuzzer JSON Output
(JSON-RPC Format v2.0)"]
+
+ B["DTOs (Pydantic Models)
models.py"]
+ B1["FuzzerAccountInput
Raw account JSON"]
+ B2["FuzzerTransactionInput
Raw transaction JSON (uses 'gas')"]
+ B3["FuzzerAuthorizationInput
Raw auth tuple (EIP-7702)"]
+ B4["FuzzerOutput
Complete fuzzer output"]
+
+ C["EEST Domain Models
converter.py"]
+ C1["Account
With validation & defaults"]
+ C2["Transaction
With gas_limit, EOA sender"]
+ C3["AuthorizationTuple
EIP-7702 support"]
+ C4["EOA
Created from private keys"]
+
+ D["BlockchainTest"]
+ E["Blockchain Fixture"]
+
+ A -->|parse| B
+ B -.-> B1
+ B -.-> B2
+ B -.-> B3
+ B -.-> B4
+
+ B -->|convert| C
+ C -.-> C1
+ C -.-> C2
+ C -.-> C3
+ C -.-> C4
+
+ C -->|generate| D
+ D --> E
+
+ style A fill:#e1f5ff
+ style B fill:#fff4e1
+ style C fill:#e8f5e9
+ style D fill:#f3e5f5
+ style E fill:#fce4ec
+```
+
+### Why DTOs?
+
+1. **Separation of Concerns**
+ - External JSON-RPC format ≠ EEST internal representation
+ - Fuzzer format can change without affecting EEST domain models
+
+2. **No Side Effects During Parsing**
+ - DTOs don't trigger `model_post_init` validation logic
+ - Parsing is purely data extraction, no business logic
+
+3. **Explicit Field Mapping**
+ - Clear visibility: `gas` → `gas_limit`, `from` → `sender` (EOA)
+ - Type-safe conversions at boundary
+
+4. **Prevents TestAddress Pollution**
+ - EOA created in converter BEFORE Transaction instantiation
+ - Transaction.model_post_init never injects TestAddress
+
+### Key Field Mappings
+
+| Fuzzer Field (JSON-RPC) | DTO Field | EEST Domain Field | Notes |
+|-------------------------|----------------------|----------------------|--------------------------------|
+| `from` | `from_` | `sender` (EOA) | Creates EOA from private key |
+| `gas` | `gas` | `gas_limit` | JSON-RPC vs internal naming |
+| `data` | `data` | `data` | Same field, explicit mapping |
+| `gasPrice` | `gas_price` | `gas_price` | CamelCase → snake_case |
+| `authorizationList` | `authorization_list` | `authorization_list` | EIP-7702 support |
+| `privateKey` | `private_key` | (used to create EOA) | Not stored in Account model |
+
+### Module Responsibilities
+
+#### `models.py` - Data Transfer Objects
+- Pure Pydantic models for fuzzer JSON format
+- No business logic, only data validation
+- Accepts JSON-RPC naming conventions (camelCase)
+- ~119 lines
+
+#### `converter.py` - Transformation Logic
+- Pure functions: DTO → EEST domain models
+- All field mapping logic centralized here
+- Creates EOA objects from private keys
+- Builds BlockchainTest from validated data
+- ~305 lines
+
+#### `blocktest_builder.py` - CLI Integration
+- Orchestrates conversion workflow
+- Handles file I/O and CLI options
+- Calls converter functions
+- ~90 lines
+
+### Benefits
+
+✅ **Maintainability**: Changes to Account/Transaction propagate automatically
+✅ **Testability**: Each layer tested independently
+✅ **Type Safety**: Full type checking at DTO and domain layers
+✅ **Clarity**: Field mappings are explicit and documented
+✅ **No Circular Dependencies**: Clean module boundaries
+
+### Alternative Design: Why Not Inheritance?
+
+**Could have done**:
+```python
+class FuzzerAccount(Account):
+ private_key: Hash | None = None
+```
+
+**Why DTOs are better**:
+- Inheritance couples external format to domain model
+- model_post_init triggers during parsing (side effects)
+- Field name mismatches require complex aliasing
+- Harder to test layers independently
+
+The DTO pattern provides cleaner separation and explicit control.
+
+## Installation
+
+See the [EEST installation guide](https://eest.ethereum.org/main/getting_started/installation/) for setting up the execution-spec-tests framework.
+
+Once EEST is installed, the fuzzer bridge will be available as a command-line tool.
+
+## Usage
+
+### 1. Command Line Interface
+
+```bash
+# Convert fuzzer output to blockchain test
+uv run fuzzer_bridge --input fuzzer_output.json --output blocktest.json
+
+# With custom fork
+uv run fuzzer_bridge --input fuzzer_output.json --output blocktest.json --fork Shanghai
+
+# Pretty print output
+uv run fuzzer_bridge --input fuzzer_output.json --output blocktest.json --pretty
+```
+
+### 2. Python API
+
+```python
+from fuzzer_bridge import FuzzerBridge
+
+# Load fuzzer output
+with open("fuzzer_output.json") as f:
+ fuzzer_data = json.load(f)
+
+# Create bridge and convert
+bridge = FuzzerBridge()
+blocktest = bridge.convert(fuzzer_data)
+
+# Save to file
+bridge.save(blocktest, "output.json")
+
+# Or verify with geth directly
+result = bridge.verify_with_geth(blocktest, geth_path="../go-ethereum/build/bin/evm")
+print(f"Test passed: {result['pass']}")
+```
+
+### 3. Integration with pytest
+
+```python
+import pytest
+from fuzzer_bridge import create_test_from_fuzzer
+
+def test_fuzzer_generated(blockchain_test):
+ """Test generated from fuzzer output."""
+ test = create_test_from_fuzzer("fuzzer_output.json")
+ blockchain_test(**test)
+```
+
+## Key Insights
+
+### Genesis Block Handling
+- The fuzzer describes the environment for block 1 (the block being tested)
+- Genesis (block 0) environment is automatically derived:
+ - `number` = 0
+ - `timestamp` = block1_timestamp - 12
+ - Other values inherited or set to defaults
+
+### System Contracts
+- The framework automatically adds system contracts (deposit, withdrawal, etc.)
+- These are included in the state root calculation
+- The fuzzer doesn't need to specify them
+
+### Private Key Requirements
+- Every account that sends transactions needs a private key
+- The private key must generate the exact address specified
+- Without matching private keys, transactions cannot be signed
+
+## Troubleshooting
+
+### "Genesis block hash doesn't match"
+**Cause**: Usually means the environment is set incorrectly (e.g., block number = 1 instead of 0 for genesis)
+**Solution**: Ensure the fuzzer output follows the v2 format exactly
+
+### "No private key for sender"
+**Cause**: Account sends transaction but no privateKey field provided
+**Solution**: Add privateKey to the account in the accounts section
+
+### "Private key doesn't match address"
+**Cause**: The provided private key doesn't generate the specified address
+**Solution**: Use correct private key or generate address from private key
+
+## Testing with Ethereum Clients
+
+### Go-Ethereum (geth)
+```bash
+../go-ethereum/build/bin/evm blocktest generated_test.json
+```
+
+### Besu
+```bash
+../besu/ethereum/evmtool/build/install/evmtool/bin/evmtool block-test generated_test.json
+```
+
+### Nethermind
+```bash
+../nethermind/src/Nethermind/artifacts/bin/Nethermind.Test.Runner/release_linux-x64/nethtest -b -i generated_test.json
+```
+
+## Contributing
+
+When modifying the fuzzer bridge:
+1. Add tests for new features.
+2. Update this README.
+3. Ensure compatibility with latest execution-spec-tests.
\ No newline at end of file
diff --git a/packages/tests/src/cli/fuzzer_bridge/__init__.py b/packages/tests/src/cli/fuzzer_bridge/__init__.py
new file mode 100644
index 0000000000..14ef2a3cd2
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/__init__.py
@@ -0,0 +1,5 @@
+"""Fuzzer bridge for converting blocktest-fuzzer output to blocktests."""
+
+from .blocktest_builder import BlocktestBuilder, build_blocktest_from_fuzzer
+
+__all__ = ["BlocktestBuilder", "build_blocktest_from_fuzzer"]
diff --git a/packages/tests/src/cli/fuzzer_bridge/blocktest_builder.py b/packages/tests/src/cli/fuzzer_bridge/blocktest_builder.py
new file mode 100644
index 0000000000..c2b832d09e
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/blocktest_builder.py
@@ -0,0 +1,90 @@
+"""Build valid blocktests from fuzzer-generated transactions and pre-state."""
+
+import json
+import random
+from pathlib import Path
+from typing import Any, Dict, Optional
+
+from ethereum_clis import GethTransitionTool, TransitionTool
+from ethereum_test_fixtures import BlockchainFixture
+
+from .converter import blockchain_test_from_fuzzer
+from .models import FuzzerOutput
+
+
+def choose_random_num_blocks(num_txs: int, max_blocks: int = 10) -> int:
+ """
+ Choose random number of blocks for given transaction count.
+
+ Selects a random number between 1 and min(num_txs, max_blocks) to enable
+ testing of various block configurations.
+
+ Args:
+ num_txs: Number of transactions to distribute
+ max_blocks: Maximum number of blocks (default: 10)
+
+ Returns:
+ Random integer between 1 and min(num_txs, max_blocks)
+
+ """
+ if num_txs == 0:
+ return 1 # Allow empty block testing
+ return random.randint(1, min(num_txs, max_blocks))
+
+
+class BlocktestBuilder:
+ """Build valid blocktests from fuzzer-generated transactions."""
+
+ def __init__(self, transition_tool: Optional[TransitionTool] = None):
+ """Initialize the builder with optional transition tool."""
+ self.t8n = transition_tool or GethTransitionTool()
+
+ def build_blocktest(
+ self,
+ fuzzer_output: Dict[str, Any],
+ num_blocks: int = 1,
+ block_strategy: str = "distribute",
+ block_time: int = 12,
+ ) -> Dict[str, Any]:
+ """Build a valid blocktest from fuzzer output."""
+ # Parse and validate using Pydantic model
+ fuzzer_data = FuzzerOutput(**fuzzer_output)
+
+ # Get fork
+ fork = fuzzer_data.fork
+
+ # Create BlockchainTest using converter
+ test = blockchain_test_from_fuzzer(
+ fuzzer_data,
+ fork,
+ num_blocks=num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ )
+
+ # Generate fixture
+ fixture = test.generate(
+ t8n=self.t8n,
+ fork=fork,
+ fixture_format=BlockchainFixture,
+ )
+
+ return fixture.model_dump(exclude_none=True, by_alias=True, mode="json")
+
+ def build_and_save(self, fuzzer_output: Dict[str, Any], output_path: Path) -> Path:
+ """Build blocktest and save to file."""
+ blocktest = self.build_blocktest(fuzzer_output)
+ fixtures = {"fuzzer_generated_test": blocktest}
+
+ with open(output_path, "w") as f:
+ json.dump(fixtures, f, indent=2)
+
+ return output_path
+
+
+def build_blocktest_from_fuzzer(
+ fuzzer_data: Dict[str, Any], t8n: Optional[TransitionTool] = None
+) -> Dict[str, Any]:
+ """Build blocktest from fuzzer output."""
+ builder = BlocktestBuilder(t8n)
+ return builder.build_blocktest(fuzzer_data)
diff --git a/packages/tests/src/cli/fuzzer_bridge/cli.py b/packages/tests/src/cli/fuzzer_bridge/cli.py
new file mode 100644
index 0000000000..37b700c7f2
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/cli.py
@@ -0,0 +1,752 @@
+"""Command-line interface for the fuzzer bridge."""
+
+import json
+import multiprocessing as mp
+from concurrent.futures import ProcessPoolExecutor, as_completed
+from functools import partial
+from pathlib import Path
+from typing import Any, Dict, Generator, Optional, Tuple
+
+import click
+from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeElapsedColumn
+
+from ethereum_clis import GethTransitionTool, TransitionTool
+
+from .blocktest_builder import BlocktestBuilder
+
+
+def count_json_files(start_path: Path) -> int:
+ """Count JSON files in directory."""
+ return sum(1 for _ in start_path.rglob("*.json"))
+
+
+def get_input_files(input_path: Path) -> Generator[Path, None, None]:
+ """Generate input file paths."""
+ if input_path.is_file():
+ yield input_path
+ else:
+ yield from input_path.rglob("*.json")
+
+
+def generate_test_name(file_path: Path, index: int = 0) -> str:
+ """Generate unique test name from file path."""
+ stem = file_path.stem
+ if index > 0:
+ return f"fuzzer_{stem}_{index}"
+ return f"fuzzer_{stem}"
+
+
+def process_single_file(
+ input_file: Path,
+ output_path: Path,
+ builder: BlocktestBuilder,
+ fork: Optional[str],
+ pretty: bool,
+ quiet: bool,
+ num_blocks: int = 1,
+ block_strategy: str = "distribute",
+ block_time: int = 12,
+ random_blocks: bool = False,
+) -> Dict[str, Any]:
+ """Process a single fuzzer output file."""
+ with open(input_file) as f:
+ fuzzer_data = json.load(f)
+
+ # Override fork if specified
+ if fork:
+ fuzzer_data["fork"] = fork
+
+ # Determine number of blocks
+ if random_blocks:
+ from .blocktest_builder import choose_random_num_blocks
+
+ actual_num_blocks = choose_random_num_blocks(len(fuzzer_data.get("transactions", [])))
+ else:
+ actual_num_blocks = num_blocks
+
+ # Build blocktest
+ blocktest = builder.build_blocktest(
+ fuzzer_data,
+ num_blocks=actual_num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ )
+ test_name = generate_test_name(input_file)
+ fixtures = {test_name: blocktest}
+
+ # Write output
+ output_file = output_path / f"{input_file.stem}.json"
+ with open(output_file, "w") as f:
+ if pretty:
+ json.dump(fixtures, f, indent=2)
+ else:
+ json.dump(fixtures, f)
+
+ if not quiet:
+ click.echo(f"Generated: {output_file}", err=True)
+
+ return fixtures
+
+
+def process_single_file_worker(
+ file_info: Tuple[Path, Path],
+ fork: Optional[str],
+ pretty: bool,
+ merge: bool,
+ evm_bin: Optional[Path],
+ num_blocks: int = 1,
+ block_strategy: str = "distribute",
+ block_time: int = 12,
+ random_blocks: bool = False,
+) -> Tuple[Optional[Tuple[Path, Dict[str, Any]]], Optional[Tuple[Path, Exception]]]:
+ """Process a single file in a worker process."""
+ json_file_path, output_file = file_info
+
+ # Create transition tool and builder for this worker
+ t8n = GethTransitionTool(binary=evm_bin) if evm_bin else GethTransitionTool()
+ builder = BlocktestBuilder(t8n)
+
+ try:
+ with open(json_file_path) as f:
+ fuzzer_data = json.load(f)
+
+ # Override fork if specified
+ if fork:
+ fuzzer_data["fork"] = fork
+
+ # Determine number of blocks
+ if random_blocks:
+ from .blocktest_builder import choose_random_num_blocks
+
+ actual_num_blocks = choose_random_num_blocks(len(fuzzer_data.get("transactions", [])))
+ else:
+ actual_num_blocks = num_blocks
+
+ # Build blocktest
+ blocktest = builder.build_blocktest(
+ fuzzer_data,
+ num_blocks=actual_num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ )
+ test_name = generate_test_name(json_file_path)
+ fixtures = {test_name: blocktest}
+
+ if not merge:
+ # Write individual file preserving structure
+ output_file.parent.mkdir(parents=True, exist_ok=True)
+ with open(output_file, "w") as f:
+ if pretty:
+ json.dump(fixtures, f, indent=2)
+ else:
+ json.dump(fixtures, f)
+
+ return (json_file_path, fixtures), None
+ except Exception as e:
+ return None, (json_file_path, e)
+
+
+def process_file_batch(
+ file_batch: list[Tuple[Path, Path]],
+ fork: Optional[str],
+ pretty: bool,
+ merge: bool,
+ evm_bin: Optional[Path],
+ num_blocks: int = 1,
+ block_strategy: str = "distribute",
+ block_time: int = 12,
+ random_blocks: bool = False,
+) -> Tuple[list[Tuple[Path, Dict[str, Any]]], list[Tuple[Path, Exception]]]:
+ """Process a batch of files in a worker process."""
+ # Create transition tool per worker
+ t8n = GethTransitionTool(binary=evm_bin) if evm_bin else GethTransitionTool()
+ builder = BlocktestBuilder(t8n)
+
+ results = []
+ errors = []
+
+ for json_file_path, rel_path in file_batch:
+ try:
+ with open(json_file_path) as f:
+ fuzzer_data = json.load(f)
+
+ # Override fork if specified
+ if fork:
+ fuzzer_data["fork"] = fork
+
+ # Determine number of blocks
+ if random_blocks:
+ from .blocktest_builder import choose_random_num_blocks
+
+ actual_num_blocks = choose_random_num_blocks(
+ len(fuzzer_data.get("transactions", []))
+ )
+ else:
+ actual_num_blocks = num_blocks
+
+ # Build blocktest
+ blocktest = builder.build_blocktest(
+ fuzzer_data,
+ num_blocks=actual_num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ )
+ test_name = generate_test_name(json_file_path)
+ fixtures = {test_name: blocktest}
+
+ if not merge:
+ # Write individual file preserving structure
+ output_file = rel_path.with_suffix(".json")
+ output_file.parent.mkdir(parents=True, exist_ok=True)
+ with open(output_file, "w") as f:
+ if pretty:
+ json.dump(fixtures, f, indent=2)
+ else:
+ json.dump(fixtures, f)
+
+ results.append((json_file_path, fixtures))
+ except Exception as e:
+ errors.append((json_file_path, e))
+
+ return results, errors
+
+
+def process_directory_parallel(
+ input_dir: Path,
+ output_dir: Path,
+ fork: Optional[str],
+ pretty: bool,
+ merge: bool,
+ quiet: bool,
+ evm_bin: Optional[Path],
+ num_workers: Optional[int] = None,
+ num_blocks: int = 1,
+ block_strategy: str = "distribute",
+ block_time: int = 12,
+ random_blocks: bool = False,
+):
+ """Process directory of fuzzer output files with parallel processing."""
+ all_fixtures = {}
+
+ # Collect all files to process
+ files_to_process = []
+ for json_file_path in get_input_files(input_dir):
+ rel_path = json_file_path.relative_to(input_dir)
+ output_file = output_dir / rel_path
+ files_to_process.append((json_file_path, output_file))
+
+ file_count = len(files_to_process)
+ if file_count == 0:
+ if not quiet:
+ click.echo("No JSON files found to process.", err=True)
+ return
+
+ # Determine optimal number of workers
+ if num_workers is None:
+ num_workers = min(mp.cpu_count(), max(1, file_count // 10))
+
+ success_count = 0
+ error_count = 0
+
+ with Progress(
+ TextColumn("[bold cyan]{task.fields[filename]}", justify="left"),
+ BarColumn(bar_width=None, complete_style="green3", finished_style="bold green3"),
+ TaskProgressColumn(),
+ TextColumn("[dim]({task.fields[workers]} workers)[/dim]"),
+ TimeElapsedColumn(),
+ expand=True,
+ disable=quiet,
+ ) as progress:
+ task_id = progress.add_task(
+ "Processing", total=file_count, filename="Starting...", workers=num_workers
+ )
+
+ # Process files individually in parallel (better progress tracking)
+ process_func = partial(
+ process_single_file_worker,
+ fork=fork,
+ pretty=pretty,
+ merge=merge,
+ evm_bin=evm_bin,
+ num_blocks=num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ random_blocks=random_blocks,
+ )
+
+ with ProcessPoolExecutor(max_workers=num_workers) as executor:
+ # Submit all files to the pool
+ futures_to_files = {
+ executor.submit(process_func, file_info): file_info[0]
+ for file_info in files_to_process
+ }
+
+ # Process completions as they happen for real-time progress
+ for future in as_completed(futures_to_files):
+ file_path = futures_to_files[future]
+
+ # Update progress with current file
+ rel_path = file_path.relative_to(input_dir)
+ display_name = str(rel_path)
+ if len(display_name) > 40:
+ display_name = "..." + display_name[-37:]
+
+ try:
+ result, error = future.result()
+
+ if result:
+ success_count += 1
+ _, fixtures = result
+ if merge:
+ all_fixtures.update(fixtures)
+ elif error:
+ error_count += 1
+ error_file, exception = error
+ if not quiet:
+ progress.console.print(
+ f"[red]Error processing {error_file}: {exception}[/red]"
+ )
+
+ # Update progress bar
+ progress.update(task_id, advance=1, filename=display_name, workers=num_workers)
+
+ except Exception as e:
+ error_count += 1
+ if not quiet:
+ progress.console.print(f"[red]Worker error for {file_path}: {e}[/red]")
+ progress.update(task_id, advance=1, filename=display_name)
+
+ # Write merged file if requested
+ if merge and all_fixtures:
+ merged_file = output_dir / "merged_fixtures.json"
+ with open(merged_file, "w") as f:
+ if pretty:
+ json.dump(all_fixtures, f, indent=2)
+ else:
+ json.dump(all_fixtures, f)
+ if not quiet:
+ progress.console.print(f"[green]Merged fixtures written to: {merged_file}[/green]")
+
+ # Final status
+ if not quiet:
+ emoji = "✅" if error_count == 0 else "⚠️"
+ progress.update(
+ task_id,
+ completed=file_count,
+ filename=f"Done! {success_count} succeeded, {error_count} failed {emoji}",
+ workers=num_workers,
+ )
+
+
+def process_directory(
+ input_dir: Path,
+ output_dir: Path,
+ builder: BlocktestBuilder,
+ fork: Optional[str],
+ pretty: bool,
+ merge: bool,
+ quiet: bool,
+ num_blocks: int = 1,
+ block_strategy: str = "distribute",
+ block_time: int = 12,
+ random_blocks: bool = False,
+):
+ """Process directory of fuzzer output files."""
+ all_fixtures = {}
+ file_count = count_json_files(input_dir) if not quiet else 0
+ success_count = 0
+ error_count = 0
+
+ with Progress(
+ TextColumn("[bold cyan]{task.fields[filename]}", justify="left"),
+ BarColumn(bar_width=None, complete_style="green3", finished_style="bold green3"),
+ TaskProgressColumn(),
+ TimeElapsedColumn(),
+ expand=True,
+ disable=quiet,
+ ) as progress:
+ task_id = progress.add_task("Processing", total=file_count, filename="...")
+
+ for json_file_path in get_input_files(input_dir):
+ # Preserve directory structure
+ rel_path = json_file_path.relative_to(input_dir)
+ display_name = str(rel_path)
+ if len(display_name) > 40:
+ display_name = "..." + display_name[-37:]
+
+ progress.update(task_id, advance=1, filename=display_name)
+
+ try:
+ with open(json_file_path) as f:
+ fuzzer_data = json.load(f)
+
+ # Override fork if specified
+ if fork:
+ fuzzer_data["fork"] = fork
+
+ # Determine number of blocks
+ if random_blocks:
+ from .blocktest_builder import choose_random_num_blocks
+
+ actual_num_blocks = choose_random_num_blocks(
+ len(fuzzer_data.get("transactions", []))
+ )
+ else:
+ actual_num_blocks = num_blocks
+
+ # Build blocktest
+ blocktest = builder.build_blocktest(
+ fuzzer_data,
+ num_blocks=actual_num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ )
+ test_name = generate_test_name(json_file_path)
+
+ if merge:
+ # Add to merged fixtures
+ all_fixtures[test_name] = blocktest
+ else:
+ # Write individual file preserving structure
+ output_file = output_dir / rel_path.with_suffix(".json")
+ output_file.parent.mkdir(parents=True, exist_ok=True)
+ fixtures = {test_name: blocktest}
+ with open(output_file, "w") as f:
+ if pretty:
+ json.dump(fixtures, f, indent=2)
+ else:
+ json.dump(fixtures, f)
+
+ success_count += 1
+
+ except Exception as e:
+ error_count += 1
+ if not quiet:
+ progress.console.print(f"[red]Error processing {json_file_path}: {e}[/red]")
+
+ # Write merged file if requested
+ if merge and all_fixtures:
+ merged_file = output_dir / "merged_fixtures.json"
+ with open(merged_file, "w") as f:
+ if pretty:
+ json.dump(all_fixtures, f, indent=2)
+ else:
+ json.dump(all_fixtures, f)
+ if not quiet:
+ progress.console.print(f"[green]Merged fixtures written to: {merged_file}[/green]")
+
+ # Final status
+ if not quiet:
+ emoji = "✅" if error_count == 0 else "⚠️"
+ progress.update(
+ task_id,
+ completed=file_count,
+ filename=f"Done! {success_count} succeeded, {error_count} failed {emoji}",
+ )
+
+
+def batch_mode(
+ fork: Optional[str],
+ evm_bin: Optional[Path],
+ pretty: bool,
+ num_blocks: int,
+ block_strategy: str,
+ block_time: int,
+ random_blocks: bool,
+) -> None:
+ """
+ Persistent batch processing mode.
+
+ Reads input/output pairs from stdin, processes each, and outputs status
+ to stdout. Protocol:
+ - INPUT (stdin):
+ - OUTPUT (stdout): DONE or ERROR
+ """
+ import sys
+ import traceback
+
+ # Pre-initialize transition tool and builder once for performance
+ t8n: TransitionTool
+ if evm_bin:
+ t8n = GethTransitionTool(binary=evm_bin)
+ else:
+ t8n = GethTransitionTool()
+
+ builder = BlocktestBuilder(t8n)
+
+ # Write ready signal to stderr for debugging
+ print("Batch mode initialized. Ready to process files.", file=sys.stderr, flush=True)
+
+ while True:
+ try:
+ # Read line from stdin
+ line = sys.stdin.readline()
+ if not line: # EOF
+ break
+
+ line = line.strip()
+ if not line:
+ continue
+
+ # Parse input/output paths
+ parts = line.split()
+ if len(parts) != 2:
+ print(f"ERROR: invalid input format: {line}", flush=True)
+ continue
+
+ input_path_str, output_dir_str = parts
+ input_path = Path(input_path_str)
+ output_dir = Path(output_dir_str)
+
+ # Process the file
+ try:
+ # Read fuzzer input
+ if not input_path.exists():
+ print(f"ERROR: file not found: {input_path}", flush=True)
+ continue
+
+ with open(input_path) as f:
+ fuzzer_data = json.load(f)
+
+ # Override fork if specified
+ if fork:
+ fuzzer_data["fork"] = fork
+
+ # Determine number of blocks
+ if random_blocks:
+ from .blocktest_builder import choose_random_num_blocks
+
+ actual_num_blocks = choose_random_num_blocks(
+ len(fuzzer_data.get("transactions", []))
+ )
+ else:
+ actual_num_blocks = num_blocks
+
+ # Build blocktest (existing logic)
+ blocktest = builder.build_blocktest(
+ fuzzer_data,
+ num_blocks=actual_num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ )
+
+ # Generate test name
+ test_name = generate_test_name(input_path)
+ fixtures = {test_name: blocktest}
+
+ # Write output
+ output_dir.mkdir(parents=True, exist_ok=True)
+ input_stem = input_path.stem
+ output_file = output_dir / f"{input_stem}.json"
+
+ with open(output_file, "w") as f:
+ if pretty:
+ json.dump(fixtures, f, indent=2)
+ else:
+ json.dump(fixtures, f)
+
+ # Report success (CRITICAL: must flush)
+ print(f"DONE {output_file}", flush=True)
+
+ except FileNotFoundError:
+ print(f"ERROR: file not found: {input_path}", flush=True)
+ except json.JSONDecodeError as e:
+ print(f"ERROR: invalid JSON in {input_path}: {e}", flush=True)
+ # Log full traceback to stderr for debugging
+ traceback.print_exc(file=sys.stderr)
+ except Exception as e:
+ print(f"ERROR: conversion failed for {input_path}: {e}", flush=True)
+ # Log full traceback to stderr for debugging
+ traceback.print_exc(file=sys.stderr)
+
+ except KeyboardInterrupt:
+ break
+ except Exception as e:
+ # Catch-all for unexpected errors in the main loop
+ print(f"ERROR: unexpected error in batch loop: {e}", flush=True)
+ traceback.print_exc(file=sys.stderr)
+
+
+@click.command()
+@click.argument(
+ "input_path",
+ type=click.Path(exists=True, dir_okay=True, file_okay=True, path_type=Path),
+ required=False,
+)
+@click.argument(
+ "output_path",
+ type=click.Path(dir_okay=True, file_okay=False, path_type=Path),
+ required=False,
+)
+@click.option(
+ "--fork",
+ default=None,
+ help="Override fork specified in fuzzer output",
+)
+@click.option(
+ "--evm-bin",
+ type=click.Path(exists=True, path_type=Path),
+ help="Path to evm binary for transition tool",
+)
+@click.option(
+ "--pretty",
+ is_flag=True,
+ help="Pretty-print JSON output",
+)
+@click.option(
+ "--merge",
+ is_flag=True,
+ help="Merge all tests into a single output file",
+)
+@click.option(
+ "--quiet",
+ is_flag=True,
+ help="Suppress progress output",
+)
+@click.option(
+ "--parallel/--no-parallel",
+ default=True,
+ help="Enable/disable parallel processing (default: enabled)",
+)
+@click.option(
+ "-n",
+ "--workers",
+ type=int,
+ default=None,
+ help="Number of parallel workers (default: auto-detect based on CPU count)",
+)
+@click.option(
+ "-b",
+ "--num-blocks",
+ type=int,
+ default=1,
+ help="Number of blocks to generate from fuzzer input (default: 1)",
+)
+@click.option(
+ "--block-strategy",
+ type=click.Choice(["distribute", "first-block"]),
+ default="distribute",
+ help="Transaction distribution strategy: 'distribute' splits txs evenly, "
+ "'first-block' puts all txs in first block (default: distribute)",
+)
+@click.option(
+ "--block-time",
+ type=int,
+ default=12,
+ help="Seconds between blocks (default: 12)",
+)
+@click.option(
+ "--random-blocks",
+ is_flag=True,
+ help="Randomly choose number of blocks (1 to min(num_txs, 10))",
+)
+@click.option(
+ "--batch",
+ is_flag=True,
+ help="Persistent batch mode: read file paths from stdin, output to stdout",
+)
+def main(
+ input_path: Optional[Path],
+ output_path: Optional[Path],
+ fork: Optional[str],
+ evm_bin: Optional[Path],
+ pretty: bool,
+ merge: bool,
+ quiet: bool,
+ parallel: bool,
+ workers: Optional[int],
+ num_blocks: int,
+ block_strategy: str,
+ block_time: int,
+ random_blocks: bool,
+ batch: bool,
+):
+ """
+ Convert fuzzer output to valid blocktest fixtures.
+
+ INPUT_PATH: Input JSON file or directory (not required in --batch mode)
+ OUTPUT_PATH: Output directory for fixtures (not required in --batch mode)
+
+ In batch mode (--batch), reads input/output pairs from stdin.
+ """
+ # Batch mode: persistent stdin/stdout processing
+ if batch:
+ batch_mode(
+ fork=fork,
+ evm_bin=evm_bin,
+ pretty=pretty,
+ num_blocks=num_blocks,
+ block_strategy=block_strategy,
+ block_time=block_time,
+ random_blocks=random_blocks,
+ )
+ return
+
+ # Standard mode: require input_path and output_path
+ if input_path is None or output_path is None:
+ raise click.UsageError(
+ "INPUT_PATH and OUTPUT_PATH are required when not using --batch mode"
+ )
+ # Create transition tool
+ t8n: TransitionTool
+ if evm_bin:
+ t8n = GethTransitionTool(binary=evm_bin)
+ else:
+ t8n = GethTransitionTool()
+
+ # Create builder
+ builder = BlocktestBuilder(t8n)
+
+ # Ensure output directory exists
+ output_path.mkdir(parents=True, exist_ok=True)
+
+ # Process input
+ if input_path.is_file():
+ # Single file processing
+ process_single_file(
+ input_path,
+ output_path,
+ builder,
+ fork,
+ pretty,
+ quiet,
+ num_blocks,
+ block_strategy,
+ block_time,
+ random_blocks,
+ )
+ else:
+ # Directory processing with optional parallel mode
+ if parallel:
+ process_directory_parallel(
+ input_path,
+ output_path,
+ fork,
+ pretty,
+ merge,
+ quiet,
+ evm_bin,
+ workers,
+ num_blocks,
+ block_strategy,
+ block_time,
+ random_blocks,
+ )
+ else:
+ process_directory(
+ input_path,
+ output_path,
+ builder,
+ fork,
+ pretty,
+ merge,
+ quiet,
+ num_blocks,
+ block_strategy,
+ block_time,
+ random_blocks,
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/packages/tests/src/cli/fuzzer_bridge/converter.py b/packages/tests/src/cli/fuzzer_bridge/converter.py
new file mode 100644
index 0000000000..62affb7839
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/converter.py
@@ -0,0 +1,308 @@
+"""
+Converter module for transforming fuzzer DTOs to EEST domain models.
+
+This module performs explicit transformation from fuzzer's
+JSON-RPC format (captured in DTOs) to EEST's internal domain
+models (Transaction, Account, etc.).
+
+Key Responsibilities:
+1. Field mapping (gas → gas_limit, from → sender, etc.)
+2. Creating EOA objects from private keys
+3. Building proper EEST domain models with all required context
+4. Preventing TestAddress pollution by setting sender
+ BEFORE model_post_init
+"""
+
+from typing import Dict
+
+from ethereum_test_base_types import Address, Hash, HexNumber
+from ethereum_test_forks import Fork
+from ethereum_test_specs import BlockchainTest
+from ethereum_test_tools import Account, AuthorizationTuple, Block, Transaction
+from ethereum_test_types import Alloc, Environment
+from ethereum_test_types.account_types import EOA
+
+from .models import (
+ FuzzerAccountInput,
+ FuzzerAuthorizationInput,
+ FuzzerOutput,
+ FuzzerTransactionInput,
+)
+
+
+def fuzzer_account_to_eest_account(fuzzer_account: FuzzerAccountInput) -> Account:
+ """
+ Convert fuzzer account DTO to EEST Account domain model.
+
+ Args:
+ fuzzer_account: Raw account data from fuzzer
+
+ Returns:
+ EEST Account ready for pre-state
+
+ """
+ return Account(
+ balance=fuzzer_account.balance,
+ nonce=fuzzer_account.nonce,
+ code=fuzzer_account.code,
+ storage=fuzzer_account.storage,
+ )
+
+
+def fuzzer_authorization_to_eest(
+ fuzzer_auth: FuzzerAuthorizationInput,
+) -> AuthorizationTuple:
+ """
+ Convert fuzzer authorization DTO to EEST AuthorizationTuple.
+
+ Args:
+ fuzzer_auth: Raw authorization data from fuzzer
+
+ Returns:
+ EEST AuthorizationTuple for EIP-7702 transactions
+
+ """
+ return AuthorizationTuple(
+ chain_id=fuzzer_auth.chain_id,
+ address=fuzzer_auth.address,
+ nonce=fuzzer_auth.nonce,
+ v=fuzzer_auth.v,
+ r=fuzzer_auth.r,
+ s=fuzzer_auth.s,
+ )
+
+
+def fuzzer_transaction_to_eest_transaction(
+ fuzzer_tx: FuzzerTransactionInput,
+ sender_eoa: EOA,
+) -> Transaction:
+ """
+ Convert fuzzer transaction DTO to EEST Transaction domain model.
+
+ This function performs explicit field mapping and MUST set sender BEFORE
+ calling Transaction constructor to prevent TestAddress injection.
+
+ Key Mappings:
+ - fuzzer_tx.gas → transaction.gas_limit (JSON-RPC → EEST naming)
+ - fuzzer_tx.from_ → sender_eoa (Address → EOA with private key)
+ - fuzzer_tx.data → transaction.data (same field, explicit for clarity)
+
+ Args:
+ fuzzer_tx: Raw transaction data from fuzzer
+ sender_eoa: EOA object created from private key (prevents TestAddress)
+
+ Returns:
+ EEST Transaction ready for block generation
+
+ """
+ # Build authorization list if present
+ auth_list = None
+ if fuzzer_tx.authorization_list:
+ auth_list = [fuzzer_authorization_to_eest(auth) for auth in fuzzer_tx.authorization_list]
+
+ # Create Transaction with sender set BEFORE model_post_init runs
+ # This prevents Transaction.model_post_init from injecting TestAddress
+ return Transaction(
+ sender=sender_eoa, # ✓ Set explicitly to prevent TestAddress
+ to=fuzzer_tx.to,
+ gas_limit=fuzzer_tx.gas, # ✓ Explicit mapping: gas → gas_limit
+ gas_price=fuzzer_tx.gas_price,
+ max_fee_per_gas=fuzzer_tx.max_fee_per_gas,
+ max_priority_fee_per_gas=fuzzer_tx.max_priority_fee_per_gas,
+ nonce=fuzzer_tx.nonce,
+ data=fuzzer_tx.data,
+ value=fuzzer_tx.value,
+ access_list=fuzzer_tx.access_list,
+ blob_versioned_hashes=fuzzer_tx.blob_versioned_hashes,
+ max_fee_per_blob_gas=fuzzer_tx.max_fee_per_blob_gas,
+ authorization_list=auth_list,
+ )
+
+
+def create_sender_eoa_map(accounts: Dict[Address, FuzzerAccountInput]) -> Dict[Address, EOA]:
+ """
+ Create map of addresses to EOA objects from accounts with private keys.
+
+ Args:
+ accounts: Dictionary of address to fuzzer account data
+
+ Returns:
+ Dictionary mapping addresses to EOA objects for transaction signing
+
+ Raises:
+ AssertionError: If private key doesn't match the account address
+
+ """
+ senders: Dict[Address, EOA] = {}
+
+ for addr, account in accounts.items():
+ if account.private_key is None:
+ continue
+
+ # Create EOA from private key
+ sender = EOA(key=account.private_key)
+
+ # Verify private key matches address (safety check)
+ assert Address(sender) == addr, (
+ f"Private key for account {addr} does not match derived address {sender}"
+ )
+
+ senders[addr] = sender
+
+ return senders
+
+
+def blockchain_test_from_fuzzer(
+ fuzzer_output: FuzzerOutput,
+ fork: Fork,
+ num_blocks: int = 1,
+ block_strategy: str = "distribute",
+ block_time: int = 12,
+) -> BlockchainTest:
+ """
+ Convert fuzzer output to BlockchainTest instance.
+
+ This is the main entry point for fuzzer-to-EEST conversion.
+ It orchestrates:
+ 1. Parsing and validation (already done by FuzzerOutput DTO)
+ 2. Creating EOA objects from private keys
+ 3. Converting DTOs to domain models
+ 4. Building blocks and test structure
+
+ Args:
+ fuzzer_output: Parsed and validated fuzzer output (DTO)
+ fork: Fork to use for the test
+ num_blocks: Number of blocks to generate
+ block_strategy: How to distribute transactions across blocks
+ - "distribute": Split evenly maintaining
+ nonce order
+ - "first-block": All transactions in first
+ block
+ block_time: Seconds between block timestamps
+
+ Returns:
+ BlockchainTest instance ready for fixture generation
+
+ Raises:
+ AssertionError: If invariants are violated
+ (sender validation, etc.)
+
+ """
+ # Step 1: Convert accounts to EEST Account domain models
+ pre_dict: Dict[Address, Account | None] = {}
+ for addr, fuzzer_account in fuzzer_output.accounts.items():
+ pre_dict[addr] = fuzzer_account_to_eest_account(fuzzer_account)
+ pre = Alloc(pre_dict)
+
+ # Step 2: Create EOA map for transaction signing
+ sender_eoa_map = create_sender_eoa_map(fuzzer_output.accounts)
+
+ # Step 3: Convert transactions to EEST Transaction domain models
+ eest_transactions: list[Transaction] = []
+ for fuzzer_tx in fuzzer_output.transactions:
+ # Verify sender has private key
+ assert fuzzer_tx.from_ in sender_eoa_map, (
+ f"Sender {fuzzer_tx.from_} not found in accounts with private keys"
+ )
+
+ # Convert with explicit sender (prevents TestAddress injection)
+ eest_tx = fuzzer_transaction_to_eest_transaction(
+ fuzzer_tx,
+ sender_eoa=sender_eoa_map[fuzzer_tx.from_],
+ )
+ eest_transactions.append(eest_tx)
+
+ # Step 4: Build genesis environment
+ env = fuzzer_output.env
+ genesis_env = Environment(
+ fee_recipient=env.fee_recipient,
+ difficulty=0, # Post-merge
+ gas_limit=int(env.gas_limit),
+ number=0,
+ timestamp=HexNumber(int(env.timestamp) - 12),
+ prev_randao=env.prev_randao or Hash(0),
+ base_fee_per_gas=env.base_fee_per_gas if env.base_fee_per_gas else None,
+ excess_blob_gas=env.excess_blob_gas if env.excess_blob_gas else None,
+ blob_gas_used=env.blob_gas_used if env.blob_gas_used else None,
+ ).set_fork_requirements(fork)
+
+ # Step 5: Distribute transactions across blocks
+ blocks = _distribute_transactions_to_blocks(
+ eest_transactions,
+ num_blocks,
+ block_strategy,
+ block_time,
+ env,
+ fuzzer_output.parent_beacon_block_root,
+ )
+
+ return BlockchainTest(
+ pre=pre,
+ blocks=blocks,
+ post={}, # Post-state verification can be added later
+ genesis_environment=genesis_env,
+ chain_id=fuzzer_output.chain_id,
+ )
+
+
+def _distribute_transactions_to_blocks(
+ transactions: list[Transaction],
+ num_blocks: int,
+ strategy: str,
+ block_time: int,
+ base_env: Environment,
+ parent_beacon_block_root: Hash | None,
+) -> list[Block]:
+ """
+ Distribute transactions across multiple blocks.
+
+ Args:
+ transactions: List of EEST Transaction objects (ready for execution)
+ num_blocks: Number of blocks to create
+ strategy: Distribution strategy ("distribute" or "first-block")
+ block_time: Seconds between blocks
+ base_env: Base environment for first block
+ parent_beacon_block_root: Beacon root (only for first block)
+
+ Returns:
+ List of Block objects
+
+ """
+ if strategy == "first-block":
+ # All transactions in first block, rest empty
+ tx_distribution = [transactions] + [[] for _ in range(num_blocks - 1)]
+ elif strategy == "distribute":
+ # Split transactions evenly maintaining nonce order
+ if not transactions:
+ tx_distribution = [[] for _ in range(num_blocks)]
+ else:
+ result = []
+ chunk_size = len(transactions) // num_blocks
+ remainder = len(transactions) % num_blocks
+
+ start = 0
+ for i in range(num_blocks):
+ # Distribute remainder across first blocks
+ current_chunk_size = chunk_size + (1 if i < remainder else 0)
+ end = start + current_chunk_size
+ result.append(transactions[start:end])
+ start = end
+
+ tx_distribution = result
+ else:
+ raise ValueError(f"Unknown block strategy: {strategy}")
+
+ # Create blocks with incrementing timestamps
+ base_timestamp = int(base_env.timestamp)
+ blocks = []
+ for i, block_txs in enumerate(tx_distribution):
+ blocks.append(
+ Block(
+ txs=block_txs,
+ timestamp=base_timestamp + (i * block_time),
+ fee_recipient=base_env.fee_recipient,
+ parent_beacon_block_root=parent_beacon_block_root if i == 0 else None,
+ )
+ )
+
+ return blocks
diff --git a/packages/tests/src/cli/fuzzer_bridge/examples/README.md b/packages/tests/src/cli/fuzzer_bridge/examples/README.md
new file mode 100644
index 0000000000..95b6f912fe
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/examples/README.md
@@ -0,0 +1,143 @@
+# Fuzzer Bridge Examples
+
+This directory contains example fuzzer outputs in the v2.0 JSON format. These examples demonstrate the comprehensive transaction coverage generated by the fuzzer and serve as test cases for the fuzzer bridge implementation.
+
+## Format Overview
+
+All examples use fuzzer output format v2.0 with the following structure:
+
+```json
+{
+ "version": "2.0",
+ "fork": "Osaka",
+ "chainId": "0x01",
+ "accounts": { ... },
+ "transactions": [ ... ],
+ "env": { ... },
+ "parentBeaconBlockRoot": "0x..."
+}
+```
+
+## Example Files
+
+### comprehensive_smallest.json (56K)
+- **Size**: Smallest example (56K)
+- **Transactions**: 17 transactions
+- **Accounts**: 25-26 accounts with private keys
+- **Transaction Types**: Legacy, EIP-1559, EIP-4844 (blobs), EIP-7702 (authorization lists)
+- **Features**: Parent beacon block root (EIP-4788)
+- **Use Case**: Minimal comprehensive example for quick testing
+
+### comprehensive_medium_1.json (62K)
+- **Size**: Medium-sized example (62K)
+- **Transactions**: 17 transactions
+- **Accounts**: 25-26 accounts
+- **Transaction Types**: Full spectrum including blob transactions (6 blob hashes per tx)
+- **Authorization Lists**: 5 authorization tuples per EIP-7702 transaction
+- **Use Case**: Balanced example with typical transaction data sizes
+
+### comprehensive_medium_2.json (66K)
+- **Size**: Medium-sized example (66K)
+- **Transactions**: 17 transactions
+- **Accounts**: 25-26 accounts
+- **Transaction Types**: All major transaction types
+- **Features**: Variety of calldata sizes (2-400 bytes)
+- **Use Case**: Testing different data payload sizes
+
+### comprehensive_large.json (70K)
+- **Size**: Large example (70K)
+- **Transactions**: 17 transactions
+- **Accounts**: 25-26 accounts
+- **Transaction Types**: Complete coverage
+- **Features**: Larger calldata payloads (up to 600 bytes)
+- **Use Case**: Testing with substantial transaction data
+
+### comprehensive_largest.json (74K)
+- **Size**: Largest example (74K)
+- **Transactions**: 17 transactions
+- **Accounts**: 25-26 accounts
+- **Transaction Types**: All types including largest blob transactions
+- **Features**: Maximum calldata sizes (up to 690 bytes)
+- **Use Case**: Stress testing with largest transaction payloads
+
+## Common Features Across All Examples
+
+All examples include:
+
+1. **EIP-1559 Transactions**: Dynamic fee transactions with `maxFeePerGas` and `maxPriorityFeePerGas`
+2. **EIP-4844 Blob Transactions**: Transactions with `blobVersionedHashes` and `maxFeePerBlobGas`
+3. **EIP-7702 Set-Code Transactions**: Transactions with `authorizationList` containing signed authorization tuples
+4. **Legacy Transactions**: Traditional transactions with `gasPrice`
+5. **EIP-4788 Support**: `parentBeaconBlockRoot` set in environment
+6. **Private Keys**: All sender accounts include `privateKey` field for transaction signing
+7. **Storage**: Accounts with non-empty storage mappings
+8. **Code**: Accounts with deployed bytecode
+
+## Field Mappings (Fuzzer JSON-RPC → EEST)
+
+The fuzzer uses standard Ethereum JSON-RPC transaction format:
+
+| Fuzzer Field | EEST Field | Description |
+|-------------|-----------|-------------|
+| `gas` | `gas_limit` | Gas limit for transaction |
+| `data` | `data` | Transaction calldata |
+| `from` | `sender` | Transaction sender (mapped to EOA) |
+| `gasPrice` | `gas_price` | Gas price (legacy transactions) |
+| `maxFeePerGas` | `max_fee_per_gas` | Max fee per gas (EIP-1559) |
+| `maxPriorityFeePerGas` | `max_priority_fee_per_gas` | Max priority fee (EIP-1559) |
+| `blobVersionedHashes` | `blob_versioned_hashes` | Blob hashes (EIP-4844) |
+| `maxFeePerBlobGas` | `max_fee_per_blob_gas` | Max blob fee (EIP-4844) |
+| `authorizationList` | `authorization_list` | Authorization tuples (EIP-7702) |
+
+## Usage
+
+These examples can be used with the fuzzer bridge CLI:
+
+```bash
+# Convert a single example to blockchain test
+uv run python -m cli.fuzzer_bridge.cli \
+ --input src/cli/fuzzer_bridge/examples/comprehensive_medium_1.json \
+ --output /tmp/blocktest_output
+
+# Batch convert all examples
+for example in src/cli/fuzzer_bridge/examples/*.json; do
+ uv run python -m cli.fuzzer_bridge.cli \
+ --input "$example" \
+ --output "/tmp/$(basename "$example" .json)"
+done
+```
+
+## Old Examples
+
+Previous examples (before format evolution and bug fixes) are preserved in the `old_examples/` subdirectory for reference.
+
+## Generation
+
+These examples were generated using the fuzzer with comprehensive transaction coverage enabled. The fuzzer automatically generates:
+
+- Multiple transaction types per test
+- Accounts with various states (empty, funded, with code, with storage)
+- Realistic transaction ordering and nonce sequences
+- Private keys for all sender accounts
+- Post-merge environment (PoS consensus)
+
+## Testing Coverage
+
+Each example provides test coverage for:
+
+- ✅ Transaction parsing (all field types)
+- ✅ Account state initialization
+- ✅ EOA creation from private keys
+- ✅ Gas limit calculations
+- ✅ Blob transaction handling
+- ✅ Authorization list processing
+- ✅ Environment setup (including beacon root)
+- ✅ Multi-transaction block generation
+
+## Notes
+
+- All examples use Osaka fork
+- All examples use chain ID 1 (mainnet)
+- All transactions have sufficient gas (16,000,000 gas limit)
+- All sender accounts have private keys for signing
+- Environment includes realistic post-merge values (difficulty=0, prevRandao set)
diff --git a/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_large.json b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_large.json
new file mode 100644
index 0000000000..02207cb840
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_large.json
@@ -0,0 +1,421 @@
+{
+ "accounts": {
+ "0x000000000000000000000000000000000000000d": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x6517fa85aafd83a02f88fe864d93249c357cce975bd1f35d0b0430a901613f76",
+ "storage": {}
+ },
+ "0x18665208d71eAF07c959cB6d2b263aCE3eF24042": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xaf09231cd0ab58828b41ee0ba14866d944b955fbc80243a5bf0bc8c86c664552",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f19fa3b5cbcf160be11cbc1ccfa69a3a86000527f9f374ddd4b02789440d795b6a2fcfda039b83d18945750af9cee8ebacc1c27716020526f014a651f7ac467a9f4f1041275a058386040527f03088f4d23e2585886dd9918f916bd25f3a9f62b6bff62fc04a5770726fdfea16060526f19f7092f2954ea173b6f38c95f4ab8f96080527f871c73b32e1e1c5da7ba9025c14e5ba83e0c6762b66e433f8f9046629488f2b860a0526f0c1303e46eb6b78c665ea65f470ac64660c0527fa6f6149c0b9505c50046c6de2883a22579de92b151f5ab7938e9c5c269a09e3960e0526080600061010060006046600b7ffe95b06b0f681723791f4161b4947e090dbfd8783baf00b3a24bc8853dcf0196f26000556000516001556020516002556040516003556060516004556f0fb6f07b2eab53e6d95b3eea7c5f15256000527f9ff4e6b8f9784adec046dea1be26fd44754d6a27c6a2b1a1d9e44930cbd311306020526f03c0d62e127d7ca9f051646a2c401ede6040527ff683bbc13510e88c04488ced8f6b688a79584ba6dbe3debed06ec8de8a23f54c6060527f85594d4af90ecf8adb547e8c0e1f2022770dbab52d41e5d7209033a36c7b9f8d6080526f158333a1f76f866236773aa642362ad060a0527e5c4adc636c7f0ef15a9de64bbde05b7dc19d3d71c1828c7c56480a761d207c60c0526f102eaee88ca53422c1d961278654cd0360e0527f0798cc38d9234d1ab9645b653fa58fef75b9bbb4fad130010abcdf8a99900f7a610100527f713197f47d0b27493f5b80e43abe59e6052e876076598c449fd315801a093b59610120526f0bb2d551f91290b5b9fce1e398dbc4cb610140527ff6cca7cc4e69b5da29f4fa52c6581aed6fc44bb1f3c0536eb504b7d221a06447610160526f061d80c19532c14099c7c684e2ccb174610180527f57228c4901d5528ebbf0c4f47dae28c3d280068e31c107be7b4e6eda8f4ddc586101a0527f1affd06170d301f6ebafc685f05a67ba51aa136ef86f6146ea179898a8dabd546101c052608060006101e06000600c7ffd0e4ef71bd81883826cfc6172ac1a2331705d36e13ad54044fbbd2f7509d1f7f46005556000516006556020516007556040516008556060516009556f08ba8a0468fb1e41a77dc4760a4973ee6000527fe6f8dd14f7ffe63b258b76ba3945fc3212dd597342360542875ef842e0b0b2196020526f0fd65a1aed9d10788788f8c8116f56af6040527f3e4297c9aeb8329e8f90cb0afef8148320439f16ebdf6680516f5d27928a1a086060526f145d501508e98e9fdc70d4076213d6146080527f14d82b1819adbaed7aa9a6ed3877d698e515829d121b61a40d224480af7a667b60a0526f1460669ebf2d0c5804bfc4ea1e662a3a60c0527fa675412270d299cdcc4fb1af786e51bde0f9c7f2fa5a48dcd7770aa3086ca85660e0526f0bd37d392b9da52284890146de3e897d610100527f9b414b75b7fbb851dfbba872378f09666e83e15c4039cb9dd41a65ecf610234c610120526f07f750deef22c9b32314fcfd4d541929610140527f2a89d9e69169ce89d55caae0d5bfb34bae1bfdd51fdead179761953c3d68488d610160526f1d1becb9ed60428375c9cba1b1e5deda610180527f6694879571ee1b0ac9e12d815b34f005639cd4214d10865159dd2a14459ea1c56101a0526f0fff5920c6dca137b60970bb9c2cbbca6101c0527fab9d343b23a24d09491af51286c567ea4e0d802d0d17da14605dd0629ef3d11c6101e05261010060006102006000600d7f8ec3983a330a1d6443ba3a96ad13eb742da259f98b422751e4d83c507eb9a495fa600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f19da63d9ed7d5028bc4ec2241e0f64d66000527f9c2a418eca251abceb9c6ceea156ab119fa41c5d817c64b5d27e378b3666fe616020526f02b6cfb26b2a957b6cea0ced22f7da976040527fbd85f4f1cf860c6b0a4cd896da77568cb92265cb47653c0d42fa17de27204b9b6060526f134e239014bc00715daa075776787a4c6080527fc3f6e58a7ccc8761817397ee792a6a5c06ac2b8c0532465909312c3f73a0411460a0526f08015e9f29388301d30ec2275593144160c0527fe781b11a8189a11b6ca94a5a75320893f20a6d24a9a5d89f403aa9e7b2b1082460e0527f3c6c108f25654670f797333386644dc2266da7009d2379ae6b1a713b1d4f1f5e610100526f0f1f81e63fb80a8c424825c4c63fecd7610120527fa9e2c7a00edb5595ac51369c4e06cb0d327c4a2bcb9540bbc071f89d5afd930e610140526f15f887c809744b267d34ea14996f9c19610160527f4a6e3e76a9560eac9ab9302f09ae45ba8390f505f9b76aa7e095d4c06731c6da610180526e781d148227c64e9e6171737a9f90676101a0527f4da46bda7b6fc8735861079c8c5190fe2452068274e77d646be4efd9824c084f6101c0526f08709c66878c65bf4b6fe916c2994c1d6101e0527fc7ada675b682bb217386e5f3e271a9afddb98dc41ac2e620c4bfcf7cd386a80c610200527f08ee20e405693fd12009d735195f7a9f0151f0073f16c63cde49582d2ee6da7961022052610100600061024060006036600e7f89e0e03253b5683c3350f95eeea40ab73353141f0d329060d6b4bb2b67b6d5f5f260135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f0f1ff58cafe856bb0c96b8cc8e84a15f6000527f4aa828579e886669fe73006f7e0eeffb46e8774f0fc9476fe9ef7eb45ee87bb96020526f0ca2fcfc114a285353488f60b0cb27be6040527f096dc37d10d6178f1acb136e37937d67acdfcfcc479ac055f69a9d3127abffb46060526f0d334f79d96f58a39b36cb539250a5516080527f6f3fb98e2e86cfe69a80955b99fbd5159bd75b68a1170ed2a2f4d39d9f54897060a0526f19b11403a23f5806db3da4e23c11898d60c0527f7e89c85d9c5951eacc54b878539d49603b85611512db65364053e9105282505860e0526f140342b31fd4daf8752074a17957a58c610100527f03a5d0d261b7693c3c3b9465bb7580ac64ab687520c5a0a792ac014ddc760458610120526f0e1834c2250017d2a88333e20b0a51dc610140527f5ea2cd2d856b17c7a1d4f5f148d4ec0a2089219d520b672e32b439c14ea1b85f610160526f1316f2bff6c70b109dad2d28a6404881610180527f3151789d6ca1019ea82ccfe4c806673dff2d9332637b20c4e6a9cb44faa2c28e6101a0526f128e3988a581fb6fe92de2e1c48f14986101c0527f4155e4151df5492a44ae4ec360c675705b8f2aea0a2831d7e9f664aa009b4dd06101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527727d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e05260206000610300600060b5600f7f26e0179e1ab64336316965140721c1c91b4c6311479bfb37b4049e57d689e429f1601c55600051601d557e40000000000000000000000000000005368347f453af419c09e3c17d5a07b16000527fcec1b822de11b01fe0b30cc1f6e431c7d6aa6297592bb9a08255062903a43a19602052608060006040600060107f75031a4a93d2ee1164a2f48228e140897995ea0e845683c90a60af8d03ac65defa601e55600051601f556020516020556040516021556060516022556f0fd5ef3e0dc0490f4dbff5e349456cc76000527fc0a883554216d95059f28016c8d8c4880eafaac915ae37e0daa01ded35c024c16020526f0392768dd75f8e50ad0c7a67d9c819fa6040527fe551075a654737e08d0f021eb117eb6b68267334b9110a1fe2e2edb67572cc9b606052610100600060806000601160f2f460235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x607660db600b602360e6604260bd1d8164a1f4329a161d8c31f11568550b5546591c4348526c53313f04452087315456197882415f647a72956540556f94460507891a053a600036306b1858421005179170995100928d5c153f92071977a137095258425e5a0a7114005e554a086e75135b0120203c15798f157837f5807e3145197d186e09161a77705c17526f37130286621945183e3e783030080616703b1e9978348a0388121879327d546079785b7c561d5e69947c927e611016347a1b6ea0358065186c7f8476507239180619137643491d72107b59186c8b8d79009909736bfe087b5f596534169d3ea4160a555f5134676890346a5c583f5bfd66598075983267519b10468e794664653f7c9f155b77047f0a721b921914067d7218868f7079781b1104173a437275f37948383f6f8e387fa2611c74455a99fa448b65460b5f1153f335143e07717e348f3173639819686c51789204386b82721a1394975a08597876618310176d30575e0168564962842097793f796d7e00953b465c410a3c775e1e79673f167448307088777057960257519752757a5e6a313e585dfe081dfd0361055cf58d8230725d5a5831891a36701842f5015b6511125b32373015f470871c465118093a59634302396447395252398603694af4185360180033141620845647391a11347a463df410779d7b030b0170163b1a15529e563f48590a420a14067f793e8f699d8f8c5780119c587a4291127a0167783d6f576012a354f21c7874315714384578346c9b7e5569961d55566f6bfd0b1851307e013899166f1683208c615c206b48076e7503fa3344a04955f5577209046d92a48474069b516b6135209146701e886e7c7b5f7796325a40848d6b519d609e1b03110b695a8b14399c6494a4361b163b3284667c8e743a023f1a7494021b9efd01fa09075912829f729f6402021a6f311740113b3c7a811808170519763d7405570953a00406ff1020536d09a0396095a17b5a456742353d10565969761439165d63101bf1598865958d375239046630516f6a1863903a497a3e6b07129a4758571d7d56051a80675914793295793f5d131a37149b5a6e3ba20b1e5341578b6571a494022065556798115648745f550398719f696d79f03e20ff429b34f3780a5e5c5077a35a6c433f77951a4059905f96371468a4025455713251591a3014fe1a557e6549395d165467915d9b63481b03531449521979068461533758f05839733205538d5e304109079c4a036d9d42f03565376418323697066b755c02a3fff1545711798d71490462101a3344591512187298565c058e1a0377f1853ff2fa095f5655466399483e69477f6e10465c3840f3413b7275906174a17c0348341d321153355563543f9d5b12fd806a20093d6100a109107e78656fa243025b067ef515",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000006"
+ }
+ },
+ "0x2837fE6BCdADEa40e14E73df3101847267659772": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2bc9eb16f330b5d3764d1e508af3bcbb84786071e249bad6f91ac38553464bf4",
+ "storage": {}
+ },
+ "0x35F694E45962Ab9eD665971FdF51A45A3b109c62": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2ac7d0629b3a39ccca4afd80b787edeccd0f9ceb5a83595c0f6a0e1cff0ebc7e",
+ "storage": {}
+ },
+ "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xd5b187a1488a0211288f3d420de324151455a6fa819850303f62bd25582b7cf6",
+ "storage": {}
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x863419417b6000600055fa6de18a449c010a7f8e9660d84a21b87dbc056763006df3b8e66035a6f5fa4f42111ec56669067f796000527f9c2a7f3804dce503d7dff8e8801825fcdbd42a90e3f308ba21073ded827269296020527ff1b14bba86f2a6dd52b5d305e67bce80b579773ed881c8b9d8ce642f5638e1176040527f5e84ef7b9dc7e340641494d24498f08e7e37c9a6b3c8c03d09233a8e4af955dc6060527fce75d7e5d40ae69e572cbc0acdf3ef1eda7986dae8c69c09ab0c6f147b39268b6080527f7102b83fa59b8625e1cf6135605774b5f0a4d1bf373ac442b586a734ea8d21a560a0527fd4734a6bf23aa02d6286e928ed2edb7de8f5cedf05ecd2414ae0b4b9b11f6ab660c0527f7aee11b5432ab2a83f63841375a8f0ae8793233f2ede14d8f438f0dbb071534360e0527fb6a898321c875fee9103f3e25ab43d83cdf69aa1272812df955436426dda111e610100527f9ef2f7a07ef9168eef5eb78e995ea5792ec9b54d26c84c2b3b293f2c75e7989b610120527fb927e00951b4d24c112987f39916cee2300c7b8daca535a96ec9ae5cfaad7945610140527f78bb0fbfc44d5382300475f28e1f1f2e18708879ea8782b491d347901fe53e23610160527f7c6d85c86a9519a7852b269fa8f73f567731325f725a7286e6c01dbfd830397b610180527fcb9090f9a3bf1b0f3eb6dc9b03d0f339b6485d5b238ed7f9d0f1d4495d7b979a6101a052604060006101c0600060017f7735e2b1ad3cdfeae4afb25583920b30da69c9092974cdea990241f743cb3a5bfa600155600051600255602051600355",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000c"
+ }
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7fa4fc4c261945511eb0a7f9289ce44ddf8c9a5f4f7945a874976ea999c00f203c6000527f848fd24256f25171129d300596cdb3b87acac92dd320fd135b469ffb3649b0e86020527f47c102713e24fc4063948a1ada6d8df826b84b4737456cb9299ee0ddd772b8436040527fa839afcab7c931f82fc7153e8c264aba55b8a32448b9ad7568d4ca274cf0f6066060527f1addfa3a484743f66c64ca09ff38394128a899b80ecaff420a4d4a24bf44ff0e6080527f152e8f081e35367b5111bf26d890c6411c2fad393021ec60f6245c542193ffd960a0527f2f6f851250f72062da28ca7528fd1ecdac47295206aee44bb04ae8c1569d159560c0527f63616e5e3b3f1a7a4de50bae2b9628d600dc21fe02e8b000d48b229dc81959a360e0527faa2d809b67023928be7c23a9e3a6436258d51a8ee50e34c95a144cf9cf2d9e31610100527f4dbb9f316420b4b6f0a903f88704b734ee1c9b08a84949ca3c8f8c1701da909761012052608060006101406000601a600b7f0bce7192ca8c2cee8f6a4969de315bf7818617316247de5551ee9bca9f98a5b1f1600055600051600155602051600255604051600355606051600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x60d4600053600560006102403960ff610245526008600061026582819290913920600c5560196019610100376080600060a082819290913e20600d5560ed610320536102455161ffff60808091905251600e556005610240fd",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x6888bf43c6b0a7bd72d3d4f360efc2fcf781b746e6de54a559882e71c4ac43a2",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x60f5ff91600aff60066000557f6133b9711c679b508736ed2f2a68fca7d4b1b912835742fb9dd74077c69c99ee6000527f2a08abae5a77926728c6ab0cbc4f81597dbf381b9162c36917ef9f42c63b99fc6020527f9abc7b34abd5117c02c1608a0397c757b19dd8644719be525176d7c9611db13f6040527f4e274ca06f8679a44b6c7d66f165c0c86aa94c5ea5653d359509dc6e8a4805bd6060527f4070778074d300ac50e862e4fc06c4149396762f44c15b6fd90917391f88e2996080527f881b5e6a55ab149fbe5a0ddfdd2cb487b9de8a1d29a61575afdcd2eb5a92345f60a0527f5c2e6bf54da29f38a89da143ea0c4e91d6c801eef8d9c0e267838ac85f71f0be60c0526040600060e06000600f7f67fcb88c6827df95a5c4a5f2547e65254ecb1b4d9a7ac77cf40b820e999e1f7ffa600155600051600255602051600355",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000011"
+ }
+ },
+ "0x7564105E977516C53bE337314c7E53838967bDaC": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7d059b496042f5250099eca0bd057a7162d05a02ce37330a5b536cd2e4c0186000527fee48cb9ff2f9b10445a8becfeb58e5119a8a83e7dd43b101bf6e1f5dd6b3a9af6020527f476d2cfa61f20f534739aa9c1f89023a4f1fae316859138a038cdebb87a7fe066040527f6b7a7ac05061f5e8cc20a76eaafddbdb811bca541786813629824f602b88562b6060527f36dd661024742f2d3fac855c9a98a06846a1b08f9f7d281167f79f77cdc773f06080527f0566af2715eb131035e0565b67e03096d6356e168932be528a6d62a6d65c12c360a052609d60c053607160c153603160c253608460c353605860c45360b760c55360ea60c653603860c753606c60c853603360c95360ad60ca53607560cb5360b860cc5360b060cd53600960ce53602e60cf53607c60d053606160d15360a660d253604060d353600060d4536040600060d56000607f60097f2c1ed359cc60aec22438443f3489dfc9b14ff971652c6f37440f4994122fb85ff2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xbc501cdb0096cc68817e5b2aa2eb7e97fcf45a56dbd22b6e2de2b234b51f12d5",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x7bc9700000000000000000023f00c00014ff002c0000000000002231081967d0212626262626266d01000000000000000000000000009010067e40000000fd000000db0000000000000000000040000000fd000000db0000017176767676767676767600000076767676767690061a7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff06900b19717676767676767676760000007676767676767a010900000000000000000000000000000000000000000000000000901d6000551569100000000000000000007a010900000000000000000000000000000000000000000000000000900690159014671fffffffffffffff6f8000000000000000000000000000000090077f7effffff800000000000000000000000000200004400000000000000000000017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006847839214543589705209600155021960025560006b10000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b00900919600355671fffffffffffffff15680100000000000000006780000000000000000719147702ffffffffffffffffffffffffffffffffff0000000300007ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000005901a7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006fdac7fff9ffd9e13226262626262626000515900b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7702ffffffffffffffffffffffffffffffffff200000000000651ce97e1ab91a900860045567800000000000000067b368d219438b7f3f68210000000000000022900990076005557cc9700000000000000000023f00c00014ff00000000000000002230080568010000000000000000901c637fffffff717676767676767676760000007676767676769002127f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe760fffc000000000000767676240000000000002b0576047900390136006557ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006a0100000000000000000000036007556101111960085560006b0100000000000000000000007d76767676767600000000007600000000000000560000000000000000000090087e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0063800000011690166f121212121212121212121212121212126780000000000000019013057f82000000000000000000000000000000000000000000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200000363800000017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10009008900b6009557e40000000fd000000db0000000000000000000040000000fd000000db0000016a0100000000000000000000900413600a557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6f121212121212121212121212121212120a600b557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff80000000000000000000000000020000440000000000000000000001901460006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xe0f8e02e171a2ef7eae37783ecfa6acb82cbacaaff229a4a403134ff420cb4c4",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fda62acddc27903598f1ddb505079f75a053a7fef4ccc0226f329a17de2b9b07f6060527fc2dec62772a59ab41d9b18a2c73337eaa9aa3fe8fc601987b1255f567d9d38d66080526020600060a06000610100611b04f46000556000516001557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b2ef26002556000516003557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006001610100611956f16004556000516005557f57f8a6f7c3f645443cfb67321cd9c90976533d2cf4694275284018e7d00502fe6000527fc542900c2dc5f9792d3b72ff6102bd1e91f6085de62264ae37160378bcfe1b126020527f602b4b4f830c525256827f91011797701b9a95cd91a6b479634c0d8b7da6193d6040527f646afb1b2d301d0d563a1a041858c646ca0f5ad9c88933d039ca8054ae8e9fe76060527f1c805336320e07d97255daa4f56aa8f70067f661fd58e36f86bf37dceb52f4bc6080526020600060a060006000610100611c63f16006556000516007557f535cb327ee8076e255306a99e24004dc0fe803cdda5fc1b1c80cff2b2be4b4566000527f928b94b18ace4fe3705e3be1552c001258a8453a5c390ae9edc7667e6cee6e746020527fbd807c3b3183046f09199d87d5164eee161b6b65e77cd48d9e252f14fc278eb86040527f8c9b92eaa05719ff02813758277a97b44bee954d63c0baee1ed0d93a3e9aa03e6060527f342b583e2ce51c261daca46acaa8c051224903898e638c9d1ca2719c1d8d6def6080526020600060a06000610100611c1ffa6008556000516009557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c7760005265200000000000602052652000000000006040527f1e7b39a3889ab016e0104c5ab9a8ce088bb14bf824070d6927aa876a820f6f376060527fd40f3c998bbe847441d310bcf4853d094ba76414809556342a231e2fe65c63b86080526020600060a060006000610100611a8af1600a55600051600b557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f06567b1f15418bf2a6c5acd78e62159b8b682f2ef0b6f58a7fbe158943fc74d16060527fff848424bfdccf985cc7e451014000366747e559808a302682b81e678988fab86080526020600060a06000610100611a9cfa600c55600051600d557f7e47794e17a1bf02718dfec57b82b103e96d7e6f953e52385b498a5712cb7df56000527f64239ad45dc382b3eefeea8f23911594d78ca076317e9f9b7960b4f8151be81c6020527fb218b903bd81401bbf734d5a2315922f0c406ec792fab423aff997bffc0bcf526040527fe41441ed659010822b187ecb4eef5d733776c9c9526d20ad3560c87afb3d07756060527fe11cdcb149b52e6547ecacf066c0a92fbc349c3cc21d7e47eda1467ca3c1dafe6080526020600060a060006001610100611a33f1600e55600051600f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611bd0fa6010556000516011557f4230ac0ce5216e094ef085206a48af255d3bfb7f11f1154fe86e93cc01c0540e6000527f7d6fb2a29ba4243be0d466cf073f0c91f381af4aabea1c1ab16255c03a79fb9b6020527f06e6dca6036bed2bbdd06d85cd1c256e5262d952a96d0aa5696e8cbc6fb86d486040527fe4f47823ae5cd8f8e881941248e114c9d191868f51c6ff8d4a520c2b1e619b486060527fd0be45345ec0957cc0a7ca0402c3bbadb04a8973ed59064a43342929d75167ac6080526020600060a06000610100611955f46012556000516013557fe6d744e8c84673f3796ca2ab4cac4e32ece670c0e4707639e18549b4e9dc57426000527ffccafa6cdef92ae5f09ee8dd0b500474a4363e074b1b7c1e6aa9eecc96f5c00d6020527fd4bfa61ec6a1f984eef74fcdf6e9f4baba748ac2a645492b4b9ad71045bdba466040527f58042d82f7404f2ce84e49ad7188d2ee525fe17a2d0c225521963800573d75406060527f32fbbbdd801c61ad130150f74e7b98a4ddc2f40bce85aa7e0e50de48de7eb39d6080526020600060a060006101006119d1f46014556000516015557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706020527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706040527fcfe9cd9e3865d36eb93ec8c8aefe537dcefa079e55a50799d03da8403f839ae56060527f84e5ab7dc40b1bfcdb5cf45020e9f98a6557442d5792722e71d6580b5324b7256080526020600060a06000610100611c12f46016556000516017557f4ce6a314bf39f6a13a2d79f56120c5ddc884ea3dd630b091501f462b1fb1ec956000527ff74b8bf1750c490c32e2b06d4aaa7a9cf52ca9a6174b528968ec5934239d00ae6020527f8b8f147f6325c4e4bf531d0d7452f1d64102fcb5fd74338cdffee1f27dc64a9b6040527f01060c697a1b1145fe7f273366539189a56770f32f68259080022da2d03fdcf06060527f1eb393010971afde7c33346378f4ed9876480c0493093869c10e6998d5e4ade06080526020600060a06000610100611bd9f46018556000516019557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527fcadaeb5d0685aab38931aa408da708e1fc2240cfd3e692405ea590fae72a42a96060527f2fde0a17840d08b2ddd90567fb3eb219a4498af7312edabca8381bbc053f544c6080526020600060a0600061010061195cfa601a55600051601b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a060006001610100611bb6f1601c55600051601d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55aaaa55aaaa555555aa5555aaaaaa55aaaa5555555555aaaa5555aa5555aa556020527f55aaaa55aaaa555555aa5555aaaaaa55aaaa5555555555aaaa5555aa5555aa556040527fc9d7038f7046df28b1c52ab47bbd9e743b96259dc6c1a5aa37bd0f61859ea3996060527f7789d6c41415f62a7c6d42c4c03efbdd920a5687f062ddeb8903830b9ba59fc96080526020600060a06000610100611b81fa601e55600051601f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527010008000000000000000400000000400006020527010008000000000000000400000000400006040526f120040000000000000001000000000006060526f120040000000000000001000000000006080526020600060a06000610100611b87f46020556000516021557f88ef4ac1bd71522fb119c27ada9a3565c4c59b719ef1c5ff605d3ceb939b00c16000527f8e3123731ccaa2d15712f5427352e4f292fb6de2e48205c36b521d47903130006020527f360d418db19e848c902f3e9b0687f936a878b8aec3fc44898fcc8bed476f90886040527f8bd66669232a7307e3af41ba9e98e1c9bcc6c2cb1bcd19290d2c6d530b3806b36060527faff058330b9cd98a00323167cb85d0db1f61479c03acf5ccf081186c8913d9796080526020600060a060006000610100611916f2602255600051602355600060005260006020526000604052600060605260006080526020600060a060006000610100611bc9f16024556000516025557fca849b4c9a4205b12124c817ddcbf4847c033e130b3a0d20ed69f6b23c950bb76000527f3dca9dac712d28e081bfc4baa2adf4f8682ae2f4f4b9da7c003ac5ae8a358e646020527f55da3ebc3e6253f26fff786271effe89802c3880bbffc899f96014ca5ab0cb686040527f2f8101fcbb1bb9df8d89b1cf4d9b16cf539d2be4af0b3b593f3c3b64f15200476060527fd21c42acb6c9d34469fe759113a847175edfa8a629b9f818566f46dbbb4c38246080526020600060a060006000610100611c47f16026556000516027557f99ac9dde4f6675ca1d36afbfacf04bc463c2cfbaec70ea51c9da4de693cc2b926000527fc4796c56cf05874d9dca8ad22e242367c4eb946ef1403e0f0b31aa8a82d3462a6020527fe29fdbe9aad9dcd0bdd43f8631bafb406bfeee1928c5c95b840831d19e5672db6040527f35643c199d007509e9adb05724cac3f6375bff7be0cb8809f18432a666850cf86060527f8d623be41859ad127e15e5c841d8be44e9f745d8110b2aada89e60ceae897b876080526020600060a060006001610100611c5cf16028556000516029557fefbbd6857db26ab2faa74a46e8075a2ea1950720cb94fb676e7ca9a5ec90def76000527f9b64ec29fc397751d4baa368bf4833e82a85a6b315280fa27d1b948022547ee26020527fc4a2746dce7b72a9094289836387233b097720ad3a65622b259e71a6f28b2aa66040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b82fa602a55600051602b557feae17c0e1411fa0aed7bdfd3afc1e59f85b60e19a8f8e2fcf912481ce42c6ec86000527fb7f329f0fa26b456c94dd7728a9c795655d39144dd37fa5ab2d16badb39a9a0e6020527fc6b3b1f287e23277cb1d27608a95a428207a8ae1721a4a004653815f43e252896040527f61d358f21da2aa3a593bc15aafe7a88217556401d687cc10bdf5ee5deac2a2456060527f44bdc7b569afbecc115de3aa4f2b2b692b38c3095c830ea4b9f8a21b1cc1dc7e6080526020600060a0600060016101006119b2f1602c55600051602d557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fe6631f1c321035ee89178482078ce3428d97ef91de4f2c9fba2dfdf296eaaff86060527ff374e4cfbda2da61927aefdf99f3d38d4aedf1ea9e99b3d37505a29858a26d906080526020600060a06000610100611952fa602e55600051602f557f9fc62f83fb8c9dd1b9bd9346fa459174294f44b2aa3f6bcafe23d61ae5e1b9126000527f6133ac5a4a5a4732b24e25d0947ba4c399039d326cd81fca87102d6114a2f3f16020527f1838fa42b4ce50f86fe545cd9998b4fa08926d3fb98b1a75eab0a0c850488e1f6040527f97fb30d0bd03dfbbe22bde034b631e6c4b44981d7efff205ec83ed80c8a244886060527fd5a8987fcd6bb092b26871d3b3d7214682783e412e2d247a6ab735a59bd692046080526020600060a06000610100611b52fa6030556000516031557f2b0d74c8ad94bf9168305e77b930d7e66b1467439fcfcae9ae160cb4681abd396000527f08180ce104c5ffd56ab782f4b7a2df4255eefc0b4239f5f84335127f744fea0e6020527fa0c8527c9cc5c2221dc644e7479db9444533d56d6da5d9dc33bd8d86e2ffb99d60405260026060527f46fe64157cc965de86c8479aed407caf925052267ed6cabd25e110bdf45ecdc96080526020600060a060006101006119d1f46032556000516033557fb5bf3fda78cf36ef7037905d5210611ca0de5a749cffaceef0f98a37752c03886000527f41ba296bc996785e233b10dd0566adaeffdb62aff99637bf86b15b4dec6ebbb46020527fcbba6c16b4894b5e67d4e9a73d33a5820c94347b14db0f6c0db20b20d654a87b6040527f2a95275f9d50e9c9758b1768b718224106a7bf810d5085f7ce468ed680088e436060527f0a1a0509b915ed3d0d216cabc9617eab026dcb8c0bfc879deca2d66107020dd66080526020600060a06000610100611964fa6034556000516035557feeaceed8e997346864eb79cecb3de252aa8af678da0add3727718b7cabd681e96000527fed12432d2e8e8e5ddd5e754e444a6703503c77cb78b07ff9fcebdc8d607fd3fe6020527faff8368c4d1b501184a9f72d061237b2e80a616b88868fb16af22dfa1681dfb56040527fd01988930efebb541269070bfb6fd062aae89208ffdd7b3dc72401094bdfe39a6060527f32eb46ca28cfc45005fbd8dc3cb6ad45fa747510279a672045c4055bab2cf83c6080526020600060a060006000610100611bd3f2603655600051603755600060005260006020526000604052600060605260006080526020600060a060006000610100611c98f16038556000516039557f484f37e54c5295cf36fe10f6aff8c229bd9aa65603a5219b46c6129f33d83a906000527f789a4669c419bd471741f57ecea4239aa11fdd902e04af9e29f13ed3ec9c796c6020527f918a4029a6b2b0b14ced5c0c3038378041dc9ed86b2b62c2db603c3a381ca1136040527f966eade76bca84cb2ce407de7a840f6d19190cf918c12d9e3a99ffcf4566a2f86060527f75fa0692a5caafb1bf87d436f99e88f5c6c28a176807517f6e64e0a34b23e63c6080526020600060a06000610100611a90f4603a55600051603b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527a0200000000000000000000000000200200000000000000000000006020527a020000000000000000000000000020020000000000000000000000604052788000002000000000000000020000000000000000000000000060605278800000200000000000000002000000000000000000000000006080526020600060a06000610100611ae9f4603c55600051603d557f6b56c62902da512a9f2f6a1258155ed595a09172d2f5f45b04be21552e910f986000527fbc305a51d5165a978c2d6464030685c2d381e622c87d2ae925788ea762cda08d6020527fe2d02b525f2d094366031877ebeedd2c6016bedab9b0616283f4b86756c02c916040527f10d424688c564c78fffbf8100adea4e5df2b26b81e2d34f36b12a6debedb4a656060527f4321dc8003645b904eaaf90a5a8065693f063d8590901c68b501e6ba3bf358e96080526020600060a06000610100611b44fa603e55600051603f557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006000610100611a76f16040556000516041557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527f625bb93891671304e13ac8dfccd4810b590321cc0d59f12879c0dec48bdda6566060527f57a412e8fb34f5ce3705734c4bd3ef4bde25e0afa47b9da61bdf1f6cd39a00766080526020600060a060006101006119e9fa6042556000516043557f2bc778e01d771a8a4d88e33c2aebfbefe484eaf86af48a14ead2133545084a2c6000527f095960ba6bdea4f7c1f23832b6b18d34d47c06b4a6b2b71a5cf78c0cc016fe3f6020527f7cbf2333cd08c279b26b7ef66d46f671f0d80fbe95dfe456b9a81eb12bc754396040527f8a292b9ce0dd42d054f219d841a85ead3b314c92f4bc5fc2a14c2894a82723596060527f09b415cbdda55d538a4f1d4a7424727e00a03c1acc229a67a6942180503fa2106080526020600060a06000610100611c4afa6044556000516045557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527620000000000000000000000000000000000000000000006020527620000000000000000000000000000000000000000000006040527fde78cb7d6ca1833eca52dd642e9e385a572d0a13a82cfb801eb93accac19f5c06060527f2b8c37f2bf887ca80a8ba691631b072b925c5cee29092de8f0ab088c334b5e8a6080526020600060a06000610100611c3ef46046556000516047557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611bf8f1604855600051604955600060005260006020526000604052600060605260006080526020600060a0600061010061191efa604a55600051604b557f927dfee61e50c7421808524a7a90f8501e0ae985faf4ad0feda06cc7ab3ba0376000527fc911cb77f5fbcc18d1fa9a2473e882ce34eaaeb259e2e3576aa121f3ceec5a716020527f78760ebce4be5905ea0b78337e1eddd627d8a997e121c691395697b909af4b676040527f3fa97b02bdb27aa7403c6dfc2692e25923d4c079e9226030c846ed22dd4f986d6060527ff565e832ba9e1d1285b75c6eecfadbe08a5164384d40a6d42c44e9b921116f746080526020600060a060006000610100611c40f2604c55600051604d557f17d331b36f45839e05e4672575bbfdd5ce3de9ad758c5956d3c91c9f723658006000527f9e0eaefb650f77c7c2f1612e42149b83d25d130026c2990fadfd7f5f2ec321616020527f3186b54dae60571d2ee512b7083864c201a9f729a1c93e530cef6cd6dfe5743a6040527f921f646ea25327d75882e7d17671b87bfb904fb78d1c5819e4a1c582ec0e309c6060527f2d3b43bcfdeda5ed8ea601d767c7831136856a80af463726d9185b3a026e0c6c6080526020600060a06000610100611a5afa604e55600051604f55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x7f0dd9ccf5a133f80f284d8119e5766fdc78abed0168e6bc910b5e0176c951e4436000527f0628c4db9f1f4f2178752223a627a0cb465ed2518827a95123c2ece65f44b4316020527f0499075786280ef4bc72e7855ff33456d8c6f125b7d1d9baaad011ea2ab9e6986040527e97cdd77deef597a2bc16d88539d254cdaa55b105a027c6ab4b83b1868370fc6060527f082be0895fb2a2e368b460cd15b64c844c38b5dc16a4b1c92e5e2798975c56926080527f1ebcfe5a688616de67316604ecdea93879b25612a3432ab4e14a26ffb53d128760a0527f1bd248bdf180ee660835d6b590c4fe6c50ccd0a060555ed2c8f37629165753a360c0527f038ba6f6510fae553b2b3ad7ed616f923858382c71b8054054746de16bf76c6060e0527f0afe62b544bd5e08f5a4d990f3989a0352495686a22f480a183823c5c0b6c3c1610100527f166f65225783504282adece0b7a23103c45a60be1b8035718589cfa007dd5bd4610120527f0636a7022c573e3bb500450a6a6781193917487a4ced2aff1a54f329a257953e610140527f1e1b2efa9cab213ae4dbff879a0610251c40ac9a41dfea3113eb5c8318c44fe3610160527f0919d4b775568b4448a2598e2aa74143d4cd29f5f94c6993cc4858c9d490b9cf610180527f2ce72450da563b7b4d652c83f0442b76d557e4eabc5519fd14d1fae51dbd10f76101a0527f0c5ddd9a6ddf253c840f29e6f1f5589039a3d31d8969dd70bc7786f7c14992fd6101c0527f0464740f9667555139ab1d405612f072c81773fa2df80237f0f30d4dd8c92c846101e0527f2c984c8a12450a4f78d13b602226bbbd93dde861fcc37f6a60ec69721d880195610200527f1356ee4dfb103fde3ed6d9a430fa55187814fb6f1688f5e5f73be48bac31d74561022052602060006102406000608660087f823050ef163d7d484e8a5a18e75335c1b282c3e3296a1e348ef6be914ec253c6f2600055600051600155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f014578955e56f6b52f72afe95be88f8080692a1af480fc571addbbca08d5e1b26000527f6b65fe58c31529e42775db26d33a3b91d21952719de31b77b4c57f84c71e69276020527f4a78953ce832910d03e29be38626662621d587622aa95bc1aa396eb65c0fc9de6040527f9278fe0e25e1b7c612b89b3219bbe81f9a558637ee40ad3e6b4c23f00be36cd86060527f28a2e51b0fa05f2973fcedb329994bc6975e405a52336c9c1d6d7f65a3f041726080527fc4cb93a0c12afab3cf3fc961123f659e89386c086b8f8c03d651ba549d34411260a0526040600060c06000600a7f61824de34891d5dd5d68d637e3889f76a90b610e42c8d6340cad9ed9ac966da8f4600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x6000600052600060205260006040526000606052602060006080600060016119fff46000556000516001557f5635d69609767cc55df05457febb80b0042d87e81eb1d22f226de79a76c708d56000527f7738ef82f2a4e2832f532706eec1556d2f325c8d5cd7930f9b3b4a409c85a71d6020527fe23a41f46cdbc28e002d9f6cc7b11c4e259671f69e9d03f4f4e45b86c9d6c5cd6040527f2531f0ec7f10dbbfff9f4b7a5d94a4f4d49ad9ef6a3de8f38ab1e6372d1e5e32606052602060006080600060006001616727f16002556000516003557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fb3bf27de565ff9a8d996e8c6f4229b90d3d785882396fc871a67df2777390a456040527f4e6497845945c0d9d7b5686784825970f0e17404398ccd269eecbd3cde93adef6060526020600060806000600161d628fa6004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f90cfb0a7e935f0e0e195c789fbb8fd85981430909cf043ddd784e13765fea44e6040527f4788f359d9f79d7e1c54ca4d982556c9b1760282a44c6344edf82108ea60b27b6060526020600060806000600161dfdef46006556000516007557fc5c3f0ed9812b3fb0cefc109617fffd894091214ef719cb57933b24c3ff7ea166000527f34f0eb248c0ad3ce9f7420c2fc2ad0ed06cf7fb6a63a679e89e7f63806706b086020527fca6f9a3c432db550d8a783c7a39e13aa23a7ed46695c52666c858c6a85c0743d6040527f568ca38fda9afebc390205b01ffe0b32479e93802e56121bc36986b476c5bb2a606052602060006080600060016201318df46008556000516009557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f5182ddea0d6c800d464f74dd82bbae46b370e73745a2ef5be0d1cd78e8b63bcd6040527f4d8aa48e8e4aa324d6b5b0568413627f3088650584f26f7d9d230dd18bef7220606052602060006080600060016001615f50f2600a55600051600b556000600052601b602052600160405260016060526020600060806000600161323dfa600c55600051600d5560006000526000602052600060405260006060526020600060806000600161e876f4600e55600051600f557f9cd1c9e669f25ff0d75358a68b742c499dd507b1929e69211f9dcebed088d2396000527f3197fe1803571e9dcc547d0914727e57a04f413c7fe0e80df6178ba721e7391d6020527ff6f60e0b8b56deb4215aa5a8791e67cccbf67bcbf28a00ddc01aa9e2834bcba56040527f5d82dc04d961c9baa8607de329bbfc5c0fda7606fa685b8f637c96cff204986e6060526020600060806000600162015414fa6010556000516011557f48e61e67c212051774e251f4694009e70b0c8cd3e53f546bd571a89cbd5d77866000527f482558bb150d8505183572baaf7a364052737fe23c1ef7883320a2cb0353921b60205260006040527f2048679e6e96fbd4128e4da15a24443d8118cde5a019a700164135e810bd0a4a60605260206000608060006000600161e2bbf26012556000516013557f36acd9425393d15e3eb4812d51043df238ef8864cf7e0d11b59e4fabdb18cf8b6000527fb65dd238c5703c5cf7eec9884f723f689330e90cf77801118035141dd442c01c6020527f8d4eceda1b4fa1f96eafc840d34ff01e2a1dec56c33838a8141d1f9b1d4811f56040527fffff8ec6cc8d5304fff1733341f73d0448e8de858f72fe1afaa8cdcdd894416c606052602060006080600060006001615e79f26014556000516015557f16cf9ac0524c5cdee7ba74b3dd710d75cccfc885ce042fe1e95668866a1bc05d6000527f7d3dbde81de980b22866b25af9b31ad7a8f45bce7feb7bb3327b91edc5536c336020527fd28c824dcb997cdfe976e7f9e4f62c09ebf1d53e969e66f045e2cd686f3996e76040527f11e5c0bfbd64e28a8078a0d9ee926aecad8bc52d65cbcb89892a169afab5142e60605260206000608060006001600161e126f26016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2f63ff12ae5e48349a3cd273ecf7a16bfd325fb80c1b3601bb1c3b6958fa76416040527f4641561778dd3463d0124b1fd9432a9cf49d4e22c761e6ca5f2a88bda1bfc05b60605260206000608060006001600162018551f26018556000516019556000600052601b6020526001604052600160605260206000608060006000600162014e9bf1601a55600051601b55600060005260006020526000604052600060605260206000608060006000600161446cf1601c55600051601d557f8bf2abb1d2d1ded3bc18adf47c552ddb500f5e4936d62c2a4bbd8604e1b89b086000527f69c2dcb690ba7704bef53049a822ac4911a7eda430bf3f1919e1ccc46e05171d6020527f5ad9fc0129eccf96c24be1edbb6d90b2baff6286288c52b86544c944d778aef56040527fee6b147e5aa16966cc768773eeba18d4ca5ad8e7b1fed292547c35ada4548eb760605260206000608060006001615edef4601e55600051601f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fb3882d7cddbfb1aeb96ea275eeba65cafd3c057d53a4650c8a623dc5d90552176040527eff0997551623a79a5bc1c2e0285120219d911b571006d7178d7b70be8506ae60605260206000608060006000600161c05ef26020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f0535a453701693dde78ff230e8ec5482f5a1087b3519b6e27f47fc871ea52c236040527f46e1c6e229537c9c25a2197a51d331418065a8a749b8c2caecfeb4138ddc661b606052602060006080600060006001620149d4f16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f6fc20df9f44aef7af01c979f835f67e0d1426f0802d6c4697844fdb5928d46716040527f4a8986d60152dbe79028c9854f61f3bb229d465ed2296e191a59caf1e8f8196860605260206000608060006000600162011d1ef26024556000516025557f4d11001caf9bbe5571fc607b41905d585f8f1156c87c3b2a1402fc525802790c6000527fe90b1362fcba1f8347e103984f99ccfec324a2f9f4635c4776259f29f60b4a1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f1454f2b26fbdfb65f37eded4dec22e9cab0feadbd60b34913691b1d08c7b008f60605260206000608060006001600161bfbef26026556000516027556000600052601b6020526001604052600160605260206000608060006001615a0cf4602855600051602955600060005260006020526000604052600060605260206000608060006000600161f2fef1602a55600051602b557f091972bef5bee21dba19e42b89499d24001da47956025c9acdaa32f2caf1aceb6000527fce3ffe160fbd50f0c627da01036b788e8423201346a6e7ec67b8e81f69d6b41d6020527eeef5f26b4d5201c901905fca0a0a3c1f53156962becd64ce499aeac07b85086040527f024974992117a12a2c64e1b3a8e547e45418b905b5b644bca78eafefc2582ce06060526020600060806000600162018411f4602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f19ccd9280715e451937d27a22990dd8c7f2528581c8d0f55dd3e0c04a68adf2b6040527f3ab9a559dbac4213538275eb6df877b42992eb9f36cc3786c62684ceddb0cdbc60605260206000608060006001612800f4602e55600051602f557ff40546baf9aea56fe68bc14aaaa1e9d21509e81f21af4987b84fa5baa893cf046000527fdfd0c846d634ef20cc13379a6382995d388806421855e2c64310a6c719bea91c6020527fa5ba6c38881bf21b5a7dcfdf690975abd5e5cc39bef2af15d7f5d0d9e5e400dd6040527fffff424734ae111844e2ba4fb368be44abb4ae3505608497f5d12526ec74f8cd60605260206000608060006001600162014526f1603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a900a637fffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0407682100000000000000227ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0901a191a7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0067800000000000000114901d60bf55778200000000000000fe000004000000ffff000000fffff7006f800000000000000000000000000000000560c055760fffc000000000000767676240000000000002b05760477e40000000fd000000db0000000000000000000040000000fd000000db0000d37e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000096a1000000000000000000000684783921454358970521b901a60c1557f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017f77676767676760000000000000001002e000000000000040000000e000000000901c682323232323232323237f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd901d90037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6005900760c25567b368d219438b7f3f600190140660c3556c0100000000000000000000000060051b637fffffff67b368d219438b7f3f90131c6f121212121212121212121212121212127f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd9011900a60c4556000637fffffff167bc9700000000000000000023f00c00014ff002c0000000000002231086f121212121212121212121212121212129014191d7e40000000fd000000db0000000000000000000040000000fd000000db0000d37f8000000000000000000000000000000000000000000000000000000000000002900b900b7e40000000fd000000db0000000000000000000040000000fd000000db0000d36f121212121212121212121212121212129002077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7effffff8000000000000000000000000000000000000000d9000000000000010760c5557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6a1000000000000000000000901d136b1000000000000000000000006c01000000000000000000000000900a900360c65576013590cab83b779e708b533b0eef3561483ddeefc841f56005177e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006a10000000000000000000000a901c60c7557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007a010900000000000000000000000000000000000000000000000000106c10000000000000000000000000677fffffffffffffff1a901a60c8557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd197e40000000fd000000db0000000000000000000040000000fd000000db000001677fffffffffffffff1b0b7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9901660c9551969010000000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee900190066a100000000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f59011067cc9700000000000000000023f00c00014ff0000000000000000223008057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10001090126801fffffffffffffffe6f800000000000000000000000000000001b900360ca557780000000000000008000000000000000800000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0090047ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90107d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97a010900000000000000000000000000000000000000000000000000678000000000000001900890191619901501717676767676767676760000007676767676766c01000000000000000000000000901d900a7f7effffff800000000000000000000000000200004400000000000000000000017f82000000000000000000000000000000000000000000000000000000000000000790141560cb55717676767676767676760000007676767676767d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9077702ffffffffffffffffffffffffffffffffff000000030000651ce97e1ab91a06107e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f800000000000000000000000000000000000000000000000000000000000000190131760cc5567ffffffffffffffff760100000000ffffffffffffffff0000000000002e0000006d010000000000000000000000000090081567fffffffffffffffe777effffff80000000000000000000000000000000000080019001900560cd55717676767676760000000000760000007600007a010900000000000000000000000000000000000000000000000000901d600767800000000000000106901b6101117bc9700000000000000000023f00c00014ff002c0000000000002231089005067fffffffffffffffff7effffff800000007effffff800000008000ff0000010000678000000000000001901d901c681000000000000000007bc9700000000000000000023f00c00014ff002c000000000000223108900290187806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a762900760076761e000200767600000000767676760000001401760fffc000000000000767676240000000000002b0576047677000000000000000117f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a57a01090000000000000000000000000000000000000000000000000068066aa0a5319bcf5cb408901960ce550a7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0610111900b60cf557cc9700000000000000000023f00c00014ff0000000000000000223008057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000111c7bc9700000000000000000023f00c00014ff002c00000000000022310863800000000a90016847839214543589705263800000000560d0556101117f77676767676760000000000000001002e000000000000040000000e00000000090051c777effffff80000000000000000000000000000000000080016c10000000000000000000000000900760d15567d021262626262626677fffffffffffffff137f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6f12121212121212121212121212121212651ce97e1ab91a900990071463800000017d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf99017027ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff6380000000901860d2557f77676767676760000000000000001002e000000000000040000000e0000000007f40000000fd000000db0000000000000000000000000000000000000000000001901790067702ffffffffffffffffffffffffffffffffff0000000300007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0790016801fffffffffffffffe7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00181502778000000000000000800000000000000080000000000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb01419166823232323232323232368478392145435897052180a651ce97e1ab91a7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200000a60d3557f7effffff8000000000000000000000000000000000000000d900000000000001774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a06016a01000000000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a001290031567b368d219438b7f3f6b010000000000000000000000079014651ce97e1ab91a7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9007760fffc000000000000767676240000000000002b05760477702ffffffffffffffffffffffffffffffffff000000030000638000000008181b7f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56801fffffffffffffffe9001191a7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007176767676767676767600000076767676767690139002686d5adef08547abf7eb6910000000000000000000020a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f40000000fd000000db00000000000000000000000000000000000000000000011160d455151960d5556780000000000000017ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb090187ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff6f80000000000000010000000000000000901460d6557f7effffff800000000000000000000000000200004400000000000000000000017f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5901a90077e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00680100000000000000001715901d7d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9760100000000ffffffffffffffff0000000000002e0000001714712000110000000d0a300e750a000000090a0a6770000000000000007f8000000000000000000000000000000000000000000000000000000000000000900990057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100076fffff716b61616160b0b0b2b0b230b000008010d0a2b00900490126f800000000000000000000000000000006801fffffffffffffffe9001686d5adef08547abf7eb76fffff716b61616160b0b0b2b0b230b000008010d0a2b00600190089010146a10000000000000000000006b100000000000000000000000901360d7557ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000610111149010712000110000000d0a300e750a000000090a0a63800000019007177f40000000fd000000db00000000000000000000000000000000000000000000017f7effffff8000000000000000000000000000000000000000d900000000000001141b7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb06823232323232323232306147f77676767676760000000000000001002e000000000000040000000e00000000060000b197f7effffff8000000000000000000000000000000000000000d9000000000000017f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9009901a04760fffc000000000000767676240000000000002b05760477ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9018901160d85568210000000000000022671fffffffffffffff017f8000000000000000000000000000000000000000000000000000000000000002778200000000000000fe000004000000ffff000000fffff700900b90167f8000000000000000000000000000000000000000000000000000000000000001774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a900590056a01000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00031667fffffffffffffffe7f800000000000000000000000000000000000000000000000000000000000000017900a197ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000068478392145435897052901060d955682100000000000000227702ffffffffffffffffffffffffffffffffff2000000000000390150a684783921454358970527e40000000fd000000db0000000000000000000040000000fd000000db000001901a900760da557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f7effffff8000000000000000000000000000000000000000d90000000000000190187e40000000fd000000db0000000000000000000040000000fd000000db0000d37f820000000000000000000000000000000000000000000000000000000000000090117f7effffff80000000000000000000000000020000440000000000000000000001760fffc000000000000767676240000000000002b05760476f800000000000000100000000000000000960db55901760dc5560006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000dd": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x00000000000000000000000000000000000000000000000000000000000000de": "0x000000000000000000000000000000000000000000000000000000000000000e"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556001496001556002496002556003496003556004496004556005496005556007496006554a6007556006600855",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x6101296000526101296020526101296040527f69e81e3e7395914bd7a174171c2abb5872a3f74bad925e171848173397d0f4ce6060527f305d0a55de9a15923e02507df70929ce7a6e0475b4153dfda8d31734ca31a7296080527f6f40e534fd50742c50dc37c0434cd6336a9a5eb9a2e45ed8d975dbddbce661eb60a0527f1221005f45cd8a15ead74d3531129fd35a822daf4255b9cfea9dc0a2e5bef40160c0527f326aeabec0290bd67bc8c0835c9b899e66dc95ed43ce31d3580fa75ceefdc43160e0527f897c7d3a7fc2e9db1eae97afdb1cbfdae405d6093612313eb18b23781d21ec6b610100527f398f99408e87f8f74c7b2df6c46c35547884c8a3d4e9578775b11d452ed8f615610120527f7c6d97d68312ab514050a3ce3beb54356639efac32d6945047635cbe25448f74610140527f1ec847857382073929b34276a0e24b618cacc3f231dc32bc7f0e6599459c1ff6610160527fcb3707198b19ed5a4bd071c3a57a194e48a9a63c4b7de8e6954512bb6ab2cb55610180527f9cd5eb4f6f1430634f33e3d0cc775581dffc61ba1d1e3d188c9574d3e01576936101a0527f467247bd7ad3a43bd64bba6815bb51953d11ffcc1d26572d43c48e478e8c5e996101c0527f397c09d19c92b79ff9e7eff33d517220dc0ae525cc76b8bbf0407189aadbec236101e0527ffcf0525acc205a9b2f0cb0a353e5b82c0da2b68c042b8a4212682f22a1aec7c2610200527fc3d4186bf05e8a8785e0c129a5a0d951f82d409eccd3d89237fb46b530f1de4e610220527f25f22b01d268d08f7793386bcdd8a84426761cc3c231cd1eabe8eb6af296e082610240527f2efeda8ce18279934df1c2f78981298c2b1982e1460fd2d12a2cab72134f6ef1610260527ffcbeb4de92c1037e3aff1bd001b5c9d763fec0ba3c782adf56d278f055d6c67c610280527f49aef127fb8b37b2bcc87b5201325b5c5b6bccbb5a9da51b00942fa86dc143f56102a0527fdd86c4c44ef5fbca928a90b54ae77be694ea2ea2b601356817c81882979e281f6102c0527ff8e07e025ebd4a65c76f68bc9a6e50c83ead6ab102aa166d0d7a687d3590c44b6102e0527f78b0a61e9d2fcd1813363be2cf16957ce8cb1285f90b91aa32ec305a1233ce2b610300527fc69de814bd478ba07ae5167dc1686cc2dda01fbcdce97d09c16cfc6a6cab4ee5610320527f2c34769a8e26508f6d287cd1a95d355928cc5dbe0580707db6d3ac4dc31d150f610340527f49b59eb4f467447d0cc6113ab1b63ab67d27f7ae398d1d432582c2e8f6a4dff7610360527f550e23fdfa28e38ecc6b28ae82e8a26e0d8cca9e625bcf0897816de7fb8bb827610380527f6a3614910a6314bb3b7f081a174054536b82bf225bb41570f6bd385558a5c8156103a05260546103c053603d6103c153605b6103c253609b6103c35360ad6103c45360df6103c55360226103c653604f6103c75360996103c85360226103c95360156103ca5360396103cb5360326103cc53609e6103cd5360466103ce53605d6103cf5360cf6103d05360ce6103d15360fa6103d253603a6103d35360be6103d45360436103d55360ef6103d653602a6103d75360df6103d85360de6103d95360086103da5361012960006103db6000600060056301174bfff25a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a55604260005260036020526101006040527fdf5f74a61ecca030138e6021dae95a5b368cae98b66c171812d2338bb86483e66060527fa5d7c8cfa18cda53cf98f7826fd3867d8fe9dd095e50d065de4d34d1cf88d48f6080527f0f9bdecc79c974a38d471073780296aad41362c1fda9885d9e789cab4b1ae54e60a0527f5aae2d5ef85a4d57afe48ec9d966da9ba744d517f8fad9f5502824033f94699360c0527fd55b0e001ee8a9e537e3761885d8cc05eaea065308f785bcce96f071b0853c5f60e0527f6c86b21c7df065ab5e94f5b1f69ce88c2e87fd50a9207bc9e29b2242194604ee610100527feee7d72b553031c54b89a8db874fb6946d115fae9037b30e77b8c0e39b50f4df610120527f4baa678533b3b484496b3321f1a53313d85cebada6ce98cfa7545e9b378cf193610140527f2032fd1ac0270d38f02e8432ec8d494921d7b7c706d5d5b0d7e0925ac818aeb3610160527f2835e066a94d1150ca5dd1af7b36b3105c9999b8229295830d1eee70dd73ad396101805260666101a05360fe6101a15360976101a25360c96101a353602a6101a45361010060006101a56000600561f68ffa5a01600b55600051600c55602051600d55604051600e55606051600f5560805160105560a05160115560c05160125560e051601355603a6000526103e4602052603a6040527f59cb660c0826be7706b5e062b238ad17fbf96d2eae2d89bc93e9881aea0495486060527f0339ed057e9aa557c676b245344845451ecac965862814cb13ad6a1d45e82ae26080527f4d1fd92e4000935a20b6909034d34b01b4e7ff6814f649ac3bc3dbe71eac3cad60a0527f69f3390bd3ce4afee1890e88d0e541c58019a9df73a2cd66964c2d034cfc5e5360c0527fc82d4950773b57d44e7161528597236e3614cfa5e54cafd8352a5abe115f44a460e0527f31760e86321b4347bb7823deea70704ea503067ecf4683f0ba5093d200ca45ce610100527f522e9393efbb864ffce417d0120084c0eba76f2fd2769e8cd5e71e0c927d5390610120527f030ab22e0ebc72b408291052cacc5ca32c1786a5888a527d74a72a6368a71a98610140527fe1fae46ccda64d1b1d588bc1ce80ee638626562b201e1fc23370f2b986af0f70610160527f9835a67ea548cbdd5cbc61a66a6feedf57f514d8216cfbdabc34e5fe985851c1610180527f0fd4604ceb36c7c98a58e1e3dbe176da1f0b92a858cbf7b66545cf28162057286101a0527fb8078e2a9b7fe21cc4bd3a6581c33056ed4b3031442d3c6ed9ef165634b3a15b6101c0527f29d8b959e94d587e725e5f73a69157ab9a9a60470488bbea5cb6d005066c9d726101e0527fcbf1d991de7de7a45b29f5408a8779319a21ab4f7ed873578ea84fb2f5c3a9f4610200527fcf72073db33f80ac63e9a12c825ccf52658f098e6f30a7a2398cc20519979cd3610220527f7f55da0405738fc69a98caf7a59ea205d4fa84efe99748effd6e763cc34f85fc610240527fb2aa10c82c9b0bb4bb6d916a57e70fd97d8c099af760268d684bcdec58b71417610260527f85008a08c9978857a3e7e055e7e9c86b7db8871d440806ad37bebab67b78d60d610280527f3958000361b187c50526765c4900a44261023f4c418b3e592da5e6b77f240c026102a0527f5340288abc1ad5421fc94f5e9be342f2bec6333017b1becd1912b45c4f19087c6102c0527f941d62ffbfbb047fd7b2a050757e246b197bc86e67a1ccdd85598f86e6ae6afb6102e0527f646fec060cfbc4f77e5be17fe7dd4a4082aea0a46b122a7058ea9492d96e8698610300527f4d7a189ca41c61843c598a8f197a2910a26c595be275ba67c28cf3c1c9e62fd2610320527ff287a0f088b71a6aab79a535d31111aa98a7fafa10d1ad802f6c1437a042cc36610340527fc39e979b0fdec7b5ccab8636ae3a1bf8e30b9ab564b51acc5fd767cd2cea4bde610360527f69a8f89674885b22757dd55d89dd2b5d7d72121bd318bfed01ffe7fb9fd5c351610380527fae7515a9426791b78ba37c231e6630ecdcbdfa73c9b0c293738d205bf883869f6103a0527fccc57c6c698c8a0de47c487da0244e367183967c4b3b65226ff11b6b8eeb777e6103c0527fbea49780f5480fb6ae0df0693c39b7a102df9268e4e011ca61b6dc7b51baecd56103e0527f8e9c5217aa66333950b594a2dec37f423a67bf65b9cb80a2f4d1b45c5c7dd7db610400527fbdb29ede3683d3904d533ee4df89d7db61ecfdb9b313377f1fabb76cc4955a38610420527fb10396556870f949e6c1ed83a081e425a4e5915beefd6d0d85f0643516089567610440527f1f348949c6143fceab9423d11f05656442bd666d73308e900d43ebef7bd7be0b610460527f489a7d036dabcb10f159d06a3aa2e326ca7976c5f5bc87e6f4b6d88bc9c310806104805260e26104a05360b26104a15360c66104a25360fd6104a35360aa6104a45360e26104a553603b6104a653602d6104a75360ca6104a85360056104a953602c6104aa5360156104ab5360386104ac53600d6104ad5360416104ae5360286104af5360f46104b05360af6104b15360b06104b253600a6104b353609a6104b453606c6104b55360f06104b65360886104b753603a60006104b86000600060056229a50af25a01601455600051601555602051601655",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x20000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x0",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x",
+ "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0x52"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x0132d6deb603df6639cddb11a72c84d811c0893563607dbfbdbccd7a1473f846",
+ "0x018e95a083430036a83e06d44d20e48c449c73887210b4fdb1754c8203e0638b",
+ "0x0117b08385e646dbfce1bf4e12453f47418f94c9210bd326a75c1e5f6ba466c7",
+ "0x010cd0225eb0ac60dcc3ea4ef75ab6bd7bffcc1a76bb55a714e12d56844e8d4e",
+ "0x01124668b9854fe4ecb676c9eb81b1bf469fd6e8e3bf726d1e996961958a2943",
+ "0x0132e4d95f2db408e3fe5a1e034a2f4782430712edbcfc1438ab49a7fc10003c"
+ ],
+ "data": "0x80e805",
+ "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x25e79e54e8c02652f2565713d311d5cb168192a4d71d9a9aee1f946cdbd6e3eaa7",
+ "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x806742"
+ },
+ {
+ "data": "0xc1a00893a8130b2ca38989576113d35462b45eecc786193b898d3eb239b6e712bb6968ed9aa996786e",
+ "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x56b"
+ },
+ {
+ "data": "0xcda935393d196ed654f80a8b358db56e6f03ef47b2c7cbd02f981b1942af",
+ "from": "0x2837fE6BCdADEa40e14E73df3101847267659772",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x2ccc98abf7db01f4304e4590fd15868ccac4894b3e147950631ff47f5365e672b74b86bc4c34d454e28ab37da11eb194acc4957216d4f77ea6279804fea86abf0be0e98ff69c0b03df2bb4f889624ebc00d2b90dec25f6b27aa4625d29cbb5fa954dfd422dcf505eee5edc3d315ddfd4fbf1f1605fac0f2e4debf9f0c45d49b44bc6902663d567f91bd01e7a8bf300368d037c90a56a155a477262a01d2bd558dbdc",
+ "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0x0"
+ },
+ {
+ "data": "0x19a13a072bb4",
+ "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0x402522"
+ },
+ {
+ "data": "0xe2",
+ "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x5"
+ },
+ {
+ "data": "0x",
+ "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x0"
+ },
+ {
+ "data": "0x34a9132814758b59273daa94386285ca6ec120a9d4481a23039b58152a8da551ea7308a94e7419cf89b239da0e569207cac855b71fab651a7b1738fc07791f901401b802befdd5aa04587a35",
+ "from": "0x2837fE6BCdADEa40e14E73df3101847267659772",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0x2adf47"
+ },
+ {
+ "data": "0xc16453d9244731365126c88036a7d21dc4e74b5e",
+ "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0x21"
+ },
+ {
+ "data": "0x8d80c554a0fbda8217a176413301cc3c60b0cf745f87ec393c2bff96faabf209afe5ff379b58c1a2150efd2f8ddea5668e528eb86081400aa5105ac67aed06755a5a4b5d45b83079a2fdaf7e9d90aa29756605b68d94",
+ "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0x3213ff"
+ },
+ {
+ "data": "0x50af4d2b0584036576383afba79c69f64fc2b71db10682ff80d5653cfdd52981f124f31baae8d20fff7e6aec48bf547e8c08651cad37205e8320a156f61f53f38acab75a",
+ "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0x7b"
+ },
+ {
+ "data": "0xfef68089f91a694f575e07f3f58904aafac957",
+ "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0x4d"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x7564105e977516c53be337314c7e53838967bdac",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x36b7ac42eec8f5237477a6169e8c357399393f59bb26761056bbff43903482a6",
+ "s": "0x460efc6055f2d148029adb295d71d6df3e226d673bb716b5bf4b2521a77ccc4c",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000001",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xe6a79d6fca48ba50006d0503ccdc43c19f9f07ecaec4c496110ce6701d9789ee",
+ "s": "0x482ba8d2c8c39595672302abc39a714ff67de25ce1c4ce76d25e09ab86f8394d",
+ "v": "0x1"
+ }
+ ],
+ "data": "0xbfdc6d5fdd81ba0f593ea74a4a2e16aade24b578c028b7d34d5528ab79",
+ "from": "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000d",
+ "type": "0x4",
+ "value": "0x3919"
+ },
+ {
+ "data": "0x00",
+ "from": "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x7564105E977516C53bE337314c7E53838967bDaC",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xb69e5f919d0b7c265606ddcc668583ef819323ff6b65b9f0485cbadb495e5bae",
+ "s": "0x7296df3d02e403899fbe72a1676027a5216c5bf1f0891d945a992eaaf8b9b614",
+ "v": "0x0"
+ }
+ ],
+ "data": "0xbfdc6d5fdd81ba0f593ea74a4a2e16aade24b578c028b7d34d5528ab79",
+ "from": "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000d",
+ "type": "0x4",
+ "value": "0x3919"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_largest.json b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_largest.json
new file mode 100644
index 0000000000..167efc7aad
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_largest.json
@@ -0,0 +1,491 @@
+{
+ "accounts": {
+ "0x000000000000000000000000000000000000000d": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f0a87ed7222327c89e32c494655ab7ab56000527f9edd68e08f46df176f43ab43e5cef82a0ec1e3b507236e9e1d29ee4865c3172c6020526f0407e673e011e005623138422425e3f76040527f33e8019de96821fd513cd74317d3759644eac2366ec002ff30599f23893d01a96060526f0c8ed51666fa89cc3b565d4debb1613f6080527f1b05e40e0f001cf0fd1708ed5ec0cf0848395141fad4e63c1906ef6826eb59cd60a0526f09ded88a18337c0914c78872d01d415560c0527f0968b8eb01921ab81aadf28a9d3184bca0490cbd0c34ba4bd4967f21af512ada60e052608060006101006000600b7fa4252a9216f3d0e78298c2b7c114a064716eddd0911583de04b66582d8ea311df46000556000516001556020516002556040516003556060516004556f1a419a917fc94f5634495deedf4a24016000527f048cc6b4caf2a633a5e8f2da8c0143c06d8c1936c890bdb2598545541f70d11d6020526f18e47fc371d0406e1d4db090510a8adc6040527fde2c75ec145e1c8c0c463746e7094ba17943d2c86a2bf2c6ef95c2fb431910486060527f2e2b2003141ba627ad513d8a983c48396ffad9321a55c93c2604bbfa2308a97c608052762000000000000003ea3ae275df42189c22df81e214368360a0527f8780adce6237aa9f065ec90a90954ea710e653548c7299c4530795fa29ee9d5560c0526f010cee41653204615b11ff580614bde160e0527f2b421b606c9ece327f85b1eb9cf1c824a346f190ca67c2f51a2457820cbc7b15610100527ff2c9a103bda905ed7b8b699659b9323f48a5c7bcc39089b56bdc479432ba3368610120526080600061014060007fb07bfea156dd2c6da61259f98c6acd1940635b34f57488f007f182e1c924e6e4600c7fcf18af1150328aff200c2fd8f999bcc0d5ee9391b1cba27c9881fe5df5887bc4f26005556000516006556020516007556040516008556060516009556f09b04f3d8e653b62c7982bd62d551ef46000527fa637f50de8135135d5d4fa0789fc81ff1aca0f5580ffa0aae9d3320b46eb43616020526f10f5d64a37c8c7af6fa86c43e7b04e246040527f50df08be2d64e37307e120865ddb737d40df135bf781af0cf34e643bda22fe206060526f141d734530e56cdb3b167ae3ac8df0a46080527fa4400211fd2cf3454a25257d075e59d3ba197c8840955c9a1354c2182eb04a3f60a0526f0e9be6e0e15cdb0b5bf6fbb5212abe3960c0527f87491a0cde1687660f12853fc9be9c16f6f82114c4874c4748328beec87f289860e0526f07d9ba7a0a45506cc5ce37f24472fe0b610100527ff428a69ea59c554de9cfc53f27a38281f1c264c784a645fa2d35289ce405de2c610120526f0762254fb0459e7df8563bee37c4d2f3610140527f491f360f159d69cb14c672d79d4feb00f024c4bfb3f40ae716b113faf88a9a13610160527a01000000010000000000000717a86a35e59903c132908dc7f52f62610180527f8a5cf0cf8a71f5664b402fb7810716888ecebc361881eba0ee7b505d7f16b1886101a0526e5a50ba7862cc7cda96c5dc5adf8f4c6101c0527f4331955a3d1e519f7274d3fb7d0462f1002580dee6f242c634c0089195186d3e6101e05261010060006102006000600d7fcef0c189c7d9456aaccdde7e801f01a3432106d9dcfe0446321931372442b159f4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f024aa2b2f08f0a91260805272dc510516000527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86020526f13e02b6052719f607dacd3a088274f656040527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6060526f0ce5d527727d6e118cc9cdc6da2e351a6080527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280160a0526f0606c4a02ea734cc32acd2b02bc28b9960c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be60e0527ffee06aacd23d0a6c86c34dc19c60536cf9a6ea877a9e9eb2f6a4df3e9a353dd2610100526f1fc25c7508e84dbd1daf7961d33bfb2f610120527fe53a40dbaf0ecd8c7eb3bd54bf2168a6d7a055ec92130ba37052b423447b0a9a610140526f05e99862765b9bcd6f7cb63826fcd392610160527f848915d53314781e8877d55caf9c4f8d34c7a8b89cb8bacc90de4a29921a44a8610180526f11af9ffe6238b2de3f7dfbe19e4e0a586101a0527f4e47686ba041f9dedf748c8d126b85c8c8edb4b2797e15dbf67683b1a73a8c446101c0526f17b6657a667d398b8f13565befc2a7e56101e0527fbb993fd6c1c8a6d8b87870d5c321b47156188f585546bfbf9033a4c86be66c4f610200527f18997f86a0ce7dabec3e81f963d5481ec93f972adc070ee52a4b1e9828a1cdb1610220526f10a4258f7530a05c9baf43860413914a610240527f525ff884a38adba5cbcdb1fa8b7ed37ff38a369a0bda3f8ce5eba0a9fd23e3a4610260526f02e67a246248652e404608af51e9ebc3610280527fe9cef9e3bd785b9348c6ac8d58796c4606539f4fbf49004c85bbe2be3801b42c6102a0526f05c8bf03e4cc59c61fe7127ec8467cae6102c0527f01153b2e813177d106fce95671a92f34680a68d71a819a47a2bd88a8c1d065306102e0526f19dfecff4a83dd53c417d38d59bd3f1a610300527fecb84b85caa8935a60b706781e85e4748de3a187062175cd88589c4e1cc33d55610320527fb985b5b035764a8b63042b39ef405bc5b863eb556ac92ee9b81220fb9ec662a16103405261010060006103606000600e7f9f28453243c7169466e0d7b52d3d089cb3a5027dfe9b6346ccd3744baddef837f460135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f165c50dbe8c0a0208acb5b4f32f320906000527f17ce7e71e958a64abf31e2fc571ddddc5f47046db222374332e6e6ed6c60725d6020526f05c327bb284a00dc257c47fdee750c9c6040527fae824af6cede547411e87562748ed6dba06e401a2092e49108a1513ac54604326060526f01e753ef84d2a5461a45b2d30b0721dd6080527f911ed29cf977b2d50d92d7085099386efb72f28aaadaa7509d47ba49e2d5576660a0526f01c9507484cfc3afac23df3f40edd4e760c0527f5153fee58f641ff7ef30da0e856bb7207d5e49b0a7d803778ba2187277878b2860e0526f034eb4d81eeb63c3e0c0df223b4e7fdb610100527f676f8c98a87583947e51d405c7102382e163fb63ebe7ad836dbe58b7af5123c3610120526f09cf32bd5a983e5edf7439888f49a36c610140527f4d51e8b926c13dc5edc5bb582946bc58a3269bb45f61b3f3c8d7d1b78bf68f5b610160526f12786c6a204b05a66b3b0ec1628fa1b0610180527f1298d31fefc9c859bff378565c1f83a3ee8bf0f7ea2ef66612ba98cc908217cf6101a0526f12f75b00d7ac4480219fc66b5e4cee686101c0527f8b6820eb8cc47694ce0d910281222a281db5431258217f13b19ee22df398813d6101e0526f053a3ec469166e07e50fe90261be6c03610200527f8bfdeebc739636d4d569083c14a1dca3d1a32a736c900150dc8e231494738086610220526f0540a51dd44fb6a1bf12d3cfec1debc1610240527f50ccd16b2499c78cd00a1ef4b1cc0df6a76f7448791912fe67ec17bc38fbd0d9610260526f1792de16e20a71f569cb872f24967936610280527fd0e86308f745cca7665e2d9da1925e7b40b1c75d377d049fd0130dbb91f8d2a76102a0526f10584eb9a95dfcf214640f20dc1720626102c0527fb1ce1e2122df67c1f67cb471c1975ef95c7f3bb7ff9a0beac9a353e8a1956f036102e0526f021eff5f0e36e91a2bb867207f6be50f610300527f69c76b34f3d7519ddaf5229586a6dcb8b7916aa8c8252027408ccf6c0293b4cc610320526f06ba87408441d868c3955895247b0cc4610340527f40ae49a43bf2e94e34f7bf730588c6387d197cd1dcf8612fa896498146a54a85610360526f024aa2b2f08f0a91260805272dc51051610380527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86103a0526f13e02b6052719f607dacd3a088274f656103c0527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6103e0526f0ce5d527727d6e118cc9cdc6da2e351a610400527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801610420526f0606c4a02ea734cc32acd2b02bc28b99610440527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be61046052602060006104806000600f7f9a3408e92b715e6b9045c4dd6fdde08ee1a07f82f2016d98ea8017dc731ae804fa601c55600051601d556f0e66dd45ed28b50efa47ef1d4e12e1646000527f17af6eb4654a2af672d9e65ef93e7937047309dd5391b617d8c629a282008c1f6020526080600060406000607160107f08836f296e06695e07ca75a2fccb39630286f5f12e73c080324df9665ae10d32f1601e55600051601f556020516020556040516021556060516022556f12bcd39d65a32144dca96ef057a1cb2f6000527f8d9f73ba8de3281fe17b080c9ec0f08dccdfb2075f0d73d05055ccbb200296a56020526f0f8af18272344255ba2fb976696e056a6040527f4175c7145eed931d03737deb73d25c3bcb8d880ed85e03ac9a9c2c74e0bab59460605261010060006080600060117ff4f2cfddbcff68a12ebf445f82c77d68d99f8b6d8eb46723ed3ef6ed2507a37bfa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x608b6085604660fa600260e660c95b1870335733826958400667a041477d7f56425744fd3741659f7e12a48f835a650667f1066d7777106337fd676f7d3603521a7b418e8f62055f3f025d1d41928b75643933a4153e32a1446470013d92343c1a5c368879f5f1067b0b1b5ef4755911333e570b0a52403d647c069d97104309395a31704841655e68338f96131a473a18a01432170b1d90076e31077d78f34339653e3534481c9d771881550889a4675f376c6c135c35063863336f9e0283505059721c526d03337d467362ff8650713f123e5f89079f361d143f80587d061e5d0a52786708055a4379f188505045ff1d4138100b0b6369996a425639881c469d7a9f8838075847067865833e791537656f3f77006ba11148598e1e7f3a426a8e358d4a667808079837528009761d6c079c83754642f0333e3a0b1e7557f31ef56da45d926f1b38fa77056601699a45816b118c74a092077268451a0b9e427b9852f2639f49145501fe103a79201351598bf2406783475e80636a795165816e1c7687986e3e10753c718052997c3e16530a3d7846111e871e358a457d70537d17556215351608516a7b09328174825c79095b6cfa31183f507861621bf16e1b0bf07d368769501c8f691e1a998410191e04747f049e886a6686189757735d6f8e3769040477f5591276167c77575e9f3a57418b1e666c1a60f18187417f004750093c43583f3e56129314201b769c7f1b0a6e09075e006e63711a81547c686d6a88508e873461fe20317882fa69495f893a4637447c617a9837fa65fe1c6f061786595b925d028d085439144979187a60603e896a0a60758752796a855b73808f7b5a68803d06120a3d6875665c39105e4501a15d02940673443947824654fa4019679b05f3668b4164803c1e028e10791e5a43169744019954680688691c72855e337480339c407cf05b8a5d51641d7b056a540031419233893a7e5730053b9c098a31076efe3e41113f123d54766045677a778a7533535f757ff21814647c9b056c55163f673130a18173349252079e7742378a329f1d0b62471a51207d6a988c446c48139738770302076f3e196b11006e30839e405a167d797e1497f2141136116f886741977b5a4571597b3181207776a1976b3f3e50431ba43684151401555b421505186f588a206d1b305079f3757b5c17615b1d8a7459513d3960506c8b5619a0f533083a7859703f7a39a08f3ea3611d1c1e36621287823a204245046a1a736f7a9f3b5c727e64007c50179f3552a0201e390a7c19637e731d527978004812373379433e4702567448fd77f5139c485b483504548e4030761678395f9b1ef1761c17424aa005001b30093d8d81519f116c336e6e9765696957806c696f955c6e9d094859111a45117b48433f143c408400796894175e3a180b6218",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000c",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000001"
+ }
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0xea60206000fd",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000010"
+ }
+ },
+ "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x3befd359c3582c3946a564263ee77fd86f740a7c55622506c5591d61737dbda6",
+ "storage": {}
+ },
+ "0x3f8A30c4E084500855A3A35b7B9Ef39cB7B90F36": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x3a650354fd40b9460e6e99f8a73f92de7aa435859e7866bdbf33c15c28575a36",
+ "storage": {}
+ },
+ "0x472C5AD2732c1CFB6B4bC190Aa174656Fe3c34C5": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2944b92eeb6bcc8a67ae9ec10064b6148bb3f7a48a383559902b5c9576e70bd4",
+ "storage": {}
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7f5d403d91784bc5a01d145ca2b3bc1126aa736b49d5b64f563dfe7aff0f5f6fa86000527f8326efe73bdcac81a56385db8739ae0dbc5e0a85a79350f9062e79f863e06cfc602052608060006040600060b460107f3533a47707127be60396663b421c89eb8b30e456501fd24af1f191416c02e125f2600055600051600155602051600255604051600355606051600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x600060002060cf3560206101f26103c0630ec7c0de3c60406102d061030082819290913720600455607d60fd6103e082819290915e20600555600061045d5261010061040061018082819290915e2060065560fd61034053606b6051610100630ec7c0de8382919092909193913c2060075560016066608039600160556102203961045d51607c60e05361032d3560085560326101e06103a05e60016080f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x600860005560f5ff600160015d60206000fd",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000003"
+ }
+ },
+ "0x7564105E977516C53bE337314c7E53838967bDaC": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7d0f1aca5f5617ba53a2964ce753903184ef3ddede5412b9d553a12b5e57076000527ffbb3be712806b233cb60c29db989d7ae5349630986cf360c21342ef0b4afd1586020527fa9c802a9e71442f14ee3df13a9c3835763425701b2e669defa0f9c30e902c4816040527f0ac85b8a752a7ca64e1e784236db571b228436cf99406f9420ff8b85e1cb180d6060527f782965ec2fde9394550b911b4dc2fde13170e3af8881782cc1f400d31112dd946080527ffdbca9e214ccfaad7f648f2a211cbdd3d557f26261a34da40a9b167bff12d11a60a052602060c053601060c15360ce60c253603260c353607360c453605760c55360af60c653606660c75360e960c853602c60c95360d160ca53602e60cb53601f60cc53604760cd53603960ce53603f60cf5360b460d05360fe60d153604160d253602560d353600060d4536040600060d5600060c660097f66b9f2049709614c2523935d617f2576cecdf6d4cd80e850e0a6fa189bd9c3d6f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x837C90dc7009df3399617a7BE4f8a0cC0ED7C350": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x71a42ea3bbd6b96a66b6411dd45c75ba29bc7183fc3c007b544405b333857d17",
+ "storage": {}
+ },
+ "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xbb3f3eb75c641dcbe1001b459c59b97fdff8938be21771df376053aada5547e7",
+ "storage": {}
+ },
+ "0x8c91B5232f6C15d412e35F7A1e10827145bdD6d4": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xba3b3739da5efe370bef502ac45ea51e77c216910dfaa0de0562c6c92a95c71c",
+ "storage": {}
+ },
+ "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x876a3a4177c591bcd7c7838ab58503507cc953a049d095958fe26dc308b25059",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x7f80000000000000000000000000000000000000000000000000000000000000007f8000000000000001800000000000000080000000000000008000000000000000901b7d7676767676760000000000760000000000000056000000000000000000007f80000000000000000000000000000000000000000000000000000000000000011a9006157f7effffff8000000000000000000000000002000044000000000000000000000167fffffffffffffffe1d90056a10000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000010490037a0109000000000000000000000000000000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a02901b7bc9700000000000000000023f00c00014ff002c00000000000022310868010000000000000000900b90027f77676767676760000000000000001002e000000000000040000000e0000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d390186000557fffffffffffffffff7effffff800000007effffff800000008000ff00000100006fdac7fff9ffd9e1322626262626262600901d90167ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb09004901476fffff716b61616160b0b0b2b0b230b000008010d0a2b006b010000000000000000000000901b6001556c100000000000000000000000007fffffffffffffffff7effffff800000007effffff800000008000ff0000010000026002556101117f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd10901b600355777effffff800000007effffff800000008000ff0000010000777effffff800000007effffff800000008000ff0000010000056821000000000000002271767676767676767676000000767676767676900660045567fffffffffffffffe600103176005557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee762900760076761e000200767600000000767676760000007e40000000fd000000db0000000000000000000040000000fd000000db00000190096006557fffffffffffffffff7effffff800000007effffff800000008000ff000001000067b368d219438b7f3f90037f77676767676760000000000000001002e000000000000040000000e0000000007f7effffff8000000000000000000000000000000000000000d90000000000000111901b6007557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff156008557ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006f8000000000000000000000000000000190046009557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a57cc9700000000000000000023f00c00014ff00000000000000002230080560009009600a557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6b1000000000000000000000001b7702ffffffffffffffffffffffffffffffffff0000000300007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100090167f82000000000000000000000000000000000000000000000000000000000000006f800000000000000100000000000000006f121212121212121212121212121212129008901d600b55677fffffffffffffff637fffffff9003600c551971767676767676767676000000767676767676671fffffffffffffff9007900360017f7effffff8000000000000000000000000000000000000000d900000000000001900617682323232323232323237e40000000fd000000db0000000000000000000040000000fd000000db0000d3712000110000000d0a300e750a000000090a0a9008901c7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0076fffff716b61616160b0b0b2b0b230b000008010d0a2b00900b900b7a01090000000000000000000000000000000000000000000000000071767676767676000000000076000000760000900b600d556101117e1f0000000000000000000000000000002000000001000000000000000000001b1b67fffffffffffffffe6c100000000000000000000000001190147bc9700000000000000000023f00c00014ff002c0000000000002231087f7effffff800000000000000000000000000200004400000000000000000000010b600e557e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000112600f55156101116b0100000000000000000000001d60105563800000017f80000000000000000000000000000000000000000000000000000000000000021b9019136011557e1f0000000000000000000000000000002000000001000000000000000000007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100090177f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017a010900000000000000000000000000000000000000000000000000116012557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7f80000000000000000000000000000000000000000000000000000000000000019018077ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7e1f0000000000000000000000000000002000000001000000000000000000006f8000000000000001000000000000000009900b7f7effffff80000000000000000000000000020000440000000000000000000001760fffc000000000000767676240000000000002b057604702076770000000000000006823232323232323232390071a6013557f77676767676760000000000000001002e000000000000040000000e000000000671fffffffffffffff900260145569010000000000000000006005774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a900963800000007f77676767676760000000000000001002e000000000000040000000e0000000001d90147e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100068066aa0a5319bcf5cb490029004717676767676760000000000760000007600007f7effffff800000000000000000000000000200004400000000000000000000010b027702ffffffffffffffffffffffffffffffffff000000030000760fffc000000000000767676240000000000002b0576047900390026fdac7fff9ffd9e132262626262626260067ffffffffffffffff900a9001717676767676767676760000007676767676766f800000000000000000000000000000017f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000190099010681000000000000000006005901c1b7f7effffff8000000000000000000000000000000000000000d900000000000001677fffffffffffffff9017037f80000000000000000000000000000000000000000000000000000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0006901a6015557ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5901d6016557ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000156f1212121212121212121212121212121268210000000000000022161668210000000000000022760100000000ffffffffffffffff0000000000002e00000010901c7f7effffff8000000000000000000000000000000000000000d90000000000000176013590cab83b779e708b533b0eef3561483ddeefc841f5900390126017557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000901867fffffffffffffffe6847839214543589705290149019017f40000000fd000000db00000000000000000000000000000000000000000000016007900110600067ffffffffffffffff1160185569010000000000000000007fffffffffffffffff7effffff800000007effffff800000008000ff000001000090039017157f77676767676760000000000000001002e000000000000040000000e000000000678000000000000001056901000000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000109901860195519717676767676767676760000007676767676767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9010106780000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90179013601a556f8000000000000000000000000000000069100000000000000000009017600768010000000000000000901a90150471767676767676767676000000767676767676717676767676760000000000760000007600000590197f7effffff800000000000000000000000000200004400000000000000000000017f8200000000000000000000000000000000000000000000000000000000000000600790089014601b55157ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7a01090000000000000000000000000000000000000000000000000018900b778200000000000000fe000004000000ffff000000fffff700684783921454358970527f80000000000000000000000000000000000000000000000000000000000000029008900567700000000000000068010000000000000000901a10610111651ce97e1ab91a900a07601c557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e40000000fd000000db0000000000000000000040000000fd000000db0000d3901a601d557702ffffffffffffffffffffffffffffffffff0000000300006d010000000000000000000000000011601e55682100000000000000227e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10009016760100000000ffffffffffffffff0000000000002e00000067700000000000000010901d7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001901c9019601f55712000110000000d0a300e750a000000090a0a7702ffffffffffffffffffffffffffffffffff00000003000090166c010000000000000000000000007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6770000000000000000890097fffffffffffffffff7effffff800000007effffff800000008000ff00000100007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0090059014682323232323232323237f8000000000000000000000000000000000000000000000000000000000000001901a90127fffffffffffffffff7effffff800000007effffff800000008000ff0000010000777effffff800000007effffff800000008000ff0000010000901d901468066aa0a5319bcf5cb47f77676767676760000000000000001002e000000000000040000000e000000000900690027f8000000000000000000000000000000000000000000000000000000000000002774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a901d900767d021262626262626677fffffffffffffff900590181960056b01000000000000000000000090167f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001777effffff80000000000000000000000000000000000080016f12121212121212121212121212121212900990056005671fffffffffffffff7f80000000000000000000000000000000000000000000000000000000000000009009901790126020557f80000000000000000000000000000000000000000000000000000000000000017702ffffffffffffffffffffffffffffffffff2000000000000b7fffffffffffffffff7effffff800000007effffff800000008000ff00000100006780000000000000011a1b6770000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee109003777effffff800000007effffff800000008000ff0000010000637fffffff10027f80000000000000000000000000000000000000000000000000000000000000026c1000000000000000000000000006901c6a10000000000000000000006c10000000000000000000000000161169010000000000000000006b01000000000000000000000090141b682100000000000000227bc9700000000000000000023f00c00014ff002c00000000000022310890050576013590cab83b779e708b533b0eef3561483ddeefc841f563800000011d6021557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006f80000000000000000000000000000001901390117f7effffff8000000000000000000000000000000000000000d9000000000000016801000000000000000090179004760100000000ffffffffffffffff0000000000002e000000760100000000ffffffffffffffff0000000000002e0000001290057f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0090187f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56770000000000000006c010000000000000000000000000990076022557f80000000000000000000000000000000000000000000000000000000000000016f80000000000000000000000000000000900460235563800000016801000000000000000010900b7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f40000000fd000000db000000000000000000000000000000000000000000000107602455762900760076761e000200767600000000767676760000006801fffffffffffffffe1c60006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7f2fe97199e8ba5d65d5949760aba55780db6d3e27337c12a9e2584c1aea6389366000527fc9c7815cd20d7a1591df55b3df8377d64505c5ca90911be70570f7cde3de19f56020527feb1c52cc5d5b95babc9859d69614a696a7754df4ec4513bc9af9fbd9d0944b0d6040527fb658d58f26c2302e35030999f40650e0466ee0af3b918849c2eda1d6c4fefcaf6060527fe4bd2ef5d6c1341b8e475c74757076268d6f1c5916d5bb01e70d7886019c23bd6080526020600060a060006000610100611acff26000556000516001557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6020527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6040527f6e28fbcffd7c03caccdd22d240b8b9ff026419e2adcdf236a36b46f43e555d0e6060527f2849144bcceeceecf83553762c7ceb27864c9f34852287bd738ec484b6f00cad6080526020600060a060006101006119b3fa6002556000516003557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fc53d059ebba0080bbcbd061e6524771ea0dc308b40f3c4ede4c8716a1eb1ec5a6060527f49237f19d71e7aaeff794817dc9f70d8a7c729a6fa39a391b5b3701d22566d586080526020600060a06000610100611935f46004556000516005557fb0c8b094b0f86fac6669fc617a9ae78274d176f28afd4133b0ff77d0f997ce966000527ffe317cbb4baf276d4432ced23f42d8c5f7d55b784db1e93057ee0fc2ea1e17786020527f4b440553855a357802be0278f1931e2e08f09691d5bea6d151656218e393092a6040527f5a91dfa926c3153f152dc0b41f6d123e4399e570bda33656750b0ffc6a7d99256060527f0b2978263b93e015de980fe4a2e55e118cf2d6c5d591977af6cf89d15631d3c86080526020600060a060006000610100611a32f26006556000516007557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006101006119abf46008556000516009557f7f895cb6c94965dae08dceddc4aefdeb4f7cc31e951d89545b74675c9fc8e6036000527fd34fbc0141a54ba0519984c5194ca9df72fd36885e115b38d896115fcad844116020527f55a221cabf682a678d6d7bd6cc1c9d49900274d396e26ce619d02b49a7b83e666040527fed0684f310b426c5b27d7218a0083cf6ff1beacd1156c21d6c2cd04ee12f13b96060527f3ff4da44d7964d7de1e66c4f90e7ff39f78f4cdf4f3a5270c1d722126abd91e06080526020600060a06000610100611a5bf4600a55600051600b55600060005260006020526000604052600060605260006080526020600060a060006001610100611b08f2600c55600051600d557f1e681d3a95c766757b88486b0afd7a08a6fa770a33d3701a22e430baf948b8ad6000527f99244a30ea26d6976d18c2b999724f354cf0437c6914f905b229d6456abace266020527f02de2f85c227c376b51fbeb7f912c93de8b3b8d1b719f96e3394c780fe92819d6040527f8362b3f221591571872637755ba29fccf0be8f3663fcd159c5b11acca7b83dae6060527f88e7544e2c3ce0d17afe0f1c5003d61d4a15ce6d121c9753999e920d526b61a96080526020600060a060006000610100611956f1600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b04f16010556000516011557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f4556070d69d9150dde4c0c405471e1e9d6f7b187c8a48db23e436e1bf0c5a2836060527fb27460818d4e6617c7c52296366cd6160ca2141e845656c7af89e748f55051e76080526020600060a06000600061010061191bf26012556000516013557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f555555aa55aaaa55aa55aa555555aa55aaaa55aaaaaaaaaa5555aaaaaaaa55aa6020527f555555aa55aaaa55aa55aa555555aa55aaaa55aaaaaaaaaa5555aaaaaaaa55aa6040527f0691a74c0334d2c5d5f65473a379ea6f3927dfe754c742a08d391ae9e4c3a1276060527fa4c383fcbe83cce6eb2b850160756c9b9567b080d70e343074b8398346c799356080526020600060a060006000610100611c84f16014556000516015557f7514614ff040dd84409ddfc302b297d29ca8714619a4dc560aa3d4608ce954db6000527fb0c02afef69e2f48ed8f894c883394d4122f4317d1e964db799bf5da52329e7b6020527f6f65d0cbf027c882dc76923072c5d7295b43905e974ddcca2b9f18af37ccfb8c6040527f6beef3c7b6f4b8c44fd071921967d0f9be21ee44928355184ec42b1a8229edc26060527f249d6d365176c805e3d4e3c72bac6c02100a90d811311ef70ccdc495e09e6bd76080526020600060a0600060006101006119d0f16016556000516017557f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605d6000526003602052600660405260036060527f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605e6080526020600060a060006000610100611c2ff2601855600051601955600060005260006020526000604052600060605260006080526020600060a06000610100611aa5f4601a55600051601b557fd2d4f8d1fa6b35538f27aae222a56776a7eff0effbfd431936715b436ff451a66000527f61f79af730ffdfc7e4e96f985821c0a9dd7b5651b7b2ad75296cadf5ef8e59cf6020527fc45866c4591a45de590699e2457094b9b000856f7149ec94f8abf4670afdd7d86040527f88c77f3feeffd14bd137ff4bb3ec5b876e05180b532f10b77c0657e563c8db0c6060527fc6e572badfb5159adf1acd6d9ad3ed81da9eec85ef888e94bc6542fa2dbd08d76080526020600060a06000610100611ae5f4601c55600051601d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6020527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6040527f393b58bcd98fe79fc2233c31884afb05d2b359bac1d264d41268621e013390036060527e70250670d4de9ed0b37629f80990116dd8270afc189249655a041d526494536080526020600060a0600060016101006119d9f2601e55600051601f557f60c6915f999a8a80a3a861f015cd24eecb142408854d05cde1b2ad1ecea053f26000527fac7f8594b93f7916770e6e5126f31801ae95ff40ae5bd478b4a1b797a17b71a06020527febc1fead5d1bedcb5bf6a7e631d9d1ff361385d8885430a71c33115ac3278b456040527f0ff45f5f73f9e822bec06a5ae4c5141d6eadfd0d5690bea74bd0b8fe1f7285976060527f41919529738f4f6232c5840ab04e3a2bd2ceb0e1e92ebafa6c28af53c57cd5106080526020600060a06000610100611cacfa6020556000516021557fcff94bfd0dc6ee2296752d48a0e6c896215b383550c60fd0f737252e86a3012a6000527f93581041febfd49fba501e7b67693d9dc64c73df8a4af587231037e4264f2bfb6020527f93581041febfd49fba501e7b67693d9dc64c73df8a4af587231037e4264f6bfb6040527f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2966060527f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f56080526020600060a060006000610100611b3df26022556000516023557f893506f03e0a80f79c48203ec81f871afda5fba19e1b5c85d8e9899f7f30ed156000527f59afbf58daa9d21e3a594d20165037571f0dbd2efee0cc099417cecdd4983f726020527f8322d130c68921c15265c8505cf39f26f51cfc6c814b95980cbced5b35aaa6126040527fe8fc8871cdcd283f1422e9f99c0075eb8061fa82c8a1df63af6c0a584c4f8e826060527f18bb7ed6399701c762f5cd56095bc0e0fb6207e8f6c82a6ad257a420b2cfad4d6080526020600060a06000610100611ac2f46024556000516025557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fbf93dfebd62c76ad15f114f950b3881bed08dc9fd561953cbc16b6bbbe5e567360205260006040527fa5c3b4cf9cbd67295dbcb27c699c6574e3d2ea63c15e9f8c8a2516c29d38b7cd6060527feba90b54b8208ef83b22016a18ba2a1a2594e6e5d238be0aa979a546909e95e66080526020600060a0600061010061192af46026556000516027557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fe2c5856908d15331d57ce42f6985fa476d70deea26c9eb600cd9941ba45846ec60205260006040527fe5b8f6469372d68b77c90e8d7dcac4c91de8b8240c24931e88ead9d567a6b6236060527f87d09aad6d64667247299bd593b3b188d5fbca5b23f07ad81dce3d152263e2b96080526020600060a06000610100611a59f46028556000516029557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f03fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b0bf18c956020527f03fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b0bf18c956040527fe99e6153b13f1459ce318e9294faa5e39366ad606aa919d8124168755b0fc98a6060527faff78ababea86849c7171ee1ac52c4630b75ab736bbf602387a7453e16eccc136080526020600060a06000610100611a71fa602a55600051602b557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527f417241b507b3a838299ce7825419fd5e77e3184e5630ed3e96b7fda7d6ae34ea60205260006040527f89f7c09aa4986bd3818ccbaf22fbf3c0a9ca814e50a5c68c86a9c2d68067a4eb6060527f0a1ac1cd8c5e4aba96b63b5b13f1cb0672c73ebd014d6a96821133fe200817136080526020600060a060006000610100611c56f1602c55600051602d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a060006101006119b2fa602e55600051602f557f1f5056964e229e6d298fb8c47ac9527e6f4b8c9f3a8533227854b892233e6d976000527f481bf80e44001b0ece48327892479534e208843b2ad69314f3ceb0dc305858716020527f7384080df121c720d275226b1a11e2314c860faa7d84bffcd6a040b39d5203106040527fc41a4b5b018d1deecb157b623dbedffe1843922d0dfa9c7e62e0c69f6af3c2206060527f303d1191101730a74720bd3bd36ca47ad40d49321263bc1a4319fd289e5d97516080526020600060a060006101006119a1fa6030556000516031557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f0c3569d6f79a64e80516f0c1baa003c0dbd85f2d942104588bc05febecda34b86060527f78373f0ff62818343d05fbf9db4552cc0e3d3bc3b3080a811748c05088c4721f6080526020600060a060006000610100611940f16032556000516033557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611971f16034556000516035557f52c7f111411b6c31c4ea5148ed1404ee72dad2c4a63b5d9c07be2d57811dd9bc6000527f6045297350c3b2df194a8f520641552563b5aa981e044bcda6a33249f524f1a86020527fbff75552493d6b56fc7a65d64b61c429fc75420946bbf7f342728f45931da0456040527f335756c6c2442feb7baab1b4c00709f5f211e95276a51cdc179a1523815642856060527fad39878e95395f34586fa5c13cb8892da3d8e793c2986720c5c6d629dd895ed96080526020600060a06000610100611c67f46036556000516037557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527fffffffffffdffffdffffffffffffffffffffffdffffffffffffffffbfffdffff6020527fffffffffffdffffdffffffffffffffffffffffdffffffffffffffffbfffdffff6040527f13045e933830966b2db4c6a0cf39f06aadca0c74937af29ff7b3c6f0450bcf2e6060527f70725c9c6c35517926279c911828164c6ddc7e97081db8fe0dd4a729b803bd5b6080526020600060a060006001610100611c77f26038556000516039557f7c2a6630a079ee1363d056bda39ae134b585af806cd9727f90fe91abd5013bc96000527f539a2d2e57a51bd8f3f70003d2236d12a9d9c728934914f19adc0b325ee3bb5e6020527fafca78e072b71496c06d81e71bd6b60b754584416e5355676f03dcb617379d776040527ff1d328d7c09978884c803174445eb275c0d6fb998b98e95df4b08d840f89aec46060527ff3bbe41941839aee29d8237388953d7e3a3dd621fb3b594c2cbf0987eeff62266080526020600060a06000610100611b66fa603a55600051603b557f975f4af54c367ce00dd0dcb9c093bc6ca66db8c689e7a75c00b2a74c923e3cd26000527f7cb05b03626922246b24bc2f58eb57afd4a0318b2d326dfc15b6ba63e827e3356020527f4a0854303660569da11ea1cf19e24b5f6a8c61a2682b315c0ddb3d4f34af483a6040527fa37a086a86b4c63de4f608623a3b109bf839637e0c4adb7688d01784ab93052a6060527f99c32c7cd905550ae9f5025b8e9c96f8f1b79739ef5a7da917c3af8d57254fd36080526020600060a06000610100611a7efa603c55600051603d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f469c3645957f81734edc5e79b5ee76faf692f010c502999fc3cfac6faebee0836060527f61c66083fc6c790d224dd7b2dcf78ae5ae6d9de7ea518daa10cce651e7fded706080526020600060a060006000610100611b23f2603e55600051603f557f183086ef5ab74e16dd3b9a9a662e247e1355399b33ad8b3e382fd7f90118128f6000527f1699eee7ae150a1333b791f118070e10b320096d9537337a6e6ab699df96250d6020527f4aa30c18c471b32295ba528c5f1913a779014f6be1366c3e096a64fc535e79516040527fa45e8ffa296f8b29cba6d3571041d76938d6e7048866a2c439aef5fe697c924f6060527f0ecddb7ec3a49789115126ebc8cebefa0f7cd0578541580c7e003aaf9df4c9db6080526020600060a06000610100611bf7f4604055600051604155600060005260006020526000604052600060605260006080526020600060a06000610100611aabfa6042556000516043557fadc5098eacdf58d42c946547737a616e805f2733b11e8217133530de1060ce086000527f3fdd1d9e9ee2a8a319768ff76ed2566a7d618b623031ee2b640b5b49e9fca4826020527f8cd2bb580fd635c34c694bcbb59895ec15efc61eb4154921973d31d47528a6df6040527f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2966060527f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f56080526020600060a06000610100611bd4f46044556000516045557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fa44b3f5d409dd6e3d25c670a74257af25a31645e5d34cf4e3a5d0da07e3efb746060527fe293774a13af9c848b513a08c0fc6f6e7cf52207895ca1463f3ebb1bc57c91c26080526020600060a060006001610100611957f26046556000516047557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fc98a56c8e90bb85ab2c47b157a062b43ec365388a7d754ca2bbb60385f8f9d286020527fc98a56c8e90bb85ab2c47b157a062b43ec365388a7d754ca2bbb60385f8f9d286040527f02fffffffd0000000300000000000000000000000300000000000000000000006060527f02fffffffd0000000300000000000000000000000300000000000000000000006080526020600060a060006001610100611a4bf16048556000516049557f0967b7041d5609bb5e799ab23aba07f6b2b91ff4555434b4268d3e9d5d222c876000527f7c14247677c6f4001db4cd3ee38341d2ca131a61eb822dcce09287c4837674a46020527f1a7e956dcb2c7f6efee5292e863ecc2203c0b874b8b35860dbc52c8b70132dc66040527f86f2d864f73f34c4db6172f7a5a6701bec0feb97250b6e5da8140cb3c6f4da9a6060527f7c77d48ea9dcf0ab8f305ed9e04481c71327dbfad9b8f8cb6753d3881c24e1676080526020600060a060006001610100611917f1604a55600051604b557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a0860005260006020527f0efe03759e8d9dc917ffe841070ed6c4fe8de83ca95db79cc73a13bb317db20c6040527ff4ba61410a012a8b7255777cab86b2896c38c36afbf2379df99524a891c928c86060527fd98510a92c7f01cc181034406ef8fc5ccdf7a03761c2c5c7d169304063f0a9e36080526020600060a06000610100611b34fa604c55600051604d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a06000610100611a84f4604e55600051604f557f0fdf6115fdff593042a35352f203f84032e8ad490fb30d88ec80c27eeb59b2706000527fad3ba7a4ff393909bc4defb600d0c8941acca5ed88cf0fad0f0ddbaca4b5a0df6020527f2ccf7b3616e76306b829d32655858a5ba425c5a186c46d36d508764f9925bcbb6040527fb3acfe28d877e38a1e317ed39d64f0cc25503d7aeac467413a5e85ce947ad0206060527f76e5e1f3adf56e0ba28ef3b39d373bad671a66adf6d8636a168ad35ff8d1ac6c6080526020600060a060006101006119e3f46050556000516051557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527010000000000000000000000000000000006020527010000000000000000000000000000000006040527fe8c3ff17a1805a8186e1a9badc25b6d8a3f210f3c69f5fea1459f0abd81a48f36060527fb6751428f32b4bc303330c6b4f799a8250ee508d35084592698c1c2da48fc1546080526020600060a06000610100611c0bfa6052556000516053557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006001610100611995f2605455600051605555",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x7f17a0e4d33fd0936c0c618d7e4b2b3c438d916a4b17d8beb84e6ac1c30c6526d96000527f0c04a87cfd4e8a1cd8a0cabb4654ecab7ac166d50758dc912bb7b0dd930251546020527f244e8bf5bd7bad6b3667d5c9e9e249b7828031e28ac02c709889a98fcc7458ae6040527f2296710c03a3206898c112df72d48e56e53313999c3a5d92586f825ec14541206060526040600060806000607760067f0ca10b062ab2a64f6d1d99bb1517e3ddf0c6fdbcff0db2921dd54f73fccb193bf2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f01d82c69e8410b07c01ca9a882e46bf6daf024e4823d135695134901bbbd39496000527f49a70da2a6c8ac6c15b1698c13769f0bfc32955f226afb8e3adbd8fbb68119756020527f329ebbf77d0d3a915ad4d379945d05c9dce64bb851465d4ef63857614dfa9bd46040527fb5e0b4106beae532d5f5b6bf1d01a3ca43eaa4867d08c13fd77ffee2055d48ad6060527f7bf13d131f09815beb049cea332adcafb8e5ffebffa0d96ce28e37868811aebc6080527f6bb554b6ef4e9071617515950d9d0a988220280a2e6fc619c6171978769cb7a860a0526040600060c060006048600a7f8b755582dbe465616c420fb4ee69487e1469b805eacb028605cff157401affa3f1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x600060005260006020526000604052600060605260206000608060006001600162013d63f16000556000516001557ff7a7fe9e23dae84e7cf812dc695686b887ee16429b445ab6f639d00ba0f0e7216000527f637def65659e99a5b407f48fdc2539b585ba2d8f6e146f0dcd04b123e174b31d6020527fa8dd002f88937f4a4f794328b660cbb69efb2ee973b7ee99ceead3246562a6616040527feed05028ad90c4cc59e5b972063b803ff0d4b37b86914edc4f781382f46811b060605260206000608060006001616a4bf46002556000516003557fa8815f75827baf28b5644e9596bceec1afa6bd4f8b32b2719949895e4abd356f6000527f881529671c00a8c400e61d1adaac433cf1571e3067ee7db7f2cbe94089e1a21b60205260006040527fe463ab2d0df8d12bd29ec5dacc16bd6e5d7ab6a157f8ccd62d907720d31ffbe46060526020600060806000600162011adafa6004556000516005557faca9c4cba9b9c955f0c7093e000eef2860e1a26cb732db37dc0b4fe883296a486000527f140e3f090a86b98839b500e4db02f9018d7f52864a511aaeffd7a1a63903bc1c6020527f397c19feea180e19aabb56a00a3ae6e9320d882b18a9d347a9eeca5de4b6f1866040527fffff93df204a54ee623369e52cfb52683e1c054ecaf04944a112512084e62c946060526020600060806000600161777efa6006556000516007557f6e39c9b393bd2ebe4956c47cff4461d0e635da55baa39496348e1afeb933b5666000527f57afb64fe0b204ae8c5e4a815b9b4c01010954da2215d6f0d8a40309911357956020527f5d17dd5498fe5460245482e0a3f402a76c9e46088f8dc789ca9af50a513dcc396040527f637d21d68bb042f7dc33061a1c4ce6ebfd237cfb1814b76ab6dfb8d25d5ea0c360605260206000608060006000600162015b7af16008556000516009557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f5f8eb30faaeab04c609babdccbaf477edd8db97db8e55ceeceb1bb493e4426f96040527f11f2cdc4b9300b15b4d525b65182b14c4403637c6bd09bc0a2bab3761a42994e606052602060006080600060016167d1fa600a55600051600b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f71298fd701c45b7c99c45bd59f5116ba047f3a4395625d5585ff1ee798a9c4966040527f1402bbae0fb1f0a7efd300077f319fdaee635704bbd83feea8e49b8b8f8f53b26060526020600060806000600060016201711af1600c55600051600d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fef4c53c19751307dfdd763c9eba37267498210df36acb7f5a1cd12c53ebb85356040527f1c1927f218f94017780fb1aa67ea63feede4fe536e045ab71780bccb672c91aa60605260206000608060006001612330f4600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fe7caa87d70f4898c2911be0d6be2779c4dc9c434b67253933c86bc67ce9377e16040527f47930e2e24a75680d3856231e44ff8769b3cb6d1337b1254a0db4b87a904c73c6060526020600060806000600161dae3fa6010556000516011557f76f66c98fb4388763e1a351d25cb29ba0c680057382b3b11f77b17adb3cc8e1b6000527f2cb34eb253be8115f8d7b8d7fb54fde77d53321c0bd2e8332f07b0c0ee45f31b60205260006040527f0ffe730bb67588130d639bd1116df90328063f88254f6ba2ba9b1ba800aecc8a60605260206000608060006001600161191af26012556000516013557f8f2e7197264574f3342f322f67212913ad475ad738c17dea8375dbfcf3a6b96e6000527f36ebd50703c77fb901f8889db2e34e8756673f19874eba2520ed9a5c8218211c6020527f6f6513104b24e8956fa1f70d1aac9b5a7fe120e5a1c6126f89645bbda8435f416040527fffff27ab007ff6fc61d422ff2e5bbca31b384d5151682bc86dcd2d0f1f986e4c6060526020600060806000600161ee23f46014556000516015557f84defe2b984135c45e723c479dac5e6b89dd55d2acd6b7c60e47af4b58356ea86000527fa5e43cafd9b28c27e2892fa9fba78c493f773d541780d6f7f4208e237a992bea6020527f270819b760296108387de76395ad21bf976accaeea1587e28ee61a5cc458552b6040527f844b530b95507450de77b39b53625832ef337d0c16a5a4098a8ce9d7a0919bf860605260206000608060006001600162017481f26016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f202f2b49fb9fa11ed602c1b85523c3d4a032730f598d258c9a8d9680690f02ce6040527f69a7c03b1b3720d0942861c62a0a3ba66646c5ff81d4812d33eb31b012aaa8e3606052602060006080600060016001620165c1f26018556000516019556000600052601b6020526001604052600160605260206000608060006001600162015bdff1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fa18a04b28cf2058bdea13c327a857e9ea55184e20513c211f8634983862d6d426040527f09d86ca930e8f4af7258d4f018bb98a0064b7a04f8c9ce34014691164c650aaa6060526020600060806000600160016201443df1601c55600051601d557f977ebf64ddef39826bf3d737ce78d9b294f1f66bc0ae5de74941b5831d5570ad6000527f63d9d89fad7549937d74776969c34f744f7e879671791c47fc65fb549915c91d6020527f5e4123666a8d8c0bfa1721dc336ddd74892fef4e23113f17772b9560a19132cc6040527fdbcc5dc4802b0a60678b70b372de8488b82989c0ae119bf4ee54dcab710b359d6060526020600060806000600060016201629ef2601e55600051601f557f62e5e98b83df356490e80276d4f393f8d11c69b0f083adf5e4eab0a1c7c921616000527f0a74d423eaaa5027e4b37cff43c906c556403ae1c53a4dc71e02192026681d1b60205260006040527f312288e39895e53d633a2fd4b0b29f721c61c4486021fa897fc95593f96a120a606052602060006080600060016001614e1df26020556000516021557fc5719f87fdec204204aa70ad285629dbc2143db1dd617cd7943fe3ec7d3216326000527facab3633bdf64a7a9c546cb5d210502386ec46069c281ab81b441d74f915c11c6020527f17a20abd30262472cfacb8968a4d5760ffc0ae44d627eeaa018c97769d197af86040527fffffa3306ea6bba29fca6ba4028aa9431910e521898e1679fd49c01e3430c6ef60605260206000608060006000600162016d9af26022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f381bcc91ef1376de335677460515c3629f70d6576ff02e1fb35fd85e007301116040527f28eb299972b3a82dd3f7c947ee00db9d790800d48283f1aca4a6b0f9a81b0966606052602060006080600060016135ccf46024556000516025557fd57bf1e77bbed8ac7b2263924719b52528499babf7091eb7d0e0079df3f37bb06000527f25f64135eb85769efc877a35d80df7917f45138abc81bf61861c1519924c161b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fb8c3d79a0302038b1f61125145d15e4518c1e7079f997a76450720ae5077be70606052602060006080600060016001615feaf26026556000516027556000600052601b60205260016040526001606052602060006080600060016001613290f160285560005160295560006000526000602052600060405260006060526020600060806000600162018590f4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fcd24a8bf0c46d83f99232640d3e8a1482888c9e65fbefacdb7bb70614087e8236040527f79cce5ee40684d76f67ba83918858707f28b4369441431e7851c6f131044ed4e6060526020600060806000600161cedefa602c55600051602d557fddbc53839af0650083dc792a3fa55ad4c85ee036b0bf5b6345a2a1eaf05a81e66000527fbd94388160d91b09b1d77c7b4963d6bd8c27768d040be765948ffbd68623881b60205260006040527fdf1f93c3f6e3568a40f29dfa769721bb0d56ecae7db187e2a2ed59bbeeee18c76060526020600060806000600161e295fa602e55600051602f557fcbda3bd6f960de2e77dc399318b20c310387489d7ad65d4b4a5c08a849ab1a2e6000527f2f5397a52ea58822ae9ace7a80e87d6064d0b72fa202fb5c9963479d137a9f1c6020527f29f7f8a130e56c85bff30453c7f6bb6ff0c3a2329aa96f881568aff7d5db57d76040527fffff356a0b0cb79c6057fdd64104f634042cebafbae748b06b976969f8240b1160605260206000608060006001620146c6f4603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x6770000000000000006b10000000000000000000000090107e40000000fd000000db0000000000000000000040000000fd000000db0000d37176767676767676767600000076767676767614677000000000000000778000000000000000800000000000000080000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d308603a5590076b1000000000000000000000007f800000000000000000000000000000000000000000000000000000000000000290049011777effffff80000000000000000000000000000000000080016801fffffffffffffffe06901a6c010000000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000010690177e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00677fffffffffffffff189007603b55774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7f80000000000000000000000000000000000000000000000000000000000000029001760100000000ffffffffffffffff0000000000002e00000071767676767676767676000000767676767676901d13603c55686d5adef08547abf7eb197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff76fffff716b61616160b0b0b2b0b230b000008010d0a2b00901a901d67ffffffffffffffff67b368d219438b7f3f901a901460016810000000000000000005717676767676760000000000760000007600007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a69010000000000000000009009087f80000000000000018000000000000000800000000000000080000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9003603d55760100000000ffffffffffffffff0000000000002e000000690100000000000000000003151c603e556a01000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9005603f556b100000000000000000000000717676767676760000000000760000007600009013637fffffff7f8000000000000000000000000000000000000000000000000000000000000000116040556f80000000000000000000000000000001774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a04136d010000000000000000000000000063800000001b6041557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f40000000fd000000db0000000000000000000000000000000000000000000001029019604255682323232323232323236f12121212121212121212121212121212900690147ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07702ffffffffffffffffffffffffffffffffff200000000000020115760100000000ffffffffffffffff0000000000002e00000063800000001c60435567ffffffffffffffff6780000000000000011c901b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee69010000000000000000007cc9700000000000000000023f00c00014ff0000000000000000223008050802760100000000ffffffffffffffff0000000000002e0000006b1000000000000000000000009011901c6044557a0109000000000000000000000000000000000000000000000000007f7effffff8000000000000000000000000000000000000000d9000000000000011a7f8000000000000000000000000000000000000000000000000000000000000000760fffc000000000000767676240000000000002b057604790146045551960006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000046": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x0000000000000000000000000000000000000000000000000000000000000047": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000048": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000049": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x000000000000000000000000000000000000000000000000000000000000004a": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x000000000000000000000000000000000000000000000000000000000000004b": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x000000000000000000000000000000000000000000000000000000000000004c": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x000000000000000000000000000000000000000000000000000000000000004d": "0x0000000000000000000000000000000000000000000000000000000000000004"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x824a1eeb2eb1cd2fed5f418cf700665ed57ec1f7852554a64e53ab714c96d76d",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556001496001556003496002554a6003556002600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x61012c60005261012c60205261012c6040527f28988182b9f8a7c79a0b95aed2466f87f9f425a457cc11ee4bf55852380a8a466060527fa5bfcb9e4a1d70b38662b6d44f23c7c4bddbdd1f28d2844f936fe9ed4bb118606080527fb03fcf95770df98315ef2b51af23285549d05625d6cfd5cffe0736904113e70e60a0527f1616db5b415312adbd59e505af5e855ca1d210196879519ae8b207e69088514260c0527f71b3c39a48356625db6957b969775a17925d33cf8280de4f7a561f27a5bfddf460e0527fe5e6216adc6e477b29568a1969d8507ae5cb6e381067759dcc20ddfe14aeb7fa610100527f71a707817752b9c6e171b6f3ada234115aeb6af498c33b5db0dc4fdd490ec997610120527f32d738512b4c2f00c4f6b9b485813c2cf29677cd20c6935cd86747935eae847f610140527ffb999b3053067e11a0741eeb60e87c0371dbb48b7d40b623e85bedfd98fa70e5610160527f268991f22889e661e3fabd207129abbf56759f2832345854e43ad1a71a339136610180527f430b14ab247e0bdb47276cedf11b5e44248e9727f7045fa7df2d545ce6f58cce6101a0527f4fd19c751096cdfa4be443726c53ee5b3d319dcafce4f195675294d476858aa26101c0527f530b2ab949778410a7c78814f61e9f6bb8321676533927a838b47ac5e28349ab6101e0527f31107fd6f10782792ddd849fa35c8fe7c90f02353ddde73098aa5247bb90689a610200527f5ffa1a6195456df5baa48f52ddffbfa7eda47f06593503c6f0ff0fd2e1e9c3ea610220527ffac10670adaae2b42169cfbb800bc8d0668b269be87b3ec21ec103a9a516fccf610240527fcc6d0629b07aa417a6c12ef714cd46fb61934d8b85342c17a39576d5f496c841610260527f2f92b102511e7127d6a76609f7ccefe157b66b938ec02b68f7e9607ca0f27a11610280527f66b91c44fdd498be0d4363e110425122affcf7593cb924a2b9df5de945c5671a6102a0527f61a97414718ff52dbcf0d9b09935a2af4fd3f7dca4990d4b607c96fb3bd8fb036102c0527f328b13a0d4892902e98820ee7471f1b7e9e97783de8ac12e9f41b0620b12b1046102e0527f7f785e3d855e1cefd16d05cd9e55a230e2f89bab26f074373defa8a9357f95eb610300527f25b8a44212fadb021ee1bd6087f2ab0696ded7219ac526c5f8c152d415cfdc39610320527f829314c23dfe811e13a3a0e993f8b4c21b3694992ada7a7e90c327da7e5a54c7610340527feccf6eea7aa9e48a96e428cc03418bc08655cb1afff348bcba819a905b88391c610360527f4ca4cb61f0e479eb14ee59a774d44edcc35ee195bf13eefeb0986f60842a7e99610380527fcc0882223f5772c358abe73bac7813da1e453b4691e26a7670c016afaca3e4686103a0527f8d5bc1107a4cd44ea32617ce6f7920fe1feaa11f278fee50c41083c271816ea56103c05260a56103e05360f76103e15360bc6103e253606c6103e35361012c60006103e46000600562e22c90f45a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a556020600052600660205260306040527f398d623257e5b0f89ca25e2b0abdc45be46019a8aaa3038a92a8a4a7b493535060605279e55480c0374b2d5f8a9067f6474d5f004633d8a76ab315800e8a608052609f60a053601960a153606460a253603460a353600060a453607e60a553607b60a65360d360a75360c860a853600760a95360a560aa53608460ab53609060ac5360f360ad53604860ae53602560af53603c60b053601260b153600e60b253603e60b353607d60b453601960b5536030600060b66000600060056102adf25a01600b55600051600c55602051600d55609a600052610419602052609a6040527fa83059b5378e329797c8727a21bbaa4a5ce17616f92d360efd0b8e0e6e87da806060527face2068e180b2f589c8ec8af18afa9106ecb77dfe8804391f5ee3ba4020ed90f6080527f48498669d1d8ea97639424edc481d8c779fe88b743b65192d555d1a56ee2eb3460a0527f57e7b79db0d94440ef273372c7400f22ee2f7e5c56ac7c1b3683103753d339ed60c0527f25d0d57ff2c195bea93ad7561a1a0b28cf532746a1ea906bcde94065471b3a1960e0527facd81708c93aaec13cf93bd961a6655812acf22bc174610fd3013c119f746857610100527fc2d637609f89fe5238e89ad03e91eacdffd4c4ba4e8fbbec05d43a8aa31cff5a610120527f5dd8c032bb02bda9842e1bf592a37715a80c94f49089b7e476ba0c3c9cf555e1610140527ff794461fd019e9c9bd830afb7945a2e31d3e43c46648ba01571bb07c355b7c42610160527ff76e0318c95a675bc8455a5aa36412381ea06763e59fd7af71602a00829fa277610180527f627eecc12d38720d86e42e31af2361907e5390197b9a17392f3185579db856d86101a0527ffde9a84b91bdc18e8af1d06f3a1b37f88103369ec05b537c3be1e74b2b69ead76101c0527fb5a148b63a962d9afb9efb48937b9d60548bfa8985671a96d6829c275c976e766101e0527f70aca763727564c42fa1b898230dad822f1bfe4ac0fc0aa22e45fbded1e90b15610200527f3628fe917cf9b6b1c72d5beacf57357ed37d6887ce82d6ad51154df4951f9a0b610220527f9566f4496b2c485b22ab07c45d87d88107f97962d46b7b8fab58cc6eebb3e7ba610240527f8660583056107961d535ec1fccc43187e7208aeb9d778e52738ab27bfaf90c29610260527f13e3acd00673b6da72efd4190c969c7d34d37c2dc895139ba54eba590b7e61de610280527f40c8c5631d46295d36fc4ddb137c5a229c8d730ea78cc08547eb942183db3c726102a0527f48227b3cb22012ab7aec285f48125ea2ee143f0a39920b30cc124f8d9bbddb576102c0527fb8accb85a3c731ca0dd92f31b72f48ac7b2a21234f87a36f478736c23c8dd8776102e0527f7df9cecf0a726cd6493942ccb6c869e5236cd60c582e5370bfafb4c59783c444610300527f9534a9669973fad1b977d22e506cf8f07efb01005d3e548f547e49adfe6fef4c610320527f9aeb73e0a20b87a4c110da952b7f6daabff42479d0fb7729a5fce5949929183a610340527fb9dd655b4599faa4e8fefa7883c8200d745e59974181f3fb9710f397252c9796610360527fff8bde752a500bcd4d15351d2fa44a2058f90404372b9ffbaee1b48176e42f0c610380527f890ac58c630a8ba9338a7cd7c322f878490274a9f3c442f7e87710c489265e136103a0527f5379258d55b4f87ab59b4a3ef618c1c21d774075858c79fcf6eacc9d12b1fb716103c0527fc26d9972d19a97de02a6c6eae49f2fda2203aed2ea8f01de1423dad42db458036103e0527f773e0597bc7c984bfec573c1a4b0e5a1b4ba6d267d65c06e2a10788f1eb06dce610400527fed85e0645d6bb0809737e9f14f46a46a383632bfc938b3d12862e9617fef2d79610420527f978069fb6b915db110abf0dd59b0406f0c091dc0144af5b9fd7a231e786cf206610440527e3c49ea6db3b5abe1ca9559078cfdbc7220be3b418e7e5157c23a3cd862c311610460527f9069ea202ab2bc6277c9d2ee25effb54df9f88779051622ad91308ae29338cbe610480527f6fff93a59978e4211222679994b72b4cd102f6c5d77643daa26b9921fc0f61ed6104a0527fee3d02cc840f56adeafd7d90f916174f9db5dd0112b56d33157d9bf127007db26104c0527f8ef41eaf79c426da513126ea7431d843dbd71f318f910a2866cd706a7a013bbe6104e0527f08a9baea223276746eaffefda11d474184de3fcc2df0503febe747a6d013f919610500527fae5a022c5755ded3cbb7367e9e2ee18518d7388f538b6810afbd1cab813ea4d8610520527fe024627e8afb95775cce17a3d68fe738ba6c62b1dcfbae57a8e41c007bad09af610540527ff0827934b93c8f6043c7cbeb9feccd06a1e7949dfe85f431e41fc7bd69292f60610560527fb1cfaa94696a3cf0b151680ff0f298c4c568af8b0b4df97d835f0fc06cbc41bb61058052601f6105a05360226105a15360466105a253603b6105a353607f6105a453601d6105a55360ac6105a65360e56105a75360ad6105a85360946105a953602d6105aa5360fb6105ab5360476105ac53609a60006105ad6000600060056301288c50f25a01600e55600051600f55602051601055604051601155606051601255608051601355",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x40000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x40000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x",
+ "from": "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0x95"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x010bcc1bacc0b4efe2fd6c8ebcb059554b7dbfec2743cb76df3b8a7ee740a14e",
+ "0x01c55f079e191202edc506f42463ec1ea104100252f606cce0626b18b381665b",
+ "0x014931ab9bd64716f12bcc820c5dd5162932205c534f4894bd6a3b622fb34375",
+ "0x01cbeb6ed0b278d5f17532cbcd6ef9549122ddc71647fe02b76102e661c2a866",
+ "0x0154f2b83c83440d2a051a27367e291a206afc88a25d7b5370e4c30c198b3893",
+ "0x0110029229592fd387075d3095d47f54b3be6ca3250185fd3c6b1819a77d7436"
+ ],
+ "data": "0x5c24",
+ "from": "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x2356de7a2eb61efa51548f",
+ "from": "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0xa9"
+ },
+ {
+ "data": "0x196ac241c0af75099e4daac205ef967b8661f7d0ee55e80169888446cab389dd646c65e29814547a1f2bfb158ce0ae9e8ae5d568801098283650a8845d9c",
+ "from": "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x24"
+ },
+ {
+ "data": "0x",
+ "from": "0x837C90dc7009df3399617a7BE4f8a0cC0ED7C350",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0x7bf9"
+ },
+ {
+ "data": "0xd6fc5421add1021ba7b3d0f87504500eb4567461d1602ef1ae47a2d245dd2cdee34746967a5147422e229a5c5c8778c4afefd07ef4180c00b3f0222bd94a12e8ae979dbd710ddc260addc6fbd1bce04c17c29aedea75e54333969278f780bc76498305159f3a8a078e56b5406c184d01ea",
+ "from": "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0x1f"
+ },
+ {
+ "data": "0x2ad0cd932856858872f48a3bfbca9954e1fbfdb23c2772e59f87706e1a3456030d23d542de2ebaca6fda3fcc9993b7d72a2f921318de9a21cab1ec8ce7e45465eac10df67fe16990a1550ec62a69fd5775d49d88",
+ "from": "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0x0"
+ },
+ {
+ "data": "0x",
+ "from": "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x0"
+ },
+ {
+ "data": "0xaa",
+ "from": "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x9a"
+ },
+ {
+ "data": "0xeee0c1280086fdb7ac532c720e1515670341d2636959bd199c4b1100ee2e922c000ade375037f79ef80f2ae56d7abf944e",
+ "from": "0x837C90dc7009df3399617a7BE4f8a0cC0ED7C350",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0x0"
+ },
+ {
+ "data": "0x4de106835d8cfd34aaa51c34b8",
+ "from": "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0xd2f0c0"
+ },
+ {
+ "data": "0x568a42c9ada39ea4fc63eca5d076638b268135716755154cce04fa66d1c83d3b8b79a782b93c2c580acfc5f492b0a5249ef931b043ed75a2577ed64d09c01e73e7a2f27f9773f18025cbcb3a61944e558cc07e2f0cf01f38acd08b33",
+ "from": "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0xa1e8c8"
+ },
+ {
+ "data": "0xba2c8f11c8a564895afd28829a476c8d367bfbb098d49098520b29a75f8f12e5bf408cce8b63124f011d4aa443dcbf2d970664c0553dc1dadf390b54da",
+ "from": "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0xa0"
+ },
+ {
+ "data": "0x45b9bac971d9e365607e39211bc22ae777703c2d",
+ "from": "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0x0"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x7564105e977516c53be337314c7e53838967bdac",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xb145569777677df0dd96c73eb6b4418c570eef418e7a4ba712917dd45a56411e",
+ "s": "0x29b42229e878d8946805d9067ed114210ae44977c12662476ff31ce3eda375b5",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000010",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x9531cc185abbefee3e6814a5cf10ce99a1e688f1d21b0740d1489dad208fb93f",
+ "s": "0x1f022a01dab73cddf08cee545dc2d66a1666887cc68547019f6afef79df9ba00",
+ "v": "0x1"
+ },
+ {
+ "address": "0x000000000000000000000000000000000000000e",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x724e5fd54b886e8a3fbcbd6fa5064a01713b695653c4d95a5814a0caffaeb5f7",
+ "s": "0xe18af166931b4e7dd222c91430328dda46067572ea741a9d91271852ed19e4e",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f9",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x18e2ec7135e23b538e1c0c5136cbe0c768feb1079fb10e6042a56253dff3d092",
+ "s": "0x29b40d8e0ff87562883833c3c9f219344eb40ad2ca43572c915c69ec77f1446d",
+ "v": "0x0"
+ },
+ {
+ "address": "0x000000000000000000000000000000000000000c",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0xd0d81ee59ae8e357dc890bbabbb05fd44eedb7be353fcc1037727be613747c5",
+ "s": "0x4806ecb33111550cb6cccd9e1d33a06001e0a9f5a79eb23763b1a45ff5f60e5c",
+ "v": "0x1"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f5",
+ "chainId": "0xd3efce7597e30565b0dbf75a5d11130000000000000000000000000000000000",
+ "nonce": "0x0",
+ "r": "0xe51906a3e0b553c35a8ca3b27cc79430e643ca8a21b696bc475c18a37a23c32a",
+ "s": "0x73fcdc525e9f628eb502b6036a651ab1915a60fac9310a35ae6a517f0d433e81",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000007",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xd3ad68f14f52131b81dd73d61dc10ac1ab6ea5d66282204c1308cfee4292cc14",
+ "s": "0x7b02caed5b8df68d1f9864528dbdafb21532fd927d5f52caaf06c29e2358014c",
+ "v": "0x1"
+ },
+ {
+ "address": "0x000000000000000000000000000000000000000a",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0x7c5495691ec38d78992b52233530e09c309e030d3364e603055192500512897f",
+ "s": "0xf6f846316d3b89c1c5b4594a72b6473e6879e507eb263c90b658636a2f5b7db",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000010",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0x7952eccadf9af9becda1646f83c0a72e6bff17969a41f9683dc9278eeae91008",
+ "s": "0x6731468363caa79b27a77b8fbb84f92e4518c6ab5bc2a8ecd97c2c73820c1d0d",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x78d6d46b41cef61362953d9890efb78f2d2956fff5e2977bd0a513dd50b99575278878e77f89d447ab43ca0e061caff5f8193095e119d15b73da",
+ "from": "0x3f8A30c4E084500855A3A35b7B9Ef39cB7B90F36",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000d",
+ "type": "0x4",
+ "value": "0xb4ca89"
+ },
+ {
+ "data": "0x00",
+ "from": "0x8c91B5232f6C15d412e35F7A1e10827145bdD6d4",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x7564105E977516C53bE337314c7E53838967bDaC",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xb89760b96f0766e01403def425f9625a3e0c56f23562e28d17a395c05a152eee",
+ "s": "0x1dae2e82b53f07c9f38c7dbb123c7d1c2e01b10ca10abcc079bda42d65e0823c",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x78d6d46b41cef61362953d9890efb78f2d2956fff5e2977bd0a513dd50b99575278878e77f89d447ab43ca0e061caff5f8193095e119d15b73da",
+ "from": "0x472C5AD2732c1CFB6B4bC190Aa174656Fe3c34C5",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000d",
+ "type": "0x4",
+ "value": "0xb4ca89"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_medium_1.json b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_medium_1.json
new file mode 100644
index 0000000000..007ede6e59
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_medium_1.json
@@ -0,0 +1,448 @@
+{
+ "accounts": {
+ "0x0000000000000000000000000000000000000006": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x0233362c058b2fCc8093841B1073A90D673E7F12": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x7f2c75141e16bea0fceec67f673a0a3578e66fe55a9b6405d1ce109be7593206",
+ "storage": {}
+ },
+ "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2825c17712cd3e7e5240fb76fe09ec612d0337b643e5c605c3cfea77e44d0b73",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f18d7e183350155e55a2059b6789e979c6000527f162a8843ab70a8eba655a2bb8d0607fa3746aad9927277b28d670f772ba0e42a6020526f0e0bbb27942303ba4643e6cc17b4e6e56040527f6d5ae618f9d71a50f10169b293f4377c461a1d03b52ec7af7b1ce02652e5cb1c6060526f0a6bdca5027d9caded893298277e37f76080527f56dee841072651c9146559bd2ae432e412014e577ac59e545c1b4ea3c3a7d20f60a0526f1edef94468137f636c21ec9b2c7d7cfa60c0527fc372437bac86e5773f2345daf41fd6677d2641dbeb85498c04a207e386d0dad760e0526080600061010060006000600b7fba950d3f783ad5c861b063c1611aab1788e41cf024c88bb16fbc34ddfb498ae1f16000556000516001556020516002556040516003556060516004556f1c12fa0ddd78a26322918fa47ee576e16000527fc52e67586447920d913c04cc3aa9d9b0cf74557abbceb64301f95290b5d98f5f6020526f1ace28b99aa546b60b40fc32cf4813ea6040527f8e261fb3e6584b44626b98af977134d78c268065600faeea62ceea235a1a4d4c6060527f7647a4aa67aa19fb376ac9862fa6bc2035a85ca785a46d13d99b2c8f68c04c986080526f07fb32d7910ec39a1559394484b8781d60a0527f217642f110a5e1af97908450f518e2b4c003babdada7c62b54933972248a836b60c0526f0b07856ee7b4a57aada15dee619726a260e0527fc03d008bc1a8657dba9292c41e0bc41dddab3c9d414d78c0b301ec95fa5aec7a610100527f185175042845c315ec8ddb2cc50b71a3e9597bce1d1528ba953af14071a6122861012052608060006101406000600c7f39438fb3e5ac23fa07111ed42f89ef3ef4a321915113e48407290248efa9839ef46005556000516006556020516007556040516008556060516009556f1819f4adb9c9197bc1b246c466357e3a6000527fa6cb0c9b4a375e66ae200da6e1635b6c498d9519be4d7e3434a75a714cab81c76020526f0215c8a410e3730f02d2607dfa1777bc6040527f435377896f04799a1096429c072af1bb7d067a82ba8ca5beefe153edfdb7e0dc6060526f0977d8785df7bdfedd6c96eb5d1b0ce66080527f902a5e36b6ba48e9b37ec7f392a20c6b6d30fe5598efa1458c16db0c1d8905de60a0526f03ad642aba1c3eb74fa9405b1c29574660c0527ff680cffdfa8abc14d05b8536bcaa9383b5a6a5395e7b3bec29149ccc3ac9afb260e0526f125e9092cebeebd9044a547721c723b3610100527faf64a6d1001edec3b9d0cbfc26a855568fcd0c7dd02eaa54654fc5cf8a41a17e610120526f1105acf307fd6b74c24fd0c91895d5d2610140527fd8870ad51fff134093ae274fbf80ed5092376bc3ee833ea1b3888f67551a28e4610160526f179592fdeba49a7c7c87d09d397c232e610180527f37ddeb4a4b52207dc0353cac7aef37e565e40aaf6315a7bb7047122a369ce97e6101a0526f0f9ba6e9332a408733d57c979b89dac56101c0527ffd7757808b6b5376955b1fab01964fffb149b470b18218402a7b5e9e06c040636101e052610100600061020060006000600d7fb79b32d94d9f9728fb0abaa92d188782899a631d43adff1e43fbf36017e0f5e6f1600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f12d4d9ac9d612b2e89094982ebb0dd056000527f6cb5f28780f25fcf5a7e00e969e5d39b059e7324dacfe868af3c2c6d97264efe6020526f0659b6b1f675dcff737d026a6275c6be6040527f1de5fac6d9157fcbd9f19472a9e9ab8c065856416f67960f6e41feb126c28d9c6060526f12a7858f7ff99c7ab499c2f4d52a63476080527fcd6fb54a854ece55f28a30d56cdd82e8eeb5d6068b163220cc23a48c2a6f27df60a0526f104ec55ef915b40a3b1fa5ef40871a1f60c0527fcf8911004ad329aeb9afaa479edb2484a7fb3f827175c20e7765adba071d2b5760e0527f2d6fd0a73fb22e08b7ee9928b2e629fdb39bae99d1ad9642a0dd33bec8c83a51610100526f1311944a5123ff0763dd92602c7ef4ee610120527f0f34546993528db770a0a08416a527c31f6ccf4ae2ed0fc3d42cdbf0da43f438610140526f08ac51bdd67f319fdcebf06fd3ad221d610160527f09c3f3379b1ef6438f3e93ec5d9a710c7f9a824888e6c7dd2235d161116fd8e6610180526f0ed139544b80307edf4541fd24bc72df6101a0527fefa9064b09bc16f538449338cc4f1a8cd82f7fd07c2a832ff533c191415c88f96101c0526f0f3ebc407dbad0cd2286d86b561b9a626101e0527fcdf55653f05e8ee2c2f5ccc6ad8f3eb2b8f33ff1bfb2ec9008c94003c3066a8c610200527faa0cd89a761006c7929e760d77864b7b9b38802e99b8f3ada864c205136afdfa61022052610100600061024060006048600e7fedc10d2f09c80b115e84dbb1b3e73ee442644855390baac1085016b748c56b13f260135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f0f36c4ee91f493823c45fcb1835c3c806000527fea7b2b2ea22b4de446fb739a72febc2a7a99156d212d97d1a13136f06689d5266020526f0210b2e54d4c413ea259b9b7f29a51336040527f28af4fc715a4c05bef9c30d07b263b98b3a6fd072b4f6dd16f4abc3f26df2d936060526f0eb656a6cbd02959e34fe5e93fc698b76080527f1ca37a22a5fffac75aae9fc0704858edd83a46264428769dd541255d9ed8dcde60a0526f0e55065268cdbdfc6f89c1f3a452c7f260c0527f68b9709ca49c9af06c27934493e952cb7d854cc37ea6df8558c06c77fad0bf4f60e0526f08b02b9db5015bf4965e874d7d21ee7e610100527fe2c3d5dcd2bcecc4de0cbf46726cd46408768e174930670ae1d91e4e2a9b9512610120526f12623863c9afac9aed09eb3dc12d1360610140527fe19cab5ea99227983aa3d4269a460b422fb68588cd95426896c86bf055279549610160526f1764827fb27b8401fd698170d88ffcd7610180527feb8f62fa7f06757a4066319ab99686efdd6a8dad8623c0dbc5bc1237bd593aa96101a0526f0187efd101687306a301cf3e33d8baa86101c0527f97a874fe3b03f271a832b0c9a5fde81b9d6418ea17af8fb91d424c57bbdb91286101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527727d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e0526020600061030060006034600f609cf1601c55600051601d556f02f499ae499faedcd82c997714c7d5a46000527f2a5fd4153be6e4c28059f4321a1049ae8a457737265470fe86c63b4726dcc3c6602052608060006040600060107f8a49f51ce511219504f9cc6a36aa91dc00fa02a2c0a3bd8131f89c6177d8fda6f4601e55600051601f556020516020556040516021556060516022556f14464c85b84b5df1762b9874fbaaf88e6000527f5f36783755beb33a13b2d48bd63aac0e0f5e9341e6850bea6aed77127dfd6df96020526eb6cca1087d6fb29d9cb9b48be39b616040527f6626c90fd491649070034b958a8fa2b0e21fc8bc073fc83871727d09f6e19ef260605261010060006080600060117f204423d923e464bf4026ba530dc24a2c11827699ce253883d0048d330f49e236fa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x6009602960256095604a609260bd54155833303b8415735142a344987d3b99958c454796335e7d3c41951c19805d1337509a12496a589a7739a2689b833e3407513d3b00031b4971a39ca24143915657f51d645b494407589af2a05076137f567d3f780a07676c4a786f7a48460930308f6b6c6c843830fa975d65a431346ff51a7c5954345e74301b3e9b3a33fe053619195d9e17661e151d515f41f306858a7a6e183e74006b68033478f2156244719262160443025f316e1e3b78008606a14647ff7c201a6f6c3070864a3008185a0a03185d04a33af508337b353ca23b3515563d7e8646803ba0751c9d480613765216187371097af43a436a53633bf5460052599c123f3c06086b0b75785c72700a0b1b8a33158a9d3b6f60476255656c370402336b03068d05037f79536d619c966d4a171b17991a6e56091c55146d5b53643d51741d399f7f62485887745a908f57766a50111cff0b6d687c80ff770a60fe6f423437407d543c325a89125a3a57315b0a6a7034fd5a58201c5341653f919c72fe633c6f147a30375f8e30486c141210773a6609130a601a799c503847171d37175e17011646765d0bf51c95188b74314316150076707049610a1080fa8d680a53204275905091175f6e516a5a67063698fd8a5f3b610237696f41466d7f331aa39d09f101897a4132916d9b1b015674885a4a55065a5770335bf58808f1a47f9288133e445671453481048e7956345a364072866b024613100ba45c321e983258058974106e69998d1b611a0b38306c156e7c683e593a7d3a3a5f91635a02453a7f6264966d40985e883d720359823a57063e6c340b5f5e10351890ff003a66755215373073097d4a97610a124566687853015d165c8f50690017197e917a523f77390b6712611df5f157657368369646160702746579033a1e6b6f5d104979609a72035d975436779b067705775880048d6f1d3e7c387052f43a9a580a006c6b63f3ffa1171892ff8a79553f406c4a046614a0638c465b58407574309e05597b5d573b05031135423c9d195262010008113d6e5e92353a4643029b9a736b8a76877a0a050a457a3541a111617b1a3e8643205e4aa4086c8a9c3a5d1a5217489b10a37d77040608651e3a343e1890406b7e8e7443349e377e57196e7478076151313e08879d19583697928989900b447a31653a040b51356962760268057b8d3136035b37585001f20776195d71a085556ef4736c338f6cfe995a7d5d12f03a5d9b681a6457053c7795761283109a81771cf24a3e71174833f253866d0b6c0138f17e7b461a441bff7f9c43376b480a45367a62193c1b581e5816327f473670f402473f1348663b9e517b0100820b56fe7e7e9b386e04f5935a8a4738090307649419173a3188ff601076511d6f473d519152323b703af0f31c016157",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000c"
+ }
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x6000ff7f1f4eaf54315c8fae4e6d3a941db177e3868769ee85c9e234085f7093ff2440626000527f9d7af2156eaac085792d574cbf73ac0b224620fba31f374ec0d4531cd6f4f7386020527f1950b494d7aeb286ce51c460d4c512946c26af7b169c969e7da114ce7adc8d766040527f909210f7f694e2ca6c1d60f6dced44d9c18e9093e026d102f8d5339046e0c1d16060527fe368c0e9c5cb0492305455ab0a1c0f37501c901b404a1c027eff554fe35a07296080527f6ad5803c0a0838d2da46ec60842496d768b7075d698cc666480038ff29e05ad760a0527ff7f742ea0d73c844228ee63b620810759f3bc275f790c8e0bfda754479b5f0e460c0527f9ee360a58a352ebb2853bc95a9181e6da00f0bd105993384d12533e7abfd46b060e0527ffa992bb9e68c423a8a3c834bb541d8986e66b1bf2eac3281420bfc1d08434219610100527f6c5b212321f86af0ac903c35f370673f0d3ca1994da43a6bad6439b610260319610120527faa3378aced9bbf492423e078b82103d33f3ae4caebe93e76a342e745fcdc9726610140527f05014092cefffeac2583a70145acf06b8d379f9a6c4eb1e2663da51a3ed400fc6101605260406000610180600060af60067f6e26585d5fd0a6ddee33d39117e99f8ae9f67d8185c13f8fed674ae80c121c74f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000006"
+ }
+ },
+ "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xaa07ea6d7ebb90738862bff26aa53633e9a6a4c2732f31c270f5a02687a06eb2",
+ "storage": {}
+ },
+ "0x535863dA03bc1834eeA10eeab8FF498565F33f2d": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xb214f8d7a564be547e6de1404f829b88b9c5f1bfc42a708554e97423e49a9def",
+ "storage": {}
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7f96e27046ed622a1ac747d68654f22e78d72ebd5dde5cfe5244e8a04d8c59307f6000527f0cdf327d2d3b444f88d3e2dd89f5def6e143135120384cd4cda73cdfe8cfb6556020527f73c2af4f9cff559dc5e76c1c8c1074891ff284df755d54c990bcfd89410efa8d6040527f7d870f436757bec47394f2c6fd4ebca744cb39659dc9759dd20a0934b93449a66060527f254171faae8c94052703883b5cc818dc8d4f0a182583388abcda9d7d3b98885a6080527f0298db5babc9b6915fd16c9d77e9a9b0d5698dcd7c6798d4406082516ff92f6460a0527fdd3fd1b61ab3f616b967192b48d6846d5eb669b8191ab24030bc5c322016ee5a60c0527f6f9f9a9dd0f96c49b9a1dd4ec33c20556baee81ee0a6dbac1027bbcbd2d78ecc60e0527f35c2c76473ef7fab214d4094ccc9fb10be83173276dddf1769cfbf1fa4fa0869610100527f084b1303321eb6708e861622f0e697a6f7bb6b28924cbff65561dc68c4d70789610120527fb38665a80c68ec7c4c5926675b598c8e2c559664f2de200ee44fe4c79c691a8b610140527fe35f61a689d051e2ef0e84c0d36c1a7deb4fec99447762591c6f6096530bbc66610160527f24589df6f317949386b8986b6a659899bb0c0b0ef1fd412a0b885921ad867201610180527f419906d725ad3628677528d9735308ef7b51c8aff282640658ee31f1e0ea04836101a052608060006101c0600060ae60107fdec1d9215e7dca700a09dcb57f9076e9d92bf98b71253c9f8aa0c2f7bf0e8c58f1600055600051600155602051600255604051600355606051600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x6102e051608060006103c082819290913e20606d5560606103206102f05e600c3560606102f0fd",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x600bff286001600055600660045d7f6001600155600060005d7f600054507fe4014fdbc93a0c052fd4d7fe3b1827156000527f906b6af91af7e5189c91966000527f5d9f7c1dd36000526040600060206000606020527ffa7f115422365081605f82110ba02d6020527f8f3f386c56309ddfcc0d9555be6040527f0ff1eb52b5a7f46002556000516003556020516040526060606053600460615360605260606080536055608153606060825360626083536053608453606060855360636086536060608753600060885360f36089537f1a2488a7583830e08a2d3d95491bc5cc8a8bd4324a308e2ae656ab355a6a7cee60a0527f202459f3ea19d89fdf452056ecb75bbedbf440c26cab6fc613700b334ce193d560c0527feb871f1876b0658470874f9ff9209b1d958f9002365e0aba7e9acbea7e98632960e0527f5d88dde4a225dadc9eb6444cfc690c047831a9d0d65d4f73a4432b8749ced7fb610100527f45b0ebf658bcae7bc00f675b825aa5749016393917c06e56554f646f20e0528c610120527f87e743b4b23c3a75cf536ed88c258677a578cc76b164b77955e5cab4bb0e3e8d610140527f37d9a1d4409d48965ceaf0bdf64f54f49194aeef28c06bbe1f1e7c0054248147610160527f039deaacdf4659d9d892b472b67a4642a5a605326275bdf953aaa76d4950706961018052608a60006000f06040600061010060a06000855af1600555600051600655602051600755600855",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x0000000000000000000000000000000000000000000000000000000000000010": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000012": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000014": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000012"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7c1810006947494e06de82ec6c913c636d201144aabea6c44cdd285c84106000527f833f564ca3bf6dc32bd8ac866434694f71293812e07d12849bc05213c23691646020527f6d33a0b53d3df1a6de97147b5157cae198686cf1533f6bb9833007bc7fb3e61e6040527f6c91e941fdb2af7b0b19db801767c3e87460dac3906a9075367654892b622a426060527f52769125e5c0d9dc254d06af85a9a45919df1ac386697f81f5c4ca9b3d0eaab96080527fa6d3cf4af84dec80aa879b35bcdbf309d777663fc6b92942e34191503b3ad03260a05260cc60c053606b60c15360f260c253609f60c353603a60c453603e60c55360cc60c65360cb60c753606860c85360e560c953601a60ca53607a60cb53602460cc53608a60cd53609060ce5360e460cf5360ff60d053609060d15360c760d253608660d353600160d4536040600060d56000603260096008f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xada9e915b45b3f9f3f335fe00a484308905ec68a78d49750e1a47ec4f9c17d23",
+ "storage": {}
+ },
+ "0x862B38c425EF5544d0127449A12c89C46dd3E050": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x35c0e7a818e7367e6218647e77752b4b0d92f50362a7eff324915762586509ba",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x7f80000000000000000000000000000000000000000000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a056c100000000000000000000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb005900b6f800000000000000000000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d305901363800000007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001712000110000000d0a300e750a000000090a0a9009901a6b0100000000000000000000006d01000000000000000000000000001d177f80000000000000018000000000000000800000000000000080000000000000007d76767676767600000000007600000000000000560000000000000000000090036000556f800000000000000100000000000000006c10000000000000000000000000126001557d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97f7effffff80000000000000000000000000020000440000000000000000000001016002557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd637fffffff1d7f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000167800000000000000168210000000000000022099011151c6a01000000000000000000006380000001901d186b1000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb1d6003557e40000000fd000000db0000000000000000000040000000fd000000db0000d36fdac7fff9ffd9e132262626262626260006600455762900760076761e000200767600000000767676760000006901000000000000000000900717197ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7f8000000000000000000000000000000000000000000000000000000000000002901d6005556780000000000000016f8000000000000000000000000000000016056006557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6a0100000000000000000000900760075567b368d219438b7f3f7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00901768066aa0a5319bcf5cb47f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6c100000000000000000000000000805684783921454358970526f8000000000000000000000000000000190071b6008557d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf967fffffffffffffffe1b60095567b368d219438b7f3f778200000000000000fe000004000000ffff000000fffff7007702ffffffffffffffffffffffffffffffffff20000000000009686d5adef08547abf7eb686d5adef08547abf7eb1d600a557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff677fffffffffffffff05901015600b556f121212121212121212121212121212127702ffffffffffffffffffffffffffffffffff20000000000090136fdac7fff9ffd9e1322626262626262600777effffff800000007effffff800000008000ff000001000012600c55680100000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a009006600d557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee681000000000000000009001137e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000651ce97e1ab91a02600e557e1f0000000000000000000000000000002000000001000000000000000000006a01000000000000000000007f77676767676760000000000000001002e000000000000040000000e0000000009009712000110000000d0a300e750a000000090a0a63800000006c10000000000000000000000000090760006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffefffffffffedffffffffffffffffffffffffffffffffffbfeffffffff6020527ffffffffefffffffffedffffffffffffffffffffffffffffffffffbfeffffffff6040527ffc3a2f02de65712b945c08d0980ad749b92bd7d38f1b3e470deed91662736a1a6060527f3da9b83f28fb59f39d695d836c4595213f2e68b3b8a5bb83a114df3734f673d96080526020600060a060006000610100611bb0f16000556000516001557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527faaeec1df015b2c79efd02a48950975617f8513d1f23dd02cb37cef70a1a76e9660205260006040527f6b25db539f5946185cbe132e22ad09e1c01fab7afcc9c52d5b940d7c87a9ebab6060527fd5a90ce8b987b05942d0d6cefa2a5c864bb377c4e876dd42453992055b4a50c56080526020600060a060006001610100611ca3f16002556000516003557fbe490cd43a8c01bf6a07ed9ffc82d88dc8661980f11412e953a32768132ef2366000527f7b952eeb664746755c081599cf42620b39a630439719b17a0dfd8beed77ccb2e6020527f01c1e19eec67f278e72a7c65b8a304172eb1290a81324a8921ae362f3a20068b6040527fff9c58a91b2e2d65525c7cc313c4d9e806efebe2b25f94e970f253fa14b78d016060527f5361d075c7705e054d8aaaf2e2bae692828827eecb21697a0e50f594dc6ec8bc6080526020600060a0600060006101006119fcf16004556000516005557f4ad81e14a688ea777d58214ecb6214763735abbd317e3ae7f789254666a873766000527fb5979f0161380baf7720bf616da397578eb9f5c54750a8bdd7b06de7d549e0f26020527f765171a147b702a79decb6174bbc322f9a5faa5737d08efa04d8ef8b2c7e355d6040527f41b63405d22ee996112005b48fe252bd767d60147a83a579003db8c80e88f4726060527fd8eadb1ad524deafd2791cba205e43ae1416040133e84075639184b180e7ae4f6080526020600060a060006001610100611ce4f26006556000516007557f95454173cfdc225fb21debd06f84ed70994e98e634852bc59122192795a562706000527f7097bc46cc19a70bea1e2122383ef1dd87ede22020e8c90232b086923d624b1b6020527f5248d32f23121577145b806de74c030e2e26052f8024092d6b7ffdf08529f6836040527f3a471768c788e80a9e0c79c6514e91e244544d18d91c5e6d647d8dbf469b13926060527fab397df44745e87f5cb6fd5c279c4456bdae8d5ab21cd0b476c802047be6aebf6080526020600060a060006000610100611b1ff26008556000516009557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000610100611cd4fa600a55600051600b557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f0985caae0f3ee3530d6ac3e401171f1dcdd87cd77137192312c65c16a0e230e56060527fbc539f7392385647f381799037936d0f8460d9aa16928f192f085d32ca60fac26080526020600060a060006000610100611b2af1600c55600051600d557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611caaf4600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611bb2f26010556000516011557fd95a8a726d8b94500f2b1da117e9b1720c4f0f4ffacab4ef82ce69e5bf0f837e6000527f18ca11386098e3bbb69f2295e67a3d92c225402224f32926597894fb0a1c338d6020527ffeafe36c9b3c6426c2f5cccb21b765f489f7a549f1b94d0fba5c5f2150a53f5f6040527f97dbd752f38179710604ba60b84b2b43c8360dcfb58a7f99bc2e4d73aaf2c0d26060527f1a6d57f85b6654b3d246f7399fc0491529acf9baf253229e1cfea1f652d56aa26080526020600060a06000610100611a58f46012556000516013557fc9423f1212150d2f42d3d65735ec98a59f0fa7cfee9851efa0da6477383f84106000527fb3f71f3eb2437c230de62fce1f175b724c23adfc6fdff1863b73e71b17a0a3416020527f47341a2c30078fc15c2d9ff0fe33dc54a2f79ec53367d6e1bab8d48fbf265bbb6040527ff9459daf8d64f0765c546c4ee8099fab2bbfa31fd8cb21df9780c31a7ed7a2f26060527faa0a9a0f8a06c5385411f2efb5791de6750fc711805044550e2883846b817d9b6080526020600060a060006001610100611afbf16014556000516015557f8ac0f7691fb4629af96eb4b962e7e557b3928b47a38f452a1cf24df0c0ce2b1a6000527f97c6bddb1a11e1e223c3008c4b5bdc48c998b30c151734a5e48acb62f7041e096020527f9ac61545dcf4cb6a47cd983e9538919611d8228a028962787ea750505cc323b76040527fcee4c729d8bf46d0e1aa5c2924b70a2e1458ac9b082a21c7fa5c8c91000a1d326060527f669d02080b01b70b086bd2a25d204c7cfdecc5a68e8aae5eeecc24df23f7d4316080526020600060a060006001610100611c4df16016556000516017557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611b30fa6018556000516019557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6020527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6040527f37cec76d1f3bbfec96d5feb30a095d8bccaf8e3b3fd246563d44876c7e023a816060527f2a5a699c56efb1b8cce8066db3ea053eca2f92fdf27d978e9d043b296dad7a376080526020600060a06000610100611c1df4601a55600051601b557fc598d1bc7b8deaad833597c6065bf2c5e39c14fbf6857d24017a9a52a783be5c6000527f1e52f24e498515f78270588cb3cdc1dad2256baf7b4350223143a9696a36574c6020527f3bbfae4facdffbb18c8f3d5df6fecda9339decc06c8d43652c73b2ba43f5773a6040527fb6a9068ce72b7e6724d70493a8e28c656aa8058a47ea010a95d73905b25bdd716060527fb674f6b897dfed1e24cd7825b4d7c25396a4b84840fe9d99201c5c5e833d96946080526020600060a060006001610100611b2cf1601c55600051601d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f7421a12359bf7f411da04037c4168a24aebdf951546d203d7f52c1d9a083086a6060527f844fa38b8e9588a8a8a6a8ecc77de074e4b104edd2ce74d0cdadd2674ba28cca6080526020600060a06000610100611a39fa601e55600051601f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006101006119fcfa6020556000516021557f9d121cc301f8aa0b6c410c09755c16006410ef563790acd435ef44521f31444b6000527f6018d9327b3eb5c170a4b5ce7177734f914c0d42d6b8706ff4cf775ed56bfe5c6020527f1216f7a990c04237f0e44a6705030d84cae4ec8d797b9373cb8afe7771824f2f6040527f83b03bf29b9090a15ce7a7cbddc2b937b10bbb71c988cefda85a0fbbe31bdf376060527f220cb57b3bae8643a825a585ffd2982ec3e5227784ff9dbd113e3c71faf998d06080526020600060a06000610100611924f46022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611955f26024556000516025557f911aa27b36f7d952dfa15589fa0acdd4353d802f9e646a27cf515b3b0c6ad9f26000527f9870e87a88d959d124a98b897a79732bd613d9363888769490327ccfbc8c85606020527f85bf05a8f523b212d5a38da5f7494760ea94f79717fb401cc31c0b52012d89c56040527f151cdc310d1c0fb068193dd9995cf6d33e21f4c543b1420b28b60e264cf438366060527fc02016e4f0a388500dda3f644c0a0a8369243df9efb5db3d08ac8d1911eb149a6080526020600060a0600060006101006119f3f16026556000516027557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006101006119bcf46028556000516029557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527f99ee9c85744518a641fb86485494690139f717ae93817a0f56ae938040e2064f60205260006040527fffc0f614ee1e3eb711183f058772b9b99f3d17ff31a7de44ea279b86e659ce506060527ffa558b6d6b4b9fb6fb28c55bce8acb4d4f437d3615dcbbc0a5cbfd8807833bce6080526020600060a060006001610100611a12f2602a55600051602b557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f37b7a14518d8e8c2c425b7a5fcb2e377296874a15dd38945013a81877a07c8946020527f37b7a14518d8e8c2c425b7a5fcb2e377296874a15dd38945013a81877a07c8946040527f04fffffffb0000000500000000000000000000000500000000000000000000006060527f04fffffffb0000000500000000000000000000000500000000000000000000006080526020600060a060006001610100611909f2602c55600051602d557f9add50aecb2590beabb40a73e52cb7d25eee639a881c53aec8229c3c89b147c56000527f22773d54fd753a32afb62abe1bc9edfa1bd447242925928b498311022a4088046020527fb4be5a59e02f6c6fdb331753e275322d60b3b6ae41886cecb24b6a0fa38b482b6040527ff9195e00fff88c599a6b5616733f28fabb45c11a93092c035562396e523a7fbc6060527ff338d766aa5b91918b6e29c80eeb8d6b912a0961e2974ec5e3d86a75e06218556080526020600060a06000610100611c62fa602e55600051602f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c83fa6030556000516031557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b9afa6032556000516033557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fc37c841d078259954317bfdcfa432ecfb86253f87270028f023bafa2dd25924f6060527f0bb4264610afcd1aaa8c08467a307f396f8de2b77a0ebdab2b2870563909da5a6080526020600060a060006000610100611aeef16034556000516035557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706020527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706040527f7c6f7895747231ac77d562339b36a17666dac663ed5e15f8ae40cadf411cee2b6060527f5dde658d2a1b8ec9ae16d52ba9d04e5c0387810a562775dced140eeb21b29e926080526020600060a06000610100611b38f46036556000516037557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f20385e628215070814ecf86812295e71fcd8a943aa03877f57f7868979eb6c6c6020527f20385e628215070814ecf86812295e71fcd8a943aa03877f57f7868979eb6c6c6040527f03fffffffc0000000400000000000000000000000400000000000000000000006060527f03fffffffc0000000400000000000000000000000400000000000000000000006080526020600060a060006000610100611a13f16038556000516039557f0d387666d4a50b0794b35a1e676f95921ab4a9a0418d6d90dd7dc279bfaf05c16000527f85053f55f125a5458f9ec4dbd99392a5e913eddfa113b37a8c6fb531e07d36726020527f93a478228437246e849746a0cf48fcd25bd8ba790ea446217d227ed1fde8b8276040527feaea26fbd043f12db289b0745b8c77395a68a6c96cbe4ad6137bbe1a7e5edc546060527f7c5406ac087ca551dad122d9088dd93360a7ad33c3c7b92d7e56887e0f61f3946080526020600060a06000600161010061199cf2603a55600051603b557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b0bf4603c55600051603d557f75a4be67ccbf899fbde0dd16b3c3f6ac6278bfe397ccff21857d15da866bcc4b6000527f1256f1fb4828792144fbf30fd0f9bd3315e64786bee2fd21f264bc2dcde845516020527f2c5723112c82d6c1f80000ce4a6ffa343377307ae58c5f2f704133bdaa9ae3c76040527fa574345be4ff67553c7bc71701665077ee4b6e3e11a15eac13770fde5b233ca46060527f3572978e4e046c9fd18ca0b5582f2a7ad14d7838aa452a18680ae3a429bc510f6080526020600060a0600060016101006119e2f1603e55600051603f557f2dd2fc34631156074982459867a4a96ed1b1e8f752e7b7a49a11780986d2d02b6000527fff057f2ddea4367d67200ac15efabad425bd7e5ee028854c6ec3b19bc8895ea36020527ff060d2a1739e51e785ef0ee757cd97560d7fc13501cb4e1c39d762a309fb841e6040527f0379e4cd9a4824cbde4686ebd16df416fba39fae4b714c5d0d24625d084469666060527fbc3e9f5e3e90c98795007800d6c0ca9cc3d7560c89c36068332792cbe4e0357f6080526020600060a060006000610100611b73f26040556000516041557f10021ad946641eef1055d665d7030c60dcf39a4b5b4eb19a18037c0097afdb246000527faee82d13e528762e433dfd89373588f00f5a3ab03acbbfaad357fb33a5fcd5b06020527f571d96ac94c21a38f85de4546e48ab2e4a579cc366def7eaf03fa803b0d0d9b66040527f2f02d0377759d89eb38a99b761a7b796495493acfe161d4634608210c551575e6060527f769332a3b848b8bd69b4129911d2d5a8d3b9548cbdf6bbb6d4b285e4fd8357d56080526020600060a06000610100611bdcf46042556000516043557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000610100611a76f46044556000516045557fc3df4030e15dc0d030692656dfa055d2b3ab7d1f1f157db691597fa809dcb3376000527f66234c39bc3363275b52c3fd44c90f98897803ec12458bd84c26d005391f3fbf6020527f9c942bc9c73cf249f3764587e3aa0f5d3f292bb38ccd0c9b4cc8f08ee0cb7c956040527fd97dce720557d57791a7aab11f659d3c3cc27f3212add2c8434faeb04e8340bb6060527f46ed59c543d1f37e8612a2e11f99882f5b5ded8ed733465b63059e7c394f47f86080526020600060a0600060016101006119aef2604655600051604755",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x6030600053600e600153603f600253609160035360056004536071600553609e60065360cf600753602060085360e0600953607a600a5360c5600b536053600c5360fe600d536044600e53608b600f5360c56010536061601153608e601253609e601353603760145360c3601553606960165360876017536083601853605460195360e6601a5360f4601b5360e8601c53608c601d5360ea601e5360406000601f600060077f9f914c6b08e682a081d2d8fd682c8093f8ed74ebb3ec8711598863921e79de7afa600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xC192f888ADA47142Ef2c856FC2C35197eea9E718": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xc14a8497cfed2168f05952f5437042184f962496ae2ad8f389cf588ae6ae5426",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f01de0d4bedf35144d5022ea8f807f68bc79f19abe604e3c4f9774f21517e0e886000527f2e91565c9e29fd6b1406b4dd148bfe805723651567cd013e1a5ff05553f1fc266020527f28d05f9ee49d9caf10a86175605981e86d9c9ae128158dcac272a1df69f7dc516040527fafad4e9799b8ab2e1f7d598ba9ab82cdef410a3f560a2f4fb300081766e9969a6060527ff4e68ee6102e13059303259b7d880ec183869e0aa85c187c3264cb3f297920d26080527fb5623bd151376ae749a02af6b642819f64a5a8d7abe46052adcfb3b44c8431af60a0526040600060c0600060e7600a7fb915f367d70f2d7ed301673fc7f9d93dc9e7df385991376505ecfd946d36de30f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x600060005260006020526000604052600060605260206000608060006001600161a321f16000556000516001557fa5621ec461df934885df87c577f28066b8c6bf7ae936471ac0ac7d1e37d176786000527fe08ef3afe4073e521f5a89f4a9188ba00a226983ccf1e46a2ebbb8109f88ea1d6020527f85f5fa439c5a885b49aa392774f346e618393818225f34cad265fac1e54563036040527fff3c4d8ff92c311289a7e7ebdb4f3be590344eba725d97f59cd048aa33828b93606052602060006080600060016201081ef46002556000516003557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fda1398e40e42e008964af3aa5f0a343e6cfcbe5305d3660334b2bbc383f262ca6040527f1d7be1825822fd58a48cb43a9760ad86a468321d843ded67848e3980fa2a79366060526020600060806000600161480df46004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527ffdae382eaa2470305db5d4fda8d1179a5183f034a042b46f19f63c933b33619a6040527f3add5cd52644881226f6d3e255d611f39ac802730d9da8b7fd8e2ef695463bb0606052602060006080600060016133f3f46006556000516007557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fa68af8eefb8844f05b0fa80aca01755e35fe788d83a7630aa0982af5e171ce1d6040527f2e7232c272df81f99c4cfb13daec393a6f68152fb69515b92b3658f2be928454606052602060006080600060016001610c89f26008556000516009557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f335075861c51f15a8180e465e33a79393b322bfd54649f1d09feb50eb18153476040527f78f516fb6cd1b8b03c91b15103321b4678a8a06e5c4767cb4fa8236116fe8a5d6060526020600060806000600161c761f4600a55600051600b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f304cf9115472b9acbe808ea11428ae5c6048a5573aa3e719b6c196922128a99b6040527f4bbae5da7b7fdcecb397082b83653a63763935c3bf619d9bf3ea978c8e0a47b860605260206000608060006001600161d3c5f1600c55600051600d556000600052600060205260006040526000606052602060006080600060016140a4f4600e55600051600f557ff32eec09a93567be48ce35b712a1b16539a8f3e797ab55cdea5bb1ef90dff3956000527fa827922f078f505525baacb818b6a15ad6b9c506a09018c68999e28a4d426a1d6020527f87a26e26ca9dd9735d1022cde00bf777924bb4f9128df846b469cab30db65c866040527f4e2c1908e8a6519aa6e9a482a1d7b45f587462bd15c06321e23dafe8c05289236060526020600060806000600161a12af46010556000516011557faab0530c99524dcafa571c784f17a37638e4c40b02df4f097a599b1ce3daf2f06000527f367819afeffb4d5e691be1a305d95e090811c8de47e3e2179b5a0880f874e81b60205260006040527fc629d9b24dc66c52fd1adfd9de1e7e5e867cc153d34e622cea630d02d24ac93b6060526020600060806000600161d41ff46012556000516013557f1275e3f62fe4f663581b8f1920a2056ef61ef6d24d3cf93b6b9300d5d1da3b0c6000527fc38af617f098d9bbf3179194a8d6536261f71ce5247d4b179de050139e25ad1c6020527fb045db9878135c9e2253636b40c2bfdd218563082adb35d1c6aa68a2666ebdc96040527fffffeb93395e132a2546d82a9bc9ec8ed63e7cc62da9f537b386ceadbbba02896060526020600060806000600162013ed8f46014556000516015557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f1bfc3594d3ea16195343c7959726c0e90a5aafc0e307e8199324a24b6d85796b6040527f7372342c5e04794a0d434073d73e0d86acba73476cfd417e32212619344983a76060526020600060806000600161589ef46016556000516017557fdfa21b05ce02e03b7f42f3385eecf8614701e057154f04b75c4edec10b0ce7cc6000527f7b01e6b04bf4f7e9f5e19592b60217fe14ab8978c0795fabec8cae297fe6591b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fc11e69a1e07329747f6042217206556668a8fbe73cd46a1552ad20cb31d7e3a0606052602060006080600060016177b7f46018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fe99324cdaaa32e6994bc8accfc797329b8a3031fb424da18bdbe7ae1ce5432cd6040527f5578556da337789cf53638e58da42301606dfe2db467cc482f282f70ee25494060605260206000608060006001600161a881f1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f71d3f0efa306fe4a489287be4bf731ba59008b5578a0575e86df979c01fa2d136040527f010fa20e9b9b26ab399bd34a5caafd8210d2c3d5b20a084287932272622fd3ac60605260206000608060006001600162014694f1601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f47ef410eef537ae6685e76a65fafbd768707f22cd7a3208e92e75553b64afc246040527f4633d74dc13137a982ad969e99f3e34ddf4043b7f71d17768d1e5d44917afdd060605260206000608060006001600161fb0df2601e55600051601f557fdd7795cb9181c1840841e9f7c35aca534a161267ca048cf99b9bde4141adda576000527f23a510455929c3747acfdbc10ef5b5a1ad79266004ee1c2e0e9726c4e172dd1b60205260006040527f714e3836b80a7055dace8298885f24695d369e7a39f528f4a3910be50d174f436060526020600060806000600161d02ffa6020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f0efe8fa94ff50316b3ec97b5f23e9a03a24f422a379860076c44d31b3a2fc2336040527f421dddebe35bb7bee2ffa96ab41122596fd92c8775123eaa7fdad753825c696b60605260206000608060006001615faffa6022556000516023557f2d013c5e51d0be3dcb6f506d18a69bc4747be02d00b4184194926067291c796f6000527f361f0ed0ac73e41bc6bfdaf5abb874da420e3eed9e2e74b35de46d271a9717596020527f651cd1bd399e2b59860ec16f3a9280a7d35f97e3490d7829e1085dd809f77e636040527faf4abbbc5ea9968b423dbb69dde46adb9388f463e97063aedefba0b60e7082a16060526020600060806000600162010951f46024556000516025557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fe9b95a12c340897c063ac3cfd1b7acbe4a0da0bfc81ec062f09675b048ef2ccd6040527f52807eb804a4fc3e794e24d1808a4f809a55a5c6c8a23b89c34f833726e2d92a606052602060006080600060016001620157baf16026556000516027556000600052601b6020526001604052600160605260206000608060006000600161f380f160285560005160295560006000526000602052600060405260006060526020600060806000600161e86cfa602a55600051602b557f73eccdeff1a8150ef8d9cf7157b51d12c07b0494ef7ae4568cac21c33bfa92c46000527f892abad06cd4a2e33e363309fc1ece4d12c3a4553617680ceeeae747a9cea81d6020527f5b7b5dc85b34de6ca00bfc58341126c699bf992b7a1ca7a6faed21ccd9ebd04d6040527fe63beea996e785a07b35f7cac66899fdb4746fe3803751fe66ee99a6bb2cae49606052602060006080600060016201793dfa602c55600051602d557f2a50c17a6e67a09ffed7c20e9d938cae76db03fc54a6547862700f1f3c146ceb6000527f4635b8a742eb226c4310ba261bfc3dd4971517130e37c539c5b948fbb7e55f1b60205260006040527fb898935f3b968fbec7fcd5efe9e2f63b1b876b0b3fb76cabaf1ed606051b288e6060526020600060806000600162013ac9f4602e55600051602f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527ff509be065ef1b1b177524ae119671796044d4b45cc30c9f36f71e737ae96c6f26040527f6b198d17a16c8f7bc38af6549c4b0f597d39c558045393137989fd22a653d8ed60605260206000608060006001600161b3d4f1603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x6b0100000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a0267d0212626262626266f121212121212121212121212121212126380000001900960005519778200000000000000fe000004000000ffff000000fffff700600501600155778000000000000000800000000000000080000000000000006a01000000000000000000001c6002557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6a1000000000000000000000901a1590147ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6c10000000000000000000000000900569010000000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7e40000000fd000000db0000000000000000000040000000fd000000db000001900960035590027a0109000000000000000000000000000000000000000000000000007f80000000000000018000000000000000800000000000000080000000000000009007600455677fffffffffffffff7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a001c0519760fffc000000000000767676240000000000002b057604768210000000000000022109018777effffff80000000000000000000000000000000000080017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1b1b6005778000000000000000800000000000000080000000000000009011901d6005557f7effffff800000000000000000000000000200004400000000000000000000017cc9700000000000000000023f00c00014ff000000000000000022300805026006557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff901b6007557176767676767676767600000076767676767667800000000000000090187f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a576fffff716b61616160b0b0b2b0b230b000008010d0a2b00901c60085515157e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0b6009557e40000000fd000000db0000000000000000000040000000fd000000db0000017f8000000000000000000000000000000000000000000000000000000000000001651ce97e1ab91a0890047e40000000fd000000db0000000000000000000040000000fd000000db0000017f800000000000000000000000000000000000000000000000000000000000000012137702ffffffffffffffffffffffffffffffffff00000003000060011a9003600a557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56f1212121212121212121212121212121201600b55637fffffff600190177f82000000000000000000000000000000000000000000000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000011d15900260017f7effffff8000000000000000000000000000000000000000d90000000000000190110219600c55638000000163800000010a197176767676767676767600000076767676767667fffffffffffffffe90039019127ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a59014147f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000017f8000000000000000000000000000000000000000000000000000000000000001901d600d5560006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000010": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000012": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000014": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000015": "0x000000000000000000000000000000000000000000000000000000000000000e"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xd5A8353a487e0749707fee138b741aeb2061C14C": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x4b5f705c5993deaa35a6d4e991c09c52f1d54151048b241126aa7c780cd2723d",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556002496001554a6002556001600355",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x60e360005261020060205260e36040527f17064e08aafc17bc922849c8372926c6a434f083594f6a07a8a45c764d5f32746060527f1f6959a22ac38f4842df68feb8894add1446f1f2b5eee105a531d9bab03dfdd96080527f95ec80853752d76fd53b9f3b5ee9028646da199627e7229bb1fdf4cce004c90760a0527f3b646cde24009c8a34bbd09080385a9aa6faa3c56360cdd8f1f6981dab2876b960c0527fbbc5ad8a8ef7dc0af7260ba09ecaa44972667a2995b572460c55e5a6bc5a54fe60e0527fd0b9e187dc2a1423bd2c32ffc276266366f4b8c23f6d9db52a800f7075e8ad7e610100527f9d0d8bc9c71ef1815e1f247afe1ddfde106adffd054ff9d0e1aa05a421d70db4610120527f4b6d6fb048e531dcfaa8d04551c0e9477487e1f42dfe6b078683edce88d707a4610140527f636d013bde3777c7d61819db32eb615638a717cd059f2b8ad9954706c98770cb610160527fa219a4f1ef80c84ba5f49f32398f3f92d2d325856dd70dba5a85b32f96cdbd96610180527f467edabf6a79713c6f62fdb7680ff03452a41bc91c2abcecc72e736e62c59d3f6101a0527fd8c7a5b6d35332bb32716638e5afc3dc11e15fdf251f301fc0b30c64e2accdd86101c0527fb65b83a80c856b89e597084abcc78eabb3a1c77561ca466f62ee699e334571c36101e0527f8e90fcd0ff032e05e75b51d9dec47825830251dc35616413af21313736dda353610200527f6fe1d91e54ab0713be14458c91ba5d750d4496890c25452adbff6d154efe2253610220527f6a50e684a75187e31a5866370cfb737ff50cd49b2303a43f466b6eb621193c21610240527f6c4b5f56d956912d88f44fb605dab278667f51189d4e3375d89b02ee40ff0efa610260527fc3503a6dbec74bdcdb811e1c648183980f4efb71f6ab7f632b416a5c8d2e7c9c610280527f02b2f7383198636bcab2bd027039c66ccec0d1bc0a9b066e4bdc871c22e527c26102a0527fae9a79a076c724db7dbf49a2d6610673568da9af9d551bba1a0c36944d1554626102c0527fe0d0ff83459d9d4a1401b8684f532643ce5d5c85e6c7194ec4726be2f3e9aa9f6102e0527f654e210bbc2793c4ceada7c42c8cdc784ff08014c941dd5123f5edd5ccedaab6610300527f0eb0abfb04c0bfefc6903c8eff6834a397b347248a5b8f09d6b053b4929cb7d2610320527fe77c26e53f9d388aeddedd75a91aec3694862f4a2bc2c704afbf0824c5997359610340527f5a6382f831c09b9ea1713902fcd17e9238e374c2a9fa49b55e344a21ab2ad0e6610360527fffc47ec16d2055eced751b3cd2ba7f4370247dbcf13a1ca513ffc09dcded5539610380527f6424b6fabee6424573a0f47c8b29c0a32bc810e559f8eab0cbb48453bb2322806103a0527f4dacfafe68f1a203c122ac379232368b3c44e6c3ea571c9690eea2288726d1d86103c0527f81dcb18b456fb670e67b800f82718896d03244459dab3fa9d6e963f4e6b0d2906103e0527f98c2300ecce35fdf2d465fb2bd595934fd16de5d0b4250dde3807d3d39d62b8061040052602d6104205360e06104215360be61042253607061042353606e61042453606c6104255360e3600061042660006005630121304ffa5a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e051600855602960005261039360205260296040527f5b18ef532970f673409e96991eedb6c6c5ebd58355c4bf48036cd4965402df856060527fb22b05c1af879b519c134bcd9cd1717c8174c23fd50323cb498d984d87e644c16080527fecfb996069bbe4b810cb2003cb46d20298de618dded8b126a207c12b8fce9a2c60a0527f431df67d39976f0e0ec3e4d34dc258b9b8ca8a0ac73bb1ae76999f3508336c5b60c0527ff83d846bb720d6a7309b5a8c66bda94fd71dfcee1071ce91829dfc7371cf45ca60e0527fecf245a33c7b2542a013ba70d04038f3a6b38444b4891098f1db09f22811244d610100527fd7240d71eefbfad870c0178707c0e73ec010aab35cefc6167b170a1fc9a03c83610120527f3b5b9e03ab8ec164160cb7e4088a16282e543d717bdfe9460d4b8e4df73ce26d610140527f802318619d643531c4b6600f4f8bd35736b0efc13b38ee9462388bdc678aa142610160527f0ae40df6f91a2a88ccf46be9638cc3703db018bfa34e93ba8fee0503c0faf437610180527f9e7ffc5727f562e636d6929bbdc801b60747e7d40a29b02d184e334983a1c2926101a0527f9e76a473cd4152669e3870d79f78c171609be04a54d52caffb6e2ff3d2c637c16101c0527fce59ed6693397cf2665136b7c2f62db543dcff91cb5871e2bbfbc0e7ff8768e96101e0527f63c2c85e54a93f234a35662c4eeb6e3cc00f3cb656bf221fcc2433fb89424dc4610200527f961f4318b87886e6a097045ff77802be19c5e730a91f6c1f5f668f71d91fde6f610220527fd74dc4216664b0a8e343a7cbc4f2f1318d1adce27cad161029d9d24ab2dc0fb3610240527f0bf743c02e0288c9c5a5a46fd92f2d3b149872c242a14ccc061269791944252f610260527f2826cb8d035823fb79638057ab32227859186d9775d1586f629de389e4be131b610280527fb766eea382e8630072c0d97b83afff7ac79f9bb44e83e00dd033659e261aca6a6102a0527fb9258ec4494918bc425e0ce55939d831a06fdd54306a316aab3555d0e14e43276102c0527fb74725c4e0a5b5f57bc966f0b8bcd19aa40b0e49fb9bf71a1469dbe07a81022c6102e0527f129dafdeb706c0f01aabda2eab3571596b70760ad4f3c96c1fa67605505b2bf0610300527f87cf9a097aa5e2d615ae37cbc44d21b5ef4a912e0872e47fd2dbc8082b3e0c24610320527fb1d99403f8e1ac532376dcdf630f8ed09ee0409771253f8a92bdd758b2f38889610340527fcfa1012d22ed9230e688fbb1ac059b3aba749813862407b76334d94ab0931c6d610360527fe5f8768375e384107bcce47c4191446b201783e221cca47c115ed6371067d8a0610380527f2197cdd8f09a558bed2656b42d4187681c870aa404f2b82422a0eca0c70f89a96103a0527fd5d0f60e764c43053ad591aad788e11d8f3d19fff798c40c9ec20830b3c37e856103c0527f1eea42a3a5b9fa7a3a67d41779badeabe3fdc1ed55a08109311d9331cf1386e86103e0527f2d10ff66d8a0dccc13b738acaa5857f9edca207c55857e0d80ac7494a125ffec610400527f629ceecf5e664b489500bfee7effd6ee1be437f9e92966e206399c92446b04906104205260c46104405360bd61044153606661044253609161044353600761044453602960006104456000600562150304fa5a01600955600051600a55602051600b55",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x40000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x20000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x",
+ "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0x0"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x0163265b8324a04c9ed8d0edb85a0d7a2007818cade0ac8688c74a99044cbc33",
+ "0x01bfc2990aab016818a9020657c03a92ad639bfe0fb95e25e62399bcbdcb2053",
+ "0x010c5d0a87a926c9f5a527b6d21ac1f3b93f47b3e0b391c5bdb0bf305d786a54",
+ "0x0147ff69e28cdd0e51fd8ae75bf49cb1c6ec900462fa181d7f3ebf63040b5013",
+ "0x018526f9e485f72923a91721812baa0527c6b93be7d5ee22a0ea78fb5b401ef0",
+ "0x0158a07bc9b0d275edb3bcdf3fb9e36830662edecd32ee1fe9839f2ea7e87527"
+ ],
+ "data": "0x8c",
+ "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x82",
+ "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x83"
+ },
+ {
+ "data": "0x946ce4e9e90aab59992f710210704de54caacbb3f144f6341c47f79f9be9dd9cb3d57b7d2fa3e26835c614f015952f0e8e079170f6ee3fad",
+ "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x2a"
+ },
+ {
+ "data": "0xd16fec5d8628da397d96ce91dcf8f35ed0971782f4a9f0cdaa464464eaea86",
+ "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0x903b4b"
+ },
+ {
+ "data": "0x49cf894cc9899f782fa6ced5aa78a40f5d1f25115ac517de3a6dc1e439fc28d40f87b47b98e8da27413d69c86ab9243cd5bb0a5667e8c024effa2e012ea2290e48722b8003f1d55f2fe170de82328b58e0715d8d1ffefc5a3708200066a2cbc13145cda01e89853d78a5385f4f71aef7ce3690a81fa9e5200302a94c517022654f4d3fae178b211256dd479d34facd5352491ef61c72dda752f2b78c9330b63dd90326c1cf41cad9955d7f575d56d275f4f2aa3a365e23aaa8f3caefed894b6a",
+ "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0xdc"
+ },
+ {
+ "data": "0x473883564bf6baab586b369a707020adb4dd9002da0da251a44de3c83d9478379bde8cc6cf20fc05e703883d561055cff8f1eb68e74a918e58af54e82b3c96fbcc9fd100e69dc06dc035ee8d1731",
+ "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0xd8"
+ },
+ {
+ "data": "0x57",
+ "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x0"
+ },
+ {
+ "data": "0xdf",
+ "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x59"
+ },
+ {
+ "data": "0x6663067150ece19358b8213b58",
+ "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0x0"
+ },
+ {
+ "data": "0xca644bc4782a166a7f1414746cdf88f780576ffb77c1a1a81d80",
+ "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0x0"
+ },
+ {
+ "data": "0xe1a8835b8666127d66b8b00bc97db84e33a19c6e7b7e57b4b00aebd3d883384b6ff6aab51feedf2fa847e8f67a26e5935fc857a1",
+ "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0xf706f7"
+ },
+ {
+ "data": "0x3bf30a40cdcc2baef21d17c6a32a4cef206f6f3c508696fc6980689f018f3ddf38c4b2",
+ "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0xce36f1"
+ },
+ {
+ "data": "0xccf3fe51190f8fb88f69ac18da750c2e5e43f2205ba3288b7593f9dca020331e1602184dff78216b6752124c2b7ae740d0a98a98d0c85876a9419f75ad86361d48371fc59154a3836b3ed9899bbc",
+ "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0xc9"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x5cbdd86a2fa8dc4bddd8a8f69dba48572eec07fb",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x3ed20ae1548d1fd9d90a1eca4f987f64219a8b416ad20454a5cf43825750cae8",
+ "s": "0x2cf38759a4ca00d224a711398e8dbd8844596dc29e14601fef012659d6207fc0",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f3",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x6d2226c5a987fd92af6e5041ab9aedc1c14cfa4b8729945d3e2658ef82618a54",
+ "s": "0x568ea8ee65ce67292e114515be368d64f76e6f32502031aab4852c127928d57e",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f8",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x93b6d4c7f0b540e53a042a79ec312616116c2597cb52feb27b77668793b8e5a0",
+ "s": "0x209057b5fa3c5387592c33993e4ada764dce62b97e6a9303f819019772ec6df6",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000004",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x431784db736d7a7b32afa2a06f9b2dd9b7947510fcfe270ea15c2ae08af9c7fc",
+ "s": "0x780ae64313ba535e023075c4b6ba0b292377005a380b83e0483cb71d70cdf9d1",
+ "v": "0x1"
+ },
+ {
+ "address": "0xdb2430b4e9ac14be6554d3942822be74811a1af9",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xd7b62ccc7a7a187ab2a16675f305830774b4d337043a2a0419e1e87fc30a5157",
+ "s": "0xa46b6d701549aef8b29ba9a6ef7c3c6366b748ea1294b88df5a8cd91edecb40",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x08d056a6464dfaa052593f5547603f5143d1fc601858fc8e45aecea245c1a56cbcf28f73",
+ "from": "0x862B38c425EF5544d0127449A12c89C46dd3E050",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000006",
+ "type": "0x4",
+ "value": "0x3e"
+ },
+ {
+ "data": "0x00",
+ "from": "0x0233362c058b2fCc8093841B1073A90D673E7F12",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xdd95902a4746dbf0cb38778983b6a5061c9784572e18492bab91b69a04315a29",
+ "s": "0x115d234e528f56cac392831ef418acb2db384b9b92749f4174e4e2ca2b2878a3",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x08d056a6464dfaa052593f5547603f5143d1fc601858fc8e45aecea245c1a56cbcf28f73",
+ "from": "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000006",
+ "type": "0x4",
+ "value": "0x3e"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_medium_2.json b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_medium_2.json
new file mode 100644
index 0000000000..d73d2b2112
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_medium_2.json
@@ -0,0 +1,433 @@
+{
+ "accounts": {
+ "0x000000000000000000000000000000000000000d": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x1028f1F4b946800E1b6D7528C4699Cc3df844fBf": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xffe5a49189ac8e319cbc7e1e0e1a40f1fd261f8706e9f8d4529fa55a2dc2d4f3",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x600060005260006020526f12da46b729d5fe99597845a4964902366040527f7bdb3a71550f71fa7f7942107297241e78338eb3604c21c1b885c35c48acd88c6060526f16de46d5414dffad552eb6f59ecfbb586080527f34fc0621617564ee4c92ac95929675eb9835e334e4976df845359c5f73e8dd5360a0526f12c09fa734e3f0289e4ed0ebfed3f86d60c0527f8baf34656290909d3369d5ee4b87ca47eafa338e78286cbc013e8cef8bda961e60e05260806000610100600060aa600b7feac041227fcee37f9758d873e36bc136c2c92a797ef826edfba231397c53359cf16000556000516001556020516002556040516003556060516004556f04556c12c0112472d3ad7764fcc242526000527f700a4b4c7c60a9e0d4a17ed4f5d0910687cd3bdcddc93caf65cd75aca3467c236020526f17838af83584d739cd9d3bfb9e7c96e06040527facf7eeaf93a5b5b862cd741e66deaab818c5bbc0e133c12a7023ec5984181fdd6060527f624abd858aabcca57ec88d91cfdadb3653c8ef629561e03091cee41549f9c35c6080526f05a13e7604c27d4f5a6f9ddc508f3ec760a0527f17b3f77520bc5dd88f7c56fadede2f6dd5fb773f97a39e4d7d86ac2b899ce16860c0526f0528b78253febdead3d353d2cf4b691560e0527fcf4ce6b18f44bd19ceaccde8ca10ac15bf5d89cc89740d4a5e96ddc380638e2d610100527f3d1708e4b25fddd12bf6c5e2b5c07dfbd20983bac930289e6996c910bc0130f7610120526f1c9a01fa112f6d22a27d3fe125ade109610140527f0242653dda65fdca5b1e80f28e2360fb3195ad1cb6d914e1c9a5342485c21dec610160526f1fabe90a7d6da23a062c0d63bc0e6c80610180527fa5afbb640e2530dc5c7db4f21e2c1d1ef3fcbf8ce5fbdc8c8fc019ffbc2bcdd46101a0527f35aa1c2ad23c66d610a5374c259610eaa6669cde15e79354b9bedca1bddedca86101c052608060006101e060006041600c7fc7264066f1cabf74058d2ced3ace5e80281c49a3c498eb80d085ad1c9703c7edf26005556000516006556020516007556040516008556060516009556f15043153691079ff8b800801a519a8996000527f49e6674f1209d211ceda5f887a519cfb173344e8638e7cb1695e83bbfb4020076020526f1592374a4fdaaab67b883dbfad398ddb6040527fe8cb651ef24f0055e31a0aaed60027f66cc7e39291c2e99c58b8f370b667496e6060526f16723a2fd291491fa598d675d7732f8f6080527fae239956720f09bc7812c2cb24341f74e93f278d7b9cf1669a0c09d444b527d260a0526f0a6bd72d6e614e15c74478c1c738feab60c0527f2aded243d43c944e4fc1a76346d4f8ca7690109b066acf4925879a8b0a1333a960e0526f018bce8a78cd8f3b7030358875f5ae27610100527f99a85cae15e756f5f4d05ffb400670ae7176229dd7ac5303c9a1c534d1ca5557610120526f11e8395922b79ac4e7e1c8a861bcc225610140527fa62c2d8665daebbbf41d4efa4ac8c5b50f1f1328f7486bead3691d18090d06b5610160526f199c667464a2b2ce3bf8804917adce69610180527f866f6a894a6b280753a2f8160b9f96835f7d531c7d7f18eb3db6e72df005bed16101a0526f120c518d3494cded818bd7059d008b146101c0527f9529f3df954cb1b0707022156b934a5bcfea7ea17a49c493162fa22b1f9688396101e05261010060006102006000600d7fefb999ff2151cd3b487bdc950acff68275a427314d465b97c59157af861690a1f4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f14cec51b5b967401b0a49786056323826000527fd1605a4f4dbb0327cf158208972c7297c7a480af8f57418db26fb9d8a57ec42a6020526f0a308a73497553ea2558f44c64a4da396040527fffcfac4fd59b6d58bc20165648d211fea03cf367a9335f567406b64dd29a6d756060526f04b58fc3f267e4e6b60dd110ba61a05e6080527f7e23fa9b3538858c2563347ca5ae3dc8345fb24b57d27bd7a1d9f101dbcecf8260a0526f19811cf90edb6826a4402bf55576069860c0527f1a8266b64e9927d372eb06284402e65f05fd750dbf62fdf9c575737ba8b695a460e0527f420e4630658c2419983969c302e1cba7496a1565cad4194ea35eb92ea6671d65610100526f10c51b3ecb9cdd339c30853998639902610120527f7640d27ccbf15be36a1b1edf9a7badab3d0b843d897d86e4f11d15b2d859a226610140526f058f95d8cd109abd3cebb68a4b5028f3610160527f581903e67af5ffb33bd524e96b5ea825d7015eb997d6d5ca7bbd29d489cfe741610180526f04da4aaa0bce3c2cf00ae6041613c62f6101a0527f261103d196247d4933d641a4fccebf58454037c1555012471ea6b0f2cddfedc66101c0526f1d901f3512c8641e3bd1e6c7cf23a0a66101e0527f3c5b40381b8cf73c39ddf391caed85641eb08ae5dcdf326d3554d72103fe0741610200527fc98ba1c875128d3c1407895a214423daa888cc29623d7df67e50f9acc52bb0446102205261010060006102406000600e7f730b6b0a81e1c498a48c1b55a7f30f4e2acc5ec19392edcb81b9037ee5d4a1e1fa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f087e790c45fa839f3fd183f65550ae906000527fd2d71dc1cf38b5ae688434dd6992ef5f2dd0d49660b7f365272e095439c6e3126020526f11b1426059eceed225f12fede8a7437c6040527f7bce7fa6d834ce84a657d64a968640121cc492bec9c8399a2073dbbfadffcd2f6060526f130a9b9736cadec87b5f67b649ab56786080527f7ffac8dc16b072f277a3a2248b955fa63d8a8bc68cb08bce0c0097e0f44880fe60a0526f14696e3c6e19d213e52ce80486f4361b60c0527f6a68cf37a154f56b8512cd1148d78eaf1d81d4079548c73d1b41bea2202ae13560e0526e5f79ecbbafb9cebcd604ae004523f5610100527fed2e2ada166d6bd877079b525144dec82e05b65d9424e5ff7d8cbc553360f23d610120526f0f901a221e5deb6d9b439fe259c0f290610140527f9f25ef61f83f8ce4f8766da70ab62ed53e46ddafb36acf280fd692e67f55440c610160526f099260ba4a9a5a3fac51565b1fcbd380610180527fe76af01600cbc075cac5d4fe75c305d2a70414f5b7b9539d91b05bef357b00f26101a0526f0647d541df6837c0047e390106df15926101c0527f525a15bf78542328efc960cfc5d5aa6e13d7a94d0e02a18d5dd3072b3fece0326101e0526ed9a2d531ecb0273ab936749bf2389c610200527f555945ce7ed1820f168148bf98e19e80b4624c37ea3ad3430b9fa7f7289d1888610220526f07c4ba9468409af2a87e772f8c2a7e2c610240527f738e75af54c95a4af93aaa720d5ca5e63b0dc683a45f2e6049793c906dbe58b4610260526f0da82f6193a31129fd1db9a1a86954fd610280527f64c98561cc043565c7dd8ccae5afc2901bc161c42b198763427fb568f9a77be66102a0526f0ced91c8bf442cdc34bf8713070b2e1f6102c0527ff5cf7367396ad1d06abb1bf3f05169024c882cedef70ae1d24628999dbfa85f16102e0526f0a4185c9e4d0baaa2a0e1498605414e9610300527fb2db2d033e084ee25b27dc5686c2b4fed9915481f4a8c6aba3e56199611bf19d610320526f022c32176f46809429aa7a6e94b0a541610340527f8b89c2eca6ad64a1d08f9e56aaf1879f1287a781bd38e944ce7de7fb2aa224b5610360526f0e29ef6ebe99e7f4f12b94b147294b10610380527f33eb7d7314e330b5c75d0e40b1faaffe5dffef1818414c15f47c372ff6fd53306103a0526f0992e8892988a7e207d03807b96495f76103c0527fe0c118af357b36cc6de661f4c3cffb8123fed50bf39926482279de5446075c586103e0526f15a1a4fe36d43d536fd227be3de90662610400527f882c8d76f346af89f2897e47fb03e1cff01f154376ba731fd67a0c5e004ea5f5610420526f0544ff26b18dbdba97e63b5e83b0639d610440527f32091000f391c2dfbf525518d4b2e4313702d936c9a365b2176629b3573d18fa610460526f03787c467ee560d77adc1e5c51a2008c610480527f01407eb311f4eddf4b89d697b5a9085c746931ffb4415e2bb11588db88edfc966104a0526f05b37347124fe87949be342f69fe0d3d6104c0527fb6c98ea7386b0666e55dd7c69ff494462a22b380edc524c220d7a19edf48bf776104e0526f024aa2b2f08f0a91260805272dc51051610500527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610520526f13e02b6052719f607dacd3a088274f65610540527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610560526f0ce5d527727d6e118cc9cdc6da2e351a610580527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016105a0526f0606c4a02ea734cc32acd2b02bc28b996105c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6105e05260206000610600600060de600f7f42fe45fa84e8928ada6733b78e40be4e28a744ea3bf60c69eb808fd2b6b00f65f1601c55600051601d556f19f0ff5cf765f8191a92dd7333f115636000527fd41f77c7b6ad482a8a42dceab06c0cc2d518223fb5ca70d288410bbc931a3147602052608060006040600060fd60107fa10d7d88e8e6ceb23cb75c8268d2abee7e2f4f843ea76f5cbb4cdc17cae5133df1601e55600051601f556020516020556040516021556060516022556f0bb44118f452e8d6256a535940c2f83f6000527febf8909f76ab23b0fe6972a6f41d32316d3483c2ba33e550d5c325f0fb1c1d776020526f01acf293ca3d4b46d36596ebc63a46246040527f6bc9d5064757af806470c48d23afa99bde4a2a31715e1b2117783f7ffa06044360605261010060006080600060e160117fe6589a52f39e3deaaed3749e845bfc9549711b79a7903754446e251342879f54f160235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x60a160eb60ad60ff60cb606160aa1a0778385a5c5e3298ff9cf0004477401c360b411c8d8dff123196f05f97556d153f18f09b6e125b4973559c097b1518381b738b5707575f53f34430139f4a1078396a6e10f11e13f4014165173c017a657a188118693e303efd1972111a5a3bf1636d026e0003514a699a315c1b60417e110805f23913626f12744a7a3e671973415f1b3820f4674754083e531ca4f05c6687915077097e90a10a36137f5c3f47466904470a7e5f0b1076067c1b0b55583c13094a7685171d59177602487f1a209f7e445c903e95476f349f8f5a124a3511723c15415b704660440803151c75761c495841626b496c3e9f898a021155205bfe9753f4068356845e44503a3b409c4a62370078586254159453673551055f5889655613fd437504866e5f163065339e1c3112347a190630323e500147543e121a6140434363440a8579747b475b576b15465c19784a90031e390805106c365519699f6b8576801b1c03436c8ba260335b535c0071000507336d49a390423d7dfe773c7a14601d5554208164016a81f2f5615a42fe35337739081e983c361d65516a136f189e958e1a6f181d97ff0a566e8208f197691e776d8964a274323c80ff001c657b474475705cf47954945b73855a1633699d3c62a41e321c9a487652406a596e876b59085e7e0b511449646d70468f3307067e567e1c4a367831619c51726f8898697e621972045e3035798e13f41c493d514941185a7a109b909a3001905072313613935c6857314545517a855a8e0a15523d95a2424a557418539a6e45646e676a6442f3fef31b307d77514912fe70331141317c495f58406e3c624866a46b11735b078e44ff77f24691863e707f5268743e675233551e04f55454486719446191687c876e48051357fe55681231073f34671e586358736d5f8c57834756087e748f415213663e5a6d2034195d786063685a495a9d6c6f09336b5173396b345d6c7561653948470509908d1d9b8255678b4389081a357749778d3943569f9299145e1733376c33041c7f02091d8148fd170612127a06771979fd7c617c7d00458d1e7f6144f19a534a8136160865616c77703e326303fd656c8042163219fe4534333a4055f1366b0506541e7549699d5f1a3a9f70081c347d0b7b7b3e5f3b5a679b3e405a7b9043475751a188167677938a5e53673f6a867b8933fd7e6c5938509a02446ba455616744424a711477356618035e8b313a7dff4a47a47311496e5a48609d137b1e691488915b54397f43343580455220a15394766c823f02727b7f356d611b69373e96741950a380150609181d5c8314011e3820323b388699039e84375c68521b725b3787448c743b1e3c5a76817f736856721bff1006f59d597a5c0918836b0382104072146d9b016061f1463c857d368981583c",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002"
+ }
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x7fac24561d9f5035ce04d964a68037cd14dbff7091ef59d77299bedb0b38c6ad556000527f2a0169a823df60688109dfb0d02ceb695fd6299c0c7df33756f060e3499a097e6020527f84adb74ea377c7cf23bb8d05ec376b6955da1dffdb831726512dc92c71ad5f436040527f6dcd32102f6a81d419ccd009b5d3a4b266dc1049edbc5e307525a2b2bda040bd6060527fc6995d1048cec095a29569af28b61a5f38dc61586062eeb401efeecf1151d7316080527f70e2858125805f578d2deb5a6d9c20170e352c20417a194c6e5035403963772660a0527f801b6949c072d646a2caf58f33ff5f8e69728a830da82da55a43a6e43c39013c60c0527f1cf0dfa518395721c04b8c6b368370acec11e662342c7c356a59255de4dee03860e0527fba75a6bb2de967e948458ce598f13431acb43b082926b3a2a330e0960b9bd2b0610100527ffa67efe960985744944789e237312835d725acf28b21557d4e6673428e36b86a610120527fe0d4c9b0112dab6624a912a175b89297731e9dd9a59112519ca0087f5bea30c5610140527f85384aa36ec17a29241fa8a2870634d2cbabf3cb0e959a607073bf591e5d733e61016052604060006101806000608760f960e7f1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000007"
+ }
+ },
+ "0x3fD261193d23d8a73a4fdfe7735892c6Ebb4f2Ac": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xe32520991692770350e0a6c3acde9b20b7ccf11ddd1d1e86cbf91ed98e2d8451",
+ "storage": {}
+ },
+ "0x48Ed5D2f29e6CF27031A62C9e4826d56B4536a36": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xcf9e2e355349971fa5c9c1774fb5ea58f30310b283b6b14d6dc779faa5499770",
+ "storage": {}
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7faabb9137e7492c9f26c298cd433b7e0318c3876d2f5ec0a905a1ca164efd28a16000527f70b020e11c1bc897b7c2b210d69a0adc3684f818c739cbf9680a11f4c7f75b186020527fff98638a49a81dd7fbb111626efcc4428a2567adcef3aa2f321381c030625f1760405260c560605360436061536068606253605f60635360266064536099606553606460665360dc606753605c606853604f606953603d606a536089606b5360ea606c5360206000606d600060087f7a615e760c7a1993a13a60cbd25477ce8f96290789500f791bbd997d0086e6f5f4600055600051600155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x60406103602061010061034960a05e608b60a0f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x677B3ccc29f7c2293364fEec7F51907756f0124E": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x83011199ca2c83c9f2275cc32037543a5c54321011ec6e342bf9e00710e5c20f",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x7fd861f3a6d05dc0b79ac2bc4d2f6ba1d52f11ad2817ab5db8af0c48ceab5773b06000527f1e0a1dd7b3b806ac4bc3fea18a4a4bc66071ae29ea60cfe9bffd7f39bec4e9506020527f3155c44ae2cb923a1f9664fa462c7c71975c57706987231a8b3ee5d04b5fe5306040527fad7d2f50e5a57baf9916e251cdcb680035a9d37f08ae7ee52b9026af284639416060527f17d5aa5a02e8859b7d7fba8338a1d07d8beabbb32c02effc5e475be4e7c3daa66080527f505c30ab6738d740e6a0fb2dc2ac162a219d72ec70fdedd81ff86150d7a067f360a0527f85712bd79e2937184e738b74b26a7f486b37903d9aae6c99a203896117d757c960c0527fbe6ee428ff22d6bfcb5832852cba8c9ab765df85938186f67b3d3400da3a3f9c60e0527f3939dc2b739558813adf772aa4b15c7eb7a7bf1409dfa479cba20297fc43ca5c610100527f6b35a7cfb1a6534523db9eb3242394caae95bf9bc31dc008342b761ad30de09f610120527f854144dc711fe375a7c065a2cd136956440e1adf2705de37bf972223c4f003ad610140527f91bc4ee89625507337e9aab34ea2cde3f18b96f18b0a27cc5e8ad661f0123021610160527f664faf22c3e905bae00c2d54a010aefafc10d74c1a000decd3467859105f114661018052604060006101a06000602460087f9b83a54ae8b5af5197c75d7a815c8bb11e81161cb04d4f7aa59b9aa578f4ef1ef2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000e"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7c9a60c23b9313f62b01b29e4eb8d423b58410678d89810ba3fcbf9b86766000527f33484703223612690945d74b3b595973ede4fdfbd022c31967190f52f9710d9d6020527f4e50abf59452e7caec6f35757bd59dddf76032ef813ebe914034c6a6515f8b1c6040527fc61f52d194f07d882f72a998cd4bd51b8857cd0a2e8663e0a665917ad2b53b686060527f5ebf56e91c6fd2c8db25b04dba00ca3457181a104af1b15f5fa560c2f388477e6080527f788179f76e7f546578d5b889305cb7fbe18e406b9979a6129fca8c7487cb3e5a60a052604f60c05360f760c15360cc60c253605460c353609760c453609a60c553608f60c65360e860c75360d160c853607e60c95360a960ca53602160cb53600160cc5360ed60cd5360c660ce53604e60cf5360bb60d05360de60d153608760d253606160d353600160d4536040600060d5600060097fe61ef44776e880511e5e8b7872c121ad30beb910665e6be4ef98603a772cc0a7fa600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x91C6Dd1A685cAE33B044370252727B57f688e5c7": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x89032b3329df88503c25a42c79eb3d5628c802530d8ee347881aeeebaf5ffdfd",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x6380000000197ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb067d02126262626262604077ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff8000000000000000000000000000000000000000d900000000000001146000556a01000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9018901a7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb6801fffffffffffffffe901a600155156002556c010000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1a7bc9700000000000000000023f00c00014ff002c0000000000002231087bc9700000000000000000023f00c00014ff002c0000000000002231080590166b1000000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a001c90147f80000000000000000000000000000000000000000000000000000000000000007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901818157cc9700000000000000000023f00c00014ff0000000000000000223008056823232323232323232390180a600768066aa0a5319bcf5cb4181c60035568232323232323232323712000110000000d0a300e750a000000090a0a90056a0100000000000000000000686d5adef08547abf7eb139007678000000000000001600790067f77676767676760000000000000001002e000000000000040000000e0000000006b1000000000000000000000006a0100000000000000000000080867b368d219438b7f3f7f7effffff8000000000000000000000000000000000000000d900000000000001140460045571767676767676000000000076000000760000197702ffffffffffffffffffffffffffffffffff000000030000638000000090111d6005557f40000000fd000000db00000000000000000000000000000000000000000000017ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200001d7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6b01000000000000000000000090046006557f80000000000000000000000000000000000000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9001686d5adef08547abf7eb7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00677fffffffffffffff089011600755638000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b00901d136008557d7676767676760000000000760000000000000056000000000000000000007d767676767676000000000076000000000000005600000000000000000000017f82000000000000000000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe90136009556f8000000000000000000000000000000168478392145435897052762900760076761e0002007676000000007676767600000009600a55777effffff800000000000000000000000000000000000800168066aa0a5319bcf5cb41314600b5567d02126262626262668478392145435897052067fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff760fffc000000000000767676240000000000002b05760471c9012777effffff800000000000000000000000000000000000800167ffffffffffffffff90039010600c557f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff760100000000ffffffffffffffff0000000000002e0000001c678000000000000001778200000000000000fe000004000000ffff000000fffff70017901b60017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006a01000000000000000000009008600d557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a567ffffffffffffffff9004600e557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd67b368d219438b7f3f1b037e1f0000000000000000000000000000002000000001000000000000000000006a0100000000000000000000901d7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00600090089008600f557d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97f8200000000000000000000000000000000000000000000000000000000000000901c7f7effffff8000000000000000000000000002000044000000000000000000000168010000000000000000901790137ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0071767676767676767676000000767676767676900511777effffff8000000000000000000000000000000000008001760fffc000000000000767676240000000000002b0576047610111900817774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7176767676767676767600000076767676767603900a6f800000000000000100000000000000007f80000000000000018000000000000000800000000000000080000000000000006f800000000000000000000000000000000890159010601055600515196011556f8000000000000000000000000000000167fffffffffffffffe901871767676767676767676000000767676767676762900760076761e000200767600000000767676760000000b1869100000000000000000007cc9700000000000000000023f00c00014ff000000000000000022300805026012557f800000000000000180000000000000008000000000000000800000000000000063800000011a601355157f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a567d02126262626262676013590cab83b779e708b533b0eef3561483ddeefc841f59008151415601455760100000000ffffffffffffffff0000000000002e0000007a01090000000000000000000000000000000000000000000000000014637fffffff67ffffffffffffffff03067f77676767676760000000000000001002e000000000000040000000e0000000006fdac7fff9ffd9e13226262626262626009007900519637fffffff7f7effffff8000000000000000000000000000000000000000d9000000000000017d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9086015556780000000000000016801000000000000000090116f800000000000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200006a010000000000000000000008601655901060057176767676767676767600000076767676767601901590076017557cc9700000000000000000023f00c00014ff00000000000000002230080567ffffffffffffffff1b7f8000000000000000000000000000000000000000000000000000000000000001760100000000ffffffffffffffff0000000000002e000000901260185563800000016007900260195577800000000000000080000000000000008000000000000000680100000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000019009900a7e40000000fd000000db0000000000000000000040000000fd000000db0000017ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00900b601a557ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff6780000000000000010b90047ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000019018026f80000000000000000000000000000000637fffffff189004712000110000000d0a300e750a000000090a0a7f80000000000000000000000000000000000000000000000000000000000000029011901a7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101119011601b557e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006f8000000000000000000000000000000005900b651ce97e1ab91a71767676767676000000000076000000760000900b9010157e40000000fd000000db0000000000000000000040000000fd000000db0000d3638000000002037f77676767676760000000000000001002e000000000000040000000e00000000068010000000000000000129011156770000000000000007e40000000fd000000db0000000000000000000040000000fd000000db00000190131019678000000000000001712000110000000d0a300e750a000000090a0a9018036c010000000000000000000000007e40000000fd000000db0000000000000000000040000000fd000000db000001141590127f40000000fd000000db00000000000000000000000000000000000000000000017bc9700000000000000000023f00c00014ff002c00000000000022310890121667b368d219438b7f3f6fdac7fff9ffd9e13226262626262626007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a091b762900760076761e00020076760000000076767676000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a0603601c55777effffff800000007effffff800000008000ff00000100006780000000000000011167d0212626262626267806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a1067800000000000000167fffffffffffffffe7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd900890086f800000000000000000000000000000017f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1b601d55677000000000000000778200000000000000fe000004000000ffff000000fffff70010017f7effffff800000000000000000000000000200004400000000000000000000016910000000000000000000901112601e557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f77676767676760000000000000001002e000000000000040000000e000000000901c6801fffffffffffffffe774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1d90047e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100069010000000000000000000505601f557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb067b368d219438b7f3f9010197f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000016801fffffffffffffffe06901c68478392145435897052717676767676760000000000760000007600007702ffffffffffffffffffffffffffffffffff20000000000090086020557702ffffffffffffffffffffffffffffffffff200000000000600116177d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff90116021557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7e1f000000000000000000000000000000200000000100000000000000000000901390126022556d0100000000000000000000000000686d5adef08547abf7eb03686d5adef08547abf7eb6910000000000000000000900690076023556f8000000000000000000000000000000067700000000000000090167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0090116024556b1000000000000000000000007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0218602555690100000000000000000015760fffc000000000000767676240000000000002b05760477a01090000000000000000000000000000000000000000000000000001116026557f7effffff8000000000000000000000000000000000000000d9000000000000016f800000000000000100000000000000001d67d0212626262626267f80000000000000000000000000000000000000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb900890046027557f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001157f7effffff800000000000000000000000000200004400000000000000000000016f800000000000000000000000000000010a19191763800000007cc9700000000000000000023f00c00014ff0000000000000000223008059001017f8000000000000000000000000000000000000000000000000000000000000000760fffc000000000000767676240000000000002b05760476d010000000000000000000000000090081768210000000000000022684783921454358970520a167f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd717676767676760000000000760000007600001b90187e1f0000000000000000000000000000002000000001000000000000000000007f7effffff8000000000000000000000000002000044000000000000000000000112900b196028557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07e40000000fd000000db0000000000000000000040000000fd000000db00000111671fffffffffffffff7e1f000000000000000000000000000000200000000100000000000000000000901c7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6770000000000000007f82000000000000000000000000000000000000000000000000000000000000000990086780000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00901c1b60007f820000000000000000000000000000000000000000000000000000000000000002900b7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0008901660295560006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7f2d48fef6d6dbc72cbd48b0915fa033ffa7d4a361118c537ed2d7edd66d78e7c96000527ffcdd0f1f8c09b3d29c80926527694e969a9ba25d383e3ba54aef34d24bd497cb6020527fe1d7cf96007291dd8c1eb2d1081963c991a1d6dea4658779516c6a7274017c806040527f66bdafcf782baea58cc2eb1141b2632df0d2f55926d787efa5412396958e25fb6060527fdf352be9237b127f7d05d548b7407b9c30207ade11fbd720718c9c5ee9d0fd376080526020600060a06000610100611916f4600055600051600155600060005260006020526000604052600060605260006080526020600060a060006001610100611c58f26002556000516003557f460591a824574b95cc69076bb607cef8d40a0c0b4c847c7dd99f0dbcb69615056000527f742e579fe0f7e725f6fdaed587cf572f5cb07e738dcb5c980e0e96bad4dda3536020527f5e824e64a8a098aead190a98c096eee9468efd48a851080108b8393dd5fe3c726040527f278fb56ae5fe76e5eb5a8a478d378e8eb6fc0a149ce9300f322cd7b91a6d4f1a6060527ff141171951bf218ff95ff9d70c99355db248dfc52db1d551a0a93b2b78c4df276080526020600060a060006001610100611989f26004556000516005557f48ec01c0e1871403bb3ca3a08fbcddadcc99a469e4a7305b81f23bc7b53193896000527f9925d5cf12ca591180ab2e8461dc882ef7e83de5b155e09a986576c23b2900de6020527f94b0e6be6afe4521f65b0d946074f1f23d5393ef2dd7da2978b0f2086a76ff2f6040527f78b4f1c71ad536b3d04db6fe5b6000e437359573fff6f11a3be9baeacba2cdfe6060527fd0859ce0e95ca9c4d981a67d181b08ada3884ae5cf6ec584d93d21c27ea2d8496080526020600060a060006001610100611c24f16006556000516007557f7e7405fe9def216c90e9e92b81e64defe43995d088898179e64c81573501ffc96000527f5feb47f2139e0858713da463e2d6e8e50248633757004714cd7720b3d7fe45bd6020527f604a2ffa598e68971c856cefd048c75305de2ad9549e9802830b4c0786e836906040527f7f57c80bc07f2580f08c7d1d69cfaed1c294761d9338c6f2ddb41fd86428ae266060527f129c44035429199b8f6e1d71295ab48df4b41f9bf0e566080908d293ce3d28736080526020600060a06000610100611cc0f46008556000516009557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fa8f7dbc25e8c7cca554fcf1f8d2ab12eb45bbc4fa90d51971281f4b413bcb9776060527f8dc09b13292575a077fb4629b0c3a3ba5fe7557de3c70246662d7be1fa768f3c6080526020600060a06000610100611c66f4600a55600051600b557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a0860005260006020527fd72bb6e19026029599b5f099d83684d02890bc6fc0cf8ac7ed234498516a43f86040527faace2731c2f9766302293f90947e01c4739475ed7f6e72f5ba57627c805423de6060527fb676d1036dab813d9fa8172cdd0b522309cac452e775f65bd7c10e3565bc1f9b6080526020600060a06000610100611a49fa600c55600051600d557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a0860005260006020527f5809acbfb7d1d265d77fad581f331327df9e2e1b8e09be2c60ffe6e1bd9ae7526040527f795acf93e6d163e6d1ffadd6cacd3744af8758c8142b2ef2b06a491cb517b3486060527f31c0407c043a0d3579017bdacf960b1be3d95235253045518f02b6afa9a4b0d56080526020600060a06000610100611b08f4600e55600051600f557f1f578153149420497e676cd6d5eced6ad7043396f1b476698d8982d5f82d51156000527f47a758179ab51312779d4529b0c4d24c59cd3c082ed5fa0024a52a2ee26ee8a46020527f068c672385b1a7d8730ccad44ea08f9bae8b8c48b15636ee8d218b2ef9a202db6040527f9823ae0e11e65fabb51477fc42c46bd9a8026bca26fe815a67a3c2f2133da64b6060527f16e38ad5ce001771fe1ee92e2ea2c17e158e8d26faf1967ba6b9726d93190f7b6080526020600060a060006000610100611b9df16010556000516011557fadd5246b8fe95262b5c92e34b66460e9fe6846fc80c0d0143ad0a7b36e6b71826000527f1f01817d03674644755b5302064fb4d951ead6492a12d1194ddda94d859fee836020527fd796ec850f4397801b66dbe752a4ec9d3cdc06c63f384b8db9cb393400dfa79c6040527f53bb06fb0a450f211e84d0d65a1bdaf5404dc24923bbab3874a17f833cdc31c66060527fd1db726c8e0dfa245af9fa7d9516999e05bfe7405e12b9c4d4b80f6278ba65006080526020600060a060006001610100611cb4f26012556000516013557f7e5f992155422239ce99f246ef28398cd19efd4945bdbcfd0906cf295f0acf9a6000527f23486150ca3798a368f956840331487ee7aae2b4c41bb3c5d06dde0bd5a8319d6020527f7262fc33081844bc6fe1324f77d816fab0596e0aa4a80911d5de1ec1065c3a966040527ff60b76f958d30c87f1f4cea06a0511e14cdcfff27f9ef7300380843e70f69a156060527fb5a22958693bdd0453d5c4c7dc392ba265a81b1a6ec356c7a0d71a2f1733933e6080526020600060a060006000610100611910f16014556000516015557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c99fa6016556000516017557f3dd166a0d3b1651ed856c109b45cc195a240a2fab23183accf87757b64d3b30f6000527f7c96ef833b5e75bd4d69819a6a13377ed249b800798e1f58fb48a3a47f0d04376020527f0285012e51e1ccd423b89be32135bc22bd266a3c66aa8e2a6d375a0a3edd93d56040527fddb9a2c3c25ff7fc7438521df5159d379cf4242e9d72c126a24deeace97d01406060527f0bd8aa57cadb8ec6ad4c294ac9fd5f2033f876b305b70da837a2e47759a83daa6080526020600060a06000610100611c70fa6018556000516019557fe723ca68f12a5176750652de172ea07516f031fc69df3e4d3f4db7991ec7f4956000527f1ea11655451f9fa1a6ebee3cf000d22d6feb8c82718cbb8ddb12dab77d1fe2256020527f5545cbac5769033d164c67144735e7fb4e5f5b778b89659318cbb40cce98fb366040527f9a8d1e5e35392b97f14359da3e744bcd711f673ffd7a101711876fcc329b4bfb6060527f8eb0802a3a39bd992fc1919de73ca1a41e627bd9d448ddd43df1a1ed9e13a3dd6080526020600060a06000610100611b0ef4601a55600051601b557f781f41bce25afe583069c7570abf9f17a52c59c73276dec66742b55a91a22c316000527f5276b48e3889087f1d05c469fcebb4b6acb88da49c7718fa3fe678a8e420627e6020527fa026f5b97a918119b4ef452550ec36faa0f2757c922c13e3aec9a82373219bcb6040527fca070f9cb46904d7e3cbf6dd138653fe8f1a1756d472d82ec6d5f7bb813a71226060527f8dac32f60ea0d00b8c67638175086178d77232c404736267b3021b5db6e72ba76080526020600060a0600060016101006119dcf2601c55600051601d557f28ecc5cfc546424311627c988e9cbe9c434fc5e2ceb5182ff18bb8485da8457d6000527f394f722770e2b9a2631399cc5916c8d1b6c87bf5a6f3138da5ec52137167a53f6020527f4fe27e8baffc4c94f1a803b14262c24588a41035455ef46ca2f68cbda15a32b96040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fa9a1d51ba3df24dbc7c9afb53437ca15d46d6dece751957fe2b24f87204a23bd6080526020600060a06000610100611bbcf4601e55600051601f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb5600052600960205260096040527f2f1a6ce97909c9947e8b05e181f97c0a0a4b142b7eec35215ba499d057ea23b96060527f157a3a06678067b0697843853539281f9caf2c41ec378bbaca088500748194db6080526020600060a0600060016101006119c3f16020556000516021557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006001610100611a37f16022556000516023557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ff7ffffffffbfffffffffffffffffefffffffffffffffffffffffffffffffffff6020527ff7ffffffffbfffffffffffffffffefffffffffffffffffffffffffffffffffff6040527f559d4c984a71993ba2299eedf7dbf226f692c1c329b899b4a29490e31f55cf326060527febf7a5aff69e762b1e871db04864e65e35e75995c68adca0154d1d925e93703e6080526020600060a060006000610100611931f16024556000516025557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6020527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6040527f8f7bbf81d570991c1dc5a300654032769d4a6dba81ee23e470bd7b6749b048d26060527f6fba636686ecf2906bb10decf2ea18ede20a5313a6bd2755b68e1c8eaba91c826080526020600060a06000610100611a5bf46026556000516027557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c13fa6028556000516029557f92dcf6a29fe268ccbfad7d1241b0d570b0490e793a871cbe3993d65f8c7631956000527fa69ce0f86c885b497070631c6763d1cc9b5a288b2c2a436f79e2816fb4b9526a6020527f7f125a6da806dd90960fec9d3a916e6b5b1e16fe518e5ce7fcae454b649dcf6a6040527f3f3c52730247cfb14ff4045b32ec699ca52cc02586a3b3db47f012772e7b53516060527fac7a5635ad3c1eb29393792efcb90c1908ce7ab9d80459a42dda216e912d65306080526020600060a060006001610100611a16f2602a55600051602b557fd0a6aae6c767f393aa8969e191293a4c502f4a7d9865373463dc8eaea20ae8866000527ff20b041a964c5e6a8a54e64e3a83e6c194317a88e88d5f0c99d03d4ed586e0b16020527f4e8f68a34e68a36828a90e7f7021495a5fd5555cc38e3cc394c1dca6b59017a66040527f2a6fa2088e0d26db96dc6ab441c3a60048ab953bd53a52c4fdf17e5239f2fe3b6060527faa09203b7edd9840fe7bfc098dfca22fb18aeffcce0179a252dc3528172e1fe26080526020600060a060006101006119f9fa602c55600051602d55600060005260006020526000604052600060605260006080526020600060a060006000610100611cc6f1602e55600051602f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f01000000000000000100000000000000010000000000000001000000000000006020527f01000000000000000100000000000000010000000000000001000000000000006040527f65c1110c0be74cb76965d2672cfaab66768f6273153b48499ab92620291661c96060527f28244fdb476e78a0ecb14370154db3a3cf0eab01383dd5996c52775760d448e46080526020600060a06000610100611c1afa603055600051603155600060005260006020526000604052600060605260006080526020600060a060006101006119a5fa603255600051603355",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xfade6018c180bd1cd998447d92b262af3473cfdbbd4c3b901b6f1b189c53e7fe",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x602f6000536038600153606f60025360e5600353607e600453608560055360cb6006536072600753608b600853604060006009600060bb60067f3e1f7155c0651aec04b04c5c8bc70f2c07a70c9372276c8b438cff34ea5b6e60f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xC4AA0D75736f14fb4971bBDe8CE49Fa1E25217bd": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x9327cce81f1cac3ff6a060f8ccd3b81f543fb0332849fa43c6c26683cadd52fd",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f0193f3b4d1bd34cc620b76788c1b0b7efa494a6a3b9b30afe63dcc0add0bf1286000527f7030eb85fc3a20e4208718167e80e0d80be0b29311eace6c92f4fb8466ddeefb6020527f52830b627d58510f8f2672ea2b9ac2b2deaadfc7a476774581844b2e6aa5c4a06040527fadc18db5ec80ce6f7ac02e7e823aca5ce50c0b6d80edf88cc50eb6ada1273b046060527fb5b6bbd639bc86335d476a042fe0760ab6a944f65e1c716602aeefb17f6329fd6080527f317ddc040b0dbe36d428cd49f9be1cb0e35527fef9bafb63f0604ac6fcdc5f6e60a0526040600060c06000600a7f9c2fc66c6fb11903613fd8b83c51568eb684932cae21637977215ab21c31f001f4600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x6000600052600060205260006040526000606052602060006080600060016194e3f46000556000516001557fcc931ae91d1ae57ee1ae991be2dc667e43cd1dc8ff19fc5ccec78bd4ebab19df6000527f9783a52c81da9f990d466b3a1e3f67197145f4c8a3696bb62611a66384fdf51d6020527f43c4bfa434bd3b91f5e79a1815c15fe2ac602508e4998fa6b283c280a415db926040527fd96c2b30519212ae3b0d24d7e96f2b1dccc96e5e928d6c62622534da108219b960605260206000608060006001600162014147f26002556000516003557fe0617947124e86583d06ccd8e934e8195ef7c763f8e784e16dbc8ee0bcb086666000527fa6d80bb7f4815e2722b9ca09e6f4512fa46ee459f5a28781f330dd12cff3961b60205260006040527fa4d8b749791a8539cb4af58f9b5243fed693d8e31d82da71abf56f6165c6b7f560605260206000608060006000600162017d5bf16004556000516005557f526a7959323beb89149c76522f91558f16cbcee030ddc8fa0b22f43a237eb2596000527f959e49aed0281ac6522e27bbc28d41281dcd3716d823e7c8cfbdf748730d271c6020527f4470f60814b8689866b44fe346006f0884e1f7c7f3a32a7d94ebd08d78d32ad16040527fffffa08a0b7881fd72c1693c3dae3852a0011d8af63aff4ddd92437a3b7a4b50606052602060006080600060016201488dfa6006556000516007557fcf96f626e87a60a687ea394b316955428eb10d42e1e4f4239698fd6c00d08cb36000527f5c1757376584c0674f7709621fa64a2078ea08000a18403b11664b70ca52d6026020527f21cce01d37a32278d253ca812f41c4c5c44e99eab20167aefade6a82ff28aa346040527f3499e9f20a655e68ff6aac3baf378aef196dfcf602498704643ebf1e17da55c6606052602060006080600060016110fdfa6008556000516009557fc2180a992da54ed7bcc3b66cc7ab15181a1986294c9675692459164f15cae08a6000527f65b49bc2356d42810531fa25681d2e5cddf2a23830f2721935ee942a794d601b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f90fa6156adc938830646bf56550d29a7ab6c07808d4c917fb907e327098e12e8606052602060006080600060016151f6f4600a55600051600b556000600052601b6020526001604052600160605260206000608060006001618beffa600c55600051600d5560006000526000602052600060405260006060526020600060806000600162015743fa600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f2286250ac79bbf13291e28d79da99adb427d9dcc5d9d210305cb8db7bc9e61fc6040527f7e22a7f0e2a324800b0cd4025aa51e3c32a13a6c60b468a214e9845a9b0527256060526020600060806000600161ec65f46010556000516011557f707c2c24eebf2dec569acbb9360b6059f29fdb785678db078d525d68197b41e96000527f872ba55696a0dfdd467dd9bb428da400c8a35ef846e497cb2b3427df6a304d1b60205260006040527f8936a997dcaae3ca6613577406824f2d9afc2b78599fc062df4198c02f14a103606052602060006080600060016121f5fa6012556000516013557f1741794b464ca914bfe3d72ab2166a284bab4512f1cf1ac5fa7585dbefa0d6d46000527f064a505fc85000dd0e064c7d38e3b3fcd61bdf4f5d44802afd3ff17ca78b101c6020527f6768b2f44970599cdc4d42de36d5ff39a10f1cd4fa0894f54bd06611aa24bf8a6040527fffff19f3d2af03a26a93a71940e0e74db00f903040c25e5b15519eac6fcd0f986060526020600060806000600162015b40fa6014556000516015557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fffd93fd2822906f26edbeba1bff10ed9aaaaa2d78eaa224433446639d341d13d6040527f422c26054c09af7cc00fcacd0bc46071b3c21726043dca5334fa9647288c7fba6060526020600060806000600162011c24fa6016556000516017557fa90ffaa963c65a3c654bf00cf6ac34f86c3a17f8029c05c5244b23d96b2916976000527fdfa7100ab09a5db4abcccbf45e6aa4a0be1d2dbc129cdc930280b985609c111b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f5a153b43cf49358856de90daf0d33fad42a42c6e5ab8a6c8cced6438af664a7f60605260206000608060006000600162013aa6f16018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2ab58abb36d14f8bc721eac991a26b8eb73efa3baddc31647d7da807ea3f6b146040527f5c66b60ffe1f3aae3f62a9c12a205d6b7d6c5ffe631d53a766b4bfea67f5573560605260206000608060006001600161e558f2601a55600051601b556000600052600060205260006040526000606052602060006080600060006001620184adf1601c55600051601d557fb908e0e234371730aeeb6793a86770a3e13390f5c8354db1d08c5a14c381aab06000527f724b9d656c076ecf5ccce4090b19986980e01c61fb74cd5f0a00f183f9772b1d6020527f61c243042f4c03a0292b98fda438efb44f6316d818b31e8821f09c5909474dee6040527fee36d3a720ff6f90c2ef947b206516a085da82674bd935afd7c6160c7d51c70960605260206000608060006001600161be54f1601e55600051601f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527ff2e8bf9a85882292bde75beda7bac92bc8a1325b9e28697699a7af4f415e913d6040527f560737dad06caf1302db510e5182e3986a6ab0798c04b7c55a1e88ad8b41f36e6060526020600060806000600160016133b7f26020556000516021557fc6212c3f5648d0e9a77343ccc80ce36daa100704ed7282871c2ccc629342a3826000527f549e53ba450f964ed2cb30b7eb094d3da8b53b9cef467661f81a0ffc4e5a3a1c6020527ff05e25052bab68bdb535c86e03a2fab5c8f8549c4b954551cfec37a7978f366d6040527fffff4f207c79659b7c1fda0afc2b8b775837677495a1c09bdf82620a5b35aeeb60605260206000608060006000600162013816f16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fc311f0f33ab412d1f6c16c80b672109e2f6f67add81efae206c3c7113a6144826040527f7d21de99c9ff97207312a5fdc060506fd6a1b5b01a3a404d77e4ac0314a5db576060526020600060806000600160016118c2f26024556000516025557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fceb2f025bf374596293fc0b0b5f4b8454cdf8ed8c69f00a5f1205c0b9c21a1f26040527f23dbf65535a35a8a20e5596fa4eb0672389c7f9679da632cbb6afa0ee049aa7860605260206000608060006001617c71fa6026556000516027556000600052601b6020526001604052600160605260206000608060006001617692fa60285560005160295560006000526000602052600060405260006060526020600060806000600161e2f6f4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f52b1f8b72565696f923a2a3c1c02884cf7715739d62da47be768787c5f6e4ea26040527f5ac903ceb935cdfb43b0456e4caea9ee634a7bdb7553a85d3f2d0673cc32fbf860605260206000608060006001613f13fa602c55600051602d557fcd3ab31c082129f8094b149405055f73cf34becb36f8dbb1a483ef9350a546d36000527fdc35f0f8f80bd27f84ce0f46ce2eda49694fe87e60398584a313db6ecbef5c1b60205260006040527f5decf45ca977b833255baa1326af0258c91ed3eb8e9d47b5fae45a9c19fdbba060605260206000608060006001600162015542f1602e55600051602f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fe0f55acbcebbfaffeea778fbd1f0651b2329d467759a5a20b528c940a7744f256040527f320b92b20a863ca1648ae7ed73f3b5a9350c78a5acba2bc82f9de2e6a6caa4716060526020600060806000600161c172fa603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x7f800000000000000000000000000000000000000000000000000000000000000069010000000000000000009007197ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe67ffffffffffffffff021660077f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a59003166036557d7676767676760000000000760000000000000056000000000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90116770000000000000006001677000000000000000087feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe68100000000000000000081d6037557ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb90057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006fdac7fff9ffd9e13226262626262626006f121212121212121212121212121212129009603855901c7d7676767676760000000000760000000000000056000000000000000000007f8000000000000000000000000000000000000000000000000000000000000002900360395563800000016000901b901d6f800000000000000000000000000000016f8000000000000000000000000000000090059014712000110000000d0a300e750a000000090a0a677000000000000000120163800000017fffffffffffffffff7effffff800000007effffff800000008000ff00000100000590176f121212121212121212121212121212127f8200000000000000000000000000000000000000000000000000000000000000110b677000000000000000684783921454358970527f80000000000000000000000000000000000000000000000000000000000000009009774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7f80000000000000000000000000000000000000000000000000000000000000026901000000000000000000900990087fffffffffffffffff7effffff800000007effffff800000008000ff0000010000686d5adef08547abf7eb1c603a557ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000067b368d219438b7f3f059012603b556a01000000000000000000007f40000000fd000000db00000000000000000000000000000000000000000000011760057f80000000000000000000000000000000000000000000000000000000000000029011126823232323232323232367ffffffffffffffff0a9017778000000000000000800000000000000080000000000000007702ffffffffffffffffffffffffffffffffff0000000300000505603c5567d02126262626262669010000000000000000009012603d556a10000000000000000000007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf990167f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001777effffff800000007effffff800000008000ff0000010000901c603e557f80000000000000000000000000000000000000000000000000000000000000026801fffffffffffffffe1c7f80000000000000000000000000000000000000000000000000000000000000017f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe900816077ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7a01090000000000000000000000000000000000000000000000000007603f55671fffffffffffffff6a10000000000000000000009013901d7f82000000000000000000000000000000000000000000000000000000000000006b0100000000000000000000001760006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000040": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000041": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000042": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000043": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000044": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000045": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000046": "0x000000000000000000000000000000000000000000000000000000000000000b"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2cc060ba5fe78470210f46455ffac3d00df319717eaa79d4593afa9062a57837",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556001496001556003496002554a6003556002600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x61018060005260206020526101806040527fc88bc00e3537574b69732b2a238d0126e3184313f737d07192139a447f56d7846060527fff6785753ee39984ecb7c9b84dc11b47fb781b88da28b6000d1b90235325fa606080527f616ff98d7ec4ff8502c4a86f709ed1a33b93c96da73d7a86be20636c3c75bee960a0527f7c7ca862cf1136b0f0171218255509196e9b8ddcc25109cb94602a88ddd46ea960c0527f8dcba5aefb18ed2c3e7cf3be3f39d83570fd524e00ab3d6cde1814ae51a4619260e0527f6bb3d76c05f73ba8cec9fd7ab35f6b5ddac7543ec6499dd66e5ce46ebf400811610100527f72699a293323eedcb8aed63f7c2d0c3c52ff40d9e806fa8570a5c9b988e35a5e610120527f3b3a032e24a3a4698ac5e059494b7e743a0e2bef3be48dd09d9bf9d77333235d610140527f54875e49a40d0ae2b81ffce06b2d68ade92272e9a21c94a5e8216c7203e1ee4c610160527fff3ecb58315b139cb07c5d93f439b2dfe4507c726a2c73c8c2234884f6b43262610180527f282ae62f4fefaf921b85b6f53bb4dada949167b3204e1673f6571046d7a6ab2a6101a0527f5d91178ce041f76cffeba58ba5a066ce9241e5d057819c097bedbf0fe2ff65606101c0527f8682ace22d5cafe24a2f58aa0eb97d825d40c0ac7c1887db376d161f582e95716101e0527fa90692dea0fcbd11600c0ded9ae428e70002b856db4baa70c981e521fa1cc536610200527ffdac109928200fa9e36aef37a751ee48870ca924f31263ae10005a79602c409a610220527f3e376542b55a21ab18a68af8a667360675b2151f12f5e3c99e8a752cfe8789aa610240527fd9900f9479d8d4e3f89dff1b4dba1ac05832d950dcd766873c9161220fbf8f21610260527fbbcaf4cf7f9c67a0705c5ea2c90c6a5dfb87fcab41cca51811966ceb30e3f76d610280527f7c71ae2db271bffe3fade5bc7111976f871bc5746a0b2f303b91ab2f9c1f651a6102a0527f582d401c25f461c28c30c79527b0091fecc7827c0614be2c554764138604e75b6102c0527fce97c8bac4249c6a637508446ba207b88aebc045620d3c9dbae6f0915bd865c26102e0527fe52c3e61df670e390fccf242c0cdd51e72c5c0410b8a1f5e73d69bca2c23627f610300527f7748ceee680bc41377a5692e7de9cc4867407fa4573faa8238fba994a3f42f12610320527fe0e1f522a003a43de6797d3f94ffef6919865113a9419e409290f38c6281e7c6610340527f97ee141220dcbb5fb338f60dba3eec7dc475c6e119333adc7a4afd1a386952e0610360526101806000610380600060056216c54cfa5a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a5561014051600b5561016051600c5560916000526103e160205260916040527f4b41fcf56e9c946f221b309933258452445555591de517a9d26f0d2a1b7c64016060527f808ea269768820a6dadabe52e6133f5bd510e1f70b00a53b9031774cc05af46b6080527f2ed65039bf4d7065e580fcb6a194637e2a8d07d938348bf4578df9844e1d146660a0527f5a67614ca53c1c119320c25af763316f78d9e6688946ee0784b00b8a803bb65460c0527fc6a8d6003b582da6bd7b1c84a15e8c43a4a75d1c151d36ebe3cb78139859c31260e0527fc1989579155f746b12ab9e4b483b4bc29866d83e683d65045e97e858957751a8610100527f23cf01a1b3b3bcf7ead3ec22e3b11c57e0936834f52474e889877ce3472506aa610120527fdf326bb9973addd5d70d7e40b3eb3e5118dba8ca848e08f9f55a84d6e7191a95610140527f64f0c5f152f6091ae72a50ca260323f5bf2b749e62ddcc6509663f0da5e6ea90610160527fcc7357dbde438cfb92eb3743bbb037da16aa7f44e14c6323b182c5de3f4ff188610180527f723a5d4e993d6f86a7c571e66adac53fa4bbc2dcd39947a29529dd2abfd9c75c6101a0527ff77cb4a60d4f5077f47d5cc2a99ed7cb8aeeee6d833de8cb9315ebcdd8bb32a86101c0527f759f01af36d502525fadb44f95066c7d115300a821d5c0db18f240f39f8c6eb26101e0527f6159732f3661df236710bfe60dd52e537b2703be72e05968781c7ec03ccabeb7610200527f5c9b851808d0b3849215278846a0a842bf2371cd003fe4d234713560dc2dcbc5610220527fd0210caaee72c4cafeac5ac7a9755c7cf0e62949c7bb69f2dd0def8dba3fec6e610240527ff5eb49654493600bc393b6b6f385b9513e4a0cd31412b08fa823d4401b9c55c6610260527f47c14f97fc0441f35445a943311fea3df2078b948229ff9a5d148e4558020e3f610280527fbe9d6d2a17318753f8adb7a6f7cac1ca07a456c835387cbf9cc3323bd0f83de26102a0527ff0575265a924887002e2e529ac61047909bcf3c576b83ee31bff3bf51d7adc956102c0527f9b080bcdb51091fa112a4b91064192330d9f7147acf8714da54cfeefbf82773b6102e0527fcc314277713bd0973ccef3db913dd38d1c0e6161d153c18a4afc9bf4d030502e610300527f154f005cf084d1aaedf71ea3e4df05d8b05b79a9e151071ceb50c39d84da78b8610320527f732b512522d4ca4f24f28e10872426408958a1c377356e3252364ec0488d36e7610340527f3c3090846254680cc9b483192b2c4870b3ab1776f50edfa98ce6ac9b04db7d3f610360527f83543676a190cad63ace2543b3063db4d7d865d81c155b77abba99cc9fa7215c610380527f7f3fe9056fc7c7d0f15f3f3c104535f6c4fc8933924160657f61646a5b7951c76103a0527fba17efe8c8ac88c63c9d12deac81dba0e3bf6663423ac7efa9f8da4c026d1bc06103c0527ff076d0cc7876097233b55072853059c5ff9776e862c9aa122346d2eaa182c3266103e0527f1fab28f57939024c7fc5e577fa2df7c34c60160fe9682bf64ad00f6e09a8daf0610400527fe6b9006b8be0626c3dceb0b5b319c14fc2d82be90cae680512995edcec093d30610420527f1da09d7671dd174e33437697541d05cb1cc29820ad59fa9b77ebe3d43f277fd3610440527f5e2c68b3ebca51422679c03e0bc3931a94ce4ca83bfe472d3661179b1a14b5d5610460527f1b011af773258ed38942bfc665962c227ea111ebbee3f7fb3d2cecdb82f3bd41610480527f303546afd8d878903066fff3419493884ff13cef00810dd261738ed9830f809a6104a0527ff298a2147d740c127c77726f4c7c32c073c7f1adc5ae6a25440a5fd0f740aeff6104c0527fee789daa860dca3e563238995adbf06c55064d6aa91ef3d721334cc272554f0e6104e0527fdbf41f32e8cdedc0930deb033f3d792bf0c0e4856c48f322c1a905e1022a1735610500527f5ca4f685f726f478922a225ffb97c3c52ccd2765b82552e56eeb73b5b081dc32610520527f87ab723d86e1167b5944ec34e727413f9cdab9783fdc856dc8ca2ecdcf1b5efc6105405260ec61056053608461056153600261056253609160006105636000600562c97aa2f45a01600d55600051600e55602051600f55604051601055606051601155608051601255605560005260ef60205260556040527fc794b2d8e2eaf072f7fef7d41ccd9915d7489b568d0aec5b331c5033092b5f5d6060527f6cf56ab9dfefcb156c3d2d3b2d98e82e5bcdfb49ed92e4489fa3717f709feb4b6080527f2b1cef471d90b89a969ba196bf62a9b0eaa02fb93b000000000000000000000060a0526b02000000000000000000000060c052600060e0526000610100526000610120526000610140526000610160526000610180527be1744d1fa7b3eb20d74c603d45de1a77e200b9368bbc81dcfba262a56101a0527f71ab2b1d08ea3e6be5a5c4ff7f294621e1f38fe76c2642fc6ae03ca909b5db406101c05260b66101e05360f96101e15360796101e25360326101e35360c16101e453604e6101e55360da6101e653606a6101e75360916101e85360c96101e95360ec6101ea5360de6101eb5360246101ec5360a36101ed5360f76101ee53607d6101ef5360896101f05360a06101f153604e6101f25360596101f35360b86101f45360db6101f55360d16101f653605d6101f75360e36101f853605560006101f96000600060056210c298f25a01601355600051601455602051601555604051601655",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x60000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0xe0000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x",
+ "from": "0x677B3ccc29f7c2293364fEec7F51907756f0124E",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0x0"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x01d389829e7c0e709e1989ec5305e8e731df7d9881b56e8a74b0a3ff6257c139",
+ "0x01ad0d7a10bd7f499e177998ee602ed0f57bffa973614c8412f178db3af2cab8",
+ "0x01400983c44bac7d4d6f52d98ce77eb2ea6935ad5938dc3cffbf3ebe5d7ad2c9",
+ "0x01fbccc493401424e414b91cec5d6c4bebdf8be74a8f818597a0ea97f9a69347",
+ "0x01bb6fff1f1c2f113286a6ca12c99baed80fc252499beacf63cab5e4d0dc0dfe",
+ "0x015369aaeb26bfdfb0eeecbdd298cc41ed5202adf8b0c997aba93a6d6d5f971c"
+ ],
+ "data": "0xb28f",
+ "from": "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x3df575b295e707c07dc1df",
+ "from": "0x91C6Dd1A685cAE33B044370252727B57f688e5c7",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x8b"
+ },
+ {
+ "data": "0xd4ce11f99d2bc3795165375c1c08364f5bfdc5f051857969990d67468d55ec7df0f8937ce6f8024a0e9c4a44a957eeefe0f5382fa9f30b0f567236f67a9db10e671c2758c3731c91a72261",
+ "from": "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x50"
+ },
+ {
+ "data": "0xa30735fdab09bb096ff451ad3d528f3307732d98c9874070c1a606c846fbcd8d8334532b56d8ba63234af9dd6c1f8f514395241fa19ecda6e195a24b3ad55e689e5ad800b0ac7406ae428d",
+ "from": "0x3fD261193d23d8a73a4fdfe7735892c6Ebb4f2Ac",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0xa4e5"
+ },
+ {
+ "data": "0x58b0f9739971e35ce10fee000eda2c1ed6ee9c0d253988fc965825e5935919840cf3fdbaa3f2274310d0006a3cd03514e790bc849f6f02467a08026835d916c636deb68b7ff2cf49295cfafa02a2b2bf743dceacd8a070070f0444d9ebc35151b4566a5239f2ef577d9fdaf29e951d5b3eac10282df33d7e6d1198ed63e5e1070480d045313411021984807664507f9eb29710e354a96f167ed5234de54d0250be5bedfe38182d3348c48d9c57d6681ce5c68875bbd9de06baeb369b0efec41164cfc2ab8bc2220fdba8f29c5ece41648a537466166e411352d5cf02428852026e8e64ea60605467fd463ff4346872cfee0300083f5cfcdb50a93a33396fb4895bd6bac23656dbab2ad22fcd3754730913dbfb7e8f828c72d21bcd05245117c69519275804de80667cde09f0b2cb4ef6e7cfe7076efc78734c08336016fd36d04e79ca6f0a8e7f0dc486557b883092203358e76999a92e83",
+ "from": "0x677B3ccc29f7c2293364fEec7F51907756f0124E",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0x263651"
+ },
+ {
+ "data": "0x4a99b4",
+ "from": "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0xc"
+ },
+ {
+ "data": "0x",
+ "from": "0x91C6Dd1A685cAE33B044370252727B57f688e5c7",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x0"
+ },
+ {
+ "data": "0x3e",
+ "from": "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x0"
+ },
+ {
+ "data": "0xcaf367a2c043521580bf2ded9a8e1b0b8ff4c77e9109ad4a78b35e6df5ec8a93af16705a1ff1740b05bf2b2d08eefcbf53b54ec3b6bfe1cb842f0f0e249d6cb6bcfd6fafd83b55ec40b1bdf17f62917ea408fcc4a3800a2e",
+ "from": "0x3fD261193d23d8a73a4fdfe7735892c6Ebb4f2Ac",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0xfb285d"
+ },
+ {
+ "data": "0xbe89f155f782357bf7038a34b224dd184c0045a929d8edd5fea33ffb3131a832686096521b6bce6d74d53fd9e907c442975a094a7cca03f2c9f4fc6af7724a80e7",
+ "from": "0x677B3ccc29f7c2293364fEec7F51907756f0124E",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0xb6918e"
+ },
+ {
+ "data": "0x2c9c0082bbe5e68dfc726e41fab672674cb60b19ec0aaacd2efe958cb1c08b8ede492c702a99ef5acd704e55ace7aca4f209c59f9151e04405d4a396fc05e50c97d125878775dee202f269a9e038ceee92aa5ed607a8b0462afe",
+ "from": "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0x9ca7e9"
+ },
+ {
+ "data": "0x5d3a30b3be577899e7e228d7ae0561981cd3e887",
+ "from": "0x91C6Dd1A685cAE33B044370252727B57f688e5c7",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0x0"
+ },
+ {
+ "data": "0x44cf53c635525fc3",
+ "from": "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0x0"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x000000000000000000000000000000000000000d",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xbfe7211c0c349339a3e3634ad737c2d33e232f89fb39d664d328afd5ea2603d4",
+ "s": "0x6b1d940a4be6b4b75d4b285ebfc1f63b599d780ea66348d3210522d155cc7716",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f2",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x44aef284b3b8fb0360a3550efdf9e4876503da8a3f0b14f56d27ff1d2f1e6a72",
+ "s": "0x2ce2b6ff7121d90053f7f56595f335d6e5bcd1e55b075ec10e0bc04e97650ccb",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000007",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xeef59efbbb9cc6b8bcca0384ddaf3ae96bc7e761ed0ff13d48ed531251a32a56",
+ "s": "0x1d270521363ccd1bbb726f908d863acfde6dcff0347885d3e6df7dc786415d39",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000007",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xe8c243c5128186444a344b011d78b24cbe52e9bffb3bf4959b986834d93214d3",
+ "s": "0x3c629a82eebf4be563712ec562627be11e9d50b2cf1e6dab4aa4dde638e29ce8",
+ "v": "0x1"
+ }
+ ],
+ "data": "0x3115c7839ee8f609514b277b51b9f9f190d191513422a143d5186d5c4dea9bda8b4f13a9592dfc025773fc03ca013c",
+ "from": "0xC4AA0D75736f14fb4971bBDe8CE49Fa1E25217bd",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB",
+ "type": "0x4",
+ "value": "0x0"
+ },
+ {
+ "data": "0x00",
+ "from": "0x48Ed5D2f29e6CF27031A62C9e4826d56B4536a36",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000d",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xdafdcae05424d2ae0fa456ad45e0707710e5e4e3c7b1af8f5997f8a464477a5e",
+ "s": "0x20eb4f7e18471a0060ebcc24066b256591e6f5a6d5b5b9adff14d3c9fe41ae96",
+ "v": "0x1"
+ }
+ ],
+ "data": "0x3115c7839ee8f609514b277b51b9f9f190d191513422a143d5186d5c4dea9bda8b4f13a9592dfc025773fc03ca013c",
+ "from": "0x1028f1F4b946800E1b6D7528C4699Cc3df844fBf",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB",
+ "type": "0x4",
+ "value": "0x0"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_smallest.json b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_smallest.json
new file mode 100644
index 0000000000..2825bec976
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/examples/comprehensive_smallest.json
@@ -0,0 +1,444 @@
+{
+ "accounts": {
+ "0x0000000000000000000000000000000000000010": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x00000000000000000000000000000000000000f6": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f06fcff69196a393d4ca702feba344df26000527fe442438ab1b839640ec7742d77053df806abed423ae6a498dc093103382749206020526f022f0c5673eddb443409f509edcab2aa6040527f9abe26305ddce240cddb9d26556bd4b9555e14d029eb88a867702b43c75375e46060526f151a683af814b7b843ef0914d5b656966080527fc6f0e3c21eacda1ed058c181dea5c54edecefe3c22d09f1b70fc504ccee0270760a0526f10fe871f92678911745d6a5791dd721460c0527fb0cf887504450cbe272528c86a6fcc368b036f7627f2b503147e788dd92fb2d860e05260806000610100600060e5600b7fad00de6676d949b2879235fbfb19b0f975c79dde8b90f395b4b322156e4b0a76f26000556000516001556020516002556040516003556060516004556f1430217071dcf4a05f9b69af6dedba006000527f47092bf14ec9d7f19ff07c710fd652c2bf72945a93b820b4d80b594801db4cec6020526f169208513a417a1e8e61bec2838a72a36040527f950dc6303e7d9b6735f1883b2d10a7219bd467187bfcbb6da18eafb8f78d3ab76060527fb2d7154982a36a940a4a09c6533e417af13231e08b223f9f07c3e7a537fa0a7c6080526080600060a0600060ff600c7f6be1e0cef74f639ff740aa84eb986d22098505fac3c26e495d8bb5e4388908fff16005556000516006556020516007556040516008556060516009556f02780635f54e105d88e2940d22d4d2f36000527fd8e8a4208f388a09b5dcd814920701343f527374169559101e60fcd4f636b0416020526f0de0e61d06d1a9cd1a6033acecd196516040527fbbf9aa91fe99f07b86314ce0c4773f41664bf03ceff26a5b3bbc11046b7426336060526f0ce031599c822d4cda00bba3b0621fd76080527fe9c08c8aecc9facb8d88e18dab0335adca4950d09292316b3c375540100d49d360a0526f104fbff0ad9fc644bb6bd13b6ace02e460c0527f96d62ee342495614596f56fe5ddc10a5bb1f162797396b9d75f1d840c8a79ad960e0526f07007d1fe6363f7bad8fe120e3c68a44610100527f7c92ee323f405f938e2e02484c62f2facbfc43cb0d28ff3f16178bd0fcaec335610120526f13768ffdcdf366e9ee63cc23475e8595610140527f26a575e5544f22c3e064dac3d495eb6b2b594fe846073026db1695ffed066018610160526f147ce84581777751a3704f7d43b119ae610180527f6aa4376abd93d8112f31876e7b337350b6a17946adc9616877967cee76d974a76101a0526f1198913a5b19ba3457b36d25d593fbf56101c0527f752b3ed53a63bb73c4ddefe4082933e93a0103780b21db8980c117f10637e9c66101e05261010060006102006000600d7f4a1b51e507433a9bd45b51429637710682598c3a5087b26ea136ee017aa52e44fa600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556e4f08014da76e7b1aa3302e2241f8736000527f8d10abc569925647915ebb5ab88486679288a9dbbf5f481f182da264ab34a4bd6020526f06d5881b1e939fc02875eae54bd32f2e6040527faaea60b13abe552a5d5350d84df14cbff41bc4bfac9e9e503df34f79993387fc6060526f0216413b0addfbb5ca4ae26c9bf45ebf6080527f86fb951e8d918cd399777392ae695a393f9411394a71295409713785105fdc9460a0526f126cdd8c9ebc88a54fa5539c5902074060c0527f6fc52da24a2337cf2fca7d6e2fee1a27a029a0ab80479d64152789fdc1465f4260e0527faa80d757ada2ee24f6fbe189479805f7061b1186cb063a550bb96d88fa418b11610100526f0c243dfde08ddddfa8949c2ecee26f14610120527f0cf1870266b91b5dad84ae43af0c6c02fa3f81f8245e5074af73afb381e48d2a610140526f124d3efb3d621c83c682e1759fbeff13610160527f87ac0dce1bd0ef742565c79c2d84f58a99ce3c1334dbdf1adbb87d9b317add3a610180526f1549d53c5544278fef820b936a0b9da56101a0527f1f765ca450e5cf7f5e1ea309d3db585d9f1fc47ec6fbceea63e9c31ae58bcfab6101c0526f0ac911e323fddc70e0dd973ec59da7526101e0527f66b33b62e4769dcc3f2173d8b4e6c207a1511c40b9e337f8b04dbf08c7e68df5610200527fa94a87066f4ae7ceca92defa2fb336767cf1ee575035d3a3a462b8adddd262056102205261010060006102406000600e7f93d23edbd187f33f27c1739cac18e93f6cd1bfc5c81828a1b3cb4814a00285bafa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f0745441fdbad4dc5a236412bf6ea07b26000527f207d89aea5a9a925d32b8007ea0c44c6e88a06fe3dc88ef32801cb9873b65b2e6020526f13402186bb791b3ee693abcbe0dee89c6040527f36e4ef4ad8c6abea65d3fd94f43fee9d40d65edf597dd2de64a8fd647f1e0ede6060526f043d2a388ccf087d3ca888a2d72d51466080527f0e1c0926a3e74772c807ed86d32169540c7de35b90db097f020ec825f81a5e9f60a0526f0d3bd03f6ec3dceed892b4cbed1a047160c0527fb8ea4b0f0e3c14bc6540f327571a1dc7245387434c6260ea8545c3a3f43f52ae60e0526f053e1e81dc8a4f0d68d0a0c23e2603c8610100527f65a9b0a2444d15e77339587e109f20caa38c7352304baadb57925cb4713e760e610120526f02abce8b992a833ecafddd3218eae49c610140527ff73bb4507c7fd63d1eaa6c29887203b04d95ea0b44c7d13c6b4ecb8533234bb0610160526e3aa8288491bd367dea58c58c500c9d610180527fc213d583c73602aa92808cb213aed86247865a978709cc5371970b15b9ad527c6101a0526f0fcd23237589ff2f23073c8417f31be16101c0527fa1634d060e1bcf6efe039ef5a11a41d90bbb05c22a595ce63103fe08960464d66101e0526f0711b1af2d891054dd6f374d2465e7e1610200527fa2c46d4e6b6235f105cd0ebfbd0293057ed0c38a4fe43d86d90eac8adcbd6b58610220526f16253bf3d1b7aba9a88abff5fd797e42610240527facd45ad966cae5da033fba84d2b954b265f9aabfcdde8ff90242beadccf09a2c610260526f19b6a239f990178d2a5f5ec618d1bb40610280527f53280e61e0bd7199af0108355ea94099ab1b61b3616d70d87c5e8c5c720ddc886102a0526f0c7f8411a266d2c99fd03f900fa0a8906102c0527f70f9b3c407c52fe2dd8965b56db2381a7d10ce2e93f52cc51d420fbd11ee13e76102e0526f10fc7f5161a560db1d3167f858f43bff610300527ff474f46440009367463cb9b447e03db4fa8e1c79a414e79e6270e6637f116d80610320526f07bc163101bc29f18e42064275adec4c610340527f5e7bfd20d8eb12d3e5d1cbfbfc15bce7a24f1eff82f8206979980ac56b0fbad0610360526f024aa2b2f08f0a91260805272dc51051610380527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86103a0526f13e02b6052719f607dacd3a088274f656103c0527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6103e0526f0ce5d527727d6e118cc9cdc6da2e351a610400527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801610420526f0606c4a02ea734cc32acd2b02bc28b99610440527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be61046052602060006104806000600f7f25e0a9449d9aa98ab896355983bd0dca54badbfe493862625ea8cabf7caf79d2f4601c55600051601d556f0dee3561b6f871f4550f22e15c3768796000527f2921b8637f9982d39db18d2d3999a8f6067fe7e48f56f3ea4e21def7679afd226020526080600060406000603060107f9d94c372e3e4486685ee8485a7486537efef6ef03d31f110b4d9756aa40fe142f2601e55600051601f556020516020556040516021556060516022556f0916c557668c9c2db6a6b6869d92d80a6000527f53efcc2a81d2672df3b335817985c423e104ef4e228c5402823930a8ffab490b6020526f12793c650781ed6cf7c127628edf18eb6040527f50ae0145e33bdddd7150b6834b309712248a3e91d2b629ed7955af38864c3a2560605261010060006080600060117f66602b2002036afe8d1f22e7a4028da230c39328019419cc67bef352f4e833adfa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x609d606660e560af60d3602560b3690b483c7050464a301c02315b3da461503a6e569c5f7d756717647d711c73303974760817747057567d035548030342816c7e35587f9c5e59f15a620a8d684805768f58909e6b107f716c167e454407688974805245698d12415e420b7c563d95876a161b74479355685451706c50165a748917324117306c156d7314048c6350731837f3fa44167f597873f46d527e7a403d01068407019f13019b191c34891004701604128c590b907309656319817e7d343d47860318677a5f68a47457151a543781faa170751d395779fef06e37193e5d11045b3e4a63618085845b547a1d1a365d615a613210f5835c5f7a915258630b345d806a9c821bf1339651755d201384f04136348604395a575f786141683d7755137b5b6612645d63883dfe6658fe14937f5d147a656f706554021e6ef38b855a44484a947a99417333053d67753b6e67a03494193f19483362503f4443783920075a5381010404a2611e349f39321335763f9a6e983670f0785c9776517558805f419914086d5c09545b80f43b439535803d515c95376d058b86f41a334530746135025f3942f187869e6a035250006f07117a8c1d399895165849fd569337a25263f05c51a06b0430771e8317881a8f5d9c0631603537588066774537017e98646b9781a07c5bfe695180f15c469e511a4451486e107d030a6a3d60593c633736f16d3867666577471d430b32063864648186165f16f533516c0407077f61711c389d9c681ea480574045367967841b41075a76636e1a484908311112176a8a3b841a66496168755c027b6888050af58933f015895e1375340143567f37743b5085904a6277474a19337b33816a3b7441411392435783497f423d10816f797253729c6a085a05803051f5324109855e108c5a3a736537618a7a7f7b755c3b3d1e517cf37105708b806b143e686e7c6755416a9f778044542055406605766b018e731e6f5d603116303b466c78753e40127a846a731783a16c3e177b545b096d0359450b9a171e31525bf0447502776c9e5566108803973a805b5c41436570840a587cf1867e3d7f1e3b31713f775c917858951b4a5b6c669e75737665736460867c6a421a16060341f05b6c5254075d793e090a05891e493068388b94677605016d5d9f5e0b3a080a891c6d187cfd1483988f953779f5569169f47a3c528156189d41138f605238037d6c796a65789f5133f36e1a828b615975929979626da0757030911581858d11143a3b6a4066095257a4453c0795fe6d6d5a6662125c601091553c4613390b0614656f9a6bf20b65435705041773fe446761876e5a5219431d333e5544f08f19453e9808455735a17252019377073e613f52587a5640387a9541127b0219368c539061630a684a77f4543035611e9c17863b54305a",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x23957dB27fD43F125fee8eB0a2Be85F1FC39Fa74": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2d16ef33a23df66bb3a4c85e596df85ef7c524808ae7eeea57475353676882fb",
+ "storage": {}
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x600054507f1bc37322bd8795aa5c0d765bb9d786a2c2ef34a695ec27232ea0ed8509cba6986000527fa18a0ad7e91a1cba90a04235dfbda77cf0549c58790669e09f88b509d33815096020527f63b6f74c4a5c6cb40ae6de0408689fcbc400291b3da160ed5a4e975415305f8e6040527f8108b2ecdb883a794c1152e92632e0a64f6a8a5d55bd29b90f7d51b3a4953f976060527f581e32c2704f32e72cd7e6ad7cb1071b92f237895e588adc7ab993aedfe2afd36080527f5aa1c972ecb9eb74528c16d451c9aa9ca317df0a4450636b4034468d39d36bb960a0527fde65e94ef04338d6ce09ac96d0ff2ec58982a6d1bf305ae6c855276fcceaf0b460c0527f8d43c21ac3785bb7cca350d44fdbe19966227e30c6b16bae02fc147c57ef402460e0527f8437286b7c84a04fdabf6afe1e0875d72be8d4fde1a3d4051478b1b20b3206ac610100527fb1a464581de2466781a0c72f1dcc93b941760f217e5a88aff6763dd525ea59f3610120527f8309b7732f9ccb14f135e34091a095196abc4dd8c3dc7bf32aa78b67afce944b610140527f52ed661a19b5c516db7c24a0782956e725fa01b61f9c8fdf9d92d0bb258d98b0610160527f92aa99ffdb4a178eb0f265d347b9358d0c2fb2fc72e0ffe189275942c409343b610180527f887bf88b7bf9d2f1da02e89e11790f03fc3a6f45cef57aedfba36a79273322906101a0527fada6af26406987cf79280e837f83cb9cdd89d26806ae700e62fd603e30283f366101c0527f2ddfb3f5e3bafa1910e8e57c7c3d45fef5024c8d298309640fdd6d771eedb7586101e052604060006102006000606a60077fd2a2dc91b7adfff42174a98e0770f27dbde9545997a551e20b2824a74bcf7708f1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a"
+ }
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7f063b9d3462f2d80599492ec1750090cfb49edd47f3bef1a1d5957a77033f9d3d6000527ff849a2ffa8a3461a482f3a22613ed0bf62a0ffb9bd07ae10c23eccb926f837cd6020527e684149fb4557de661e5a06f306db0ef1a74ea674d299798a296735cbeeaeb96040527f585531de2fe977bf410e4b688e209d146281c4e3462321851ed413b2a0686f306060527f5f1b5a92ce191927ef8a99675520ad450f127080f9b344ab13bb64eb1f92c83e6080527fb42fb286f11a883b5b335e5ef2d5477569aa8a4d8430496d2d5109c40d6436ce60a0527f075e55f44883857cac5e60f122e4d3c635b99507a3a06941c0cab3564984bd8660c0527f4d35d25f52d6ca0bc2f7ab9b9b39b14e646e9e45e333bab86231e6d3dd923c8260e0527f337fc2b6a185f66f133b7f02d43de1c294e96db2bd41b446d367c9cd93f888b0610100527f65aa838654bb90480d83fa2e3077ff6054cdc5f35e5758c74769f5cd642cd643610120527fe852da9bae2aba92623982d69a62052d0de78a796ee1f0079fdf3eef27645b87610140527f583309beb4dece1ca64314d7119a948bd0bd9250a16aa2a367a080aa5c96ec3d610160527f742878009f403251a96de70c5813de6710ee4036b04b589ea5354778cd843650610180527f1cb588dae2ed495d5025e814a1cfe05f629abf0a7e89ffd6f70158219a42c04f6101a0527f1aaea7750e284228ac6dd044545a90ab4f063bb266721afb0503d980a4762ee16101c052602060006101e0600060886101007f47d7e060bd3dd5829e781863df7b5ac9b170d37543f1740059c8e0d89eaa5a4ef2600055600051600155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x60005160016060f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x7f0ba0370907b7d6bcf961e381f77377af06df0572990c889c82b7c74f1e90f8de6000527f9826a8d0a9e3d00cb36c029caffaac161013bada23a90db9e8c9094de47cfa3c6020527f3c377edc4581270e7bfe23963fde77a95dce4e1958f673e76ecd1002488df8cc6040527f92ab51e33a39f0d13d88d8289ab18894b3ac7c2ea89a5bff9def6250dea461106060527f93c199a032e468ec45dd11b7827ea994289c6ac47c45f3dfb3f54c987255c3bf6080527f4d562b0308a2434ff7868a0702561923970abad32ac03f5a58ca902b7ded758160a0527fc584e1ac59d9d6416adc32d759f72e78ce7cdfad0128b477f96924147f66cb4b60c0527ffbb8d840baf881780dad88f8243aa46ca65214725bb4da5dd82242513fca909560e0527fb7f9b70fc4f2a0809a524d3fe329bd25015b1b5bff94225815eff18acc2ab46e610100527f5a3ce6d41a8eaeebab2d0fb1c78741ec5749b1fb23fdbfd2ee37d9e3a115527c610120527f28171e9dfa097d3e025060a1a7dce9eeeccb0562450a5f0fbbc8637302ca40e9610140527fb35e30b4c8f5070eb1120979c1a82336118624c8138e2ca026a0dd0ecd531b32610160527feaf23bed9d70590d96e25b2f9c1dcccb04e0cb94221e6728bb8c1f250ec744af610180527f1c2e979f28cdc255c646859306139ea4111fce459c056b760439ce2cf68b18a26101a0527f463df923aadb23509b5a813bccee78cc68873d42ed8712225341f89f4972b3ae6101c052604060006101e06000600e7f51c346e9c8ee8b23f64efc42ce303b46b7a555d3ec49a8f2922c3bc20740a256f4600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000c",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7d02886c65c9baacdc167c99d8d4b203ca59c9c5eaac2647906bb8c5619ba96000527f7d653106964d182963c381adc6ef7caa35be72a76cf8837e854e28ebc20b67f06020527f5844d18a6ce56f0d2e63c6cdcc1f27f51e936bf6190ca2ad94718d29e5f0db1d6040527f44d2715a6b6e3a3df172f36ce09cdca3a48a1b5e5ff40de302f3895fd32a734a6060527fbbec99a8077daa3775d4e1e47a920a5a9035f1bde0378b33b70becb47af43c8a6080527f956302c42f2686070942a30c4a27d37d7fab7a1dc94194d2b8fe80ac7fc0b70d60a052606a60c05360c860c153600060c253601960c35360dd60c45360b060c553602760c653600060c753601b60c853604a60c953605360ca5360f660cb53602460cc5360cc60cd53609060ce5360f760cf53604860d053602960d15360f160d253604f60d353600060d4536040600060d5600060097f2c798e304e82a8acba8a9b9936ffa652a6ef6a118272cd1f71c32c61d15ce085fa600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x8b632B705a6Ab4ee30e08eD21A0AEE1C3b6583B8": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45d548a69d16dbb51608188756e9b4e2125431bfc7c8900afd1cd15a45df5689",
+ "storage": {}
+ },
+ "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x3af15a0aa381091abf31af1f4363ccda85c9e17ea76d6743a55cb18ef1aca326",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x60017f77676767676760000000000000001002e000000000000040000000e0000000009007197e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007e1f00000000000000000000000000000020000000010000000000000000000004900763800000007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10001b90186fdac7fff9ffd9e13226262626262626007176767676767676767600000076767676767602077f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7effffff8000000000000000000000000000000000000000d900000000000001901b177ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000777effffff800000007effffff800000008000ff0000010000901d106b010000000000000000000000712000110000000d0a300e750a000000090a0a901c076f800000000000000100000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d310116101117f62d8fffffffffffffffffffffffffffffc18000000000000000000ca0000000110901c760fffc000000000000767676240000000000002b05760477e1f0000000000000000000000000000002000000001000000000000000000000b901867800000000000000060051d90066a10000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0004901d7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007e40000000fd000000db0000000000000000000040000000fd000000db000001901a6000557f7effffff8000000000000000000000000000000000000000d9000000000000016b100000000000000000000000186001556005600103600255712000110000000d0a300e750a000000090a0a6000901214197f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56b10000000000000000000000012600355637fffffff6801fffffffffffffffe9017187f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f40000000fd000000db0000000000000000000000000000000000000000000001111476013590cab83b779e708b533b0eef3561483ddeefc841f5678000000000000000901390117f80000000000000000000000000000000000000000000000000000000000000027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0081590126004557f40000000fd000000db0000000000000000000000000000000000000000000001157f7effffff8000000000000000000000000000000000000000d9000000000000017d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9901c900267800000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f590057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007e1f00000000000000000000000000000020000000010000000000000000000067b368d219438b7f3f0902901367fffffffffffffffe6b010000000000000000000000046005557fffffffffffffffff7effffff800000007effffff800000008000ff0000010000682323232323232323239013901460006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7f1ad252f41f24a4e47e3b30cd077e62ec5e97a21593b08ecf63ad797c845aa7b86000527f6fbc7de1246b5c82e32038eef1c50b793f80ff9ffd5d94ba0201758921e895756020527fe96280d9bf66a984d8429554eeee5d66f13b77754eea60b5914cb1c70d88da1c6040527f8aaf6944e59f427beb0d6335a9403e372a2a8db59ee99e352b7db426f88ba8c46060527ffdd5139e421a516cc016174ae8fe299812e0afcd0dea30757f1f68d1d5b3b7396080526020600060a060006000610100611ce3f1600055600051600155600060005260006020526000604052600060605260006080526020600060a06000610100611b56f46002556000516003557f03c5e492839c5c2a6b19faa426486d273e5df7df0532a9f9d383c91cd9bbf7936000527f20e0282db9e31ae6b468087fcf52aa711f00a9dbf73b175409070c9ae273822c6020527fe447e297c6692bf0e8e2cb8d719eeb6f9f5ea25df880fc9905033106d25d318e6040527f09815f1b92071b6bb2fd09dbca9fa959781493ac972d9589fab850a11a088ae26060527f4ad5492f2514adec949add6efa491707a9e123aad36c8765c6ffa0e2cb17d27c6080526020600060a060006001610100611aabf26004556000516005557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f61ed34369e8bae5efec15bc2180448deb0300cf1b070a5a26a46011a920110216020527f61ed34369e8bae5efec15bc2180448deb0300cf1b070a5a26a46011a920110216040527fffffffff000000010000000000000000000000010000000000000000000000546060527fffffffff000000010000000000000000000000010000000000000000000000546080526020600060a060006001610100611ac0f2600655600051600755600060005260006020526000604052600060605260006080526020600060a060006001610100611ce5f26008556000516009557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527f73a36436fa98c0fc51a987b95addff4fc9c75bb81bebe4de704dff46e505fb576060527f38e1d909e72e3aa17fbaae010c05f983cf22bc32e8185e753dfaea1ad1ab90ef6080526020600060a06000600161010061197af2600a55600051600b557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6020527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6040527f33564af2e42df9370e250b21edd1008473a5b1949296e746d3748b2bc41003c06060527f5b9c6cf0c4700189db47f7b04d8797e0e081455ddc17dc4a138bfe67932356186080526020600060a0600061010061197ffa600c55600051600d557f8d4159e7e3803d936acee7d4612c733ac930b2fb51f6174ac35de8f39ee534036000527f9f6469e303a270c1cf5086bdb94ffa1302bdcba38e064aa3ec68172b6cdd81a66020527fe5370d64927b00b5108dd7dca14a43ba347ef449ddb21817a3c11a8bed8088436040527f45522722aa893c41562916d31cc615d400da709ef10584642286833ce28ef7cb6060527ff2ffbe167212bf8d3259f185ace7398c2ac93afef5afb18d6b54adfcbc6f42116080526020600060a06000610100611c0efa600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611c52f26010556000516011557f1171c00fee29e1938e2a6b6f34e9197442dd80d7199a6c10d35237168f36c3506000527fc2402ac2e231e03da69f462f2e5e6be072787a8991672df9ff14679bdd0700ec6020527f63a862c6560c083a6d23336744366d42c66ca9a4b4190cc5d71eb3b666ebdbad6040527fd05f4d1319607b3d6b7a3312a68dd20f137cde4cae15d980c17633597984ef086060527fc325a6b95842461aa3b5c3498d64193ed54e02f57f0be0537242a66a68b5ab646080526020600060a060006000610100611a4bf16012556000516013557fbda6b6b71c43a35a2143ed305ef881ff6517885a2b2bdb3f552af2367f692a846000527f76db0519ff4b38d2dc0d66547b4108b9048cf323d4dd0eb0abcd6fb83e21b56f6020527f204ca45c158b1eccdb890e200e477755770d4b8f1e3b8a36cb8a7357befb64f36040527f457db2bda9a5ca9b5593e485b1f4bfd82dd3a951c4b63b517151fe491589afa16060527f7b14407d90693d5b3e7b7b7cb0b64d372190d7a66ae8b0b513355c330717923f6080526020600060a06000610100611a12f46014556000516015557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006000610100611cdef26016556000516017557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fcd3fc77ee4012b5c4a1b53c5505eb714ee8ed5cd87dd8b73eb6f0d49dcaf4e7c6060527fbc3dc47c6bd4ef0ef3884db62acd5869593b03b899a242f1c6d7cb9735da242d6080526020600060a060006101006119b2f46018556000516019557ffc4aa970a0e7b17c095b40b850ceded317761a1a16147e214ccaa96d9ee14f266000527fcb00f4ebd745a67a7c4a55a4bef1454967bd2de0d81c83c834c6731e8e317b126020527f972603641d77617c5b93acf08c51db4c7b4422d0819ff38df9cc3d0c21e949636040527f882de2caeb49647cab0bcc63f06360c7f8b0ebb146e7cf9d6eaf103f65c825c56060527ff286e0e711e69166f764ddc113afa12d7161be84a40f80c0e6089b96c606f3526080526020600060a06000610100611c87f4601a55600051601b557f6d6682250096f33214278016bb1b507795293e4e0dd283f3ab83b795c4a9bd396000527fe100ec27eb368f3463b3a786e77984d1acf9840e4e092fac95b0a34a588a55de6020527f770fe499ff9ece0cd34a38b1b0689749b64e3f5cac291131ac7da89609b182b76040527f4bb791d72d7eb44f291d53f70d52231fd15f5bb4870e21b0c4f6b67c314ea2716060527f0960e09df623eaf10d78118c9a145cf266d44c838c02fbf28b223593b9c7baba6080526020600060a060006101006119c1fa601c55600051601d55600060005260006020526000604052600060605260006080526020600060a0600061010061196ffa601e55600051601f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611bd2f46020556000516021557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fd2afb235f5597e2aee0408594b854a67f0e4975710114a3f5496ef4d96f9b5006060527f75c614dd29c2c3803c76e5a6de4c63139668f8e380a4ffb98fe2e1a6654a9e786080526020600060a06000610100611ce0f46022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b91fa6024556000516025557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f89c6d5fdbbaa7c407fa80fb9cdac80a029fcb4f8ee2304f1312ecccdbb1e41ea6060527fca4ecc2889086480a754452c08cec711cd805c63200655f021bc418da89eb71b6080526020600060a06000610100611b48fa6026556000516027557f8e9dc16c462acf426681e70f761fea49dfef131264f9b0669577fcfdd70f2ba76000527f751dfbc62bd426e8511df1a12bbac73d5de7dedea04fd75cac1a59e948b323ae6020527f5414ab14f228830c07a2c7ce94922fa4c78a43bd7a45d74f15fee7d8836211536040527f175d1de0e00e6f26f7b487d3ffaf8fff9fc6df7839dae9e6e70c708fb692bbf76060527f86c7248ef0667b8977a8bd67594ae4dcd371541d2091567f7d84a7d4bb99b9266080526020600060a06000600061010061197af16028556000516029557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f0f4ba6ac4a0370f9c52d177f52e5fed8f8e0732b342b804596904879dc2220946060527f58ecd351bc27ca231233fb4412e1cf7023886e2b97e1e983459f3ff6da79479e6080526020600060a06000610100611b4bf4602a55600051602b557fbda369cd0602201df26b907dcb52b6a024645f509dd784cc175defdf009ee2936000527f9e5f40b672050788563557bb58931bdd7144f959a52ee1b58d36934825c50e5f6020527ffc4dbd3dee137e5e000cee5fa85efaa40a924b04465d0cdd0c289b472df6502d6040527feb63f70b39bb575552c38831324f4b8694b9b2d3340e39eb3136e12b94d251e16060527f4d3d300f9b1904f1482fcce852285fd861108b67d5eca18993a2c009e08e98fa6080526020600060a060006001610100611ba9f2602c55600051602d557f9094a45689e1f3cfd0bc968b521cd96d091f0d224e0a5fbae7bdab98c16c65276000527f932998a71fbe19159a57f33ab2d599721cb95deab14045707752698d700631156020527f6aabdd3f95e53a8066b3ece600ca962e57c12da74850196abc0ef9eeda6d11e26040527f1a6f7d6c7fb2ffb638b0d851de935c20cd472fef92327ff6205c903b426592186060527f0fb87b1c13bb67755816f4b4b02a7a39137878dc92b9ee676df9e13da2e853fd6080526020600060a06000610100611c84f4602e55600051602f557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f0537ccb278355352e685946c9163e32ac76c72dce7ea05da8e4078dc6589393d6020527f0537ccb278355352e685946c9163e32ac76c72dce7ea05da8e4078dc6589393d6040527f01fffffffe0000000200000000000000000000000200000000000000000000006060527f01fffffffe0000000200000000000000000000000200000000000000000000006080526020600060a060006000610100611a32f2603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xAC364Fe8a53B3B06E4ffc43a61e6b6aE111F8B60": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x1a99c1ffc59d50b72111e84f5d61d63204cd7d7e8b6ce298d4a90852322615e2",
+ "storage": {}
+ },
+ "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xabe2b602ab377c7797019f012a0e5eac45892762493a745125435d1f1969fc8d",
+ "storage": {}
+ },
+ "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xd8202e39fbc64c17d1fdd7dfde35c6ac6a6048407cca837f85cf3a92a054b6ee",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x7f1e3ec63b030c7721b195943c9e930fd54a2243b19a6b8f02ccb4d36de4f51cfa6000527f0846ca5cee09fdaa635a885d1bfbdb0fbb95c8ea3b5cc13a480c18459f58ea466020527f07ed8d82547c81a477a07ce6e3c2ab2f2fe9e4722f5605a1dd11b1d9decc37586040527f0c171f4c23860fcf50b25e53dac759e220cf16285be0f41d823131f2d0cc59f9606052604060006080600060067f1deffa299c37fcd9de705bd75c6ae69fd020d9a1b71ffca3a342363f85644ef7f4600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xbe7e199e4f874aec32866370704d58651fd0b7254c5df2d0cd5e3482475a47c0",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f011d81e0f48f2e0a4ec52fbd74772f1d3ffd13e39941dc2be3734bc8120495646000527f09328d03a44d267cbd550663d7ef3ebd8e8eba55e9e08165066890393d6b7aa86020527f13a01bed25f2ebc06b2cbdc4ccbebaf1f8baf4eeb7dc09a92ff5a4bbe25b29a76040527f90cb218380878d54b59a327fba1dc57c9554fa98a51a67c00acd773b2a7aa3aa6060527fce7c256d67b551be7e15626d7c2b8af5b40a61ecafbdce9a1ac030e5ce7c4d0f6080527fef6e10a89e0b4a03ac19f1f3dfaed522841d37e427e7478d598bb60a7ac53f0a60a0526040600060c060006000600a7fb72daca576fbf03d76c0b31da23b0686ca502ef473f7257e68b9612642f56eb1f1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x60006000526000602052600060405260006060526020600060806000600161cd15f46000556000516001557f43d1c02f84f79ae1492e9d2b89ab0fc9c103b392014bc60e1f173dc2a0d1fcd16000527fd414fa0aa72304bb922aa543cad14c25d2e4628cc5dd8d4cf81654e930c1551d6020527f6a3e96376126e8d3213e473f976810ff99a400fb7dced848459d5819a2ee6c3d6040527f1b3d6f19413e4bdef71bf5e03f0f25f47e6a7cf4fed7c2e89c4e5c01b486530160605260206000608060006000600162013eabf16002556000516003557f9906fc552d3ec01e0b96f107dd7dbcc884d10916865d2b483dbc35bb38fe0e996000527fd0b61eabc3c8fdfb793f5637eda97b84fad76f65dfdb26fdecefef2b65c5241b60205260006040527f1bc98b07747845577aea1c943af100df8b2d6917ecb9a1900d366713e6dc21fb6060526020600060806000600161ce70f46004556000516005557f180bf3f60fbc13743779da4dbee67b9fb0a63a819247264d1e961c12072f883a6000527fbb7b0b8c1ba91b810339f399b0740d77465bedeb824ab54f3fc47c579960ba1c6020527f64bf56ba321a655d7303c3cd42f07d3690bb7f70fe3fe04da89e4a617314dbe16040527fffff5f62bbe5ce1a329e700125d900cc88904616ec42ed8c92402ac49a7e97ae6060526020600060806000600161b052f46006556000516007557f8e19a52298f25ab5e498d779c824d5e5f9a82349543ae1775f3f19cd9e7dddaa6000527fb1336383b66a81ccf29284e94cd334f2d2af7c15295f540d2b3179178c05bde86020527f13444f6f7c48837047f68dfde90b784979d5c6a48e811f99552df2cc59f5d29c6040527f704cec5b3329e7229764e23af1de861f1a21e9c7a7aa1f4d79061a05d36a0c4160605260206000608060006001619dd4f46008556000516009557f5ea7f56c36e9e4c0522b1f5a2431991a21e4bbb6b577e907304a3d2391fef00c6000527f6ca40332b424d7bb466b25be0125685eecccad4fc76a32f36177e52a94f7741b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f12e8c58a0d25d7d3b8e54a1d2351692154176fb53aa675696145892159127671606052602060006080600060016132f8f4600a55600051600b556000600052601b6020526001604052600160605260206000608060006000600162013010f1600c55600051600d55600060005260006020526000604052600060605260206000608060006001600161c800f1600e55600051600f557f5eed20e4b3ced00fddb6ae28295dd9f327c822b92d48c8317ab258f7354890ea6000527fba5b5f2f20638cc0ed85c2bf7d5dbef69c7ad41fc63fa2dd95d055133d59631d6020527ff1aa8fe91f95559c861bb9f62234f1f730eee73ad5e5b9414eaec78e4b0911406040527fc33d84f13d192b77c8a6c072207b9a3e212100df63f56cdbbb28e3b8548c870660605260206000608060006000600161b0e2f26010556000516011557f0370ec4cd113a16faa25fb1be5ad2ebb4953a67250f780e0412495c039f004e46000527f5963b02c2c91e0247518a1941341b22e70a27e252ea45dccc4b8c0eb407b581b60205260006040527f33938ddbb7182f02f24dfd6745b0c329cd20da3212b2e3bdac7921a49bc55481606052602060006080600060016170edfa6012556000516013557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f85c283986bc3d889d40819dc1d1b54cd73407be4818d72e52a104b738fdb91fc6040527f7fa53c21bc99e7af078dc6f035377ea7bbdc87559f5940189979693b16822676606052602060006080600060006001611736f16014556000516015557fc56302c5e8354a195485e3071c0fd415eae836ea0b31a43b7a92f20446d8f5b46000527fe4aaabc67a48efd62a65b3bfaa602d36ae5be5bfd89975b00f6e543c81a8a92d6020527fa0fdc4680e1a90dabd5dedde26d1abc0f0682ae7d009b7ff897d5e4022ff6f866040527fcdcc7fb3739c6c85bef9d8ccc82a4d121a3cee7ac43ae9e760f3fa9e8b9583fb606052602060006080600060006001613b6cf16016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f4ec33bf7c871488fdce24f7ecf0a8fc010b739ec785fcd3638dca6a377219c5d6040527f14da99b4e79b4645e98051cc3146991dc08a4ae3eaac621a1e40208cf6df710860605260206000608060006000600161c5e4f26018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fab21f62421bb4acf9d252d6da285819ce6bb336f395872f89ebf744435f0c7f56040527f4aa5fa48a4f383446987fbdc957f643e384894228b080d54c1a7cb5c045749856060526020600060806000600161a3dcf4601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f912066e90ec6d7677e6fd8649cbdec3d4055d45dc3dd902745d835200f2a5f826040527f321aeb012e43ef288403416873ce3ded971cdf34df79e96f736b8cf03cbe83b860605260206000608060006000600161ae9af1601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f0d25e1b503d26804d6f732c050c961dbdc7ecc983905a76d583f470f579286186040527f5b73f2b518477c7afe6c5a119b42ead82b47f6e9f3b1de85fde3ad0a1486f8fd6060526020600060806000600161702efa601e55600051601f557f191fee423fb7f9a733c422df7c994b5477d27864589dba7a7fc28e48b8c2b2366000527f997fef11a8a4d589d2bd5a16a377af25e5cbbe813d65809db1e7bff336dcc61b60205260006040527f0b9e657c2b3bc2373a59b95a2bf3cf2306a2cab40b1845a7b33ba8f243ce7c8760605260206000608060006001620146e8fa6020556000516021557f73fc5af59dcce95b2824cf40e1c7e9f977da9f39d54bd4a6de5e69f05eb1aa9d6000527f2c4bf0413d4ce2f0658575771d3285e9f6e3282d6555d8bc86cccdcf86fb681c6020527f07dfbd7899eee43c9c7b0845b36528cc21febe6545aed949b08de39679cae3126040527fffff1f7a9c047f143904f54fc68101d4e35b6c61d1d29b47df3b23c2c51e3eba60605260206000608060006001600161dad5f16022556000516023557f6dce7564da0f627bb73184c062700c46b5fa40e038a26c6a09eee7992e7e77046000527ffae46ed9f1946468fc654e3169a858414c39f3231022971b08a6b9dc9d6024116020527f84e739bef13197615698bdfabfc1b886287b2209d526e0b88b8f55ba85686fcd6040527f2492d934f166e91909ab699d514a7c8945a3c1b2fdfe76a00ed909de0dbc4ccc6060526020600060806000600162016754fa6024556000516025557f25dcd8208d704c68a2751182346d2332b924bfb5f43ff4bb095c84343eed888f6000527f6fe4fd7dbf2d88c709f0e59813a6f58c27e01a1897848daec12d81bc1eefae1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f8fa1ab083edbcf3b8a7de09fd4044ff3e9a11fe374d4b15c65a950e2973acc5460605260206000608060006001600161b1a3f16026556000516027557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f6caa89f589fb21ffb2b20bc89cb3d36db7d98733cc9308d9d2366bf43090091d6040527f6eb4c20a32f3ddeafec7a5bf91ec6c400addc6532ab4af4473433035465cd2b36060526020600060806000600160016139f3f2602855600051602955600060005260006020526000604052600060605260206000608060006000600162014a19f2602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fc2572296cd1fcd3374840b60d4ff9eb33c3298e4e0086147e1e5e58a5cfe504a6040527f544c1008f7d5d111dd146db87a85232dbdc8c77bad357000653fdc2861a35b0360605260206000608060006000600161a5f1f2602c55600051602d557f08fc53f403c7cd48139e619636d480ff67993d8d59b986ca81622b913e224cdc6000527ff5e0393483b02dbe4abdd1121437ea1890c8ce44770700c775411594fece3c1b60205260006040527f0e06d11efa9fc8e458187396b1e1cbcc0b5a29af8755ad270262a9d68f0606d5606052602060006080600060016001611154f2602e55600051602f557f2f8c6555338a6deb90638b65fa8d38a23ac9b5a29c3c0de86607ea580f2dc8406000527fd13d5b86d6e628e20f07808e3d8d3ea9bc09b2b87135f84a5050eba6a71c9c1c6020527f67e38b6c13a0ee8fe9df12ca0e010dab052985ac852d1f107bddf86a78e7e47e6040527fffff4145f42083b2c92ccabe7f2b3b18c183a1d89758ac508242806f53d1807160605260206000608060006001620122dcfa603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x717676767676760000000000760000007600006f121212121212121212121212121212127806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a90097176767676767676767600000076767676767668210000000000000022901411717676767676767676760000007676767676767f7effffff8000000000000000000000000000000000000000d900000000000001901390186085557f82000000000000000000000000000000000000000000000000000000000000007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe027f7effffff8000000000000000000000000000000000000000d900000000000001717676767676767676760000007676767676769011046086556fdac7fff9ffd9e13226262626262626006823232323232323232390147f82000000000000000000000000000000000000000000000000000000000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0901090136fdac7fff9ffd9e1322626262626262600671fffffffffffffff900402682323232323232323237ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200001c1c608755681000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9016157f40000000fd000000db00000000000000000000000000000000000000000000017f8200000000000000000000000000000000000000000000000000000000000000901b6088557702ffffffffffffffffffffffffffffffffff0000000300007a010900000000000000000000000000000000000000000000000000111868010000000000000000651ce97e1ab91a9001901b7f80000000000000000000000000000000000000000000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a0260895567800000000000000169010000000000000000000b901c608a557176767676767600000000007600000076000060011767ffffffffffffffff67800000000000000090020360056c0100000000000000000000000007901d7f80000000000000000000000000000000000000000000000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00059006717676767676760000000000760000007600006000017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7effffff800000000000000000000000000200004400000000000000000000017e40000000fd000000db0000000000000000000040000000fd000000db0000d309901b7f80000000000000000000000000000000000000000000000000000000000000027cc9700000000000000000023f00c00014ff00000000000000002230080560070890181a6380000001777effffff80000000000000000000000000000000000080017f80000000000000000000000000000000000000000000000000000000000000000805608b557ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe76fffff716b61616160b0b0b2b0b230b000008010d0a2b000663800000016380000000901190066f8000000000000000000000000000000068232323232323232323901c608c557e40000000fd000000db0000000000000000000040000000fd000000db0000d37ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000090056380000000600068100000000000000000089019901c11608d5560006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000008e": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x000000000000000000000000000000000000000000000000000000000000008f": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000090": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000091": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000092": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x0000000000000000000000000000000000000000000000000000000000000093": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x0000000000000000000000000000000000000000000000000000000000000094": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x0000000000000000000000000000000000000000000000000000000000000095": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000096": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000097": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000098": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000099": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x000000000000000000000000000000000000000000000000000000000000009a": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x000000000000000000000000000000000000000000000000000000000000009b": "0x000000000000000000000000000000000000000000000000000000000000000e"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xd8C19eFeDe5AC667bcaC98d9E23A7ecDf49174Ab": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xa5d82b3ed5a4c81ecb208ed654c3afe5ff5a47f79737c75b2ca157448e545334",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556001496001556002496002556003496003556004496004556005496005556007496006554a6007556006600855",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x60e360005261020060205260e36040527f68ba69fd3d79033c88699f723b3ce8fc174e29617c0fdf5ca331345cfc88b3956060527f685a1289529ff6e4b8b0484285ab55b3f76dac15363842ec9b2d336b992ea10f6080527f36353ceec362a372703a5cbd12668f037d544cd7c5264f4b268658d99c9db80960a0527f67f2d2ba771a9e1d252660d4152e6b8c1ce1a15ffdc8cd107f44c9c0a7d3f31f60c0527f71a1fc485056395faeb3e337098b3eb579ecd77697bd38b7556d8c634f682e0760e0527f344453774915ee11d19d67019c1ab1cbf96284ebefdce23024b39297c3c86809610100527f0f3fc9fef99f49e7bbcb69512cb677dd0086b428baf1e45e86549109856b1f4a610120527f322173301aa0eb293c7a1a3cf35632d3e42be43b6f8a36b91810ae73fbfea52b610140527fea8823493f7e5e580c92ddd9f0b79a23cf39bb08378429ba4ff8c1c750e59dd8610160527fd83b25754b08bb09b9dad3f96e50bbaa26c21a516c7940b5a8d078e6dab85a9b610180527fceabfd9310faf929caa07eb2c16a5cf3220ad4ba347ce0fe46085d20ba75071c6101a0527f24f6d0eebee5563dbe1e9dbe7e5689c9327c1789ded8138a4be72594f913513d6101c0527fd17fb4869234da5ad1b1cfb239de0786236d865ed2cc386c97cb7fe2a692cf136101e0527f43b98da2bf7162f8e98dd6ee834e94d31db5b2a76894cc91c6f58a5143bb0036610200527f2774108405df680dce4dba7259b45a6db14c441d7804509ea5ede9dddc75223d610220527f96e7ea97d826d2439804598fc7876496be861a6ca50fda1429ee97f3c50aeae0610240527f431d4329971916f7e101455383ead34fb5abe5248acae9647a371fa6bf738cf9610260527ffe3bd91f70c14502003b140401804b9d89802c6a9fed066381650106babb9c3a610280527facccc13cdad040f47b674e9069c1626fade6322831db3e26bee1f4440770ef6e6102a0527f12d04d5e92ab3ba2bf08df17cd2e5b13e4ebfca850d995fae5b365342c16e7796102c0527f0748435c74300793195d4019c4e460346070e707a450ef6eb46c0cdaabacecd96102e0527fafb4c5e73d81081a0ed8969d16ddf0d93b2894302081351f20f428748609b85c610300527fa1136e7dca75863f6344598ba67ea78be7eede3fd603cc272682d41c55b54981610320527f77790a8dadad8b64cf67b4d1c698b3d17abc404e51ffcf26949e3708d03349af610340527f7616852f1e0314560baa48f0f80956faa938efab1743869fa0c40ed1fc187703610360527f0411af79acdc67e00252f798319ceb984f7f938fa5c477e5000deb9c87cdf7a3610380527fdfd48a4eed3f2c68bbe464b128a5692bcbe8404e85cc77067428633fe3ce77fc6103a0527fa923a6709345117ef6665b922f87b32bbddaff432fd51f1aea04c789d495a7636103c0527fbcf7aea7ffc385cf2e2694a1e44181a7106c4bd667959c6e8d3d40eca5c3d7e76103e0527ff55e9dd571ba1201b63ca49bab9e270b451bb49fc5fb30dcfd7c8d55426701636104005260396104205360526104215360556104225360d16104235360e66104245360446104255360e360006104266000600060056301253018f15a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e05160085561012c60005261012c60205261012c6040527f4c13aa7bd89ec1d2c97320c06de11439a3ef9f76f35cbef4a26bdaa531facb886060527fe936ad5a1ff2ae08e306e0675c45b5897bc54bd20ebb7401b8d0bbf7c8d740006080527f6e89c3b9088a0adc7f74bf8d5b78bebb6a608cd96c3d3ff56a2aca44cffb859760a0527f5ef8d2a654c19fd41f23d7154e6d4d39e1f7f83f350b3eeaee406db1cf882fdb60c0527f10582dc1df5ff7a13a5c4da82250077d56b4f3431de716f4140bd06a5f75e8d260e0527fad66636358287940d2e94232ea2849556b2ec8a990e15bcaf0be81232ec49ea1610100527ffdb224be211341222db5e820df4c160a3463e297f9c5dd460b4d0e0212bf25c2610120527f1de01c72fada90d9d23a7b8a3f34a01e3c5ea262f1be04457af21bebbc1b197a610140527f256e0ed7425a4a0ddcf8daabd1ee80e3a9a2b591233b7472521bb4e762e81e3c610160527fc02e02687247389cd723176ff321a468b17b0a9935ddff9fc995864eae74e129610180527f5d1c6e53c08315d8ca820b2da313676a3f607630be87d188154c529b5d98483d6101a0527f8f01e5b864f6406c46d2e6236303538d60a6326bbcd34b27736baf670e5e64906101c0527fbd11741f29b8112c2fd1bfacb8f381818b6b84c3fcc47e228dafe7622fdf5a266101e0527f0ec1be3cb9dbb1aa2ddafbd6839456c0b93ad959d9f032cc072cc4a7f67cf523610200527f7cde68df5a162da4f59c6d125fe25659a3d284949cde9f03e76142cccde98745610220527fcfb60777ffebf9e64be81d40180bea6dc4a5f6336b2b8a13c21df333baf7a2ce610240527f0226d7361c97d87324984f784e53b3494567d268d709630d595ca42f8753125d610260527f831f7f613cc4940a56d74a282a2f158f4ad6eec1b3a540cc4f2e70649eeb2ee6610280527f3f1db47e40ae8bdb42dac89e92e946d18c8dc4762e3d112d9a806f47e5749be16102a0527f30dbc5d2c3454b56123f0cefb0b8409e97d661959987129440081d476b6f6dbd6102c0527f9f959d6ed8f803e00cada84448dd3afa609dfff3b0536748ca0ec3b14be0ad936102e0527f04f126df3fe3b3f230519fce73d16706e0941891db3281f3859bc57f18c55f0e610300527fafdb95645eb77981cd68bd03e9fdb3bbb9edcb8e7995a1ab87c55c17dc7110e8610320527f38f6bc0d087f7348be687868f26e7c2ce8063f1e1785a1e8522959a21855b799610340527ff498e688264e826b3e2d34f0778b61afd62977d5e711976224a9ee3bb0cae3d9610360527f90e914d74e9d5366ef98fe6ad24437b59e9f026b8c098fbf61413149cd501b60610380527fd12b58e018d6c64acf92bcbd311784ff44446d651bd1ff78f5193da46abaa62d6103a0527fd7183b49e5f51ac4cb8d35b0bb50d90bbadbc0a91c98998fb1ad5a2b2b0a3bf96103c05260326103e05360f46103e15360826103e25360026103e35361012c60006103e460006000600563010a4374f15a01600955600051600a55602051600b55604051600c55606051600d55608051600e5560a051600f5560c05160105560e0516011556101005160125561012051601355",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x20000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x80000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x",
+ "from": "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0xeb4e32"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x0151232cf675c935ef391b8fd558a10e093eb25d5e78fe6170c1f8ce23b06e17",
+ "0x01bfc9c4e99a03f3708fd387e97733f3c5b2a65e459587674598eda695b354b0",
+ "0x015a37c0077673cf8aeaa690fefed9714b00490c5c45dc43ad4990256f744250",
+ "0x017effe0e39459c4c2c9e96b0e1ccc963179783ba07f37e28c9ea3588c24b80a",
+ "0x015051974a4f040fa74fde7e1f10a3caa0958210540822e965dca0cc089421de",
+ "0x0136aab88a6300af782af468b9dbd33a5e7f09dd88c940c7e8bc9696351a2396"
+ ],
+ "data": "0xb8a1",
+ "from": "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x979ef803f86d8da0b051f1c1978a54f1f249e777afe349bde7784af3af3736a1cf6427992bf070b8b3237445a46c46c0",
+ "from": "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0xf6d8"
+ },
+ {
+ "data": "0x234f36b00b899acd82ee47db9ee3eacb23dfa61b9692c8fa886079a4cc27a4ec89c56555cdcbb295e6aaf676bb35a74e2660bca16010",
+ "from": "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x57"
+ },
+ {
+ "data": "0xa16b5f3897ee5da10daf1d2482cd3d61f3acd4e947b01f8e646aecd279",
+ "from": "0x8b632B705a6Ab4ee30e08eD21A0AEE1C3b6583B8",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0x9993"
+ },
+ {
+ "data": "0x5c1f04f49b87fba351403d18f62492f20fa63c360685451c204c39496b48757ccd9e4b286bf9150936c0107298861c5f87343a0c638efcfd30d06b69906fa2a572d9fb3b019659ddc85daa806cd5f9a9bde5889720800a7d1ad910c9d5c08be332af0816a2f03512f0e4af7338eea9409a415c9a92a310cd70dbdebc32bc590642bc5437f9bed555c5afa58252ef0433",
+ "from": "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0xe4"
+ },
+ {
+ "data": "0x02a401377e008d7264913d4b8f133df0bf2fe023635467aff9b5b2b7fb87ee092248f6e94051377206c0ac69fb01ea0662e1f8642d017a58d0",
+ "from": "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0x6e6593"
+ },
+ {
+ "data": "0x6c",
+ "from": "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x0"
+ },
+ {
+ "data": "0x",
+ "from": "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x0"
+ },
+ {
+ "data": "0x8c8c7d9be0d21bb7e20e11cdf09d9bab1f7afb0acbe01c2c7208d5d61975c330918b75aa79b0bd7ada434555a16755e14cbcf4bae04220c84caf7a01cad4856a",
+ "from": "0x8b632B705a6Ab4ee30e08eD21A0AEE1C3b6583B8",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0x34"
+ },
+ {
+ "data": "0xa1a576ba71d1586c137ffbf26a64a0f08839c904930a3ccdd5fb49a22bfdeae09fd83fe4205d3d81f6d5347a416e9dbe1a01845aaebf4bfd54f441d02d1245",
+ "from": "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0xb6"
+ },
+ {
+ "data": "0xeb4d46c8676782f9a0e27952006dade15be39bfcd5e93b473bec8286c82129e97a95df024b8ac429c3a12675fa5d33f5bd0368ee51954e118f45bbe0d5c75e0f14511626e3cec36f8a0fea34debb42f4ad3b",
+ "from": "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0x2586"
+ },
+ {
+ "data": "0x37fbd9d422a2d3b07bdd02651e16a09771aed6a8afadded3fe3554b8e93812ee89bc1934160eb425798dfb23a67a07d6253bf4ef552a8047a43e6c0afcfc0d59611e445f59284029ea0185197b1b68c34695af3ae1596bb7260ab1f9ffcbda973774c9",
+ "from": "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0x0"
+ },
+ {
+ "data": "0xf079043fb1e333119c9f37c0da1e7c37afaa7bd4f0a48cc4c13dfa7b0f1fdad73b5b9e0693640d461ef391412d33458c44b23b59ebf9209b43fe85fdbedb04e99fa64b",
+ "from": "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0x2a25"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x00000000000000000000000000000000000000f6",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x7c48536e23d335550aeafe4c1a83a723d065f2e5b3a5ee92a511407047864475",
+ "s": "0x205759410d303ec597e2dc6393fd16b9fdc3822b291964ffc8ce0b38d37443ff",
+ "v": "0x1"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f4",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x54c674400688f718ee9e00c2c3a55d381086f0b5c02a1c4f858a7163fe894f00",
+ "s": "0x4cfd634ceaa675a52cb1d7ca3ad14ca67c6655e807fb31b4a4594ba92878a697",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000008",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0xc6956404e7cf31ffbeeb302279839736467b40fb83017c2b2541dac5e31f691a",
+ "s": "0x4d92016e2691de9b91edb8b4164b729d285e88d1189b9fb7cac1a100464a4d94",
+ "v": "0x0"
+ },
+ {
+ "address": "0x1563915e194d8cfba1943570603f7606a3115508",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x9f7853fc3910422af738e43f0cdfca99e563e26c8191674ff73e451bdb76f920",
+ "s": "0x74296c8652d2063bdc5babf2f29d407eecbd33cbbc64039487c464d48b0be33a",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000002",
+ "chainId": "0x0",
+ "nonce": "0x2",
+ "r": "0x661803e8303b235dd6c107384ea9de0b00bc66c64ebce4eb656a4f5b2c9d18f1",
+ "s": "0x2b034a6129d8e3a6e719bd58cc085c355e8cb14ce9c77566bd430c4fa56b6877",
+ "v": "0x0"
+ },
+ {
+ "address": "0x8fd379246834eac74b8419ffda202cf8051f7a03",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x66dccffe43cd270b38a7e7f384e73e48f305ff9eb08795b67b0a98760321116a",
+ "s": "0x6a55044bdaea2aa0b6231b536dff7844907538f69cebaa0fd94c50702f883c58",
+ "v": "0x0"
+ }
+ ],
+ "data": "0xc159",
+ "from": "0xd8C19eFeDe5AC667bcaC98d9E23A7ecDf49174Ab",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000010",
+ "type": "0x4",
+ "value": "0x8e"
+ },
+ {
+ "data": "0x00",
+ "from": "0x23957dB27fD43F125fee8eB0a2Be85F1FC39Fa74",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x00000000000000000000000000000000000000f6",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xb8ddf540ae2c650211ff9615477d69061db710b2b73a527a8f5d3e9cebfee5e7",
+ "s": "0x77a01c72961d20542f9ebfb2169fd30fb798f730e95636dd0d904cc62b93de80",
+ "v": "0x0"
+ }
+ ],
+ "data": "0xc159",
+ "from": "0xAC364Fe8a53B3B06E4ffc43a61e6b6aE111F8B60",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000010",
+ "type": "0x4",
+ "value": "0x8e"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/fuzzer_bridge/models.py b/packages/tests/src/cli/fuzzer_bridge/models.py
new file mode 100644
index 0000000000..925d24edac
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/models.py
@@ -0,0 +1,121 @@
+"""
+Pydantic models for fuzzer output format v2.
+
+This module defines Data Transfer Objects (DTOs) for parsing
+fuzzer output. These DTOs are intentionally separate from EEST
+domain models (Transaction, Account) to maintain clean separation
+between external data format and internal representation.
+
+Design Principle:
+- DTOs (this file): Parse external JSON-RPC standard format
+- Domain Models (EEST): Internal test generation logic
+- Converter (converter.py): Explicit transformation between the two
+"""
+
+from typing import Dict, List
+
+from pydantic import BaseModel, Field
+
+from ethereum_test_base_types import AccessList, Address, Bytes, CamelModel, Hash, HexNumber
+from ethereum_test_forks import Fork
+from ethereum_test_types import Environment
+
+
+class FuzzerAccountInput(BaseModel):
+ """
+ Raw account data from fuzzer output.
+
+ This is a DTO that accepts fuzzer's JSON format without triggering
+ EEST's Account validation logic or defaults.
+ """
+
+ balance: HexNumber
+ nonce: HexNumber = HexNumber(0)
+ code: Bytes = Bytes(b"")
+ storage: Dict[HexNumber, HexNumber] = Field(default_factory=dict)
+ private_key: Hash | None = Field(None, alias="privateKey")
+
+ class Config:
+ """Pydantic configuration."""
+
+ populate_by_name = True
+
+
+class FuzzerAuthorizationInput(BaseModel):
+ """
+ Raw authorization tuple from fuzzer output (EIP-7702).
+
+ Accepts fuzzer's camelCase JSON format.
+ """
+
+ chain_id: HexNumber = Field(..., alias="chainId")
+ address: Address
+ nonce: HexNumber
+ v: HexNumber # yParity
+ r: HexNumber
+ s: HexNumber
+
+ class Config:
+ """Pydantic configuration."""
+
+ populate_by_name = True
+
+
+class FuzzerTransactionInput(BaseModel):
+ """
+ Raw transaction data from fuzzer output.
+
+ This is a DTO that accepts standard Ethereum JSON-RPC transaction format
+ without triggering EEST's Transaction.model_post_init logic.
+
+ Key differences from EEST Transaction:
+ - Uses "gas" not "gas_limit" (JSON-RPC standard)
+ - Uses "data" not "input" (JSON-RPC standard)
+ - Uses "from" not "sender" (JSON-RPC standard)
+ - No automatic TestAddress injection
+ - No automatic transaction type detection
+ - No automatic signature handling
+ """
+
+ from_: Address = Field(..., alias="from")
+ to: Address | None = None
+ gas: HexNumber # Will be mapped to gas_limit in converter
+ gas_price: HexNumber | None = Field(None, alias="gasPrice")
+ max_fee_per_gas: HexNumber | None = Field(None, alias="maxFeePerGas")
+ max_priority_fee_per_gas: HexNumber | None = Field(None, alias="maxPriorityFeePerGas")
+ nonce: HexNumber
+ data: Bytes = Bytes(b"") # Will be mapped to data/input in converter
+ value: HexNumber = HexNumber(0)
+ access_list: List[AccessList] | None = Field(None, alias="accessList")
+ blob_versioned_hashes: List[Hash] | None = Field(None, alias="blobVersionedHashes")
+ max_fee_per_blob_gas: HexNumber | None = Field(None, alias="maxFeePerBlobGas")
+ authorization_list: List[FuzzerAuthorizationInput] | None = Field(
+ None, alias="authorizationList"
+ )
+
+ class Config:
+ """Pydantic configuration."""
+
+ populate_by_name = True
+
+
+class FuzzerOutput(CamelModel):
+ """
+ Main fuzzer output format v2.
+
+ This is the top-level DTO that parses the complete fuzzer
+ output JSON. It uses pure DTOs (FuzzerAccountInput,
+ FuzzerTransactionInput) to avoid triggering EEST domain
+ model logic during parsing.
+
+ After parsing, the converter will transform these DTOs into
+ EEST domain models.
+ """
+
+ version: str = Field(..., pattern="^2\\.0$")
+ fork: Fork
+ chain_id: HexNumber = Field(HexNumber(1))
+ accounts: Dict[Address, FuzzerAccountInput]
+ transactions: List[FuzzerTransactionInput]
+ env: Environment
+ parent_beacon_block_root: Hash | None = None
diff --git a/packages/tests/src/cli/fuzzer_bridge/performance_utils.py b/packages/tests/src/cli/fuzzer_bridge/performance_utils.py
new file mode 100644
index 0000000000..e64e44921a
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/performance_utils.py
@@ -0,0 +1,153 @@
+"""Performance utilities for fuzzer bridge processing."""
+
+import json
+import mmap
+import os
+from functools import lru_cache
+from pathlib import Path
+from typing import Any, Dict, List, Optional
+
+try:
+ import orjson # type: ignore # Fast JSON library (optional dependency)
+
+ HAS_ORJSON = True
+except ImportError:
+ HAS_ORJSON = False
+
+
+class FastJSONHandler:
+ """Fast JSON operations using memory-mapped files and optimized parsing."""
+
+ @staticmethod
+ def load_json_mmap(file_path: Path) -> Dict[str, Any]:
+ """Load JSON using memory-mapped file for better I/O performance."""
+ with open(file_path, "r+b") as f:
+ # Memory-map the file
+ with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mmapped_file:
+ # Read the entire content at once
+ content = mmapped_file.read()
+ if HAS_ORJSON:
+ return orjson.loads(content)
+ else:
+ # Fallback to standard json
+ return json.loads(content.decode("utf-8"))
+
+ @staticmethod
+ def dump_json_fast(data: Dict[str, Any], file_path: Path, pretty: bool = False) -> None:
+ """Dump JSON using optimized serialization."""
+ if HAS_ORJSON:
+ # Use orjson for faster serialization
+ if pretty:
+ content = orjson.dumps(data, option=orjson.OPT_INDENT_2)
+ else:
+ content = orjson.dumps(data)
+ with open(file_path, "wb") as f:
+ f.write(content)
+ else:
+ # Fallback to standard json
+ with open(file_path, "w") as f:
+ if pretty:
+ json.dump(data, f, indent=2)
+ else:
+ json.dump(data, f)
+
+
+class BatchProcessor:
+ """Optimized batch processing utilities."""
+
+ @staticmethod
+ def calculate_optimal_batch_size(file_count: int, num_workers: int) -> int:
+ """Calculate optimal batch size based on file count and workers."""
+ # Aim for at least 4 batches per worker for better load balancing
+ # But not too small to avoid overhead
+ min_batch_size = 5
+ ideal_batches_per_worker = 4
+
+ ideal_batch_size = max(
+ min_batch_size, file_count // (num_workers * ideal_batches_per_worker)
+ )
+
+ # Adjust for very large file counts
+ if file_count > 10000:
+ # Larger batches for many files to reduce overhead
+ ideal_batch_size = max(50, ideal_batch_size)
+ elif file_count < 100:
+ # Smaller batches for few files to maximize parallelism
+ ideal_batch_size = max(1, file_count // (num_workers * 2))
+
+ return ideal_batch_size
+
+ @staticmethod
+ def calculate_optimal_workers(file_count: int) -> int:
+ """Calculate optimal number of workers for processing."""
+ cpu_count = os.cpu_count() or 4
+
+ # Scale workers based on file count
+ if file_count < 10:
+ return 1 # Sequential for very small workloads
+ elif file_count < 50:
+ return min(2, cpu_count)
+ elif file_count < 200:
+ return min(4, cpu_count)
+ elif file_count < 1000:
+ return min(cpu_count, 8)
+ else:
+ # For large file counts, use all available CPUs but cap at 16
+ return min(cpu_count, 16)
+
+
+@lru_cache(maxsize=128)
+def cached_fork_lookup(fork_name: str) -> Optional[Any]:
+ """Cache fork lookups to avoid repeated module imports."""
+ try:
+ import ethereum_test_forks
+
+ return getattr(ethereum_test_forks, fork_name, None)
+ except (ImportError, AttributeError):
+ return None
+
+
+class ParallelProgressTracker:
+ """Thread-safe progress tracking for parallel processing."""
+
+ def __init__(self, total: int):
+ """Initialize progress tracker."""
+ from threading import Lock
+
+ self.total = total
+ self.completed = 0
+ self.errors = 0
+ self.lock = Lock()
+
+ def update(self, success: int = 0, error: int = 0) -> tuple[int, int]:
+ """Update progress counters thread-safely."""
+ with self.lock:
+ self.completed += success
+ self.errors += error
+ return self.completed, self.errors
+
+ def get_stats(self) -> tuple[int, int, int]:
+ """Get current statistics."""
+ with self.lock:
+ return self.completed, self.errors, self.total
+
+
+# Memory pool for reusing buffers
+class BufferPool:
+ """Reusable buffer pool to reduce memory allocations."""
+
+ def __init__(self, buffer_size: int = 1024 * 1024): # 1MB default
+ """Initialize buffer pool."""
+ self.buffer_size = buffer_size
+ self.buffers: List[bytearray] = []
+
+ def get_buffer(self) -> bytearray:
+ """Get a buffer from pool or create new one."""
+ if self.buffers:
+ return self.buffers.pop()
+ return bytearray(self.buffer_size)
+
+ def return_buffer(self, buffer: bytearray) -> None:
+ """Return buffer to pool for reuse."""
+ if len(buffer) == self.buffer_size:
+ self.buffers.append(buffer)
diff --git a/packages/tests/src/cli/fuzzer_bridge/production_test.py b/packages/tests/src/cli/fuzzer_bridge/production_test.py
new file mode 100644
index 0000000000..d2d2a416f5
--- /dev/null
+++ b/packages/tests/src/cli/fuzzer_bridge/production_test.py
@@ -0,0 +1,364 @@
+#!/usr/bin/env python
+"""
+Production-ready test suite for fuzzer bridge with geth verification.
+
+This script:
+1. Loads fuzzer output
+2. Converts to blockchain test
+3. Generates fixtures
+4. Verifies with go-ethereum
+5. Reports comprehensive results
+"""
+
+import argparse
+import json
+import subprocess
+import sys
+import tempfile
+import time
+from pathlib import Path
+from typing import Any, Dict, List, Optional
+
+# Add parent directory to path for imports
+sys.path.insert(0, str(Path(__file__).parent.parent.parent))
+
+from ethereum_clis import GethTransitionTool
+from ethereum_test_fixtures.blockchain import BlockchainFixture
+from ethereum_test_specs.blockchain import BlockchainTest
+from ethereum_test_tools import (
+ Account,
+ Address,
+ Alloc,
+ Block,
+ Environment,
+ Transaction,
+)
+
+
+class FuzzerBridge:
+ """Production-ready fuzzer bridge with validation and verification."""
+
+ def __init__(
+ self, t8n_path: Optional[str] = None, verbose: bool = False, keep_fixtures: bool = False
+ ):
+ """Initialize bridge with optional transition tool path."""
+ self.t8n = GethTransitionTool(binary=Path(t8n_path) if t8n_path else None)
+ self.verbose = verbose
+ self.keep_fixtures = keep_fixtures
+ self.stats: Dict[str, Any] = {
+ "tests_generated": 0,
+ "tests_passed": 0,
+ "tests_failed": 0,
+ "validation_errors": [],
+ }
+
+ def validate_fuzzer_output(self, data: Dict[str, Any]) -> List[str]:
+ """Validate fuzzer output format and return list of errors."""
+ errors = []
+
+ # Check version
+ version = data.get("version", "1.0")
+ if version != "2.0":
+ errors.append(f"Unsupported version {version}, expected 2.0")
+
+ # Check required fields
+ required_fields = ["accounts", "transactions", "env", "fork", "chainId"]
+ for field in required_fields:
+ if field not in data:
+ errors.append(f"Missing required field: {field}")
+
+ # Validate accounts with transactions have private keys
+ if "accounts" in data and "transactions" in data:
+ senders = set()
+ for tx in data["transactions"]:
+ sender = tx.get("from") or tx.get("sender")
+ if sender:
+ senders.add(sender)
+
+ for sender in senders:
+ if sender not in data["accounts"]:
+ errors.append(f"Sender {sender} not in accounts")
+ elif "privateKey" not in data["accounts"][sender]:
+ errors.append(f"No private key for sender {sender}")
+ else:
+ # Validate private key matches address
+ if not self._validate_key_address(
+ data["accounts"][sender]["privateKey"], sender
+ ):
+ errors.append(f"Private key doesn't match address {sender}")
+
+ return errors
+
+ def _validate_key_address(self, private_key: str, expected_address: str) -> bool:
+ """Validate that private key generates expected address."""
+ try:
+ from ethereum_test_types import EOA
+
+ eoa = EOA(key=private_key)
+ # EOA class returns the address directly via str()
+ return str(eoa).lower() == expected_address.lower()
+ except Exception:
+ return False
+
+ def convert_to_test(self, fuzzer_data: Dict[str, Any]) -> Dict[str, Any]:
+ """Convert fuzzer output to test parameters."""
+ # Validate first
+ errors = self.validate_fuzzer_output(fuzzer_data)
+ if errors:
+ raise ValueError("Validation failed:\n" + "\n".join(errors))
+
+ # Build pre-state
+ pre_state = Alloc()
+ private_keys = {}
+
+ for addr_str, account_data in fuzzer_data["accounts"].items():
+ addr = Address(addr_str)
+
+ if "privateKey" in account_data:
+ private_keys[addr_str] = account_data["privateKey"]
+
+ pre_state[addr] = Account(
+ balance=int(account_data.get("balance", "0x0"), 16),
+ nonce=int(account_data.get("nonce", "0x0"), 16),
+ code=account_data.get("code", ""),
+ storage=account_data.get("storage", {}),
+ )
+
+ # Create genesis environment (block 0)
+ env_data = fuzzer_data["env"]
+ genesis_env = Environment(
+ fee_recipient=Address(env_data.get("currentCoinbase")),
+ difficulty=0, # Post-merge
+ gas_limit=int(env_data.get("currentGasLimit", "0x1000000"), 16),
+ number=0, # Genesis is block 0
+ timestamp=int(env_data.get("currentTimestamp", "0x1000"), 16) - 12,
+ base_fee_per_gas=int(env_data.get("currentBaseFee", "0x7"), 16),
+ )
+
+ # Block 1 environment overrides
+ block1_env = {
+ "timestamp": int(env_data.get("currentTimestamp", "0x1000"), 16),
+ "fee_recipient": Address(env_data.get("currentCoinbase")),
+ }
+
+ # Create transactions
+ txs = []
+ for tx_data in fuzzer_data["transactions"]:
+ sender_addr = tx_data.get("from") or tx_data.get("sender")
+ secret_key = private_keys[sender_addr]
+
+ txs.append(
+ Transaction(
+ to=Address(tx_data["to"]) if tx_data.get("to") else None,
+ value=int(tx_data.get("value", "0x0"), 16),
+ gas_limit=int(tx_data.get("gas", "0x5208"), 16),
+ gas_price=int(tx_data.get("gasPrice", "0x1"), 16),
+ nonce=int(tx_data.get("nonce", "0x0"), 16),
+ data=bytes.fromhex(tx_data.get("data", "0x")[2:])
+ if tx_data.get("data", "0x") != "0x"
+ else b"",
+ secret_key=secret_key,
+ )
+ )
+
+ # Create block
+ block = Block(txs=txs, **block1_env)
+
+ return {
+ "genesis_environment": genesis_env,
+ "pre": pre_state,
+ "post": {},
+ "blocks": [block],
+ "chain_id": fuzzer_data.get("chainId", 1),
+ "fork": fuzzer_data.get("fork", "Prague"),
+ }
+
+ def generate_fixture(self, test_params: Dict[str, Any]) -> Dict[str, Any]:
+ """Generate blockchain test fixture."""
+ # Get fork
+ from ethereum_test_forks import Cancun, Osaka, Prague, Shanghai
+
+ fork_map = {"Osaka": Osaka, "Prague": Prague, "Shanghai": Shanghai, "Cancun": Cancun}
+ fork = fork_map.get(test_params["fork"], Prague)
+
+ # Create test
+ test = BlockchainTest(
+ genesis_environment=test_params["genesis_environment"],
+ pre=test_params["pre"],
+ post=test_params["post"],
+ blocks=test_params["blocks"],
+ chain_id=test_params["chain_id"],
+ )
+
+ # Generate fixture
+ fixture = test.generate(
+ t8n=self.t8n,
+ fork=fork,
+ fixture_format=BlockchainFixture,
+ )
+
+ self.stats["tests_generated"] += 1
+
+ return fixture.model_dump(exclude_none=True, by_alias=True)
+
+ def verify_with_geth(
+ self, fixture: Dict[str, Any], geth_path: str, test_name: str = "test"
+ ) -> Dict[str, Any]:
+ """Verify fixture with go-ethereum evm tool."""
+ # Write fixture to temp file
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
+ json.dump({test_name: fixture}, f, indent=2)
+ fixture_path = f.name
+
+ try:
+ # Run geth blocktest
+ result = subprocess.run(
+ [geth_path, "blocktest", fixture_path], capture_output=True, text=True, timeout=30
+ )
+
+ # Parse output
+ output = result.stdout + result.stderr
+
+ # Check if test passed
+ if result.returncode == 0 and '"pass": true' in output:
+ self.stats["tests_passed"] += 1
+ return {"pass": True, "output": output, "fixture_path": fixture_path}
+ else:
+ self.stats["tests_failed"] += 1
+ # Extract error message
+ error = "Unknown error"
+ if '"error":' in output:
+ import re
+
+ match = re.search(r'"error":\s*"([^"]+)"', output)
+ if match:
+ error = match.group(1)
+
+ return {
+ "pass": False,
+ "error": error,
+ "output": output,
+ "fixture_path": fixture_path,
+ }
+
+ except subprocess.TimeoutExpired:
+ self.stats["tests_failed"] += 1
+ return {"pass": False, "error": "Timeout", "fixture_path": fixture_path}
+ except Exception as e:
+ self.stats["tests_failed"] += 1
+ return {"pass": False, "error": str(e), "fixture_path": fixture_path}
+ finally:
+ # Optionally clean up
+ # Note: args is not defined here - should be passed as parameter
+ pass
+
+ def run_full_test(self, fuzzer_file: str, geth_path: str) -> bool:
+ """Run full test pipeline from fuzzer output to geth verification."""
+ print(f"🔧 Loading fuzzer output from {fuzzer_file}")
+ with open(fuzzer_file) as f:
+ fuzzer_data = json.load(f)
+
+ print("📋 Fuzzer Output Summary:")
+ print(f" Version: {fuzzer_data.get('version', 'unknown')}")
+ print(f" Fork: {fuzzer_data.get('fork', 'unknown')}")
+ print(f" Accounts: {len(fuzzer_data.get('accounts', {}))}")
+ print(f" Transactions: {len(fuzzer_data.get('transactions', []))}")
+
+ # Validate
+ print("\n✓ Validating fuzzer output...")
+ errors = self.validate_fuzzer_output(fuzzer_data)
+ if errors:
+ print("❌ Validation failed:")
+ for error in errors:
+ print(f" - {error}")
+ return False
+
+ # Convert
+ print("✓ Converting to test parameters...")
+ try:
+ test_params = self.convert_to_test(fuzzer_data)
+ except Exception as e:
+ print(f"❌ Conversion failed: {e}")
+ return False
+
+ # Generate fixture
+ print("✓ Generating blockchain test fixture...")
+ try:
+ fixture = self.generate_fixture(test_params)
+ except Exception as e:
+ print(f"❌ Fixture generation failed: {e}")
+ import traceback
+
+ traceback.print_exc()
+ return False
+
+ # Extract test info
+ genesis_hash = fixture.get("genesisBlockHeader", {}).get("hash", "unknown")
+ pre_count = len(fixture.get("pre", {}))
+ print(f" Genesis hash: {genesis_hash[:16]}...")
+ print(f" Pre-state accounts: {pre_count}")
+
+ # Verify with geth
+ print("\n🔍 Verifying with go-ethereum...")
+ result = self.verify_with_geth(fixture, geth_path, "fuzzer_test")
+
+ if result["pass"]:
+ print("✅ Test PASSED!")
+ if self.verbose:
+ print(f" Fixture: {result.get('fixture_path', 'N/A')}")
+ else:
+ print("❌ Test FAILED!")
+ print(f" Error: {result.get('error', 'Unknown')}")
+ if self.verbose:
+ print(f" Output:\n{result.get('output', '')}")
+ if self.keep_fixtures:
+ print(f" Fixture saved: {result.get('fixture_path', 'N/A')}")
+
+ # Print statistics
+ print("\n📊 Statistics:")
+ print(f" Tests generated: {self.stats['tests_generated']}")
+ print(f" Tests passed: {self.stats['tests_passed']}")
+ print(f" Tests failed: {self.stats['tests_failed']}")
+
+ return result["pass"]
+
+
+def main():
+ """Main entry point for production test."""
+ parser = argparse.ArgumentParser(
+ description="Production test for fuzzer bridge with geth verification"
+ )
+ parser.add_argument("--fuzzer-output", required=True, help="Path to fuzzer output JSON file")
+ parser.add_argument("--geth-path", required=True, help="Path to go-ethereum evm binary")
+ parser.add_argument("--t8n-path", help="Path to transition tool binary (optional)")
+ parser.add_argument(
+ "--keep-fixtures", action="store_true", help="Keep generated fixture files for debugging"
+ )
+ parser.add_argument("--verbose", action="store_true", help="Verbose output")
+
+ global args
+ args = parser.parse_args()
+
+ # Check paths exist
+ if not Path(args.fuzzer_output).exists():
+ print(f"❌ Fuzzer output not found: {args.fuzzer_output}")
+ return 1
+
+ if not Path(args.geth_path).exists():
+ print(f"❌ Geth binary not found: {args.geth_path}")
+ return 1
+
+ # Run test
+ bridge = FuzzerBridge(t8n_path=args.t8n_path)
+
+ start_time = time.time()
+ success = bridge.run_full_test(args.fuzzer_output, args.geth_path)
+ elapsed = time.time() - start_time
+
+ print(f"\n⏱️ Completed in {elapsed:.2f} seconds")
+
+ return 0 if success else 1
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/src/ethereum_spec_tests/cli/gen_index.py b/packages/tests/src/cli/gen_index.py
similarity index 91%
rename from src/ethereum_spec_tests/cli/gen_index.py
rename to packages/tests/src/cli/gen_index.py
index 753b137136..e1d8de1af2 100644
--- a/src/ethereum_spec_tests/cli/gen_index.py
+++ b/packages/tests/src/cli/gen_index.py
@@ -1,4 +1,6 @@
-"""Generate an index file of all the json fixtures in the specified directory."""
+"""
+Generate an index file of all the json fixtures in the specified directory.
+"""
import datetime
import json
@@ -53,15 +55,6 @@ def count_json_files_exclude_index(start_path: Path) -> int:
required=True,
help="The input directory",
)
-@click.option(
- "--disable-infer-format",
- "-d",
- "disable_infer_format",
- is_flag=True,
- default=False,
- expose_value=True,
- help="Don't try to guess the fixture format from the json file's path.",
-)
@click.option(
"--quiet",
"-q",
@@ -80,15 +73,14 @@ def count_json_files_exclude_index(start_path: Path) -> int:
expose_value=True,
help="Force re-generation of the index file, even if it already exists.",
)
-def generate_fixtures_index_cli(
- input_dir: str, quiet_mode: bool, force_flag: bool, disable_infer_format: bool
-):
- """CLI wrapper to an index of all the fixtures in the specified directory."""
+def generate_fixtures_index_cli(input_dir: str, quiet_mode: bool, force_flag: bool):
+ """
+ CLI wrapper to an index of all the fixtures in the specified directory.
+ """
generate_fixtures_index(
Path(input_dir),
quiet_mode=quiet_mode,
force_flag=force_flag,
- disable_infer_format=disable_infer_format,
)
@@ -96,7 +88,6 @@ def generate_fixtures_index(
input_path: Path,
quiet_mode: bool = False,
force_flag: bool = False,
- disable_infer_format: bool = False,
):
"""
Generate an index file (index.json) of all the fixtures in the specified
diff --git a/src/ethereum_spec_tests/cli/generate_checklist_stubs.py b/packages/tests/src/cli/generate_checklist_stubs.py
similarity index 97%
rename from src/ethereum_spec_tests/cli/generate_checklist_stubs.py
rename to packages/tests/src/cli/generate_checklist_stubs.py
index 36d3839b36..9468521dbf 100644
--- a/src/ethereum_spec_tests/cli/generate_checklist_stubs.py
+++ b/packages/tests/src/cli/generate_checklist_stubs.py
@@ -86,16 +86,17 @@ def generate_checklist_stubs(output: str | None, dry_run: bool) -> None:
Generate mypy stub files for EIPChecklist classes.
This is a development tool that generates .pyi stub files to help mypy
- understand that EIPChecklist classes are callable, fixing type checking issues.
+ understand that EIPChecklist classes are callable, fixing type checking
+ issues.
Examples:
- # Generate stub files (auto-detect location)
+ Generate stub files (auto-detect location):
uv run generate_checklist_stubs
- # Generate to specific location
+ Generate to specific location:
uv run generate_checklist_stubs --output /path/to/stubs.pyi
- # Preview content without writing
+ Preview content without writing:
uv run generate_checklist_stubs --dry-run
"""
diff --git a/src/ethereum_spec_tests/cli/gentest/__init__.py b/packages/tests/src/cli/gentest/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/gentest/__init__.py
rename to packages/tests/src/cli/gentest/__init__.py
diff --git a/src/ethereum_spec_tests/cli/gentest/cli.py b/packages/tests/src/cli/gentest/cli.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/gentest/cli.py
rename to packages/tests/src/cli/gentest/cli.py
diff --git a/src/ethereum_spec_tests/cli/gentest/request_manager.py b/packages/tests/src/cli/gentest/request_manager.py
similarity index 79%
rename from src/ethereum_spec_tests/cli/gentest/request_manager.py
rename to packages/tests/src/cli/gentest/request_manager.py
index ab9ccc80d8..ac517b7490 100644
--- a/src/ethereum_spec_tests/cli/gentest/request_manager.py
+++ b/packages/tests/src/cli/gentest/request_manager.py
@@ -1,13 +1,17 @@
"""
-A request manager Ethereum RPC calls.
+A request manager Ethereum RPC calls.
-The RequestManager handles transactions and block data retrieval from a remote Ethereum node,
-utilizing Pydantic models to define the structure of transactions and blocks.
+The RequestManager handles transactions and block data retrieval from a remote
+Ethereum node, utilizing Pydantic models to define the structure of
+transactions and blocks.
Classes:
-- RequestManager: The main class for managing RPC requests and responses.
-- RemoteTransaction: A Pydantic model representing a transaction retrieved from the node.
-- RemoteBlock: A Pydantic model representing a block retrieved from the node.
+ RequestManager: The main class for managing RPC requests and
+ responses.
+ RemoteTransaction: A Pydantic model representing a transaction
+ retrieved from the node.
+ RemoteBlock: A Pydantic model representing a block retrieved from
+ the node.
"""
from typing import Dict
@@ -15,7 +19,7 @@
from config import EnvConfig
from ethereum_test_base_types import Hash
from ethereum_test_rpc import BlockNumberType, DebugRPC, EthRPC
-from ethereum_test_rpc.types import TransactionByHashResponse
+from ethereum_test_rpc.rpc_types import TransactionByHashResponse
from ethereum_test_types import Environment
diff --git a/src/ethereum_spec_tests/cli/gentest/source_code_generator.py b/packages/tests/src/cli/gentest/source_code_generator.py
similarity index 82%
rename from src/ethereum_spec_tests/cli/gentest/source_code_generator.py
rename to packages/tests/src/cli/gentest/source_code_generator.py
index e437631aad..d78dc82693 100644
--- a/src/ethereum_spec_tests/cli/gentest/source_code_generator.py
+++ b/packages/tests/src/cli/gentest/source_code_generator.py
@@ -22,18 +22,22 @@
template_env.filters["stringify"] = lambda value: repr(value)
-# generates a formatted pytest source code by writing provided data on a given template.
+# generates a formatted pytest source code by writing provided data on a given
+# template.
def get_test_source(provider: Provider, template_path: str) -> str:
"""
- Generate formatted pytest source code by rendering a template with provided data.
+ Generate formatted pytest source code by rendering a template with provided
+ data.
- This function uses the given template path to create a pytest-compatible source
- code string. It retrieves context data from the specified provider and applies
- it to the template.
+ This function uses the given template path to create a pytest-compatible
+ source code string. It retrieves context data from the specified provider
+ and applies it to the template.
Args:
- provider: An object that provides the necessary context for rendering the template.
- template_path (str): The path to the Jinja2 template file used to generate tests.
+ provider: An object that provides the necessary context for rendering
+ the template.
+ template_path (str): The path to the Jinja2 template file
+ used to generate tests.
Returns:
str: The formatted pytest source code.
@@ -49,11 +53,11 @@ def format_code(code: str) -> str:
"""
Format the provided Python code using the Black code formatter.
- This function writes the given code to a temporary Python file, formats it using
- the Black formatter, and returns the formatted code as a string.
+ This function writes the given code to a temporary Python file, formats it
+ using the Black formatter, and returns the formatted code as a string.
Args:
- code (str): The Python code to be formatted.
+ code (str): The Python code to be formatted.
Returns:
str: The formatted Python code.
diff --git a/src/ethereum_spec_tests/cli/gentest/templates/blockchain_test/transaction.py.j2 b/packages/tests/src/cli/gentest/templates/blockchain_test/transaction.py.j2
similarity index 100%
rename from src/ethereum_spec_tests/cli/gentest/templates/blockchain_test/transaction.py.j2
rename to packages/tests/src/cli/gentest/templates/blockchain_test/transaction.py.j2
diff --git a/src/ethereum_spec_tests/cli/gentest/test_context_providers.py b/packages/tests/src/cli/gentest/test_context_providers.py
similarity index 85%
rename from src/ethereum_spec_tests/cli/gentest/test_context_providers.py
rename to packages/tests/src/cli/gentest/test_context_providers.py
index 54b913cf86..42a56f3f0d 100644
--- a/src/ethereum_spec_tests/cli/gentest/test_context_providers.py
+++ b/packages/tests/src/cli/gentest/test_context_providers.py
@@ -2,13 +2,14 @@
Various providers which generate contexts required to create test scripts.
Classes:
-- Provider: An provider generates required context for creating a test.
-- BlockchainTestProvider: The BlockchainTestProvider takes a transaction hash and creates
- required context to create a test.
+ Provider: An provider generates required context for creating a
+ test.
+ BlockchainTestProvider: The BlockchainTestProvider takes a transaction
+ hash and creates required context to create a test.
Example:
- provider = BlockchainTestContextProvider(transaction=transaction)
- context = provider.get_context()
+ provider = BlockchainTestContextProvider(transaction=transaction)
+ context = provider.get_context()
"""
@@ -19,7 +20,7 @@
from pydantic import BaseModel
from ethereum_test_base_types import Account, Hash
-from ethereum_test_rpc.types import TransactionByHashResponse
+from ethereum_test_rpc.rpc_types import TransactionByHashResponse
from ethereum_test_tools import Environment, Transaction
from .request_manager import RPCRequest
@@ -80,7 +81,8 @@ def _get_pre_state(self) -> Dict[str, Account]:
def _get_transaction(self) -> Transaction:
assert self.transaction_response is not None
- # Validate the RPC TransactionHashResponse and convert it to a Transaction instance.
+ # Validate the RPC TransactionHashResponse and convert it to a
+ # Transaction instance.
return Transaction.model_validate(self.transaction_response.model_dump())
def get_context(self) -> Dict[str, Any]:
@@ -89,7 +91,7 @@ def get_context(self) -> Dict[str, Any]:
Returns:
Dict[str, Any]: A dictionary containing environment,
- pre-state, a transaction and its hash.
+ pre-state, a transaction and its hash.
"""
self._make_rpc_calls()
diff --git a/src/ethereum_spec_tests/cli/gentest/test_providers.py b/packages/tests/src/cli/gentest/test_providers.py
similarity index 78%
rename from src/ethereum_spec_tests/cli/gentest/test_providers.py
rename to packages/tests/src/cli/gentest/test_providers.py
index 75a44fbe89..d9cdeaba6a 100644
--- a/src/ethereum_spec_tests/cli/gentest/test_providers.py
+++ b/packages/tests/src/cli/gentest/test_providers.py
@@ -1,14 +1,21 @@
"""
-Contains various providers which generates context required to create test scripts.
+Contains various providers which generates context required to create test
+scripts.
Classes:
-- BlockchainTestProvider: The BlockchainTestProvider class takes information about a block,
-a transaction, and the associated state, and provides methods to generate various elements
-needed for testing, such as module docstrings, test names, and pre-state items.
+ BlockchainTestProvider: The BlockchainTestProvider class takes
+ information about a block, a transaction, and the
+ associated state, and provides methods to generate
+ various elements needed for testing, such as module
+ docstrings, test names, and pre-state items.
Example:
- provider = BlockchainTestProvider(block=block, transaction=transaction, state=state)
- context = provider.get_context()
+ provider = BlockchainTestProvider(
+ block=block,
+ transaction=transaction,
+ state=state
+ )
+ context = provider.get_context()
"""
@@ -17,12 +24,14 @@
from pydantic import BaseModel
from ethereum_test_base_types import Account, Address, ZeroPaddedHexNumber
-from ethereum_test_rpc.types import TransactionByHashResponse
+from ethereum_test_rpc.rpc_types import TransactionByHashResponse
from ethereum_test_types import Environment
class BlockchainTestProvider(BaseModel):
- """Provides context required to generate a `blockchain_test` using pytest."""
+ """
+ Provides context required to generate a `blockchain_test` using pytest.
+ """
block: Environment
transaction: TransactionByHashResponse
@@ -103,8 +112,9 @@ def get_context(self) -> Dict[str, Any]:
Get the context for generating a blockchain test.
Returns:
- Dict[str, Any]: A dictionary containing module docstring, test name,
- test docstring, environment kwargs, pre-state items, and transaction items.
+ Dict[str, Any]: A dictionary containing module docstring, test
+ name, test docstring, environment kwargs,
+ pre-state items, and transaction items.
"""
return {
diff --git a/src/ethereum_spec_tests/cli/gentest/tests/__init__.py b/packages/tests/src/cli/gentest/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/gentest/tests/__init__.py
rename to packages/tests/src/cli/gentest/tests/__init__.py
diff --git a/src/ethereum_spec_tests/cli/gentest/tests/test_cli.py b/packages/tests/src/cli/gentest/tests/test_cli.py
similarity index 95%
rename from src/ethereum_spec_tests/cli/gentest/tests/test_cli.py
rename to packages/tests/src/cli/gentest/tests/test_cli.py
index 27ff66489b..cac98388d9 100644
--- a/src/ethereum_spec_tests/cli/gentest/tests/test_cli.py
+++ b/packages/tests/src/cli/gentest/tests/test_cli.py
@@ -92,10 +92,10 @@ def transaction_hash(tx_type: int) -> str: # noqa: D103
@pytest.mark.parametrize("tx_type", list(transactions_by_type.keys()))
def test_tx_type(pytester, tmp_path, monkeypatch, tx_type, transaction_hash, default_t8n):
"""Generates a test case for any transaction type."""
- ## Arrange ##
- # This test is run in a CI environment, where connection to a node could be
- # unreliable. Therefore, we mock the RPC request to avoid any network issues.
- # This is done by patching the `get_context` method of the `StateTestProvider`.
+ # This test is run in a CI environment, where connection to a
+ # node could be unreliable. Therefore, we mock the RPC request to avoid any
+ # network issues. This is done by patching the `get_context` method of the
+ # `StateTestProvider`.
runner = CliRunner()
tmp_path_tests = tmp_path / "tests"
tmp_path_tests.mkdir()
@@ -106,6 +106,7 @@ def test_tx_type(pytester, tmp_path, monkeypatch, tx_type, transaction_hash, def
tx = transactions_by_type[tx_type]
def get_mock_context(self: StateTestProvider) -> dict:
+ del self
return tx
monkeypatch.setattr(StateTestProvider, "get_context", get_mock_context)
diff --git a/src/ethereum_spec_tests/cli/hasher.py b/packages/tests/src/cli/hasher.py
similarity index 97%
rename from src/ethereum_spec_tests/cli/hasher.py
rename to packages/tests/src/cli/hasher.py
index bd5caaeca5..ab1dd87480 100644
--- a/src/ethereum_spec_tests/cli/hasher.py
+++ b/packages/tests/src/cli/hasher.py
@@ -20,7 +20,10 @@ class HashableItemType(IntEnum):
@dataclass(kw_only=True)
class HashableItem:
- """Represents an item that can be hashed containing other items that can be hashed as well."""
+ """
+ Represents an item that can be hashed containing other items that can be
+ hashed as well.
+ """
type: HashableItemType
parents: List[str] = field(default_factory=list)
diff --git a/src/ethereum_spec_tests/cli/input/__init__.py b/packages/tests/src/cli/input/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/input/__init__.py
rename to packages/tests/src/cli/input/__init__.py
diff --git a/src/ethereum_spec_tests/cli/input/input_repository.py b/packages/tests/src/cli/input/input_repository.py
similarity index 87%
rename from src/ethereum_spec_tests/cli/input/input_repository.py
rename to packages/tests/src/cli/input/input_repository.py
index 0a75d14de8..83b31c830b 100644
--- a/src/ethereum_spec_tests/cli/input/input_repository.py
+++ b/packages/tests/src/cli/input/input_repository.py
@@ -6,8 +6,8 @@
class InputRepository(ABC):
"""
- Abstract base class for input handling.
- This class defines the interface for different input types that can be swapped out.
+ Abstract base class for input handling. This class defines the interface
+ for different input types that can be swapped out.
"""
@abstractmethod
diff --git a/src/ethereum_spec_tests/cli/input/questionary_input_repository.py b/packages/tests/src/cli/input/questionary_input_repository.py
similarity index 90%
rename from src/ethereum_spec_tests/cli/input/questionary_input_repository.py
rename to packages/tests/src/cli/input/questionary_input_repository.py
index af0e2e144c..8ddc6b18b6 100644
--- a/src/ethereum_spec_tests/cli/input/questionary_input_repository.py
+++ b/packages/tests/src/cli/input/questionary_input_repository.py
@@ -9,7 +9,10 @@
class QuestionaryInputRepository(InputRepository):
- """Repository for handling various types of user inputs using the Questionary library."""
+ """
+ Repository for handling various types of user inputs using the Questionary
+ library.
+ """
def input_text(self, question: str) -> str:
"""Ask a text input question."""
diff --git a/src/ethereum_spec_tests/cli/modify_static_test_gas_limits.py b/packages/tests/src/cli/modify_static_test_gas_limits.py
similarity index 97%
rename from src/ethereum_spec_tests/cli/modify_static_test_gas_limits.py
rename to packages/tests/src/cli/modify_static_test_gas_limits.py
index 17f0b5137c..35a259d88f 100644
--- a/src/ethereum_spec_tests/cli/modify_static_test_gas_limits.py
+++ b/packages/tests/src/cli/modify_static_test_gas_limits.py
@@ -1,6 +1,6 @@
"""
-Command to scan and overwrite the static tests' gas limits to new optimized value given in the
-input file.
+Command to scan and overwrite the static tests' gas limits to new optimized
+value given in the input file.
"""
import json
@@ -46,7 +46,9 @@ class StaticTestFile(EthereumTestRootModel):
def _check_fixtures(*, input_path: Path, max_gas_limit: int | None, dry_run: bool, verbose: bool):
- """Perform some checks on the fixtures contained in the specified directory."""
+ """
+ Perform some checks on the fixtures contained in the specified directory.
+ """
# Load the test dictionary from the input JSON file
test_dict = GasLimitDict.model_validate_json(input_path.read_text())
@@ -207,7 +209,9 @@ def _check_fixtures(*, input_path: Path, max_gas_limit: int | None, dry_run: boo
help="Print extra information.",
)
def main(input_str: str, max_gas_limit, dry_run: bool, verbose: bool):
- """Perform some checks on the fixtures contained in the specified directory."""
+ """
+ Perform some checks on the fixtures contained in the specified directory.
+ """
input_path = Path(input_str)
if not dry_run:
# Always dry-run first before actually modifying
diff --git a/src/ethereum_spec_tests/cli/order_fixtures.py b/packages/tests/src/cli/order_fixtures.py
similarity index 76%
rename from src/ethereum_spec_tests/cli/order_fixtures.py
rename to packages/tests/src/cli/order_fixtures.py
index 7b90281452..d35412e755 100644
--- a/src/ethereum_spec_tests/cli/order_fixtures.py
+++ b/packages/tests/src/cli/order_fixtures.py
@@ -1,18 +1,17 @@
"""
Functions and CLI interface for recursively ordering and sorting .json files.
-example: Usage
-
- ```
- order_fixtures -i input_dir -o output_dir
- ```
+Usage Example:
+```console
+ order_fixtures -i input_dir -o output_dir
+```
The CLI interface takes the paths of an input directory and an output
directory. It recursively processes each .json file in the input directory and
-its subdirectories, and sorts lists and dictionaries alphabetically and
-writes the sorted output to .json files to the corresponding locations in the
-output directory.
+its subdirectories, and sorts lists and dictionaries alphabetically and writes
+the sorted output to .json files to the corresponding locations in the output
+directory.
"""
import json
@@ -27,16 +26,15 @@ def recursive_sort(item: Dict[str, Any] | List[Any]) -> Dict[str, Any] | List[An
Recursively sorts an item.
If the item is a dictionary, it returns a new dictionary that is a sorted
- version of the input dictionary.
- If the item is a list, it returns a new list that is a sorted version of the
- input list. The elements of the list are also sorted if they are lists or
- dictionaries.
+ version of the input dictionary. If the item is a list, it returns a new
+ list that is a sorted version of the input list. The elements of the list
+ are also sorted if they are lists or dictionaries.
Args:
- item: The item to be sorted. This can be a list or a dictionary.
+ item: The item to be sorted. This can be a list or a dictionary.
Returns:
- The sorted item.
+ The sorted item.
"""
if isinstance(item, dict):
@@ -45,8 +43,8 @@ def recursive_sort(item: Dict[str, Any] | List[Any]) -> Dict[str, Any] | List[An
try:
return sorted(cast(List[Any], [recursive_sort(x) for x in item]))
except TypeError:
- # If a TypeError is raised, we might be dealing with a list of dictionaries
- # Sort them based on their string representation
+ # If a TypeError is raised, we might be dealing with a list of
+ # dictionaries Sort them based on their string representation
return sorted((recursive_sort(x) for x in item), key=str)
else:
return item
@@ -60,8 +58,8 @@ def order_fixture(input_path: Path, output_path: Path) -> None:
to the output path.
Args:
- input_path: The Path object of the input .json file.
- output_path: The Path object of the output .json file.
+ input_path: The Path object of the input .json file.
+ output_path: The Path object of the output .json file.
Returns:
None.
@@ -78,9 +76,9 @@ def process_directory(input_dir: Path, output_dir: Path):
"""
Process a directory.
- Processes each .json file in the input directory and its subdirectories, and
- writes the sorted .json files to the corresponding locations in the output
- directory.
+ Processes each .json file in the input directory and its subdirectories,
+ and writes the sorted .json files to the corresponding locations in the
+ output directory.
Args:
input_dir: The Path object of the input directory.
@@ -106,7 +104,7 @@ def process_directory(input_dir: Path, output_dir: Path):
"input_dir",
type=click.Path(exists=True, file_okay=False, dir_okay=True, readable=True),
required=True,
- help="The input directory",
+ help="input directory",
)
@click.option(
"--output",
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/__init__.py b/packages/tests/src/cli/pytest_commands/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/pytest_commands/__init__.py
rename to packages/tests/src/cli/pytest_commands/__init__.py
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/base.py b/packages/tests/src/cli/pytest_commands/base.py
similarity index 95%
rename from src/ethereum_spec_tests/cli/pytest_commands/base.py
rename to packages/tests/src/cli/pytest_commands/base.py
index 7061741e47..444de79561 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/base.py
+++ b/packages/tests/src/cli/pytest_commands/base.py
@@ -24,7 +24,10 @@ class PytestExecution:
"""Path to the pytest configuration file (e.g., 'pytest-fill.ini')."""
command_logic_test_paths: List[str] = field(default_factory=list)
- """List of tests that have to be appended to the start of pytest command arguments."""
+ """
+ List of tests that have to be appended to the start of pytest command
+ arguments.
+ """
args: List[str] = field(default_factory=list)
"""Arguments to pass to pytest."""
@@ -80,7 +83,8 @@ def run_multiple(self, executions: List[PytestExecution]) -> int:
"""
Run multiple pytest executions in sequence.
- Returns the exit code of the final execution, or the first non-zero exit code.
+ Returns the exit code of the final execution, or the first non-zero
+ exit code.
"""
for i, execution in enumerate(executions):
if execution.description and len(executions) > 1:
@@ -102,8 +106,8 @@ class PytestCommand:
"""
Base class for pytest-based CLI commands.
- Provides a standard structure for commands that execute pytest
- with specific configurations and argument processing.
+ Provides a standard structure for commands that execute pytest with
+ specific configurations and argument processing.
"""
config_file: str
@@ -138,8 +142,8 @@ def execute(self, pytest_args: List[str]) -> None:
@property
def test_args(self) -> List[str]:
"""
- Return the test-path arguments that have to be appended to all PytestExecution
- instances.
+ Return the test-path arguments that have to be appended to all
+ PytestExecution instances.
"""
if self.command_logic_test_paths:
return [str(path) for path in self.command_logic_test_paths]
@@ -149,8 +153,8 @@ def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]:
"""
Create the list of pytest executions for this command.
- This method can be overridden by subclasses to implement
- multi-phase execution (e.g., for future fill command).
+ This method can be overridden by subclasses to implement multi-phase
+ execution (e.g., for future fill command).
"""
processed_args = self.process_arguments(pytest_args)
return [
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/check_eip_versions.py b/packages/tests/src/cli/pytest_commands/check_eip_versions.py
similarity index 97%
rename from src/ethereum_spec_tests/cli/pytest_commands/check_eip_versions.py
rename to packages/tests/src/cli/pytest_commands/check_eip_versions.py
index 46e0875b3d..32b714b64e 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/check_eip_versions.py
+++ b/packages/tests/src/cli/pytest_commands/check_eip_versions.py
@@ -14,6 +14,8 @@
@common_pytest_options
def check_eip_versions(pytest_args: List[str], **kwargs) -> None:
"""Run pytest with the `spec_version_checker` plugin."""
+ del kwargs
+
command = PytestCommand(
config_file="pytest-check-eip-versions.ini",
argument_processors=[HelpFlagsProcessor("check-eip-versions")],
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/checklist.py b/packages/tests/src/cli/pytest_commands/checklist.py
similarity index 98%
rename from src/ethereum_spec_tests/cli/pytest_commands/checklist.py
rename to packages/tests/src/cli/pytest_commands/checklist.py
index 2114853636..d87b2a14a8 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/checklist.py
+++ b/packages/tests/src/cli/pytest_commands/checklist.py
@@ -41,6 +41,8 @@ def checklist(output: str, eip: tuple, **kwargs) -> None:
uv run checklist --output ./my-checklists
"""
+ del kwargs
+
# Add output directory to pytest args
args = ["--checklist-output", output]
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/consume.py b/packages/tests/src/cli/pytest_commands/consume.py
similarity index 96%
rename from src/ethereum_spec_tests/cli/pytest_commands/consume.py
rename to packages/tests/src/cli/pytest_commands/consume.py
index bf4d662000..cc9b202038 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/consume.py
+++ b/packages/tests/src/cli/pytest_commands/consume.py
@@ -36,7 +36,7 @@ def create_consume_command(
)
-def get_command_logic_test_paths(command_name: str, is_hive: bool) -> List[Path]:
+def get_command_logic_test_paths(command_name: str) -> List[Path]:
"""Determine the command paths based on the command name and hive flag."""
base_path = Path("pytest_plugins/consume")
if command_name in ["engine", "rlp"]:
@@ -66,7 +66,7 @@ def consume_command(is_hive: bool = False) -> Callable[[Callable[..., Any]], cli
def decorator(func: Callable[..., Any]) -> click.Command:
command_name = func.__name__
command_help = func.__doc__
- command_logic_test_paths = get_command_logic_test_paths(command_name, is_hive)
+ command_logic_test_paths = get_command_logic_test_paths(command_name)
@consume.command(
name=command_name,
@@ -76,6 +76,8 @@ def decorator(func: Callable[..., Any]) -> click.Command:
@common_pytest_options
@functools.wraps(func)
def command(pytest_args: List[str], **kwargs) -> None:
+ del kwargs
+
consume_cmd = create_consume_command(
command_logic_test_paths=command_logic_test_paths,
is_hive=is_hive,
@@ -118,5 +120,7 @@ def sync() -> None:
@common_pytest_options
def cache(pytest_args: List[str], **kwargs) -> None:
"""Consume command to cache test fixtures."""
+ del kwargs
+
cache_cmd = create_consume_command(command_logic_test_paths=[], is_hive=False)
cache_cmd.execute(list(pytest_args))
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/execute.py b/packages/tests/src/cli/pytest_commands/execute.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/pytest_commands/execute.py
rename to packages/tests/src/cli/pytest_commands/execute.py
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/fill.py b/packages/tests/src/cli/pytest_commands/fill.py
similarity index 84%
rename from src/ethereum_spec_tests/cli/pytest_commands/fill.py
rename to packages/tests/src/cli/pytest_commands/fill.py
index 9b98628f67..87d5af0041 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/fill.py
+++ b/packages/tests/src/cli/pytest_commands/fill.py
@@ -5,7 +5,8 @@
import click
from .base import PytestCommand, PytestExecution, common_pytest_options
-from .processors import HelpFlagsProcessor, StdoutFlagsProcessor
+from .processors import HelpFlagsProcessor, StdoutFlagsProcessor, WatchFlagsProcessor
+from .watcher import FileWatcher
class FillCommand(PytestCommand):
@@ -18,16 +19,19 @@ def __init__(self, **kwargs):
argument_processors=[
HelpFlagsProcessor("fill"),
StdoutFlagsProcessor(),
+ WatchFlagsProcessor(),
],
**kwargs,
)
def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]:
"""
- Create execution plan that supports two-phase pre-allocation group generation.
+ Create execution plan that supports two-phase pre-allocation group
+ generation.
Returns single execution for normal filling, or two-phase execution
- when --generate-pre-alloc-groups or --generate-all-formats is specified.
+ when --generate-pre-alloc-groups or --generate-all-formats is
+ specified.
"""
processed_args = self.process_arguments(pytest_args)
@@ -48,7 +52,10 @@ def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]:
]
def _create_two_phase_executions(self, args: List[str]) -> List[PytestExecution]:
- """Create two-phase execution: pre-allocation group generation + fixture filling."""
+ """
+ Create two-phase execution: pre-allocation group generation + fixture
+ filling.
+ """
# Phase 1: Pre-allocation group generation (clean and minimal output)
phase1_args = self._create_phase1_args(args)
@@ -85,14 +92,16 @@ def _create_phase1_args(self, args: List[str]) -> List[str]:
# Add required phase 1 flags (with quiet output by default)
phase1_args = [
"--generate-pre-alloc-groups",
- "-qq", # Quiet pytest output by default (user -v/-vv/-vvv can override)
+ "-qq", # Quiet pytest output by default (user -v/-vv/-vvv can
+ # override)
] + filtered_args
return phase1_args
def _create_phase2_args(self, args: List[str]) -> List[str]:
"""Create arguments for phase 2 (fixture filling)."""
- # Remove --generate-pre-alloc-groups and --clean, then add --use-pre-alloc-groups
+ # Remove --generate-pre-alloc-groups and --clean, then add --use-pre-
+ # alloc-groups
phase2_args = self._remove_generate_pre_alloc_groups_flag(args)
phase2_args = self._remove_clean_flag(phase2_args)
phase2_args = self._add_use_pre_alloc_groups_flag(phase2_args)
@@ -136,7 +145,10 @@ def _remove_unwanted_phase1_args(self, args: List[str]) -> List[str]:
return filtered_args
def _remove_generate_pre_alloc_groups_flag(self, args: List[str]) -> List[str]:
- """Remove --generate-pre-alloc-groups flag but keep --generate-all-formats for phase 2."""
+ """
+ Remove --generate-pre-alloc-groups flag but keep --generate-all-formats
+ for phase 2.
+ """
return [arg for arg in args if arg != "--generate-pre-alloc-groups"]
def _remove_clean_flag(self, args: List[str]) -> List[str]:
@@ -174,6 +186,30 @@ def _is_tarball_output(self, args: List[str]) -> bool:
return str(output_path).endswith(".tar.gz")
return False
+ def _is_watch_mode(self, args: List[str]) -> bool:
+ """Check if any watch flag is present in arguments."""
+ return any(flag in args for flag in ["--watch", "--watcherfall"])
+
+ def _is_verbose_watch_mode(self, args: List[str]) -> bool:
+ """
+ Check if verbose watch flag (--watcherfall)
+ is present in arguments.
+ """
+ return "--watcherfall" in args
+
+ def execute(self, pytest_args: List[str]) -> None:
+ """Execute the command with optional watch mode support."""
+ if self._is_watch_mode(pytest_args):
+ self._execute_with_watch(pytest_args)
+ else:
+ super().execute(pytest_args)
+
+ def _execute_with_watch(self, pytest_args: List[str]) -> None:
+ """Execute fill command in watch mode."""
+ verbose = self._is_verbose_watch_mode(pytest_args)
+ watcher = FileWatcher(console=self.runner.console, verbose=verbose)
+ watcher.run_with_watch(pytest_args)
+
class PhilCommand(FillCommand):
"""Friendly fill command with emoji reporting."""
@@ -213,6 +249,8 @@ def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]:
@common_pytest_options
def fill(pytest_args: List[str], **kwargs) -> None:
"""Entry point for the fill command."""
+ del kwargs
+
command = FillCommand()
command.execute(list(pytest_args))
@@ -225,10 +263,13 @@ def fill(pytest_args: List[str], **kwargs) -> None:
@common_pytest_options
def phil(pytest_args: List[str], **kwargs) -> None:
"""Friendly alias for the fill command."""
+ del kwargs
+
command = PhilCommand()
command.execute(list(pytest_args))
if __name__ == "__main__":
- # to allow debugging in vscode: in launch config, set "module": "cli.pytest_commands.fill"
+ # to allow debugging in vscode: in launch config, set "module":
+ # "cli.pytest_commands.fill"
fill(prog_name="fill")
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/processors.py b/packages/tests/src/cli/pytest_commands/processors.py
similarity index 87%
rename from src/ethereum_spec_tests/cli/pytest_commands/processors.py
rename to packages/tests/src/cli/pytest_commands/processors.py
index 5810d87f0c..b63cd3a132 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/processors.py
+++ b/packages/tests/src/cli/pytest_commands/processors.py
@@ -18,8 +18,9 @@ def __init__(self, command_type: str, required_args: List[str] | None = None):
Initialize the help processor.
Args:
- command_type: The type of command (e.g., "fill", "consume", "execute")
- required_args: The arguments that are required for the command to run
+ command_type: The type of command (e.g., "fill", "consume",
+ "execute")
+ required_args: The arguments that are required for the command to run
"""
self.command_type = command_type
@@ -48,8 +49,8 @@ class StdoutFlagsProcessor(ArgumentProcessor):
def process_args(self, args: List[str]) -> List[str]:
"""
- If the user has requested to write to stdout, add pytest arguments
- to suppress pytest's test session header and summary output.
+ If the user has requested to write to stdout, add pytest arguments to
+ suppress pytest's test session header and summary output.
"""
if not self._is_writing_to_stdout(args):
return args
@@ -118,6 +119,20 @@ def _has_parallelism_flag(self, args: List[str]) -> bool:
return "-n" in args
+class WatchFlagsProcessor(ArgumentProcessor):
+ """
+ Processes --watch and --watcherfall flags
+ for file watching functionality.
+ """
+
+ def process_args(self, args: List[str]) -> List[str]:
+ """
+ Remove --watch and --watcherfall
+ flags from args passed to pytest.
+ """
+ return [arg for arg in args if arg not in ["--watch", "--watcherfall"]]
+
+
class ConsumeCommandProcessor(ArgumentProcessor):
"""Processes consume-specific command arguments."""
@@ -126,7 +141,7 @@ def __init__(self, is_hive: bool = False):
Initialize the consume processor.
Args:
- is_hive: Whether this is a hive-based consume command
+ is_hive: Whether this is a hive-based consume command
"""
self.is_hive = is_hive
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini
similarity index 100%
rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini
rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-consume.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-consume.ini
similarity index 85%
rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-consume.ini
rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-consume.ini
index b6efe7a551..e8e005aaa1 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-consume.ini
+++ b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-consume.ini
@@ -8,6 +8,6 @@ addopts =
-p pytest_plugins.concurrency
# disable pytest built-in logging entirely `-p no:logging`
-p no:logging
- -p pytest_plugins.logging.logging
+ -p pytest_plugins.custom_logging.plugin_logging
-p pytest_plugins.consume.consume
-p pytest_plugins.help.help
\ No newline at end of file
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini
similarity index 85%
rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini
rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini
index 439116dab5..9b098a5efc 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini
+++ b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini
@@ -6,7 +6,7 @@ python_files = *.py
addopts =
-p pytest_plugins.execute.eth_config.eth_config
-p pytest_plugins.help.help
- -p pytest_plugins.logging.logging
+ -p pytest_plugins.custom_logging.plugin_logging
-m "not eip_version_check"
--tb short
--dist loadscope
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini
similarity index 100%
rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini
rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini
similarity index 100%
rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini
rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute.ini
similarity index 93%
rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute.ini
rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute.ini
index 8e476ead0c..9797d1f892 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute.ini
+++ b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute.ini
@@ -16,7 +16,7 @@ addopts =
-p pytest_plugins.execute.rpc.remote
-p pytest_plugins.forks.forks
-p pytest_plugins.help.help
- -p pytest_plugins.logging.logging
+ -p pytest_plugins.custom_logging.plugin_logging
--tb short
--dist loadscope
--ignore tests/cancun/eip4844_blobs/point_evaluation_vectors/
diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-fill.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini
similarity index 94%
rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-fill.ini
rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini
index 72476e7e5a..e447738bbf 100644
--- a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-fill.ini
+++ b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini
@@ -16,7 +16,7 @@ addopts =
-p pytest_plugins.shared.transaction_fixtures
-p pytest_plugins.forks.forks
-p pytest_plugins.help.help
- -p pytest_plugins.logging.logging
+ -p pytest_plugins.custom_logging.plugin_logging
--tb short
--ignore tests/cancun/eip4844_blobs/point_evaluation_vectors/
# these customizations require the pytest-custom-report plugin
diff --git a/packages/tests/src/cli/pytest_commands/watcher.py b/packages/tests/src/cli/pytest_commands/watcher.py
new file mode 100644
index 0000000000..bec93dc02f
--- /dev/null
+++ b/packages/tests/src/cli/pytest_commands/watcher.py
@@ -0,0 +1,86 @@
+"""File watcher implementation for --watch flag functionality."""
+
+import os
+import subprocess
+import time
+from pathlib import Path
+from typing import Dict
+
+from rich.console import Console
+
+
+class FileWatcher:
+ """Simple file watcher that re-runs the fill command on changes."""
+
+ def __init__(self, console=None, verbose=False):
+ """Initialize the file watcher."""
+ self.console = console or Console(highlight=False)
+ self.verbose = verbose
+
+ def run_with_watch(self, args):
+ """Watch for file changes and re-run fill command."""
+ file_mtimes: Dict[Path, float] = {}
+
+ def get_file_mtimes():
+ """Get current modification times of all test and source files."""
+ mtimes = {}
+ # Watch tests directory
+ tests_dir = Path("tests")
+ if tests_dir.exists():
+ for py_file in tests_dir.rglob("*.py"):
+ try:
+ mtimes[py_file] = py_file.stat().st_mtime
+ except (OSError, FileNotFoundError):
+ pass
+ # Watch src directory
+ src_dir = Path("src")
+ if src_dir.exists():
+ for py_file in src_dir.rglob("*.py"):
+ try:
+ mtimes[py_file] = py_file.stat().st_mtime
+ except (OSError, FileNotFoundError):
+ pass
+ return mtimes
+
+ def run_fill():
+ """Run fill command without --watch / --watcherfall flag."""
+ clean_args = [arg for arg in args if arg not in ["--watch", "--watcherfall"]]
+ cmd = ["uv", "run", "fill"] + clean_args
+ result = subprocess.run(cmd)
+
+ if result.returncode == 0:
+ self.console.print("[green]✓ Fill completed[/green]")
+ else:
+ self.console.print(f"[red]✗ Fill failed (exit {result.returncode})[/red]")
+
+ # Setup
+ mode_desc = "watcherfall mode (verbose)" if self.verbose else "watch mode"
+ self.console.print(f"[blue]Starting {mode_desc}...[/blue]")
+ file_mtimes = get_file_mtimes()
+
+ # Initial run
+ self.console.print("[green]Running initial fill...[/green]")
+ run_fill()
+
+ file_count = len(file_mtimes)
+ self.console.print(
+ f"[blue]Watching {file_count} files in tests/ and src/ directories."
+ "\n Press Ctrl+C to stop.[/blue]"
+ )
+
+ # Watch loop
+ try:
+ while True:
+ time.sleep(0.5)
+ current_mtimes = get_file_mtimes()
+
+ if current_mtimes != file_mtimes:
+ if not self.verbose:
+ os.system("clear" if os.name != "nt" else "cls")
+ self.console.print("[yellow]File changes detected, re-running...[/yellow]\n")
+ run_fill()
+ file_mtimes = current_mtimes
+ self.console.print("\n[blue]Watching for changes...[/blue]")
+
+ except KeyboardInterrupt:
+ self.console.print("\n[yellow]Watch mode stopped.[/yellow]")
diff --git a/src/ethereum_spec_tests/cli/show_pre_alloc_group_stats.py b/packages/tests/src/cli/show_pre_alloc_group_stats.py
similarity index 93%
rename from src/ethereum_spec_tests/cli/show_pre_alloc_group_stats.py
rename to packages/tests/src/cli/show_pre_alloc_group_stats.py
index a5d10183e1..492c1f0c6a 100644
--- a/src/ethereum_spec_tests/cli/show_pre_alloc_group_stats.py
+++ b/packages/tests/src/cli/show_pre_alloc_group_stats.py
@@ -15,7 +15,9 @@
def extract_test_module(test_id: str) -> str:
"""Extract test module path from test ID."""
- # Example: tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::test_beacon_root_contract_calls[fork_Cancun] # noqa: E501
+ # Example:
+ # tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::
+ # test_beacon_root_contract_calls[fork_Cancun]
if "::" in test_id:
return test_id.split("::")[0]
return "unknown"
@@ -23,8 +25,12 @@ def extract_test_module(test_id: str) -> str:
def extract_test_function(test_id: str) -> str:
"""Extract test function name from test ID (without parameters)."""
- # Example: tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::test_beacon_root_contract_calls[fork_Cancun] # noqa: E501
- # Returns: tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::test_beacon_root_contract_calls # noqa: E501
+ # Example:
+ # tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::
+ # test_beacon_root_contract_calls[fork_Cancun]
+ # Returns:
+ # tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::
+ # test_beacon_root_contract_calls
if "::" in test_id:
parts = test_id.split("::")
if len(parts) >= 2:
@@ -43,9 +49,10 @@ def calculate_size_distribution(
Calculate frequency distribution of group sizes with appropriate binning.
Returns:
- - Group count distribution: [(range_label, group_count), ...]
- - Test count distribution: [(range_label, test_count, cumulative_remaining, group_count),
- ...]
+ Group count distribution: [(range_label, group_count), ...]
+ Test count distribution: [(range_label, test_count,
+ cumulative_remaining,
+ group_count), ...]
"""
if not test_counts:
@@ -80,12 +87,15 @@ def calculate_size_distribution(
# Test count distribution with group count
tests_in_bin = sum(groups_in_bin)
- test_distribution.append((label, tests_in_bin, 0, group_count)) # Added group_count
+ # Added group_count
+ test_distribution.append((label, tests_in_bin, 0, group_count))
- # Calculate cumulative values
- # For the table sorted from largest to smallest:
- # - Row N shows: if we exclude groups of size N and smaller, what % of tests remain?
- # - Row N shows: if we include groups of size N and larger, how many groups is that?
+ # Calculate cumulative values For the table sorted from largest to
+ # smallest:
+ # Row N shows: if we exclude groups of size N and smaller, what
+ # percent of tests remain?
+ # Row N shows: if we include groups of size N and
+ # larger, how many groups is that?
cumulative_remaining_tests = 0
cumulative_groups = 0
@@ -100,7 +110,7 @@ def calculate_size_distribution(
return group_distribution, test_distribution
-def analyze_pre_alloc_folder(folder: Path, verbose: int = 0) -> Dict:
+def analyze_pre_alloc_folder(folder: Path) -> Dict:
"""Analyze pre-allocation folder and return statistics."""
pre_alloc_groups = PreAllocGroups.from_folder(folder, lazy_load=False)
@@ -167,7 +177,8 @@ class SplitTestFunction(CamelModel):
split_test_functions[test_function].groups += 1
split_test_functions[test_function].forks.add(fork)
- # Filter to only test functions with multiple size-1 groups and calculate ratios
+ # Filter to only test functions with multiple size-1 groups and calculate
+ # ratios
split_functions = {}
for func, split_test_function in split_test_functions.items():
if split_test_function.groups > 1:
@@ -355,7 +366,8 @@ def display_stats(stats: Dict, console: Console, verbose: int = 0):
# Sort modules by group count (descending) - shows execution complexity
sorted_modules = sorted(
stats["module_stats"].items(),
- key=lambda x: (-x[1]["groups"], -x[1]["tests"]), # Secondary sort by tests
+ # Secondary sort by tests
+ key=lambda x: (-x[1]["groups"], -x[1]["tests"]),
)
# Show all modules if -vv, otherwise top 15
@@ -412,7 +424,8 @@ def display_stats(stats: Dict, console: Console, verbose: int = 0):
# Shorten function path for display
display_function = test_function
if display_function.startswith("tests/"):
- display_function = display_function[6:] # Remove "tests/" prefix
+ display_function = display_function[6:] # Remove "tests/"
+ # prefix
split_table.add_row(
display_function,
@@ -475,12 +488,11 @@ def main(pre_alloc_folder: Path, verbose: int):
The pre_alloc file is generated when running tests with the
--generate-pre-alloc-groups and --use-pre-alloc-groups flags to optimize
test execution by grouping tests with identical pre-allocation state.
-
"""
console = Console()
try:
- stats = analyze_pre_alloc_folder(pre_alloc_folder, verbose=verbose)
+ stats = analyze_pre_alloc_folder(pre_alloc_folder)
display_stats(stats, console, verbose=verbose)
except FileNotFoundError:
console.print(f"[red]Error: Folder not found: {pre_alloc_folder}[/red]")
diff --git a/src/ethereum_spec_tests/cli/tests/__init__.py b/packages/tests/src/cli/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/tests/__init__.py
rename to packages/tests/src/cli/tests/__init__.py
diff --git a/src/ethereum_spec_tests/cli/tests/test_eofwrap.py b/packages/tests/src/cli/tests/test_eofwrap.py
similarity index 100%
rename from src/ethereum_spec_tests/cli/tests/test_eofwrap.py
rename to packages/tests/src/cli/tests/test_eofwrap.py
diff --git a/src/ethereum_spec_tests/cli/tests/test_evm_bytes.py b/packages/tests/src/cli/tests/test_evm_bytes.py
similarity index 92%
rename from src/ethereum_spec_tests/cli/tests/test_evm_bytes.py
rename to packages/tests/src/cli/tests/test_evm_bytes.py
index 64bebd4182..e7e32a81e3 100644
--- a/src/ethereum_spec_tests/cli/tests/test_evm_bytes.py
+++ b/packages/tests/src/cli/tests/test_evm_bytes.py
@@ -8,7 +8,9 @@
basic_vector = [
"0x60008080808061AAAA612d5ff1600055",
- "Op.PUSH1[0x0] + Op.DUP1 + Op.DUP1 + Op.DUP1 + Op.DUP1 + Op.PUSH2[0xaaaa] + Op.PUSH2[0x2d5f] + Op.CALL + Op.PUSH1[0x0] + Op.SSTORE", # noqa: E501
+ "Op.PUSH1[0x0] + Op.DUP1 + Op.DUP1 + Op.DUP1 + Op.DUP1 + "
+ "Op.PUSH2[0xaaaa] + Op.PUSH2[0x2d5f] + Op.CALL + Op.PUSH1[0x0] + "
+ "Op.SSTORE",
]
complex_vector = [
"0x7fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf5f527fc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf6020527fe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff60405260786040356020355f35608a565b5f515f55602051600155604051600255005b5e56", # noqa: E501
@@ -24,8 +26,9 @@
]
rjumpv_vector = [
"0xe213b1465aef60276095472e3250cf64736f6c63430008150033a26469706673582212206eab0a7969fe",
- "Op.RJUMPV[-0x4eba, 0x5aef, 0x6027, 0x6095, 0x472e, 0x3250, -0x309c, 0x736f, 0x6c63, 0x4300,"
- + " 0x815, 0x33, -0x5d9c, 0x6970, 0x6673, 0x5822, 0x1220, 0x6eab, 0xa79, 0x69fe]",
+ "Op.RJUMPV[-0x4eba, 0x5aef, 0x6027, 0x6095, 0x472e, 0x3250, -0x309c, "
+ "0x736f, 0x6c63, 0x4300," + " 0x815, 0x33, -0x5d9c, 0x6970, 0x6673, 0x5822, 0x1220, 0x6eab, "
+ "0xa79, 0x69fe]",
]
diff --git a/packages/tests/src/cli/tests/test_fuzzer_bridge.py b/packages/tests/src/cli/tests/test_fuzzer_bridge.py
new file mode 100644
index 0000000000..46815e7b05
--- /dev/null
+++ b/packages/tests/src/cli/tests/test_fuzzer_bridge.py
@@ -0,0 +1,421 @@
+"""Test suite for fuzzer bridge DTO parsing and conversion."""
+
+import json
+from pathlib import Path
+from typing import Any, Dict
+
+import pytest
+from pydantic import ValidationError
+
+from ethereum_test_base_types import Address, HexNumber
+from ethereum_test_forks import Osaka
+from ethereum_test_tools import Account, AuthorizationTuple, Transaction
+from ethereum_test_types import Alloc, Environment
+
+from ..fuzzer_bridge.converter import (
+ blockchain_test_from_fuzzer,
+ create_sender_eoa_map,
+ fuzzer_account_to_eest_account,
+ fuzzer_authorization_to_eest,
+ fuzzer_transaction_to_eest_transaction,
+)
+from ..fuzzer_bridge.models import (
+ FuzzerAccountInput,
+ FuzzerAuthorizationInput,
+ FuzzerOutput,
+ FuzzerTransactionInput,
+)
+
+
+def load_fuzzer_vector(filename: str) -> Dict[str, Any]:
+ """
+ Load fuzzer test vector from vectors/ directory.
+
+ Follows the pattern from
+ tests/prague/eip2537_bls_12_381_precompiles/helpers.py
+ """
+ vector_path = Path(__file__).parent / "vectors" / filename
+ with open(vector_path) as f:
+ return json.load(f)
+
+
+class TestFuzzerOutputParsing:
+ """Test parsing of fuzzer output JSON into DTOs."""
+
+ @pytest.fixture
+ def fuzzer_data(self) -> Dict[str, Any]:
+ """Load test vector."""
+ return load_fuzzer_vector("fuzzer_test_0.json")
+
+ def test_parse_fuzzer_output(self, fuzzer_data):
+ """Test parsing complete fuzzer output."""
+ fuzzer_output = FuzzerOutput(**fuzzer_data)
+
+ assert fuzzer_output.version == "2.0"
+ assert fuzzer_output.fork == Osaka
+ assert fuzzer_output.chain_id == HexNumber(1)
+ assert len(fuzzer_output.transactions) == 17
+ assert len(fuzzer_output.accounts) > 0
+ assert fuzzer_output.parent_beacon_block_root is not None # EIP-4788
+
+ def test_parse_account_with_private_key(self, fuzzer_data):
+ """Test parsing account with private key."""
+ account_data = next(acc for acc in fuzzer_data["accounts"].values() if "privateKey" in acc)
+
+ account = FuzzerAccountInput(**account_data)
+
+ assert account.private_key is not None
+ assert isinstance(account.balance, HexNumber)
+ assert isinstance(account.nonce, HexNumber)
+
+ def test_parse_account_without_private_key(self, fuzzer_data):
+ """Test parsing contract account (no private key)."""
+ account_data = next(
+ (acc for acc in fuzzer_data["accounts"].values() if "privateKey" not in acc),
+ None,
+ )
+
+ if account_data:
+ account = FuzzerAccountInput(**account_data)
+ assert account.private_key is None
+
+ def test_parse_transaction_with_authorization_list(self, fuzzer_data):
+ """Test parsing EIP-7702 transaction with authorization list."""
+ tx_data = next(
+ (
+ tx
+ for tx in fuzzer_data["transactions"]
+ if "authorizationList" in tx and tx["authorizationList"]
+ ),
+ None,
+ )
+
+ if tx_data:
+ tx = FuzzerTransactionInput(**tx_data)
+
+ assert tx.authorization_list is not None
+ assert len(tx.authorization_list) > 0
+ assert isinstance(tx.authorization_list[0], FuzzerAuthorizationInput)
+
+ # Verify authorization fields
+ auth = tx.authorization_list[0]
+ assert isinstance(auth.chain_id, HexNumber)
+ assert isinstance(auth.address, Address)
+ assert isinstance(auth.nonce, HexNumber)
+
+ def test_parse_authorization_tuple(self, fuzzer_data):
+ """Test parsing individual authorization tuple."""
+ tx_with_auth = next(
+ (
+ tx
+ for tx in fuzzer_data["transactions"]
+ if "authorizationList" in tx and tx["authorizationList"]
+ ),
+ None,
+ )
+
+ if tx_with_auth:
+ auth_data = tx_with_auth["authorizationList"][0]
+ auth = FuzzerAuthorizationInput(**auth_data)
+
+ assert auth.chain_id is not None
+ assert auth.address is not None
+ assert auth.v is not None
+ assert auth.r is not None
+ assert auth.s is not None
+
+ def test_parse_environment(self, fuzzer_data):
+ """Test Environment parsing (using EEST Environment directly)."""
+ env = Environment(**fuzzer_data["env"])
+
+ assert env.fee_recipient is not None
+ assert env.gas_limit is not None
+ assert env.number is not None
+ assert env.timestamp is not None
+
+
+class TestDTOConversion:
+ """Test conversion from DTOs to EEST domain models."""
+
+ @pytest.fixture
+ def fuzzer_output(self) -> FuzzerOutput:
+ """Parsed fuzzer output."""
+ data = load_fuzzer_vector("fuzzer_test_0.json")
+ return FuzzerOutput(**data)
+
+ def test_fuzzer_account_to_eest_account(self, fuzzer_output):
+ """Test account DTO to EEST Account conversion."""
+ fuzzer_account = next(iter(fuzzer_output.accounts.values()))
+
+ eest_account = fuzzer_account_to_eest_account(fuzzer_account)
+
+ assert isinstance(eest_account, Account)
+ assert eest_account.balance == fuzzer_account.balance
+ assert eest_account.nonce == fuzzer_account.nonce
+ assert eest_account.code == fuzzer_account.code
+
+ def test_fuzzer_authorization_to_eest(self, fuzzer_output):
+ """Test authorization DTO to EEST AuthorizationTuple conversion."""
+ tx_with_auth = next(
+ (tx for tx in fuzzer_output.transactions if tx.authorization_list), None
+ )
+
+ if tx_with_auth:
+ fuzzer_auth = tx_with_auth.authorization_list[0]
+
+ eest_auth = fuzzer_authorization_to_eest(fuzzer_auth)
+
+ assert isinstance(eest_auth, AuthorizationTuple)
+ assert eest_auth.chain_id == fuzzer_auth.chain_id
+ assert eest_auth.address == fuzzer_auth.address
+ assert eest_auth.nonce == fuzzer_auth.nonce
+
+ def test_create_sender_eoa_map(self, fuzzer_output):
+ """Test EOA map creation from accounts."""
+ sender_map = create_sender_eoa_map(fuzzer_output.accounts)
+
+ # Verify all senders are valid
+ assert len(sender_map) > 0
+
+ for addr, eoa in sender_map.items():
+ # Verify private key matches address
+ assert Address(eoa) == addr
+
+ def test_sender_eoa_map_validates_address(self, fuzzer_output):
+ """Test that EOA map validates private key matches address."""
+ # This test verifies the assertion in create_sender_eoa_map
+ sender_map = create_sender_eoa_map(fuzzer_output.accounts)
+
+ # All created EOAs should pass validation
+ assert all(Address(eoa) == addr for addr, eoa in sender_map.items())
+
+ def test_fuzzer_transaction_to_eest_transaction(self, fuzzer_output):
+ """Test transaction DTO to EEST Transaction conversion."""
+ fuzzer_tx = fuzzer_output.transactions[0]
+ sender_map = create_sender_eoa_map(fuzzer_output.accounts)
+ sender_eoa = sender_map[fuzzer_tx.from_]
+
+ eest_tx = fuzzer_transaction_to_eest_transaction(fuzzer_tx, sender_eoa)
+
+ assert isinstance(eest_tx, Transaction)
+ assert eest_tx.sender == sender_eoa
+ assert eest_tx.to == fuzzer_tx.to
+ assert eest_tx.gas_limit == fuzzer_tx.gas # Key mapping!
+ assert eest_tx.data == fuzzer_tx.data
+
+ def test_transaction_gas_field_mapping(self, fuzzer_output):
+ """Test critical field mapping: gas → gas_limit."""
+ fuzzer_tx = fuzzer_output.transactions[0]
+ sender_map = create_sender_eoa_map(fuzzer_output.accounts)
+ sender_eoa = sender_map[fuzzer_tx.from_]
+
+ eest_tx = fuzzer_transaction_to_eest_transaction(fuzzer_tx, sender_eoa)
+
+ # Fuzzer uses 'gas' (JSON-RPC), EEST uses 'gas_limit'
+ assert eest_tx.gas_limit == fuzzer_tx.gas
+
+ def test_transaction_authorization_list_conversion(self, fuzzer_output):
+ """Test authorization list conversion in transaction."""
+ tx_with_auth = next(
+ (tx for tx in fuzzer_output.transactions if tx.authorization_list), None
+ )
+
+ if tx_with_auth:
+ sender_map = create_sender_eoa_map(fuzzer_output.accounts)
+ sender_eoa = sender_map[tx_with_auth.from_]
+
+ eest_tx = fuzzer_transaction_to_eest_transaction(tx_with_auth, sender_eoa)
+
+ assert eest_tx.authorization_list is not None
+ assert len(eest_tx.authorization_list) == len(tx_with_auth.authorization_list)
+ assert all(isinstance(auth, AuthorizationTuple) for auth in eest_tx.authorization_list)
+
+
+class TestBlockchainTestGeneration:
+ """Test end-to-end conversion to BlockchainTest."""
+
+ @pytest.fixture
+ def fuzzer_output(self) -> FuzzerOutput:
+ """Parsed fuzzer output."""
+ data = load_fuzzer_vector("fuzzer_test_0.json")
+ return FuzzerOutput(**data)
+
+ def test_blockchain_test_from_fuzzer_single_block(self, fuzzer_output):
+ """Test single-block blockchain test generation."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ num_blocks=1,
+ )
+
+ assert blockchain_test.pre is not None
+ assert len(blockchain_test.blocks) == 1
+ assert len(blockchain_test.blocks[0].txs) == 17
+ assert blockchain_test.genesis_environment is not None
+
+ def test_blockchain_test_multi_block_distribute(self, fuzzer_output):
+ """Test multi-block generation with distribute strategy."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ num_blocks=3,
+ block_strategy="distribute",
+ )
+
+ assert len(blockchain_test.blocks) == 3
+
+ # Verify all transactions distributed
+ total_txs = sum(len(block.txs) for block in blockchain_test.blocks)
+ assert total_txs == 17
+
+ # Verify transactions maintain nonce order
+ assert len(blockchain_test.blocks[0].txs) > 0
+
+ def test_blockchain_test_multi_block_first_block(self, fuzzer_output):
+ """Test multi-block generation with first-block strategy."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ num_blocks=3,
+ block_strategy="first-block",
+ )
+
+ assert len(blockchain_test.blocks) == 3
+ assert len(blockchain_test.blocks[0].txs) == 17
+ assert len(blockchain_test.blocks[1].txs) == 0
+ assert len(blockchain_test.blocks[2].txs) == 0
+
+ def test_blockchain_test_pre_state(self, fuzzer_output):
+ """Test pre-state (Alloc) generation."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ )
+
+ assert isinstance(blockchain_test.pre, Alloc)
+ # Verify all accounts are in pre-state
+ for addr in fuzzer_output.accounts:
+ assert addr in blockchain_test.pre
+
+ def test_blockchain_test_genesis_environment(self, fuzzer_output):
+ """Test genesis environment derivation."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ )
+
+ genesis_env = blockchain_test.genesis_environment
+
+ assert genesis_env.number == 0
+ # Genesis timestamp should be 12 seconds before block 1
+ assert int(genesis_env.timestamp) == int(fuzzer_output.env.timestamp) - 12
+
+ def test_blockchain_test_block_timestamps(self, fuzzer_output):
+ """Test block timestamp incrementing."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ num_blocks=3,
+ block_time=12,
+ )
+
+ # Check timestamps increment correctly
+ base_ts = int(fuzzer_output.env.timestamp)
+ assert blockchain_test.blocks[0].timestamp == base_ts
+ assert blockchain_test.blocks[1].timestamp == base_ts + 12
+ assert blockchain_test.blocks[2].timestamp == base_ts + 24
+
+ def test_blockchain_test_beacon_root_first_block_only(self, fuzzer_output):
+ """Test parent beacon block root only in first block (EIP-4788)."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ num_blocks=3,
+ )
+
+ # First block should have beacon root
+ assert blockchain_test.blocks[0].parent_beacon_block_root is not None
+
+ # Subsequent blocks should NOT have beacon root
+ assert blockchain_test.blocks[1].parent_beacon_block_root is None
+ assert blockchain_test.blocks[2].parent_beacon_block_root is None
+
+
+class TestEIPFeatures:
+ """Test EIP-specific feature handling."""
+
+ @pytest.fixture
+ def fuzzer_output(self) -> FuzzerOutput:
+ """Parsed fuzzer output."""
+ data = load_fuzzer_vector("fuzzer_test_0.json")
+ return FuzzerOutput(**data)
+
+ def test_eip7702_authorization_lists(self, fuzzer_output):
+ """Test EIP-7702 authorization list handling."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ )
+
+ # Find transactions with authorization lists
+ txs_with_auth = [
+ tx for block in blockchain_test.blocks for tx in block.txs if tx.authorization_list
+ ]
+
+ assert len(txs_with_auth) > 0
+
+ for tx in txs_with_auth:
+ assert all(isinstance(auth, AuthorizationTuple) for auth in tx.authorization_list)
+
+ def test_eip4788_parent_beacon_block_root(self, fuzzer_output):
+ """Test EIP-4788 parent beacon block root handling."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ )
+
+ # Beacon root should match fuzzer output
+ assert (
+ blockchain_test.blocks[0].parent_beacon_block_root
+ == fuzzer_output.parent_beacon_block_root
+ )
+
+ def test_sender_is_eoa_not_test_address(self, fuzzer_output):
+ """Test that transaction senders are EOAs, not TestAddress."""
+ blockchain_test = blockchain_test_from_fuzzer(
+ fuzzer_output,
+ fork=Osaka,
+ )
+
+ for block in blockchain_test.blocks:
+ for tx in block.txs:
+ # Verify sender is EOA with private key
+ assert hasattr(tx.sender, "key")
+ assert tx.sender.key is not None
+
+
+class TestErrorHandling:
+ """Test error handling and validation."""
+
+ def test_invalid_version_fails(self):
+ """Test that invalid version is rejected."""
+ data = load_fuzzer_vector("fuzzer_test_0.json")
+ data["version"] = "1.0" # Invalid version
+
+ with pytest.raises(ValidationError):
+ FuzzerOutput(**data)
+
+ def test_missing_private_key_fails(self):
+ """Test that transaction without sender private key fails."""
+ data = load_fuzzer_vector("fuzzer_test_0.json")
+
+ # Remove all private keys
+ for account in data["accounts"].values():
+ if "privateKey" in account:
+ del account["privateKey"]
+
+ fuzzer_output = FuzzerOutput(**data)
+
+ # Conversion should fail due to missing sender keys
+ with pytest.raises(AssertionError):
+ blockchain_test_from_fuzzer(fuzzer_output, fork=Osaka)
diff --git a/src/ethereum_spec_tests/cli/tests/test_generate_all_formats.py b/packages/tests/src/cli/tests/test_generate_all_formats.py
similarity index 93%
rename from src/ethereum_spec_tests/cli/tests/test_generate_all_formats.py
rename to packages/tests/src/cli/tests/test_generate_all_formats.py
index 9f49678464..a939f61932 100644
--- a/src/ethereum_spec_tests/cli/tests/test_generate_all_formats.py
+++ b/packages/tests/src/cli/tests/test_generate_all_formats.py
@@ -30,7 +30,9 @@ def test_generate_all_formats_creates_two_phase_execution():
def test_generate_all_formats_preserves_other_args():
- """Test that --generate-all-formats preserves other command line arguments."""
+ """
+ Test that --generate-all-formats preserves other command line arguments.
+ """
command = FillCommand()
with patch.object(command, "process_arguments", side_effect=lambda x: x):
@@ -86,7 +88,8 @@ def test_legacy_generate_pre_alloc_groups_still_works():
phase1_args = executions[0].args
assert "--generate-pre-alloc-groups" in phase1_args
- # Phase 2: Should have --use-pre-alloc-groups but NOT --generate-all-formats
+ # Phase 2: Should have --use-pre-alloc-groups but NOT --generate-all-
+ # formats
phase2_args = executions[1].args
assert "--use-pre-alloc-groups" in phase2_args
assert "--generate-all-formats" not in phase2_args
@@ -110,7 +113,9 @@ def test_single_phase_without_flags():
def test_tarball_output_auto_enables_generate_all_formats():
- """Test that tarball output automatically enables --generate-all-formats."""
+ """
+ Test that tarball output automatically enables --generate-all-formats.
+ """
command = FillCommand()
with patch.object(command, "process_arguments", side_effect=lambda x: x):
@@ -124,7 +129,8 @@ def test_tarball_output_auto_enables_generate_all_formats():
phase1_args = executions[0].args
assert "--generate-pre-alloc-groups" in phase1_args
- # Phase 2: Should have --generate-all-formats (auto-added) and --use-pre-alloc-groups
+ # Phase 2: Should have --generate-all-formats (auto-added) and --use-pre-
+ # alloc-groups
phase2_args = executions[1].args
assert "--generate-all-formats" in phase2_args
assert "--use-pre-alloc-groups" in phase2_args
@@ -132,7 +138,10 @@ def test_tarball_output_auto_enables_generate_all_formats():
def test_tarball_output_with_explicit_generate_all_formats():
- """Test that explicit --generate-all-formats with tarball output works correctly."""
+ """
+ Test that explicit --generate-all-formats with tarball output works
+ correctly.
+ """
command = FillCommand()
with patch.object(command, "process_arguments", side_effect=lambda x: x):
@@ -150,7 +159,10 @@ def test_tarball_output_with_explicit_generate_all_formats():
def test_regular_output_does_not_auto_trigger_two_phase():
- """Test that regular directory output doesn't auto-trigger two-phase execution."""
+ """
+ Test that regular directory output doesn't auto-trigger two-phase
+ execution.
+ """
command = FillCommand()
with patch.object(command, "process_arguments", side_effect=lambda x: x):
diff --git a/src/ethereum_spec_tests/cli/tests/test_order_fixtures.py b/packages/tests/src/cli/tests/test_order_fixtures.py
similarity index 96%
rename from src/ethereum_spec_tests/cli/tests/test_order_fixtures.py
rename to packages/tests/src/cli/tests/test_order_fixtures.py
index 27a88ceef7..0c3f2db4f7 100644
--- a/src/ethereum_spec_tests/cli/tests/test_order_fixtures.py
+++ b/packages/tests/src/cli/tests/test_order_fixtures.py
@@ -57,7 +57,9 @@ def test_cli_invocation(input_output_dirs):
def test_input_is_file_instead_of_directory():
- """Test the CLI interface when the input path is a file, not a directory."""
+ """
+ Test the CLI interface when the input path is a file, not a directory.
+ """
runner = CliRunner()
with TemporaryDirectory() as temp_dir:
temp_file = Path(temp_dir) / "temp_file.txt"
diff --git a/src/ethereum_spec_tests/cli/tests/test_pytest_execute_command.py b/packages/tests/src/cli/tests/test_pytest_execute_command.py
similarity index 96%
rename from src/ethereum_spec_tests/cli/tests/test_pytest_execute_command.py
rename to packages/tests/src/cli/tests/test_pytest_execute_command.py
index a8faae6518..d6df1d5c0c 100644
--- a/src/ethereum_spec_tests/cli/tests/test_pytest_execute_command.py
+++ b/packages/tests/src/cli/tests/test_pytest_execute_command.py
@@ -28,7 +28,7 @@ def test_execute_help_shows_subcommand_docstrings(runner):
assert "Recover funds from test executions" in result.output
-def test_execute_subcommands_have_help_text(runner):
+def test_execute_subcommands_have_help_text():
"""Test that execute sub-commands have proper help text defined."""
from ..pytest_commands.execute import hive, recover, remote
diff --git a/src/ethereum_spec_tests/cli/tests/test_pytest_fill_command.py b/packages/tests/src/cli/tests/test_pytest_fill_command.py
similarity index 90%
rename from src/ethereum_spec_tests/cli/tests/test_pytest_fill_command.py
rename to packages/tests/src/cli/tests/test_pytest_fill_command.py
index 95c3a3e8f4..0386b05d4e 100644
--- a/src/ethereum_spec_tests/cli/tests/test_pytest_fill_command.py
+++ b/packages/tests/src/cli/tests/test_pytest_fill_command.py
@@ -50,11 +50,12 @@ class TestHtmlReportFlags:
@pytest.fixture
def fill_args(self, default_t8n):
"""
- Provide default arguments for the `fill` command when testing html report
- generation.
+ Provide default arguments for the `fill` command when testing html
+ report generation.
- Specifies a single existing example test case for faster fill execution,
- and to allow for tests to check for the fixture generation location.
+ Specifies a single existing example test case for faster fill
+ execution, and to allow for tests to check for the fixture generation
+ location.
"""
return [
"-k",
@@ -81,8 +82,8 @@ def monkeypatch_default_output_directory(self, monkeypatch, temp_dir):
"""
Monkeypatch default output directory for the pytest commands.
- This avoids using the local directory in user space for the output of pytest
- commands and uses the a temporary directory instead.
+ This avoids using the local directory in user space for the output of
+ pytest commands and uses the a temporary directory instead.
"""
def mock_default_output_directory():
@@ -101,7 +102,10 @@ def test_fill_default_output_options(
fill_args,
default_html_report_file_path,
):
- """Test default pytest html behavior: Neither `--html` or `--output` is specified."""
+ """
+ Test default pytest html behavior: Neither `--html` or `--output` is
+ specified.
+ """
default_html_path = temp_dir / default_html_report_file_path
result = runner.invoke(fill, fill_args)
assert result.exit_code == pytest.ExitCode.OK
@@ -141,7 +145,9 @@ def test_fill_output_option(
fill_args,
default_html_report_file_path,
):
- """Tests pytest html report generation with only the `--output` flag."""
+ """
+ Tests pytest html report generation with only the `--output` flag.
+ """
output_dir = temp_dir / "non_default_output_dir"
non_default_html_path = output_dir / default_html_report_file_path
fill_args += ["--output", str(output_dir)]
@@ -156,7 +162,10 @@ def test_fill_html_and_output_options(
temp_dir,
fill_args,
):
- """Tests pytest html report generation with both `--output` and `--html` flags."""
+ """
+ Tests pytest html report generation with both `--output` and `--html`
+ flags.
+ """
output_dir = temp_dir / "non_default_output_dir_fixtures"
html_path = temp_dir / "non_default_output_dir_html" / "non_default.html"
fill_args += ["--output", str(output_dir), "--html", str(html_path)]
diff --git a/packages/tests/src/cli/tests/vectors/fuzzer_test_0.json b/packages/tests/src/cli/tests/vectors/fuzzer_test_0.json
new file mode 100644
index 0000000000..2525655832
--- /dev/null
+++ b/packages/tests/src/cli/tests/vectors/fuzzer_test_0.json
@@ -0,0 +1,456 @@
+{
+ "accounts": {
+ "0x000000000000000000000000000000000000000F": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x0233362c058b2fCc8093841B1073A90D673E7F12": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x7f2c75141e16bea0fceec67f673a0a3578e66fe55a9b6405d1ce109be7593206",
+ "storage": {}
+ },
+ "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2825c17712cd3e7e5240fb76fe09ec612d0337b643e5c605c3cfea77e44d0b73",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f0304bb487cf38ca47fa3bdb2fcd17f446000527fbce853b19c5e1fa4e21a75f5c633b19093d16e4225a1e18f93e6b0280d553f456020526f12907f8e8e33612bb1cd28222515089f6040527ff9ccd6deac82230464c9a0b6b46ae6cdd7488cbcb2701e4ae34128fbc7278be66060526f0f648013c07e63d91b12e235737d86626080527f152b1247f61c53a7c05b6282599a5a565624a120e3884ee2cf02e267fe10be1e60a0526f0ca29f1d84c20b8318dfc76159fa754560c0527f8730ae6c1b52728688bb33a14d5e57c18fe660ff55431c5fcc749dfbfd027a2060e052608060006101006000608c600b7fb2a9d981edef956e7c15a8f00819612f341891f265ea91e2d1bf0c9ddf17706bf16000556000516001556020516002556040516003556060516004556f0a1d7979d389cc17fa6234b538473d336000527fabda0c5fb1790d0da3b62020c61a9e0d09bf34d7299d048a86be80fd34ecc4a86020526f0560d9b5c15fec8dff6be987c92016df6040527fa66b5477a91ae92db1582bd62fffc0a3b6bafc39ad9636987f953f1acd6011036060527f6eb221e467bd443a6fd33fcac3eec22e63e51613f05df0310c0ecab2124210386080526f089358667ca389db7562f52f881de51e60a0527fa3b281e831d4286f5cdaebb3161f352f9f5cbed6b20674ad02b7606c56d675a860c0526f17f1263e3a15d93c02a8f6557c73bc0160e0527faeda0be01631b7b34d0fed1325f69b428679a30b79321b4ee50a7a382da092b5610100527f8f53d4aa5331cb3dad00de83c80191ebccf46fb3f1527416ebb22311d8cdf5ca61012052608060006101406000600c7fd4fc806c73fce35b7910639bcd5e440f3240dbba1f1db35ffd40ac39bd9ed326fa6005556000516006556020516007556040516008556060516009556f0e98e9c5a0ce1800ea000f728c792ebd6000527fc62c5196c7362c18572f8150745dbd193236def47b700cfd019f6a63c232e7726020526f17305bfbf895a75a1b4e0374fe26d8f96040527fb6dfed3e090fc8b5952d6ed6d4722f9d0d12419a9dac52386160f712bbcaf1fb6060526f03cd0052fd56e53a9904f76c29b4f6e76080527f62c168176691eb3f0c43f3263ebbfae78287a9110f2e7210f8615b4c0deedc9560a0526f0d99d442b87f10626da56ae4efc4557660c0527f5b87b2d664e585438fc0e5c2529f960b8421293bc9e64cf73c3681315c67cceb60e05278100000000000000000142f2b61de3fd9f5fae7f30f9a200465610100527f69a2fa1a70f398346b86baf9a1caf04c81261ce8120d073e480c017d1072ea86610120526f16367e551460bdf8b55514e5fbc98336610140527f4e41aa34f39059f6b645f11adc22a135c4cac0f8073c4a48dc3e326dd64570da610160526f1559a897fe4d9101750cf0c50d759307610180527fc6f2b0bbf73d7f6e7397777e2839216f0636957d997b14fa1dc9183d10ef4d806101a0526f10d05bbe32b66859d000015085fc6fb36101c0527ffd839495def4a7a0217ae1194b79e4e4a929cec96eea279ca635aa528718c5e16101e052610100600061020060006087600d7f4997fb8662809f846cccb8072b5a665549bced5ba0babf36c900744358ed4715f2600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f0a80f16dec66305836d93b07b6a14b746000527fd694453efa14cf142cc5b48cd8e49e5fa6d52f6b904f3c51a1e99be6ebeebc626020526f17ec12f7a83252673a562e934ae83c7d6040527fd980e2a6787fe55b5d6250b8c8c909f4c5fa906b7ae1e359fa84225966b4585e6060526f0201c07465f5a818868d265f2b9d3a5a6080527f4382a23b79074ccec8e1ad21c580fc1fe95213d4798af4aaa22855bd021050c360a0526f170d94a3398fd8fe44b7ff548fe6d93160c0527f726ae0d035252f5ec681388307703619e6198ba67ce8e3380cb576edb1a871f160e0527f1f4158e9331a61d7f6666fa0bbfea04cf804c27cc8b8ac749176fd7ea110a2016101005261010060006101206000600e7f903dbfde19bbf5a150cce310c94c5fde73f13db285135e8fa471e112a500dbb2fa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f060500d8f2788f675515321a657ec91d6000527f2f68c11e9812c09c2d1ea3667837f81666de01b7136237cd59d0e4fdd23f03496020526f1029733bf268a8dfa83ebd6870b9c5b36040527f8f3731515fdfb60678ef7e109ad680738e1c20e6e7ac6c1daa02e3fbca9ff4526060526000608052600060a052600060c052721000000000000000000000000000000000000060e0526000610100526000610120526000610140526000610160526f0671a07ffe971a913c8e718e1f8aff72610180527fddad0b334b7407fc1fec9eb7273da17aaaff013426274ab1f61cd0f04ee188c36101a0526f123c38b43dec7cb6345624c5f8b403c06101c0527fff208bbb12cc604d5cdd3ed163805d0bae5d8c8ec7b5bacd6a0ec529327c719a6101e0526f181cce65e82fd9347b1b66b4bdcade50610200527f71ea0bbfc0be2f5d930fdb39907aac0765d1e38b4b10cc44d4e8b89bf0848a12610220526f19669ebdbfec5754e13c61595fb28b72610240527f47795a1822a6b61169b1fdf8c13a66993bc9a0a9b03b236d1ae9619f80274c7c610260526f0bee714d419295547b26ad30f3f6d265610280527f0c5cc9a7d2a9d234cfbae47ccc7b753fb83ba16ea7b8c9100fc4ab9664b34ae76102a0526f01c0c352f3bb92ccfc65ba09ce10e2bf6102c0527fff7b95a9a3502e998e571f6b14a95669015c4065160fe57862c56ba26dc223e86102e0526f0a5027e9bff89a14938cce229b6608ed610300527f0f15b6977401680f5eac13988d4d5223190b3ead586a370df633fed4e2c2fbdc610320526f05fd50e2ac95e4d5ee6f46f492485ef0610340527f11c90229dd700ca24d7560d6318ac814c8f2cf0fdcdb6734ba88088a82c78b48610360526f0a9cddc7b8e0a02a9d05efeb7135a08a610380527f1edf3ccff9518b554a7169b9664ecbbae8e1fb5712d6eb21e507e91b58e0f1726103a0526f071f0b7f899b0ecc684373f03693e3f26103c0527f0973056eab4f7cd509c36304f21d5685d7bf3adfbcae30b1543c2b360af306e66103e0526f08780fd2546a36beb1ca303e02af7b14610400527f8252ab31a0707573563e183b8cfcf36dd3b166e6303a79d9787cbeb04bad0b99610420526f055bc48aa14fb1c46c09ea909afd6bfe610440527f25acb1249e874468f4e3b73366b400bc6bfe4f542a412bc91c9c83615f3501ab610460526e6fce599f3edafd3ec2cf034379f3ed610480527fb7bc1878c6b16a4c036f54f228c5fd735c10975d62caaaf0e9624900efddd6b66104a0526f16287deaced22aeece826750d5f96d0d6104c0527f493b5d3ddb685f425f5b727a5b85a82ebeef92615ee32877afc243908bd50d2c6104e0526f024aa2b2f08f0a91260805272dc51051610500527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610520526f13e02b6052719f607dacd3a088274f65610540527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610560526f0ce5d527727d6e118cc9cdc6da2e351a610580527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016105a0526f0606c4a02ea734cc32acd2b02bc28b996105c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6105e052602060006106006000600f7fd4124f75d9f67bb9297799198175ef8987c66e6c7afad5fc75719adbe2e89dc9f4601c55600051601d556f048ecddc27cb7b231e2079d5c96adb456000527f549123f3e3c3d28ff640bc3a1adb125dad75897d889e48d44f0f77ac28f020ed602052608060006040600060107f01298de28edfc331e1c52caa4e4d9601b30e5980bd635744a17225c5168975d7fa601e55600051601f556020516020556040516021556060516022556f13eba7cc9982c91920252877d0c114016000527f7c2cd98b0a402e7d0d5d015f9412eb553a9c306edf04e6dfebb84be9fd306cff6020526f12eade4a55567c4180d389eab65e95626040527f0eaf9b6cee65d9ac1233d2143011bdde7a2a2ed1306214f985d48cd255e4166f60605261010060006080600060117f3f0844a363566ce2919046fe2ab2946fc4152e80ec32229cb032f73b21f4c162fa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x60d360fe60286079600f60ec60b12008326f52059b3f3d528a53656d668c36445c1899f01a4a466151845c61368ca35c8005048e95193f551d209510615502414a3c77104309044a6d45570968789058f53749193e817f5f807d9e025f793d755575028b5d3c8f9e3a91097d5f6cf39a4768798a66111c0a3979807ff37e0b31f3188f8a0856006464fa818b75140096629833556e1e59607b9c53ff5f056105f53a8a5416160b533c54317514638106616607936f3c00023716095a69437e52411d59437b751c8a46573e595f671c8af203341c6e7c741017705f126a56727ef08f515a461a5e506d18126f72506b0638434537024009074081a163f0f002135857107698446917376d506379643b07431a20ff681c3e091049410516418a0353458b5aff685c6f977114578fa47531771d5e00536e1959605e733b147e72356bfa194291556d1069007f1d811e563d12863a7b336d51093266788d74451a197916f4764801630bf11cf242f032f30217445a3d6a57900751876b4930606b483161047432743a3a333a88787548797a4206467e33955269959f1c5865556b1b51194a446f023808a27c3d475e133d686937f0656c46780a33004a503e188f5c16597d69a20517466a5e6615474769540081050606631b605b7c7a37496cf58d8207f56e085b986f6f7d467762861940f17b3f3a661d401d6d46681c050a3d3d501d49653903561a406b483b7e38679336a363505fff736120516a6934818a5b556a3a0a12ff6f9b71841184763b077c8d106809861b881c9e405e3e388672081b727a77817b7a83a26c16560770794a703a6904684800786d00198130fa32074a6b5f07881d3d5659843f3d56735d5b31a0050083381609190539a002360a424538430b3e748173433d726d83416d497f153e440231fd1384396e5a9361045795613a87991e54ff1c6a701b05540a6103718d56718a536c85a0313853569781873754413861336e72975a47503e55a25b02a336361a6542a4708736839846fd316766933d567a3e718e537d1576414694588a609b1531366d0b19080a6435703c73027a3d32591e6a723305156a1991603204380b486a619b6b83083e7390807d5d8a7f57f05a78024a511ca20b360292543f660436676f5a1b03f473667d07545300f36a96974a56358e8f653e3b38005393671a47121802583e191172461214ff87176f9f51fe99071d68065565810a03865c8857723e09618181900b3775515a51461c7249503d403403f5161b6b5e5740604a55758b6a7180fd63721c9b5801047e9e68a33176015e095b380737799a45015e6c3a8796a08f5916110978f2454a570335504a7e335c3a166d520a53627678325245745338727b7df309a1830a74374a6d325d58f3711e7f6ffe684271363b325c5d00979b8c15561e8a42",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000012"
+ }
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x6000545004121e6f7f56198c1e35957e3f1771fc736167d061e5a3771e4ea7b6224c5795c0bfb9e27d6000527f073b1b146e22e2cbc33be43483ed67045cde7dfc18abfbc072e3007d1759a6436020527f25a5d983835b0a0a8ddda9e973ca774131d07a607a50fff393e8eb4cc1f26c6c6040527f9c248c3c71446e447ce71a16117be91eeb6887774ecc073bf3687f333852154c6060527fea9d67c047c8937ae33e470ae93ab841543e412d7fad66143778f8bc924fa5d46080527fd5b2f67b2063905d37d496c15a25d758c22b2b44cc1236b0ed5b7984e779d46360a0527f0a2e60472c4944e9fe2c9cb40ee4ef6d4664a0b3a11b5385c4b7e0bbff14540660c0527f2f523606c6d7ecf0fa8698a50b184183e745a9fc62ac210b2c697b0990eef9c960e0527f76eb16a60b21c1f33f72b6fba934a49df31cc33495c2a5448c52c4678fd235f4610100527f7eec64c80233121f38717239977ee9780a8bd90f8503cbafad56b1d154a42fc6610120527f7587ae46cbb70adcab17b5b0de3acb3145a7c274822643a1f60445b25869683b610140527f2b379af570b1ecd121b6a8fa57f5b95070dfc6f568bf5fcd6463325a70dfeabe610160527fcab611c6fce59eb2d48e25746327158cbe1e56043270425b912c395a481140d7610180527fb278bfc525b03b0bdc36704d4f33402e419bf94220a962778732dee8df0701af6101a0527ff31a16cecd89cbbe248c1180cbe3ab9d47f0608191ebae06c8ca65da94a6cf0e6101c0527fdab48b0443e2f74491047cb5043ec3ab52a64c3cd9207829e01c0c7db9767e4c6101e0527f48fe70c2e6614d7a443a9e349eab5d084c38b49a7915188567b9fed7bb303205610200527f4cd71e66c5664a1f0cb150d3c620b349dd38c1cc760aff91f76927665de296a6610220527f4fa12b0350149110fa8a0c12251cd216f5ef2a6933dd28cb7ab6de9f613097e2610240527f0f4c3ea9097e42038e26855e750999a40ab7f90ea69d1a2a2c1fd97fa79a0613610260527fe7faeb6bccf6487cf16aa52814ebdc29fb624527e80805b08a504d1598dd7831610280527fa445a986e95b0f4e0378e18b97819ff5f3c5c534d436d4b648c297b91568a10c6102a0527f8c4eda6372fd44629eba2c9d2dcd470136c712ab976abb3396c1da6f4ddcb6826102c0527fda48bafb7e3ff88251bb85a28ee3fbfea120a23150a8d2d725989f9c4502a5286102e0527f47a217e00683fa23ecf58f04b7663a46be40a80bdbc7910d7a7a6ea7528c24326103005260ce6103205360cd6103215360266103225360b66103235360db61032453604060006103256000609660f47f80dd5cba9287bdc9d8484da6db0c443bcf39f18dc9a3b877daa4b47b152f695af1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000c",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0x000000000000000000000000000000000000000000000000000000000000000d"
+ }
+ },
+ "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xaa07ea6d7ebb90738862bff26aa53633e9a6a4c2732f31c270f5a02687a06eb2",
+ "storage": {}
+ },
+ "0x535863dA03bc1834eeA10eeab8FF498565F33f2d": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xb214f8d7a564be547e6de1404f829b88b9c5f1bfc42a708554e97423e49a9def",
+ "storage": {}
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7fb858c07c2fb9fb447c54bdf506edb58f631476bed129929800bdb8049510aa7e6000527f3a410073dc03e299ea3618ffb2e7292ecd57563edff75605855ca16c9cb158e66020527fc3ac92c70cc33b79c43ed311142981018abce5f5cbc322fb4d4cc081031ec1ce6040527f73d594fd80189ea82db6754b27de68050a84ba50ed82afefe5b900ff19a00aac6060527ff1a8e519f5aa98550f849cff101dee44b99100c44eac7a7f2cde3610cd54656e6080527ffd7b744a4d233ee11b0b11f746f2d48a6563968ccf0b8a2f3f99d60ab16b146460a0527f756af369bcf3131ecc8d276e72b38074f3f02a253f611208f70b72661c27458f60c0527f3078b132f36721702d0b4ee6c4c30fb87f4860d76c267f1a3fc1a3e56901fbe160e0527fb903e43f3659db206c8e26d8f3276f2696926e86f82ba6cb69639480bb9e85b5610100527fa0225a93a51f5cf08e2829018fc694fc8dbfe36ee19d9c33e8f6cd0918a823076101205260206000610140600060027f3d5fcc6dc637aa0a00e46f5c03d83b8b4476d9fbaab5d9688c67e13eceaa005bf4600055600051600155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x6008610400fd",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x600054506003fff87f9dfbc28738b4aa81098db57872f5db652fb31e6563a7e0444aef68ed160a85c5600052604060006020600060b660077f6b0476a7d3e48eaca4fb3595c2ad7657f4da9552ffaebcd13068b1c91fad8d6bf1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000f"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7d08361ee866d39c2fb444e88ff7ee2a8e023c8c049aae8a67f7f686951abb6000527f2884635f8539e311ae790c2a42ca96eb6a850235a6ab1e3de3ab9106f17f69806020527f9c3330a9d409a3128e5da585e8d90364692c33c7b156330f7a9d0466b958016c6040527fbe4b1c709bb0327f1bc07d29da9e49dbc164adef56992936f18fef5d9bea45086060527f861e3e31afb13f20925a2ef9718e14add535afc482c88a4429ddd65c050491926080527f054efe1978cffd5b49f3791f5c168bf912146245ba05b3425577697c24436d8d60a052601f60c053602a60c153601260c253602960c353609c60c453605f60c553604660c653609c60c753608d60c853601a60c95360b860ca53609260cb53601c60cc53602060cd53602660ce53602860cf53608560d053604660d153609760d253602160d353600060d4536040600060d56000604d60097f67a046b0dcdd07f5640269c0b1d159c2f87bc5cab9c9cbcbfa19613952b719d0f1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xada9e915b45b3f9f3f335fe00a484308905ec68a78d49750e1a47ec4f9c17d23",
+ "storage": {}
+ },
+ "0x862B38c425EF5544d0127449A12c89C46dd3E050": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x35c0e7a818e7367e6218647e77752b4b0d92f50362a7eff324915762586509ba",
+ "storage": {}
+ },
+ "0x88f9B82462f6C4bf4a0Fb15e5c3971559a316e7f": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x777effffff80000000000000000000000000000000000080017a01090000000000000000000000000000000000000000000000000090176000557f800000000000000000000000000000000000000000000000000000000000000276013590cab83b779e708b533b0eef3561483ddeefc841f5136001556780000000000000017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000901d7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5901d9007678000000000000000690100000000000000000006760fffc000000000000767676240000000000002b05760476007717676767676760000000000760000007600000909760fffc000000000000767676240000000000002b05760477f800000000000000180000000000000008000000000000000800000000000000090050b197702ffffffffffffffffffffffffffffffffff2000000000006801fffffffffffffffe90109017197ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000677fffffffffffffff7e40000000fd000000db0000000000000000000040000000fd000000db0000010913682100000000000000227f80000000000000018000000000000000800000000000000080000000000000009006107ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000686d5adef08547abf7eb90066002557d767676767676000000000076000000000000005600000000000000000000637fffffff901819901b7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f800000000000000000000000000000000000000000000000000000000000000018146d010000000000000000000000000069010000000000000000001a16610111774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1090167feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7bc9700000000000000000023f00c00014ff002c00000000000022310814177ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02901615682323232323232323237f7effffff80000000000000000000000000020000440000000000000000000001901d7a010900000000000000000000000000000000000000000000000000778200000000000000fe000004000000ffff000000fffff700637fffffff0990161b71767676767676767676000000767676767676638000000116901a682100000000000000227ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000090109005681000000000000000007f82000000000000000000000000000000000000000000000000000000000000006b100000000000000000000000080b6d0100000000000000000000000000777effffff8000000000000000000000000000000000008001051960035567d021262626262626680100000000000000001090137f80000000000000000000000000000000000000000000000000000000000000006c01000000000000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a90081b60006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000610100611915fa6000556000516001557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527f8302763a7a03204c2f880bc82f3d38d8747211f1a910880e90004c102538f3ae6060527f7d8da52b6ebd1b2c2d84b07a8d2092e09d27777575aa939ed783a54cddd2b0c66080526020600060a0600060006101006119fff26002556000516003557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffdfffffffffffffffffffffdffffffffff77ffffffffffffffffffffff6020527ffffffffdfffffffffffffffffffffdffffffffff77ffffffffffffffffffffff6040527f91dbff4fb710b1e81ce14be3bd88f06cff8428403452b064321bebeabec55f7d6060527f54c975daf7c93874c068af196208eda9c8f9ced3460ef5bffcc93b3dd8f2ff8a6080526020600060a060006001610100611a1cf16004556000516005557f86f977edffd2ddaf1c5779296743fb477fe65e68d47bb0716a1ab8157207455e6000527f43c36642eaba53487655950d16ee65b9f61ee0c605a4388cffeacc12f2b01e856020527f4aa560a8b3dec45915d077759ff76a3efaa44d25c93aa98b466e59fbf502684e6040527e9047ae74c90ca58dad54af6f18f053e27deb4632fcbf5998f269e614536b826060527fdadda5824c6bcf8a00a246be87fd739d8751107ef5ce89c85d3da736c3fc69326080526020600060a060006001610100611a77f16006556000516007557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f81f541a8a3462901f68ba711ca1e3aec670f9cc713e1972a1606fbceb2ebd2886020527f81f541a8a3462901f68ba711ca1e3aec670f9cc713e1972a1606fbceb2ebd2886040527f04fffffffb0000000500000000000000000000000500000000000000000000006060527f04fffffffb0000000500000000000000000000000500000000000000000000006080526020600060a06000610100611af4f46008556000516009557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffbffffffffffffffffffffff7fffffffffffffffffffbffffffffffffffffff6020527fffbffffffffffffffffffffff7fffffffffffffffffffbffffffffffffffffff6040527fc9e005dd1af6d82d77505fbdc1b18fd3d9741240907a510e5ddc9febe80c768f6060527fc75def9510f5aba00f7917e84ea6002991ba59604d84fe1cf2b6b4cd6ea7c6746080526020600060a06000610100611c3ffa600a55600051600b557f63b53bcdd52d82e3e5ae5108ed590a8631113f6abba1624acfd0cd5be0a0d56b6000527f890c4ce6a855ff49e201e0ed48e8274c14be1cbd115364818c32fe3cedfa7c106020527f236ad4b6d7f6ef8bb45b6d45172b950216c0738bdd2be455d33a3058d34a061260405260006060527f5a824510cc45547b0a39a6b8767f15f0ac481a630dbaac91803d3bfc6b9c6ebd6080526020600060a060006001610100611cbef2600c55600051600d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c7760005260016020526001604052600160605260016080526020600060a060006001610100611c1ef1600e55600051600f557f6ed85366d9c82e9481594355f9b55ca5408697bca7ef1d349e6d8e37e2b4c85d6000527f7bc7b5eb03d4cd86c342c7dd8f06d8e2a952439d2e8a630919d74500a4a344496020527faacc19c91c17de70c9873189d63e0d28987290f3089e5ace18d13d5ea618439e6040527f8047db8b33c977bf4d8069f8c3715097251328b395f3cfe5c475ddf3f762e5606060527fa75ed49f31331b289b30793cefa79a7e0ccece8fdc7796f909112e53d509d3746080526020600060a0600060006101006119f1f26010556000516011557fe506e35f179221d3ed2944ac1ac29b7483a73e7adbd784c5ee7bd38b345dabf26000527fab4deaff0494294b86417f8c8d2238649f97e5c45f926a183e5cd1594c4cb07e6020527f4afb0bae902a54052d1bd6b411d165669850774bb42b8ecc73cb102c48786bd66040527fa7c4a4fb78abc4a6cd32f47ce4db416c91208a04f7ae267e8151968fc3a609646060527f89d7f7cc508073e2cc8644c5154846a74315dacbdadbadda1cafd82e386dde4b6080526020600060a0600060006101006119c6f16012556000516013557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611be3fa6014556000516015557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527f8be9b57e112a8abb6ec40524a35e864b5293159b6a77f4860f8e00ceee6348d260205260006040527f48209be5e8f0e89ee1f0d4b74645ed38280f0bc6ddafec46f395720346b12e1a6060527f5512a03479460ecd88cf83565013839e24c5a84008f6edba23f0d0b9dfcceb4c6080526020600060a06000610100611bfbfa6016556000516017557f69955cf40e14f69443bf4f8ee5432aa2b843671673ccae71a51215fba3872a426000527f8ec01f4b15fe0c755482f5e90658c5a758699386c587b3657aed859e90eb69d76020527fb5eb6c9b3994887c43c6f40747ff3494f507592761d915254a01827d7f36d10a6040527fd26cfb0cd81d2a94cd7a10a5972d6d20d1f06ccdc6cbb0f578a4bcfca45f2df06060527faad80ba35b270796c9cae745b7a027b43027d54af56540fedd8c9b73114f47156080526020600060a06000610100611b01fa6018556000516019557f500b93dd1d2a593c5a87657f32a4a7c2688fc81d9696cdcbad878cf630537a9c6000527fd78d8eeffa7139961a28191e23ec8bd01da90e63007ce5f9425fc50ec264d6f96020527f0ee4e5c1a1819348b133f191aeebecfe2f27b9be698d6ffcb5fa441ddffbd9196040527ff1db2ab546530306590bae04535c1353a7f14b8e8b3a893bd88358612774b4a16060527fab214a7af0d280dfbe046277723d67cefbdb88c22aae39f752e872c257a372556080526020600060a06000610100611b16fa601a55600051601b557f5da1d3b0edc7e8bf95cb6f26d1c264d9bdf4ea04f05a9ed1e541bacb8672f675600052603d6020526059604052600060605260006080526020600060a06000610100611b8cfa601c55600051601d557f22fdb863e2df7a57588e5cc6b8b128c8ed3e88b5ad088f1b37a2f981bf41bdc56000527f69bc3329e8cb108c84c98ceea1bd99d39a2efe8517074b1a79ffb6c8fa5d163f6020527f5d80d369a9dd69d08bb0389ff4dc31d3a179aa82f61a2543e9dd3b58326f7b216040527ffdcdaac7043a1c5a4abe5883e66744659480933d3fc6d79f388d18a72a0f11076060527fa4edfe3c45411b6d8bb1aff118ca3d1a2c56beea9a2b9778a6c093d0ff22e25e6080526020600060a060006001610100611970f2601e55600051601f557ff5c112beb21695afb638f1032170f8b4af1040fe570bf6356c74082a31bd6bb36000527f399ca9ad9f8dc34b7964f8a853550a4901e3eec73fa5604131d2e7ab2d0e6f156020527fc048cf554cbffaa48220a65412e471ed20e28bdd82ffe99589e3867ee7e9069b6040527f1a8634914abb264491eb6c117d8a3c72a74965333bedfb0494bdf448da64838d6060527f57ed3625d9e134d129cfd6a7d3fe7f6c898fc9aff54c3ae2ef0890479e5e5e8e6080526020600060a06000600161010061192cf2602055600051602155600060005260006020526000604052600060605260006080526020600060a06000610100611987f46022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a0600060016101006119e2f16024556000516025557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f22276e0d2c74bdb35707e25acac41b33490f53b461dde80d2c6114f1698391d96060527f470aab8b0fde69b11fb96c7d20a0ca75f3654fe23a02f19e7d98eefc7ccb8c8b6080526020600060a060006000610100611b93f16026556000516027557f160e6420d863db6655fa27dd50cf8e353f9ef4a20092520f63ac63f4e0eb32556000527f343c3b8c8e2ceba457169b28ae411d0a278741b36f671feac0fea97a45cf40d26020527ff6f052ffdb97a606b3ac7009313248236b4ae112d3acfa537663d4c38452de6b6040527fa25d6665169122469ad9dceff29c3e6e871360326eb49e49e0261adf89361f016060527fef7b14d9fae44f66fc4ee9b481ca0a6ac49cf8eeb913b4efac7a064ed9ffe6946080526020600060a06000610100611b93f4602855600051602955600060005260006020526000604052600060605260006080526020600060a060006001610100611928f1602a55600051602b557ffa194dba78ee8b822744bdbcb38ec187ce7e6957ba51c87d846781edc354c2de6000527f7df9c36794bc5982da95b00d072d4de68c47c54b7764b1a445bd00c418d489c16020527f6c1d819223cb31c461c96697f336c1da899f543a61d5964258167c4b874db3dc6040527f4ce7bacbcebb07f25acb5ef88add479e12c3b0d61e4c0b8bae8d909ad260f0226060527f77c9584e2c81ff7a15790f44da433b1774037cdad4197b7f5919f3c7362439a26080526020600060a06000610100611aa7f4602c55600051602d557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f01fffffffe00000001ffffffffffffffff79cdf55b4e2f3d09e7739585f8c64a6020527f01fffffffe00000001ffffffffffffffff79cdf55b4e2f3d09e7739585f8c64a6040527f615dd4a0a844dbbc1ba9dbc9caa8a519a38e98fc4b354dbc92833c2762344bb66060527f633ba1bdcc154fe6e0c3d52306e212ae81f22910d9775e2c0b7ce8a7a88b1c896080526020600060a060006001610100611940f1602e55600051602f557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f8f9cd5d78b75c2accc5121383427522b84cb4c2a8b56c1f94eb4a0576183d3c46020527f8f9cd5d78b75c2accc5121383427522b84cb4c2a8b56c1f94eb4a0576183d3c46040527f02fffffffd0000000300000000000000000000000300000000000000000000006060527f02fffffffd0000000300000000000000000000000300000000000000000000006080526020600060a06000610100611c20fa6030556000516031557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6020527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a06000610100611978fa603255600051603355",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x7f20aef1c1f12d6a92cb52c4715a73e8c2614607f6ac041e6430cab9fe7fcdc1f66000527f1c939c4275bf050dfd34fa9b8f3f385d8aceeea459e4da4d6f5be4bf21c30c4e6020527f041d957b0f7cd04de520dbdfb6caf3b7e2c93f15dfb83ee4964259dc3a71010c6040527f1187ca1a59643ea4c84ebf358eb75f0197b94ccf1de9a611a8aacc67e98b81596060527f04c60f013196b55a72e324986492f7fb42bf9a29dc1eab9f3600576e609908386080527f01de910256aa0b0cf620ad54825cea02f2a010466e03f48525a844480ce7ca2b60a0527f12bd4e9e7da40cb226005e886d4157519c785583ee0b628a7e170afca0040a8360c0527f2af1146a5a0a77a33db10bb29c0e88c2f129f12da3e337e07207adc8fe35fd9360e0527f18d9d93d2709144afd90541edb4c76af2e1dc914e7b798802dbec728e8545e8e610100527f0f6c1fc929b35d345b04e7311bd92a7c4cb484f45a4a2de21d822b646ec56bb2610120527f197f6a2343a24edf4f5ca3b3bb758accb273d4d73665d6fa3162b3aa91641baf610140527f167a452ec75749fa735a9fbb78d97befc3f7728664c4addcb0685ab2f56ee7846101605260206000610180600060ec60087ffd27c6ba6a708c14c70af9ba56fa769590455ac5d595eb467381738bd373d77df2600055600051600155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xC192f888ADA47142Ef2c856FC2C35197eea9E718": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xc14a8497cfed2168f05952f5437042184f962496ae2ad8f389cf588ae6ae5426",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f010ecc09792089d18d4479db8993c8fcdb89a002902be5ece3271bd6659d7e0b6000527f044972c01a9d6ba28efc73430f44409753c29ddbae5bff87273015f602ab1ce46020527f05843ae5b1feef147e98cfc86520ffba73ac7d193619ecffbebcb43a646bb8ce6040527fa1b37d411bf6aef0bf6fc51999378760024b9887c33d3bb81a68d3c9b75081706060527f9560b0ce42d34e540905f397216d5c5db68e507e5f426d697153eca14de27d006080527fec577da7b3b854936beb95a33eed744afad1634bb7caf1367891d297cbc7c0ed60a0526040600060c06000600a7fb3e4b6e12f51d93384e52aedcde8fdb6b014c0a3d95f3ded6e7f0d2b57dbef4efa600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x60006000526000602052600060405260006060526020600060806000600161d14ff46000556000516001557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f7a716c6c3afadd1671084c199b249ab67cb13b24bda9e286436fa18f7864e4976040527f10fae069ce12132048de75c2026c733caaf588c455a968b3651f7c228fa44b246060526020600060806000600162010699fa6002556000516003557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f99f4746ad5cf85f771993c0fd69d90ba6aff84fd3b54bbfaf5f37452d1b728976040527f1b8f04ef96c64881c8e59ba85d32c031b8596e1d8902abdb28efa35741bdd6a960605260206000608060006000600161c852f16004556000516005557ff27665304201615ebfd77f43b648a3dcfafff868a7cdb9aeffd48ec1e264856c6000527f64bdcb002895982b9ce61851c1432eb49a3950047c2d7ffec0cbef0c1e64391c6020527f183664ca17e24e37d11872d0c0598d15bd9ef3b7795ccfac411d31c772a67cea6040527fffffbb016c07414c332e7c980d032465d78ecda7783ba73789fcf5d2d4d9c0c56060526020600060806000600162011c5ef46006556000516007557f41ba54f83d2c0d9b4f38d9d9d3ca20379b17295a7086a01b2abe79a8836e7e186000527f51b34b41f839df524328d27001af78a2278758e6ac46b9e370472fd52ae78ce26020527f0916b5e6f73c3cda7ba0fd79206f5dcaf3f2ac62da7223f3da4d316e6c31426a6040527fa7360ef9b3f7448986a48fdc1eb2f8d1739b2dbf1e02dbc629f01ddb0a8f5d0d60605260206000608060006001620185fcf46008556000516009557f4537e59187daada0452406912ad285677796e5f3343eaf3f6a8cc62d8da6092f6000527f0b256a3b254f8a868901f48311a481702c817405e994b48ddfad842d4058071b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f114edb3d78635682a891fa57035b3411904f8a3f346d440faf7534c7e6077ed2606052602060006080600060006001620162ccf1600a55600051600b556000600052601b60205260016040526001606052602060006080600060016001620160faf1600c55600051600d55600060005260006020526000604052600060605260206000608060006000600161f04af2600e55600051600f557fc6dc4bda4074f5f3b4e12522a9a0223053dab048a7d424e88ee966270a22eb4c6000527f94dc6447ffd64c131b25e7319daae0f199fa9166236b1548f969de00aa09641d6020527fa407f508e892c43f0dd3ac2cc0dddbd939d39bb6faba6e498fe6e97cef5be3196040527f5d615f63e658f52f872d2b7bbb4bcbdbae0b4c3df2a73bee519578b185d3e58e6060526020600060806000600160016153bff26010556000516011557f33d5feefc5519ec25cc0100957b7608d3665a475d3783bdb88ba5b53908dae916000527f36812bb46b76453c52d59b88b683c4c28ab62ee6a35e4433ad3a054d81d9971b60205260006040527fb1375053bcc1d5d98acd0f6ed39352aa4c0956210280d87cb01ff69e265234476060526020600060806000600060016201352df26012556000516013557fdce6a42b5553622247140cde69633c8b457fa610f13d087cd48fb82e2995b1a66000527ffdb503ac2d6d53bd6a5a40ed90c1c40c1e41a5486ec04ccd5f0ea21b3ef59c1c6020527fbef9c5fd0a2414d203c03893359266c7c0b935596670b0f03c9c2d71bc58a6376040527fffff827136bbf05cf1256f0c6dcc1d55f964e1e8dc8eac450b56370ed6b7c3e660605260206000608060006001600161bc37f26014556000516015557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f6eb702a6332e56b41cc0cd5235b32b1ff7c6cb9d486e2b3216f08a77433033f96040527f572979406e827f3ef2b31fc2678f1f6c7b89605ddea9106fa302fda7af29095c6060526020600060806000600160016201596df16016556000516017557fd2d2ddc40c9eba073cf7dc252b24d4b859faf5f4d76c484030bd7442f773dc9b6000527f42ceb9bfd0c82e953f894afeb9fa4bac618ac96fbcb6ad0ceb923912acfe281b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fcf55bdbc0e2471363b3ff29e3c95b4fb79c962bfddcdc25fd7687dc28ece8edc606052602060006080600060016201452cfa6018556000516019556000600052601b602052600160405260016060526020600060806000600060016201245ff1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fd47dd3c1d041a555aca1b52f7198fb903eb030222fa613eef67ba627fa0640a76040527f7b5642d919eeed48663cc5f5af3c554069729e2cff8be177adf994f65f722fa560605260206000608060006000600162013c1ef1601c55600051601d557f563ac94508886a144c2c03279382fbd9ecbc8710b0527dedee83332fbaa1df176000527f08433182194af83c622691218fbe4760f097cb4d9bffe06d3db15b921eaf191d6020527f45dd3caa2bbdf31bc21b70e30dab5617e2062864ace8d7b2b0d783b08bd3274e6040527fb047a3a77f908c13d37b2763331b7a52fdbc0780d8e3b53cfa1b7df03c4f072060605260206000608060006001611793f4601e55600051601f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f743bc6098efdaf75f878572b65040cf9459e05d875e65eb140592f6a5e82e6ab6040527f765e9112299a4b18d31198eca89311fcbabc0d5b238be6f688a496e7751ef882606052602060006080600060006001615560f26020556000516021557f2e098924832cc1e3e61f37e39c0e5865e5060ed0268aeabf381558565149cf606000527f30ca5d41c93b865e912445e13e0113cbfbc76d48a59e7ca00ea304f6c1d63e1c6020527f9cb92db99c342a7a4d550f5e732dc30201822319a7aa4ee4f599c5c648bc66d76040527fffff0164291505107e496abdb5738a5cd089195b547afb043b09909da06cb13760605260206000608060006000600162014ad8f26022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fd61240180ee4ba2ac39064feba53f2f5655a3555f1ad982b68f24d46fb0abcd76040527f2833151b144a0411b05c2904e358f54bc7dcb1f23ccff4cfaa2913ec1c5fff376060526020600060806000600160016182ccf16024556000516025557fa8ad052dc706ed8513a5e200da416e7230339f1417edbc36810e6390887621af6000527f33184a5cf1dacc9891af332af34024f1aa98ba82751572cd1ea2a00ee2a84b1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f16a0fae6f494f63f176aab5f15d2b09c5da5fe43f6650c406d1432b5f5786ccb6060526020600060806000600162013a8af46026556000516027556000600052601b602052600160405260016060526020600060806000600160016201829ff2602855600051602955600060005260006020526000604052600060605260206000608060006000600162015b6df2602a55600051602b557e5013d7a5fe09b36373406442599663a125ad3f4a11bd9780c149f1f83827ff6000527fab11953158f950c085665e576ccba0a135e0ff7acf5b87417f0237b0a5d61c1d6020527f4480cc59fa0a1b3ade81cac1ea3e8a596b4966086e72948923348d7aacc52ce56040527f91a72e339775f3bc04cc1233063435de168690521311f42fe25ac55e9f4001ac60605260206000608060006001620156a9f4602c55600051602d557fac6eaac38cc30405f1571eefb890b4a4ec94ae45782d8107158c7b4f25ea8f726000527f2717660cf7c0a7a6d80ee4adc0158d9550deecf7744d959605c3754f9f9e191b60205260006040527f299f28af54efce351b5d16681e5bdd6e58427c9e0c031986d8828f9ec078ff8c60605260206000608060006001600161b3e5f2602e55600051602f557f7b931c95a91a9b1adfffe8d278110e6894ba93fd1e6300cffe0e37ba6952efc36000527f8ed55391f54fb886f4598d4d0ae7ed1fea86797718916b9c63c41fe0890aaa1c6020527fac275c5d8acc7f4bf159626eff9b88d082ef2cb85970ce49cc51bb25685c28f86040527fffff3e35ccf1ff364dd43fb8c80a5b24dc9233de11caf201c065570ad28934c060605260206000608060006001600162011234f2603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x6c10000000000000000000000000197f82000000000000000000000000000000000000000000000000000000000000007702ffffffffffffffffffffffffffffffffff00000003000007077702ffffffffffffffffffffffffffffffffff0000000300006780000000000000011b1a7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006801000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f59009127cc9700000000000000000023f00c00014ff00000000000000002230080567d02126262626262616137d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007bc9700000000000000000023f00c00014ff002c0000000000002231089009677fffffffffffffff7702ffffffffffffffffffffffffffffffffff000000030000690100000000000000000090089010900b60b2557702ffffffffffffffffffffffffffffffffff2000000000006001901876013590cab83b779e708b533b0eef3561483ddeefc841f57f7effffff8000000000000000000000000000000000000000d900000000000001900b1c7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60057ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000090080460b35567d0212626262626266a100000000000000000000090167f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5717676767676767676760000007676767676761c1160b4557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f7effffff8000000000000000000000000002000044000000000000000000000190066c100000000000000000000000007702ffffffffffffffffffffffffffffffffff200000000000900390077f80000000000000000000000000000000000000000000000000000000000000016f800000000000000000000000000000000660b555678000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1d901c7f80000000000000000000000000000000000000000000000000000000000000027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901390177ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd90186101117f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd68066aa0a5319bcf5cb4090760b65569100000000000000000006000900460b75576013590cab83b779e708b533b0eef3561483ddeefc841f5680100000000000000009010900260b855760100000000ffffffffffffffff0000000000002e0000007f820000000000000000000000000000000000000000000000000000000000000090176901000000000000000000671fffffffffffffff900160b95519691000000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f507900468066aa0a5319bcf5cb46801fffffffffffffffe1290177702ffffffffffffffffffffffffffffffffff00000003000060001c6f121212121212121212121212121212127f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5777effffff800000007effffff800000008000ff00000100009008901260ba5571767676767676767676000000767676767676712000110000000d0a300e750a000000090a0a90101b677fffffffffffffff7f8000000000000001800000000000000080000000000000008000000000000000678000000000000000900990037f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6d010000000000000000000000000090109012671fffffffffffffff6a10000000000000000000001712651ce97e1ab91a7f7effffff8000000000000000000000000000000000000000d90000000000000190180676fffff716b61616160b0b0b2b0b230b000008010d0a2b0060070360bb557ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007176767676767600000000007600000076000090051469100000000000000000006810000000000000000010901d7f8200000000000000000000000000000000000000000000000000000000000000777effffff800000007effffff800000008000ff000001000090109016760fffc000000000000767676240000000000002b05760477f77676767676760000000000000001002e000000000000040000000e0000000001c60bc557f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff76013590cab83b779e708b533b0eef3561483ddeefc841f59001901d6f1212121212121212121212121212121276fffff716b61616160b0b0b2b0b230b000008010d0a2b001060017a01090000000000000000000000000000000000000000000000000068100000000000000000091a9015900467ffffffffffffffff68478392145435897052900a7f80000000000000000000000000000000000000000000000000000000000000027f7effffff800000000000000000000000000200004400000000000000000000016b10000000000000000000000008901690176a01000000000000000000006b01000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0009177e40000000fd000000db0000000000000000000040000000fd000000db0000d37702ffffffffffffffffffffffffffffffffff20000000000090079019027f77676767676760000000000000001002e000000000000040000000e00000000069100000000000000000000a901b60bd5576013590cab83b779e708b533b0eef3561483ddeefc841f5156d01000000000000000000000000006f80000000000000000000000000000001901d60be557176767676767676767600000076767676767667d021262626262626900307197176767676767676767600000076767676767667700000000000000090030415637fffffff7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd9001167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6f800000000000000000000000000000011d04156f800000000000000000000000000000016101111060bf5567d021262626262626637fffffff0790147ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7e40000000fd000000db0000000000000000000040000000fd000000db0000019012901060c05568232323232323232323197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8000000000000000000000000000000000000000000000000000000000000000900190047fffffffffffffffff7effffff800000007effffff800000008000ff0000010000690100000000000000000010900560c1556801fffffffffffffffe7f77676767676760000000000000001002e000000000000040000000e000000000901a7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb760fffc000000000000767676240000000000002b0576047901360c255156101117f40000000fd000000db000000000000000000000000000000000000000000000190036d01000000000000000000000000007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf96f8000000000000000000000000000000009060a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff7effffff800000007effffff800000008000ff0000010000677fffffffffffffff08047ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb06910000000000000000000901490187e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100063800000001613157176767676767600000000007600000076000067700000000000000090136f80000000000000000000000000000000717676767676767676760000007676767676767bc9700000000000000000023f00c00014ff002c00000000000022310890081b90137f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f8000000000000000000000000000000000000000000000000000000000000000901d900b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9007901c717676767676767676760000007676767676767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb901660c3557f80000000000000000000000000000000000000000000000000000000000000026b010000000000000000000000900a03157f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1d1460c4557ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f62d8fffffffffffffffffffffffffffffc18000000000000000000ca0000000110671fffffffffffffff777effffff8000000000000000000000000000000000008001900216684783921454358970526c010000000000000000000000009012027f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00030b7f800000000000000000000000000000000000000000000000000000000000000068100000000000000000900160c55515760100000000ffffffffffffffff0000000000002e00000076fffff716b61616160b0b0b2b0b230b000008010d0a2b00901d90037806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901090057e40000000fd000000db0000000000000000000040000000fd000000db0000016f80000000000000010000000000000000169015017e40000000fd000000db0000000000000000000040000000fd000000db0000d37f80000000000000018000000000000000800000000000000080000000000000009016176780000000000000006801fffffffffffffffe901867fffffffffffffffe774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a6c1000000000000000000000000008900b0b7f7effffff800000000000000000000000000200004400000000000000000000017cc9700000000000000000023f00c00014ff0000000000000000223008051d9002777effffff800000000000000000000000000000000000800169100000000000000000001612156801fffffffffffffffe691000000000000000000002147f77676767676760000000000000001002e000000000000040000000e000000000691000000000000000000005017f800000000000000000000000000000000000000000000000000000000000000068478392145435897052021a67ffffffffffffffff680100000000000000000360c65560057ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb09009027f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000016380000001900660c755677000000000000000690100000000000000000090171760c8557f8000000000000001800000000000000080000000000000008000000000000000682323232323232323231763800000007f800000000000000000000000000000000000000000000000000000000000000090140767d021262626262626760fffc000000000000767676240000000000002b05760476823232323232323232308036101116f80000000000000010000000000000000778200000000000000fe000004000000ffff000000fffff70008901067ffffffffffffffff600090031467b368d219438b7f3f7f800000000000000000000000000000000000000000000000000000000000000090121b777effffff8000000000000000000000000000000000008001778200000000000000fe000004000000ffff000000fffff7000690017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0068478392145435897052901260c9557f40000000fd000000db00000000000000000000000000000000000000000000017e1f0000000000000000000000000000002000000001000000000000000000001719016801fffffffffffffffe67b368d219438b7f3f0b03157d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf96770000000000000006f8000000000000000000000000000000009056f800000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe69100000000000000000000860006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000ca": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x00000000000000000000000000000000000000000000000000000000000000cb": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x00000000000000000000000000000000000000000000000000000000000000cc": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x00000000000000000000000000000000000000000000000000000000000000cd": "0x0000000000000000000000000000000000000000000000000000000000000003"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xd5A8353a487e0749707fee138b741aeb2061C14C": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x4b5f705c5993deaa35a6d4e991c09c52f1d54151048b241126aa7c780cd2723d",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556001496001556003496002554a6003556002600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x61026260005260246020526102626040527ff1fec7959374ce5d274bb0a066fd25d6a7a0eda5d66247e90611eea900d93dd66060527f3261bf7f4a1354ec9c06574626a9f622a4b463d8547013098dcafb926e4736a46080527f2a2f602320d89b1d7330c8afdb044737104b3c1df434e20cecdfe27fff1d1f2760a0527f1ecad556a17a8a7bd6e68d5a04868ada5e17684e3f260e2fc8142dee9b3812e660c0527ff1f6436c628b04937be67aaf3df114fba877dcf697e789ef8f3e0d65da018b6e60e0527f5134802f76d89e54193a1efd277cb40b2fef4819b6c71803b540d35a5736fa07610100527fb82884b8ee0bdd6d160bb37981688eaf2997550bd816f22d790b68f6a613f115610120527f4b0cfb396fcd8d20c873179465d91a926b35a127da6851106e93a1c95d306531610140527f2cf297554aea5d6a9c03a2397f17e3ed672af0c83dd0250acceb68e7297b7704610160527f64f27ad759e258d9021631c63ecdc8e4586ce55237f3a4107c35975cc158def1610180527f24b24b5973e1f540c0f4120009a97e64b8184beff858d50d4ad2ffad3951ddc06101a0527f819c0f43d13523fa4ff0d19e2125a05c420517eca779beaa2a7cd38184210c476101c0527fad10b5f2259319e47bd25046de0a0b2affb1610fa4b7e3750143e9aa35c44f726101e0527f9f0ec1800e9fdc12fac4dbfeb087c50e073b95c24b68419e31aade25653ba836610200527f2aa1362bdf0f50a44625a6f6cf94471ec9e37e1362f1ae6c54bd73bc48d175f1610220527f7432b4e648de16c9ff2ccd7d0c46bde6d99f0202b94ad09effb10a3e03e82c1a610240527ffc3c493d3e7658f8de59135f4183cac601e3f940b0f269625ff68a106420ff66610260527f0581e520bada0d8aea39b5df5cc1580f3743fcf4367944cc3a777f8687c3dc6b610280527ff2d859b0ae0467db1581a1825ea8f32b041b6fb47b084986f8aa7add00e69b496102a0527f8008a31bb9d8901fdc563425ed15567fa92f3f2caac4a95b4f69986861257b3e6102c0527fa6535c9d5c6eb1fd9d1af1ffa7d9a17daff3d9f390b94cdb30adf8856754b1406102e0527f7ce7a6bbb1642d6d4497b7f29914c5ce41da9915e5b1ffc8b418226d175c7478610300527f070aa85789733ac4df0330e4dc3359ce3cfd092c7ca52fb4e7329ba9478d0a49610320527fb31b0f71a8f651c80427c925f7866f5eb09570a1c0c916bd287824b01a30a76b610340527f4596e9e1d193313e1f1404d9ce3b9f0426230c24927405a48bf4adff74e76fde610360527faeb92923019d16f8790ccc7b71e92b68924f64798ef2a9208548c15e21b4086c610380527fb99ab67cd7c8af790ab5356fe5a0e28d5df8c51dc22b83ccb2711f30965f1e616103a0527f2479fc94a5451dabd9828512b8b40f67ee0b6d8e7eb1bd866992cb058930d5116103c0527f092a2183f2c6ef97cfde4785cc1c896c8bd768bc0a870ffa104345dd7a38aa216103e0527ffb91f752acdcf005d60392fce991749582688ef75179c1e5bc302e3474fa092f610400527ff01bf4a1ca9ec98b16516dd639870c7da21822e753f618566bd4116407bfa814610420527e7b1078ef968ef0d58cefb9442b9f72a949f123d74fe9cbfbeba9d1ebaa50e9610440527fadf61176f5482726f72e521273f004ff47ca791a2d36f46ad735d8c5daa7522f610460527f6a8c8353f541becd5b975007a0cedebcf07546cadb88f89c3611c4532159b0a2610480527f6fd6ca54878a97d886a2496d88a97f39a91ed2ea43b2e287949f111b94e2bf116104a0527fa52821a5b62778a1f910b7dd380e0d35f460a71b9ea7b63e4f2b751af2911e766104c0527fa8680a459d4dc3edeb3b23251632ae8a41949552e870913ce7de2ecfccde155d6104e0527ffe15c24c187667c8910e993fb1d04570b7e0d9ac330b1a0ea68beeb755e9d7ae610500527f3d2c6bb3e5ec048336342fa09dbcffd6e3bc9db43d8d273c618328d4e312dc3f6105205260eb6105405360686105415360766105425360366105435360306105445360df6105455360ab6105465360286105475361026260006105486000600060056245d72df25a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a5561014051600b5561016051600c5561018051600d556101a051600e556101c051600f556101e05160105561020051601155610220516012556102405160135561026051601455601c6000526003602052600b6040527fae8cb809085836c6461fd847d701b558c26c51eb89ded0e4ff921ede82f27af66060526060608053600760815360456082536058608353609460845360806085536072608653606560875360c3608853602f608953600b6000608a6000600060056102bcf25a01601555600051601655609560005261046560205260956040527f51e308cca5d5ac57dbe129b458780de43b42d08aa050668a10113010a49dc6f66060527fd82d6601a2baecac57f0e1c15c28b44dabcd90369f1a2f8cd1b1c791b5e41a776080527f7b30038e72372e57653bbd08827dc52e9d409e9c3f856cf957e3aa07935efd3f60a0527f607b55147384e53c54b16ad07bb4f2a4552a5ef66aac08876aa63adcd96fd73360c0527f98ea449950d7e2b1211249ba3a5497695f288c7cfd000000000000000000000060e05260006101005260006101205260006101405260006101605260006101805260006101a05260006101c05260006101e05260006102005260006102205260006102405260006102605260006102805260006102a05260006102c05260006102e05260006103005260006103205260006103405260006103605260006103805260006103a05260006103c05260006103e05260006104005260006104205260006104405260006104605260006104805260006104a05260006104c05260006104e0526000610500526000610520526601864f62290a6d610540527f6e280af90f6c1ab0488405bda8fc417b0f391199fd48342e4336d01c8de18952610560527f5b8ad7f1b5b421f9e73ee1e6fbd2dcac4422fe7a7912ab495c50857aa41d927a610580527fd21c9732633fdfc61ce2b92bb93b1a8138c99bf822c316fdf2a767ec2f111cdd6105a0527f6841a331d9ba76ecdac0bc037be9690a436647ea5f0a066ec929d3f0d103d1596105c05260696105e053604a6105e153607d6105e25360106105e35360596105e45360886105e553605e6105e65360986105e753606b6105e85360716105e953603f6105ea5360fa6105eb5360056105ec53609e6105ed53602f6105ee53609560006105ef600060056301060193f45a01601755600051601855602051601955604051601a55606051601b55608051601c55",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x40000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x20000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x2d",
+ "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x0"
+ },
+ {
+ "data": "0x",
+ "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0x0"
+ },
+ {
+ "data": "0xd62ca02e7d6738996d60a387da91a74c438dff99e2e30450d66a7985d5c657d0e2",
+ "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0x62f3"
+ },
+ {
+ "data": "0xa2c35d7d43a94d59ac5163860c03d7c78e1d76a7ba7c31a46b",
+ "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0xfec4"
+ },
+ {
+ "data": "0xf22e90978887563e1316e37d58f9c440c5ff3dad0958ad7a135ac3e2e9138b5341c1194761f2bd698fdc91b7058e657af5941ff7aa1b8890e51ed18677d541eca021c6efe2762bbf0ee6baf42c741a1134ea12",
+ "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0x6c64"
+ },
+ {
+ "data": "0x8ad4c41cac6d56fbbf1d0d0bf5d6",
+ "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0xe27363"
+ },
+ {
+ "data": "0x5214c25b6a7f0ecedc0b5a4aabac02ae1235d3503dfe2b50df5ec8e1dfe00b1785cf0f6c000eb9413b0e2929ee87f64c7044853eeed72caba5df53681e4e7b1344ad1f0d79801b94464afb3b080b99953ee906",
+ "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0xcf8207"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x01247b3190ad6b61d69c66ac67a278508b7cc80b63a7d3f183965818f46d71c2",
+ "0x012cad5172a80ba067a9836349573f8c09a6dc870eb9933ed445787556a4ea59",
+ "0x01b7b97c0fd264b8559089187f1e9c8b736854d626379b9db34473fd96d3bce3",
+ "0x011907322c3d5ec3b09fa61dcc48f7a0eb8750e9b3cb911a338f126f1a54d2b6",
+ "0x0159e0a1867bb093a1ed6beb9a7e1aa843a926a8c77ee604899bbea1222ba448",
+ "0x011eb4c2246fec736cda7b5e62a4f5eded1e6b4948632ed38b7da929c1ca83e5"
+ ],
+ "data": "0x87d848",
+ "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 1,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0xd317cdd0be355269b7c5b51cd37d519950d774cb5598ffc8e74bca40d0c243a3b83a00612a30fc5faa80722094f38c6002904e1307cddc4e8f191e47191b9584c28bd7561a80b0f4c91be21f4556640d3dd85033038ec2c7a52d951b93c283e4dec10482186d3a732a269deb66abb6d8f560df063baa4ccf74baf3dd0f579b387985541ee3f0427ee3c3c3c229ccd82da43ca03e3561da96eb66c7e983d6efdfc48583998abe381e796863f666bf1a6f99e019a96ca80b8b12415b811f0201f051e6ba702173beca86251fd19b5f172e27d977a730e6986543989a58e39fae4ed6a75a59b9ae505890b2a195001704fab5a0b4af848c04862be48bdd5c82babf9e56b9adff9fa642c762f64b5536cacb260a2615d7b852dc7fc807b1d67a0e54d82557f5d39dbf3c8ef14deee959d261321fc9c7ca64dd05ef869cdfbedc19ac49fa8a92725b1b180a57d1c777e34f583f14215a57c7d33f4b3fa04c81f7cfea48c64ce135aed55b3c23ec58c8bdac489b8f38c6631cfe594b63",
+ "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0xa4"
+ },
+ {
+ "data": "0x",
+ "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x0"
+ },
+ {
+ "data": "0x23c2eec37c11cce00a8f704284073089267e7f0bb5b5258035f584b6cd8e3dc2f8c9196e4c4194faf6d4fd4db3",
+ "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0xd0"
+ },
+ {
+ "data": "0x061997d49b5528665dbc3d800ae7d897ac84137fa32000299fdb0c9777ebc080a9aed590d6",
+ "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0x85689d"
+ },
+ {
+ "data": "0xcde33a3fa310af41e8a2fc059de3fc0222e0982551d5d80fb8bc2e5f3e34b4f4fe3a8201a9d47b414357fd2db6817eca4d6b81504f6874f82ecd62e6720a0fc7b39d3a4201b024b7ba304e8e7c765fffed771999cc53fd9c93cad3",
+ "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0xf45bc"
+ },
+ {
+ "data": "0x88a6f05cf67bbdcc10c4826a7f3dc1a835777e9b99148f860aaa0f4e3403db9d05c9824e2afad1dfff78ca58c8eb57b3570d472049fecb75495effc83061f8561fcdb6a395e35a467359fecab218",
+ "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x6b2d3b"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x88f9b82462f6c4bf4a0fb15e5c3971559a316e7f",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xbcad8bdc514baf5efab74757cec1366ad303cb086e4fc286650a499aa2c51979",
+ "s": "0x291e47131cefbca9f42434f163e1be4d6fec29160ce5f1ed716b3735e5b01e7f",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f9",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x71a82efb37c3ecda82184a469fe3095e61f879e9cd6cd5cc57c8db85623be99d",
+ "s": "0x62b8658048dc674f566db07998c96909310096f5e90788af763e6b3034e78387",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000010",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xcabfcca10b4052db14893fc01934f4d9ce6a4a06984a8ade1fa538783c89bd7f",
+ "s": "0x1768f53ad91b153d1340e0e9b1b2cbac0045f3de0fdfc05a108aad36c033091b",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x36a9141d12a6a5ac448d602b8aef8cad98744204d15197dc9f78e501e792d07e",
+ "s": "0x32e21e07bd4dfbe1a4f009a32d9e1e69006f290993324c31787e5f110a42e115",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000002",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0xd66534866f9f76bc71377f381e6a57df9e7ced92cb350241c0f48b5c776848a8",
+ "s": "0x4c40ed83b35061e1a7c94909aff2b00ac4b936150ad4de8a3ae3b3e498be0635",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f1",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x64aa96c5157c207876e42787e9dcdb83fea43c95b3264a41a88f5e1d9d4c99ea",
+ "s": "0x49d207f4228fd08c0b2be3fe77d341fd466ddb4b2cee0426903f608f0ff881eb",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000003",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0x7b740e7556488f71d67851fa3b750ed08dc672413d8bc85a31aa10d8b3d41e14",
+ "s": "0x508ba9c3d39cd3061ec7db5533f01342abd201dc964487baa4eba8ab4394d02c",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x68f591a70cb6fefad1b2aa3c181edb3b87c7fecc8376afb6719b5c0801ed65920341fc1cab010d3695f9151974e40051a84371823d7b65f1",
+ "from": "0x862B38c425EF5544d0127449A12c89C46dd3E050",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000F",
+ "type": "0x4",
+ "value": "0x5192a0"
+ },
+ {
+ "data": "0x00",
+ "from": "0x0233362c058b2fCc8093841B1073A90D673E7F12",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x88f9B82462f6C4bf4a0Fb15e5c3971559a316e7f",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xdd95902a4746dbf0cb38778983b6a5061c9784572e18492bab91b69a04315a29",
+ "s": "0x115d234e528f56cac392831ef418acb2db384b9b92749f4174e4e2ca2b2878a3",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x68f591a70cb6fefad1b2aa3c181edb3b87c7fecc8376afb6719b5c0801ed65920341fc1cab010d3695f9151974e40051a84371823d7b65f1",
+ "from": "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000F",
+ "type": "0x4",
+ "value": "0x5192a0"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/tests/vectors/fuzzer_test_1.json b/packages/tests/src/cli/tests/vectors/fuzzer_test_1.json
new file mode 100644
index 0000000000..fa44c8e294
--- /dev/null
+++ b/packages/tests/src/cli/tests/vectors/fuzzer_test_1.json
@@ -0,0 +1,497 @@
+{
+ "accounts": {
+ "0x0000000000000000000000000000000000000010": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x00000000000000000000000000000000000000f7": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x0b530C4203F212318CE214ae2F1089d2478cb56c": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x157cbf9b700eef449fabd47069fdbe505932ef1adad4838332992036780813d3",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f19caff34fc5d41317e29d5e9f4f6d82a6000527fe2e0acd91783ca4e41ad927047dd549ad45b2219aa5422dd2c26b3399e84c82e6020527101000d80549ce27f0e5d07c4d9e259b070936040527f11e50838d9b10616817a4190ff6df2638128184b156a81f8c518e6baf19227a16060527a01000000000000000000001246341896a0554751d9a2bf3af6980a6080527ff0a8a04a2ccbd323e6e2346cc2be29847a6706d90abd298ec45e7744d4ef260860a0526f03ade5bba92764a5b115252fb5cc366c60c0527f880d73ac87aa9125199460ab8cab072f8b31ac20d28109b5e243f61d880fd4f660e05260806000610100600060d9600b7f6696b9800943dc76700342da15183f39d04923e24aa510de8c23d73c99cae7dcf26000556000516001556020516002556040516003556060516004556f167215b1682993653beaeff0004b14ca6000527fb88e8f2ceae397ab24a56be8ca4b3d6e2274886602ccd162cf64e110fa4a52b760205275040000000000063cf200b79ed865de1688cdf2b3b5236040527f55f49c08a47c5915a84548a59fc200e5ba430068bb0d1935341a6e634aeb2ded6060527fa9306a65a0e604373a8cb4339d55eb0b53fdff55b9379d1133f18c62d14c6f2e6080526f07b653e774e775f620ddf0e6b50fc9dd60a0527f53953e3cfd57d6616abde936c03f1c94b8c31dae7796cb3553212f26960c012160c0526f07aeb25d937d3d5eccbba85393bac1ea60e0527f5b70af1ae11a228b368f5c67f3c038f40be90299f4118a3dbd31c82b8d909840610100527fc2b9d98f02a25efa9fa8860fa9f80a43c73460a0d20e2113bec1c1fd7bf1618d610120526f02701b17eac732f65624ea3cd8be10e4610140527f70a5c5c3a3d6c10d8e4b45dc00bdc0a5e47f1aca6dcdbfb0e121775d61aa5226610160526f042e9f71c007d9db64ebb918fab442c7610180527f1dbe92ebca595a268909659e8db809e1617398e16e62c5f27cbf81d1c5d19ce76101a0527fc55655c9c78415954c172a18aa445dec340dc63eb0e866afdb0a25bdf1244c286101c052608060006101e06000600c7fcfdafdcbe09640f2464567b36afea525ec5de9358dd848c0b53b421a24139393f460055560005160065560205160075560405160085560605160095560006000526000602052600060405260006060526000608052600060a052600060c052600060e0526f06dd8919fb14bfdfab0f526a1f5239b6610100527f0b450443de757b82dd27fd61c3cb9a71e0573f50c339192ae937a298d2fda166610120526f04eda0faed5992fbedf736c817215d2a610140527f061ab4611c80704a98232c964308c34a42eadf0376a9a6e7a3d70ed862ac5b58610160526f14abc9f2f81080bd0071687392261e83610180527f604dd562c7c618761e4853b134fab49f395d4cfdc10a7779e1ee640d1f87af366101a0526f0621325b4b3f4d5b280989cba49a40446101c0527f8cbc5e4e87ea344b0a59a59cbd6c3f485ffc4f24fc4c0358a89e08e1cffd70006101e05261010060006102006000600d7f7524c013a9951987355d80fe3ac319676bf5d5135301c343fd3d5b79d46da74df4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f17921415f9ff8bb3fe699b6495fe9bb16000527f6a142ab1e5e402bf55aefa40069d0c51592ce1586eaac5ffc39c1b63b3d0ba7f6020526f0e0aa5850d480a3d8cd9d5fa6f1d24856040527f3d0e7f46925e64fdaf666a9e5141aafcaed131e79d8261666dc8b142122e38126060526f0da917cc0d444ff2df50086d85e9b9576080527f6535e60c11eeafa970e381f95da3ed077e0cd30753342840d2db4d489d475dbe60a0526f0f2d7f29490255daba12b39022dcb6c360c0527fc4393dcbf2c5473d49f853993a9a833a2749a590356dfa608666ccd55c0cd04160e0527f0f83fc7c6c0587c4b87d800c8ef57ce037f9a317cbc6cddd33f9c725dc0d268361010052610100600061012060006000600e7fc4895dcd70512f399cd4a6ab3b9a94e6bce2e677769bf3fc66c3287bebbd89eff260135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f16e9a53c8298651e6d39e7d5b323284c6000527f10244f68ae94dd48bc745fe049e67d70681df88b199a2a2ba8f4ed3ff9e6e1d56020526f08e10f8f043e399f7f98e3a77cf2ed3d6040527f8f4928ca60da534ea929dd155350b5ea46f3f9e561a2b4d210c71b56e3e3c8f06060526f07d50b4d03ba978330fc267892bb168d6080527f746e3109a61583a4a2af18673590c08d1209336e235c8b113f81645a1d0fb7d960a0526eda68b12ee5ae79581f8c5ecf4eee4560c0527f62e30c2043d9336045d9594171a87f85caf11cdce1d305def393e6913110095660e0526f174988222802e2e5c94a516878b8c6db610100527fa56b52a69d70336ae79118f527eb303d2bf1c73c98a839485f5c493b9e738149610120526f0ceb05b1a555e9fb31fdf86cccad49d6610140527f4ce60cd5739c269a1a32b33d0c2ced561bbd35d9f2249edb3b7eb4b788ac8f83610160526f02ac71c4092cb44485e40bb9aba9c9d3610180527f443a137d91357ac2f396c90f00c7108f07e48bea04abc4ce8d31af0f47a2fde26101a0526f0853b2e555c99f7b42203a596493b5536101c0527fbc638d3a9954816a8d1d3a248d75d45df83cdb4362d93ecc3b0ebad969f3ce076101e0526f0e47ed6095014c6bb26aebf873f578d9610200527fba610c5276428f46a65f1eea6a8e69fd917eccbb7df1a06467cf06d59a6e0024610220526f11844e132dce68e4345276947724a03b610240527fdda05c2c6a9c936a9a8775a4b2075b7a6103ce6c2f11a225d13ce265fe55394d610260526f01964a9416e284e459360fa860c89a01610280527f23d65d9a7679e4c9ce0fd8ad33fa07bd6060b60eec7fde88fd73dfca094f94e36102a0526f085b4a9ac88c960ddb422fa88b3568c46102c0527f48604784513f5221eb963855b06bce22bda53affdd70e4b98a0ff40b98beaf676102e0526f15447a27385181684a148242396311f8610300527fc2c01489c6e714f44f14c6bac555c3f09c21f3e1cb8f5a4c9cc667e76bb375a8610320526f187bdee96685d72b15768e87738ac090610340527fce1046af57eb88b9c87977253bfb3fdf10e1e8e8d5eed280766bf6fc3d7b9cd0610360526f024aa2b2f08f0a91260805272dc51051610380527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86103a0526f13e02b6052719f607dacd3a088274f656103c0527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6103e0526f0ce5d527727d6e118cc9cdc6da2e351a610400527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801610420527d40000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99610440527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be61046052602060006104806000600f7f7f80628a357d42b11e6fd04a25350afcb2a4ddc960c762759e0edc19d2f2d4fbf4601c55600051601d556f190b5d5db51c6a5368c6fb2aeeeed8fc6000527f55c128be3a72201564946bef2a9190c8a1956d850bf5e72ee546f4d883b6d219602052608060006040600060107f99646682ed7d62087f392cee9340a90c98295fe4038d6b5f2c3e6e457a3870baf4601e55600051601f556020516020556040516021556060516022557d080000000000000000000000000011c2b0d6fb41c389c5d3b1d07553e1896000527f63b36a67f2a0ea76ddc11609088fe22a47fca4dc88ce65fc0209c6918f8b9fd06020526f034cf4436a26bd7f98373de09ce810a36040527f6309d107ead83d7f3c1007b00d58be95a0462264196e81262fb57f47dd18c72060605261010060006080600060c160117f3516f04fd741b0b10a8c7a84cca64e82bed0c8fc4b1c16c0ba6f2fed80e74aeaf260235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x602260b960b760f2609060346021148a990397444a3a18991c5214863c4103788a8c3a3d5ef59a857b357d063e555e5d49771b4a1a476f545c9d6f53156238486c45395c465c7a32a37f72a186041785628280440668f55f7d9a315d166159657a13f35264786b7e427359017c7b5e01086f89547335046e99635b647d5c191b477e7e4830076372f2f1635f5479581a129e66a16a853afa733c58467c335f4777375e630bf0557647776d72480038a0417261f2313772561843a34011795e0588714a823e6da174119b928972a220001c444873033e9b9668a2747506997c435430575b7b889b7f7e49ff67703c8f0774441b0695325e95368971028630335b44fd1450f439808cfd73733b547d1071f51470183d6054180640425e72719177643c7981706f579c7a647a9e4a5d357431046e3d6857069105f35ca0741113415d381d064809010a11a33650644410170846557181107a5b9f815b06a450711c3217118b1268167f56757f1210967f3116f24308523a9c024370465851667f626f50746ffe386c351b3263307d133e7b413f5f1e5489790a6c438343a241017a75a0536780895c469b1379856c6a1793090a3997651e9451f147323b3539a1623d9d967d7f428c345108f157396e708972500339806088556cf33e76a0586836100730067006038354036b398059368d3063168a8c006f3c6a5744331a3539876e520a3801a0a160093d67fd093b82a474023d5a3b567a6c816f30415416475f12308e531449578fa0083b14386c5b4412953155f04a78033f6f1597379d3512607219311c6314804918666c8a138663106dfe5e76126479649c096176698330689a6334469d14611b463f73f17f3ff354f0fd301e58a2868f1c42194386760264446c586e376c6dfd75513003027f6a691a65445c8e5b33a07b93156d02707465956a647a9a61924073050a1d17040437f35b6644587d33036c3511764846a3125114531e564490101c345d4a1c8e48525e0b59756c101993413e35455b6e050b9d986d7618919d905c6f8e605f77553b8204517a3a9b80967c507f126a3e639d587a3f8ff0185b01f36e6a513f195646478d6617a3327d5991471e55983980381119856d3e7848810833348f51696c77851c06343863545c677b006681368f407a571a618d3771116f706f329676195d5940135a907000387a3597756e519109948b96799c7a98677c345e668139171a14579f3f6f43081203553a3901160a0a691643517d0889365ff03542026e795c49549288323119416020553d36805201038675197d0942633684696c7b3c3e634646897f044463093a41546777895c58138f8b427c80639406566f1d84956ff530fd6f60fd399ea23631197f31446c330271973a32a3155c41480351774263325a79178919761744335f143a6a7d50",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000c"
+ }
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x60006000557f60016001556000600255600154506001600355600160045560025450600060056000527f557f604060006000600060047f36b4f1d52647aba45de94939600358e701ebb36020527fabb1600052608a60205360bf60215360d5602253600c602353608d60245360226040527f60255360af60265360d960275360c160285360c260295360c7602a5360f4602b6060527f536060602c536006602d536055602e536060602f5360006030536051603153606080527f606032536007603353605560345360606035536020603653605160375360606060a052603860c053605360c153606060c253600860c353606060c453603960c553605360c653606060c753605560c853606060c953603a60ca53605360cb53606060cc53603b60cd53606060ce53600060cf5360f360d0537f3726516ff6afb368da0d12e86e99748428aed23ee5bf03f75aeaee14cf1bdae460e0527f2b83cb68e5ba2c412b683dd5faa66a07e182f4f59dc70d6b320d6d4181ce0ed7610100527f746be7ca124aa2bca0fe3dc55c6cc8f44a5e1e2930f84f5a822b44303e0f790c610120527f92d2f1690821e731d4cb9203421ee925f00617320c317a8671939e61666fd133610140527fc08586e712d5efc118cba245e33dc78269240ffb3b2250da12cd5a9bd4dfcac3610160527fddae063a1cd1400af8af40c2b53904fb939a812c511af8821453f2e611b782c2610180527f0eb6da4b4c07e1e290339bbe5c64f16c5e2666bc7c96910d55531ba23ac61f256101a0527ffa397670c3a25dd3500af010e3310f878ab850ab7d66ec1ce0ba296ca5f10fac6101c0527f29c5aff225053603b31d5c5418eda6d9b8b8f02daac699980d5aa18a904f62d96101e0527fb18cb29151d86fce51629e9de4ec92ddf705dfdd9e8d1208052e43b32d83bed5610200527fbdc9469bf7f3a5f394770b6c66aed956de7be64f028b96da7538d61f8c502f5e610220527ffeddd512f914664dedf2381aed820bb578fd2d56b27d78a603db69035f6ada3d610240527f305910ad13ce1288194c6761cbfaf9ecc04bbd56752ee34bd47752e247b266e1610260527fdd79a40b36434911a9631444daaec918c08d2bc9d045f336796e760045622282610280527fb7ca6111bc82161339ab1a2959e78f60bdedbe67c284558c7ebe989d80a8d8e96102a0527f0b3c1a4cbebf19e61db29be4bbdb79f49c2b3ebf94d3ac00375a12c51a495a886102c0527fff11f7e91dd2f5a922e585bf4a3ccf4caf00088d8497fdd4d0eeb03e24a07dfb6102e0527fcccb5a1b972bb15393867efc308981ef6a625bc031d835cc0120177360590534610300527f13b8f82231514ae3ea8a19a6dd7537c0808bde918b15ff1fa1b2dda28f9d1792610320527fc1e328a14eb9a03ff7eb9d65af91d83301b67a3914960b7e7963bc10a010c767610340527fbc4d45ba427d312da4c934a47dc632e6dc7c14119e16b4cd1a81dab6a5e1fc4d610360527fbcaba568741eccb9f3310a67e3b0974970dc10a337f3be9a65642293c265367f6103805260d160006000f0604060006102c060e0845af4600955600051600a55602051600b55600c55",
+ "nonce": "0x0",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000010": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x0000000000000000000000000000000000000000000000000000000000000012": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000005",
+ "0x0000000000000000000000000000000000000000000000000000000000000014": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000016": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x0000000000000000000000000000000000000000000000000000000000000017": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x0000000000000000000000000000000000000000000000000000000000000018": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000019": "0x000000000000000000000000000000000000000000000000000000000000000e"
+ }
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7fe1a31e9d6b65985c0db9b672bb6d55b454de1ca89f693b6305eab9d051e63dac6000527f9ceb3fd5b29ea165b971ea736fc32fbad18ff4464bed46f638085a1005fbf5df6020527f1ec47106d4e3c0c6bc569e045db7b6e890d1687ead46da9e515c6e3b9eef31356040527f8fd11b1d99f82e0f419eb7a9ed13736d83391798a157196fb445495b89a675926060527fc531ca15c827b1b596bd1107f362ad6afc0d426a2c951502734e346f2de8dde56080527f79ff9827b2c0534e01787a1b8dd7fe855adc62a47e55a138dab9c9e368a1ece660a0527f4b2bb32f436806c15bbdd5aa1685271167f90090b0867ed9b9f65467dd01278460c0527ffafa4918f584bd1e5540ffef9ae8737a1f99e0246b8275d48a30893cf987b0f960e0527fa4bbdc014d8d97cb917aaa73d6f9ee28abb331248b7ad35afbc2deda96f49d75610100527fd4994add7a509bf6a3ebc9653b49ef6e7f95399349aabe9d7bdb3b61bdf858d0610120527fa3da114679ef650c371fbf94125a8adce0b2826c9015a258304e0bda3c51118e610140527f27463379eeea92d94e8eba640c22d0de41bff611b1754695905841267161f30e610160527fbf90547c700258cb2d8dd93c097de8359a6599ed8d0780cb59539cc1c2638b44610180527fc3096ad3f1873283d828b50c41efc4ac41aee51cd7f2bd7d3d4f33afbcbe032e6101a0527f5aff79e915ce4ab6f25d50594f799404aceb01050e881e3db774e4d55d5978c26101c0527fba56951b64e7152bcb9194971dda9b0df5f930200b8273734682715c4e6056396101e05260406000610200600060107f2f97ddd75c0c05125fae073ccba46c5e539d71bed8ff23853bf1764460229fdaf4600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x600051600d5560ca610160818120600e55f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x401d746660008b994772f255600860005560005c5060076001557fbc8df58e6eed20da90e13f5ad2c08765cb6e81439a6da04b12de0540574684ad6000527f7159dcb73f8965ac626a129d4079b06b37f92f0421e62bba810cc8110558453f6020527f1df0080d280babd78d73e16c819f791cde947558cb175008b6491426ef95094e6040527f5c4784a311acf42f8cd893a5c489ea07c3d637d7b64e8ada04ec7c12b46fabf86060527f1d5cb4b437399e6bde518642eae21cc163175f8434d59979098c4d0dbeb50f736080527f852be8ca72f3700871dbbfa86f890081180b5551a802f20a1f5f12de55f3e2f960a0527f318dba96318f6da5462adf7e9589495080040023ef8d45f1a34672ecf71338e760c0527f23936a7f7fbec00a3880ea52fe3e86568ce44061752d5d0bc62d4c83883a57ed60e0527fc467bdb7b28d098a1f1451d9d5c4e8ea8b81e03db78fc63cabb1ca744f75e81a61010052604060006101206000603f60087fa266b49f47d3fe71da4e7a84d4e319f7affb522119f7de9f9a600a5627456b1df1600255600051600355602051600455",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000007"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7c204ca729dad386476072a674923939c221cb19c4b7b4abd0cc43fa5f776000527fd4abaed1ff03eb0617079641124fc2da5e11e3b4eed3f35a8e5a04ba046b72486020527fb2bafb6e4fcecd331fb65ddac17759c71080b15831692735583c69c439e5c7656040527f7443edd4af446493c3011fde316b91daca78c8f767dced885b3166d83feb88046060527f4f016aa7ded3858aff740a0df5c2472456f4278461ba7e89007aa3f1ef7e45236080527f81c3dd9d889bba4caad01c180160b3d402aefc9a33ef0a422dbfce85e5146bbc60a05260ab60c053607260c15360cb60c25360ce60c35360f760c453607860c553601760c653606a60c753603660c85360ef60c953605560ca5360be60cb5360b860cc53604660cd53600a60ce53602b60cf53606560d053607660d153603760d25360ce60d353600060d4536040600060d5600060f060097fe6b64d3649bed6e6bc3a97338bb4211990955bff747c3a0cb26696f5c97e8212f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x4d9d461b0689c4bd2e0a75f78f8fc9dde4920c554402cac511acdd600e023977",
+ "storage": {}
+ },
+ "0x79caC06f747229e9F79FA47049fb37884ec384b1": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2d7dce3ec394fd470eca53cc6fae4c8d8b38f19433d56ba6e549a98ab2bec9e9",
+ "storage": {}
+ },
+ "0x7c2C923D79B9903f29A71bFAB11B24c30C9FF962": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xb1330d826f506a345059475813d946401278a870614ea1128f04ed451d5c9aac",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x63800000017d7676767676760000000000760000000000000056000000000000000000009018156000557702ffffffffffffffffffffffffffffffffff2000000000007f800000000000000000000000000000000000000000000000000000000000000190117f7effffff800000000000000000000000000200004400000000000000000000017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00069012760100000000ffffffffffffffff0000000000002e00000068010000000000000000901d684783921454358970527e40000000fd000000db0000000000000000000040000000fd000000db0000016801fffffffffffffffe0990161c600155760100000000ffffffffffffffff0000000000002e00000060057bc9700000000000000000023f00c00014ff002c0000000000002231089008778200000000000000fe000004000000ffff000000fffff7007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a1b901b7d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97702ffffffffffffffffffffffffffffffffff00000003000013600255682100000000000000227ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb1a6003557f80000000000000000000000000000000000000000000000000000000000000016b100000000000000000000000901d901860045571767676767676767676000000767676767676651ce97e1ab91a901676013590cab83b779e708b533b0eef3561483ddeefc841f5778200000000000000fe000004000000ffff000000fffff70090036005557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff1a6006556d01000000000000000000000000006005900790116007556f121212121212121212121212121212126f1212121212121212121212121212121290056fdac7fff9ffd9e13226262626262626007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90181b15762900760076761e000200767600000000767676760000006801fffffffffffffffe1002677fffffffffffffff7f7effffff8000000000000000000000000002000044000000000000000000000190069019901160017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00901a6008557e1f0000000000000000000000000000002000000001000000000000000000007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10009017901c7f77676767676760000000000000001002e000000000000040000000e0000000007fffffffffffffffff7effffff800000007effffff800000008000ff0000010000901c901c6009557e1f0000000000000000000000000000002000000001000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17600a557f82000000000000000000000000000000000000000000000000000000000000006823232323232323232316600b557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7effffff8000000000000000000000000000000000000000d90000000000000190017702ffffffffffffffffffffffffffffffffff2000000000007cc9700000000000000000023f00c00014ff0000000000000000223008059012600c557f7effffff800000000000000000000000000200004400000000000000000000016c100000000000000000000000001790146d0100000000000000000000000000677fffffffffffffff1603684783921454358970526b0100000000000000000000009012126380000001686d5adef08547abf7eb13600d557a0109000000000000000000000000000000000000000000000000006f8000000000000000000000000000000003600e55682100000000000000226770000000000000009006901560006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7fb511be36d35b74739a85351c052fa4de58db198a76d03d145a2d33203c2c32b66000527f26ee5abbb7ea9e33fbcc013139bb00934e98d3f25e6da159a52d2e0152bfc4f56020527f6d0dff51561b32482bf7e6dd4c7c2b630ec00581ae93c8e88b02ea3ba6e3f7586040527fe6e1d60bd9c1f8c2f5ac77b0a75b1ac10d5d436517f67132ee04da57ad66c61a6060527f4089ebd6d189c7085362bb204ede3e28c7de082ea6906a192d6fe1e86cfaf16f6080526020600060a060006001610100611b1ef1600055600051600155600060005260006020526000604052600060605260006080526020600060a060006000610100611ac6f16002556000516003557f9a92cfae6639594ef5a936af7206a825039830b70121bd288099792299610c776000527f357d5942107baca8191dc32f847229ea93a7ecd634f96cf82b77603fe057a6676020527f84b09f3632409869d2fa6f36de4eee7cd0071520e71905199c75e18bcfeeef3b6040527f941d0fd4fc5d0a735c27ae11507ab5ea2a786cf14a9254c9afc3df2bd2c08be36060527f3d4798b3215eb8fe2dd88edf7b0b569bf34b9026925eea60bc315c65931ac1cc6080526020600060a06000610100611b2df46004556000516005557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f2caca4cd87938c0530ef51cd1db94e01e69b7e4b7e03df64fcc0805927fabca06060527f7887b1df3e1b05a0ee2e48b7c1165c05befb4beea8606070e12e62c12c127a1e6080526020600060a06000610100611ac8f46006556000516007557f0bbb06c7aeef3093a1a0eff5c46deb9d7d7cc7cf8d821ed636871c880b1a6a556000527f3e28ff5c73e7130c61c678d789af2a87ae9f7c290d7deb610d6ad79f113d94186020527fe671e799198805f8189928646d971703d44cdf97409ddcaf27223f93f54fea606040527fb8122e7f2fea191d2802cb055c051aa598069afddec63d69cc994c7e900172d16060527f60c335144e54220c97209ea95244251059d0f3d442e5bb6dc51af9ae73a457e56080526020600060a06000610100611c1bf46008556000516009557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611be7fa600a55600051600b557f592c81d1677b5196e4d245929e6496a2899555bd2a946d57c23ab32ade99ca986000527f46b70fe7265f36468e64a4361f32e849dd282a0320c260735f21ac79dd1bf26a6020527f042e0e533318524d279d357a0d8e74efc9ba6d3accdf2371a11ceb55c76e59026040527f4b4525528aa2a41f53151a6f41f345989e19dc826bfb59fae30dd3b99411fc816060527f288e3f6c0d35bf78e6cfcfa5f9da83ef49e11dca41b560ce612fb573a94794546080526020600060a06000610100611947f4600c55600051600d557ffa70288e2ea04596712d5db7d2648d0fe15a93ef1361cb32193ea71208b4e1d16000527f01cc6513c119ca09301a270e2b688b54eb9cdfa4f82910ab5e9575c876fd28106020527fadfea09485c17d44738a41923ea61cccf37a76b86392f7df3e5bdeabdf91a3636040527f54bf277179e68b0be4828fb6f0abbc32c5dd04b6f94041dbbc318ca2b73c87e66060527fcce03cbdf75a6153c5f68b229d5eec99c9cd3a3b909759e052555fd3461c18f66080526020600060a06000610100611b48fa600e55600051600f55600060005260006020526000604052600060605260006080526020600060a06000610100611a18f4601055600051601155600060005260006020526000604052600060605260006080526020600060a0600060006101006119c5f16012556000516013557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611bb4f16014556000516015557fd900eed45d1776f9c7fb5481006bb7c814974494d8d64cb48ea64fc45fbb0ba46000527f69c2d7f49d906367e5162dab8ee5a7bd7823c111f921dc9f8f0067da568c7c6f6020527ffdae48e7c41220e433a48c84156e2d83ede6dd68a80e3f272632b2743eb4c7e66040527f0992f0090cad0a5a66b1abbffd6f3edf2cb6479b56e43b587d580a13ef05fbcc6060527f5c80af8232db2e0eaacdd05ff44633998ea9718b003da0288868905ee1f551c96080526020600060a06000610100611a07fa6016556000516017557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f75415288bb9affb8bce0c2c7e9e621d6a039a9eab09a1a9a3a5d948db555530a6060527f1e425924b0e734bf3e320737c8c4d93466125ec8ab3f1c6e27d874d61d8459696080526020600060a0600060016101006119e0f16018556000516019557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f24af7a688a7415dee8c9f61925d9ce1b49c6c52fbd58ca95ed6c966a68abdb626060527f7850ec2e896e2e95eeb06daf3f97f70c7c749ee9dd193cb34e92a5606c0f56ed6080526020600060a060006001610100611bb2f1601a55600051601b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffbffff7ffffffffffffffffffffffffff7ffffffffffffffdffffffffdfffff6020527fffbffff7ffffffffffffffffffffffffff7ffffffffffffffdffffffffdfffff6040527fea73e64300f1f62cc62a21316d8c321f0d94bd46ddd81a3ccc28637e9fcc059c6060527feb47b65c82e04c8d9e2b76e469127a34cc255d65fa7e972c4a2e59b43f362c456080526020600060a06000610100611b99fa601c55600051601d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c7760005260016020526001604052600160605260016080526020600060a060006000610100611b35f1601e55600051601f557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6020527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6040527f9f9f373679c7afa4dcabfd13c9ad7caadb7a21a1cb644f3cab82894c2fc3945d6060527f1a38fb7e2ae12442797eaf42952fe8c6e1c1905413d679d3b214a795573c66896080526020600060a06000610100611be7fa6020556000516021557ff081432cc644bc72156bf6142c4c64d2e4fc97a00b031e7cbb351d295757248b6000527f3889aeeccb261d4f724fa0f8e59e98808c196af04c6254e04ab6eb4d092450a46020527f142719b3436d45c38cb709a57c9ed6fd29275349ec7cbd8c9bd41de0889642186040527f88f4a68540ab8a1b50cabd1cf090cceeb373d82664498c439a4a32779c0d22c96060527f3e6f058623651dce23bb510f143af1a5ac880c2d37fb418c5842372d1f8c34066080526020600060a060006000610100611a70f16022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611a65f16024556000516025557f07dde465c9a3eafef9f67182ac66f082bd13b079e6e1987a230a289731751aca6000527f818ae986aaf82a2557850c44fa8c66c08cbf773a40926c4207f4dedef7f268ff6020527f5d0f62fe7ecedb18fc0a6816290c84e1babcfc3ce7c45eaebd2b3e240590e0d66040527f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2966060527f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f56080526020600060a06000610100611c7af46026556000516027557fc80aeda6f4081e9c31cbb36b0197cc22a8efd63adcb4485f61236cfd06a71ca16000527f1ed7abd2c30eefb6d147a7d0d2f3a8131ec404d52ff52646139398d66a01f3f26020527f79c92381a2a06bfb3b1031bb1b4cdc77d639373002ab0ac314b1523a7de7f68f6040527fafbb22c18f1d6d660576338408c29a612c553e312ba6f8b29b93506aac7adce96060527f0f515ec269b4211979d43151e407cc25f6696ede802c24b68ea55f1342b96fda6080526020600060a060006001610100611b9df16028556000516029557f7c12b2191d8ef871047530a206958736d82d157a10f5f9988f3f751f7c7692426000527f2f5258e2c042a1da26a26c70833f7995b6b861a45ab2fb138f436b5b085b8fcc6020527f5737f2db6ec576ea11b9441ed36d37cfe21d49f779edd05b50fb7e9eb68a4e626040527f7d11792e312872bbb04b7aaefde5e2550098c3f3ccd932512ac1aea601fc47b16060527eba8209eac9863d2b1f4a437705c9ccf468310512b30b8bd9fe41cdfdf2ef9a6080526020600060a06000610100611c33f4602a55600051602b557fcd43b17ee6fcb602f1e29abfa2a9d5b48cdd5c092d98c32e26b1302d4960a5a86000527ff64f37e50c8f8a6ad3aa7ea6b3ccc0bfbd5c2f023a1dba33e7c26f90b72ee02b6020527f66a4bec343d4643c8dbf09232a8b5b00449cf8a99ab6f4038334dd54d6cd7f8f6040527f7db82f7ec4beba67b179c1c2a8983df79a36413992aa5a39503f1428cc4e25016060527fae00f9aece5008162b6f21c518e3ee6434941526acfe840344e9be157bd169636080526020600060a060006001610100611bf4f1602c55600051602d557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006000610100611aa3f1602e55600051602f557f7373927df8ebb8a5ac091c307565643314c299619e3aa81e01a2ec6e115f916a6000527f1f248c01540fa05841fcccbb52901e202faec36341b941b94f7adf285b0123446020527ff49056605d85bf9bdf7895b87aeb87d34b5aa57b60d87e53e206c9b2f6074e336040527fec54228434f47ad27d147bc0b47ea82f5c31e0f2eeb2d7aeed573a4c36fcd1d16060527f6d1cec152f3e3e8c6e0d7a4fc389ca47b94c8e34478fb0f61567663746bda2b06080526020600060a060006001610100611ba2f16030556000516031557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006001610100611964f2603255600051603355600060005260006020526000604052600060605260006080526020600060a0600060006101006119aff16034556000516035557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611b07f26036556000516037557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6020527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6040527f19fca7d59f879cc12ec4bf084df587cd4d3ccbc733ec54a0147cc582b4adc0036060527f9e03dddb7ee6f0c81ba11c47ba04d3c039c85cf63f37150313a47cd4c7fd4fc76080526020600060a06000610100611c0dfa6038556000516039557fdfd58aca08532a61992566dc9b53fdb5dd609a84267fc29f28ef77fc4e3c36546000527f11576b29c809bcce8678b900952429f5d435c71987b644e1a07cb6be2fc5e87c6020527f5baf683fefa7a13120e806df4a57cfee97e9d69605b839ac94182a1cf6301e146040527fcdb9ea9af1bf1cde5b8bd83ef72b4fb5b65427b883ccf4e0ada5eec1f167b4176060527f9da601bccdebd3c0a6ad3a73dda7875df3bdba8df4367998adba9839c3aaf8486080526020600060a06000610100611ab8f4603a55600051603b557f8d91d8ef900d4b1496bd67fda046a82037bc18eec3722e72de615262aacfe02f6000527f988aea2d9c20396d364c85b705076a5505a697dc7d60c8ea91d380576745f4e06020527f3e83d58208c5353e179a2f374c2aa5a4f3101dfccd9ca8dd229fa6e801b045e76040527f32f9ae03f79f5f7dbbc96223efb8f7def32a2f7047d7de0d3980706eb8c1fec16060527f96b6a590c004c3a276de89397bdb137f5bb1724daf08e3211477535cb8ca969f6080526020600060a060006000610100611973f1603c55600051603d557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000600161010061190af1603e55600051603f55600060005260006020526000604052600060605260006080526020600060a06000610100611c18f46040556000516041557f6cab6c2b703f7d67afcc860f56d8437f3b9ee4c209a5acd9986d3b05ab60d9bc6000527fe7f933b46936a5004907e55c4dc53092c174ba06943bbfbf90e0802164689e816020527fc488f7fb05d3a80397b19b03318deb37babc32c05504c26a6f7d837938506f186040527fdecb3acc028e66754176866c6109a03ac60eff659b87f633ff18ce41a4f9ea616060527f9d95f2926562086975131b2402043777005a5bfb393da343f66f829b77c1969b6080526020600060a060006001610100611b18f16042556000516043557f90d223bd3b8895ad2d6820592d063af8ea6170dd2a6c6800187c545eb592a8116000527f727b03b61f5dde152e04c2ab579d839782cbb29909e54b219e895551cee9798c6020527f71e1a22cae857823d054a504ebe486c1f5edf176ebc327289a90ff07800c453d6040527f37ee2531e5c4063994edecf64d483d05316a25907afa516d9055ac86155b44f96060527f7b7108261418d866350dc293f13dab89cc9782cf00b0936264fccd768e1ba0306080526020600060a06000610100611b11fa6044556000516045557f89a43b8ca5df83cf7b97fde1b28f74c693d1afbd6fd0cb1ae1642625c718b0156000527f0bf972cce64c6fbcb27b07fd0803ff3c4fbfe3f306cd3b1375da67ed0cb725f56020527f71dff7030f06d40941d92a188072478f7387cfb411df41abe6a75efd6d9441176040527f47de18a2173098799b70d71e171fb432f7cff8592d735dab7063c246c37838c56060527f7e3fb2e586aa10db8130958294c8ca92f86746dd39313f9f044ed92ab51ebec66080526020600060a06000610100611902fa604655600051604755600060005260006020526000604052600060605260006080526020600060a06000610100611cb0fa6048556000516049557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6020527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6040527f95f802a4de6bd804746155b418f062143764ef2a147233201bf8495b228647466060527f9d0ef95979bbd0ab36881723e5201d79464fd2b1d4f2f4132c5bc720b4d444206080526020600060a060006001610100611bc8f2604a55600051604b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffffffffff7fffffffffffffffffdfffffffffffffffffffffffeffffff6020527ffffffffffffffff7fffffffffffffffffdfffffffffffffffffffffffeffffff6040527fe353b148a8865c34312ec4be2fd75654fd51c2a6ad9fe7c2415b99e1e88b8d626060527f6ecc2a0c493d21397f0afed91183fe3eafc4608aafbe16752fe678d72a9e2c326080526020600060a06000610100611b4afa604c55600051604d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6020527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6040527f890be92aa6553fafc61f2d7bc894e0364cc05674cde976108be782fe256658346060527fd327c7ccdc52c8148e193aaa15b9198ce0ac3dfb38edb0fc3f97562ee0cff9c06080526020600060a060006001610100611c4ef2604e55600051604f557f70d493d413d0f97b38ecf03f9936de5569134743f8ebba326bcab2fce1b308bc6000527fad6b307f682762fe700f50be21df0eae15576e3310374b5286fa01f4f580dcb36020527f410597b9fa20da8d725be815a38adf9641d936b67d4e253de45aa0cd0e7531fc6040527f0c75e73b83f06dde3f187454439cec155a7f4085ddb5b0d7c0dc603521ec6a076060527fbcbe14af3e150e96451f8ac7fd46dd5e25e2d6e8877e557d47fd886d930eef996080526020600060a06000610100611900fa605055600051605155600060005260006020526000604052600060605260006080526020600060a06000610100611c38f46052556000516053557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f50adc68d1ed4bc57595c7d24187a1ce9cb7af2a28fcaa41abcc98a4de3884ebc6060527fb88ec0b67329d7fd2dd4689999ff22382c9acf7c067992ba3760f30aeacc60af6080526020600060a06000610100611b3cfa6054556000516055557feff60afe0f78740345253b3cbb65e6dbe63a68fed452790bcbc9c55bc18a70566000527fb9818c88fa8b83ed5a07f59a313424cefca5fdc64dfb8ae2ea83f7d297033c586020527fb5497fdaee7d666f38c78cdefc0050ea7cbe3b27d366332216fc2194c3e6deb36040527f6f9356e40c32cf53e6fe489c0732ab8a6efd0a5ee50c801851cdc2b292f82c006060527fd981ea59cded394ac871b2d0932db19b36121cfaa9827ab6044622b62d5ad6dd6080526020600060a060006000610100611c6ff26056556000516057557fe8a6997bc3ef18a0bfd1f976c6b3a8bbacc623adec46faa8d943dca231d7574a6000527f80795269cfdd07798be6857e606cc0accaeeffe856e6b15f9071cff36579364f6020527f9111e1ee6e26e672d97219d759b5f01d8a511065921ffd3ddadbb52b79552ead6040527f8a4ecb4101550650bfcd765d7131923ae8e507f9bf6aa4fc066f5f793ed9c4b86060527f0e0d94805b96e84096463dc843cdd27b35a31f921115128fbfb97bef4fad13836080526020600060a06000610100611c90f4605855600051605955",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xAff0d1Fad46ff203C5b9FF00F10FE1134862571D": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xb20e2e99f2b7b64c0028bfaff9bdbc56f583bc930a85b190582c9f0d4033ede4",
+ "storage": {}
+ },
+ "0xB6754926EBc05d33a936ffdE524617F45429CCFC": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x9effa2a88d9a8cccb99a856d5e63c52601b8b08c69d7acd0ee942483a4b89370",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x7f02c2c265e04023dcffe20e4ccec637696d77c6e6fc4e369317999de4e2f22f056000527f23ce7327362b8cb7aa786d6b1df1634b880c790b63e59815801d6b8e2740ff8d6020527f0fc77f348be20708ea60d3b94d9817a096cdc59fb0cc5af2e58566764b522dd26040527f085883a36120154e32ad2690541ef9e1efb62f786b14483153b4972e5974ca216060526040600060806000606960067ffdb4e6ce5813b605ee9a363e27821972b4f64a511b4f4a1c6180eaa3f349e122f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x80ee8021793940859903f6f4b4b5f8e54cd8d71e8343a4ff0be43248585a7ff7",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f0169f1039479a1cb9e010b1fb7af9e0040fc25c7c635eb7e0c226cbb0ce6bfbd6000527f21ccad796c904514ddd7eed89662d0c10d19c93f8f3bfd9c6654a21e6ff957806020527f5bc83896961a345b57d239af35bc308ac25f6da92e25e50b1463bc186b2346556040527fad5f2939a5f241fa3075babc85771cf9ac6e3106badf3c4531a4ed255601e8e06060527f6d2e313e0bcde117a25041cf347fd8eea303142178574eb114d747bb6e878fe26080527f9db97a5ba9d948ff02d8eabb1cea46d2c924386521f3a546124bdab654f2e36260a0526040600060c06000600a7f85e2bed24cca9c9205c7e917491240569e0469906022d7487d17577195938020fa600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x6000600052600060205260006040526000606052602060006080600060016117d0f46000556000516001557f296f78b9a90bdd931ccfbe330ac522c4bc3674011373a5c6e2a07dced217e9786000527fc9ad117b3f4d2d304b12779a3c5c7378fee4cbb1ecc43547ea778aa62c67b21d6020527ffff0880374cd8b7b114142bcd47efcfceb46ea1c8b93de691208f6310ef4ab936040527f69d62d9240644396f4d1b2714cda0f47f619aa2c009ff577308390dbe7eef4926060526020600060806000600060016201846bf16002556000516003557f9495b0aedddd62eee6febe6e895d905ef8362d3664e5be36d7a12382a42865216000527f462a3f411ac3c1e25b397435a686a08c5a8c9b4c12daf4c076ec745105b35b1b60205260006040527fbbe793cd818974373af7368a4216889be43f792fee2525b13d65bcc11fb266eb60605260206000608060006001617c77fa6004556000516005557fcd46aad27501fd036bd5103506652b0b8971130ef7fb3ad11c627ff7c48e24ee6000527f34107e6abd2d2894bd30f1dcb5261dbba40132e4ac5adadf633a11970a79131c6020527f317ef659ee0a8e855ba05d47b4ec0dbcc59d155e6763c7f8dc77735787c608a16040527fffffeb1e76363ef29bac4bc4c703ca193c1df892e5322cbbe3e9206f286c8b7b606052602060006080600060006001620146e1f26006556000516007557f7a140174c51cf25c703fee4273fcafa7ac7a2fc87b78e7eb531cedace92187f56000527f60e22f951c13b1025f4eeeac8ec7abf355c91b116b34003e0f1a7de1908cfecb6020527f377bcdf2776552334cf3407b7e20ff850eb2b5e41c6c29a8b0ec7501af4021136040527f7c1301d938bd805aa46a5d4f618e8e6d4748c20f45eb2eb9b9bbfd86b04b0879606052602060006080600060016001611471f16008556000516009557fbdb142cb033f938315b0997d0fedba0f94678ad5ba6157b65d3fbe10fc2a6dbc6000527f66e2364050b7bb9ed95fb653732ce385d4ba8c46432378b1e177a25e5e31b21b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fd1d3f61e7328a38915ae5d4fe64d90cae583c13e412367e083eeefb6241d3d8a6060526020600060806000600162013de4fa600a55600051600b556000600052601b602052600160405260016060526020600060806000600161c914f4600c55600051600d5560006000526000602052600060405260006060526020600060806000600162016e1bfa600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fe90dc134b5745cdf092acec96cea2bf73c870375726f8366c1fa92c9bb9ced266040527f370c68cbf48ab4a9cf9c40b8b97805bc574ef0e0dbac5171e326f8566d290d4e60605260206000608060006000600161d2d8f26010556000516011557ff264b4e7da06c72fb575c7f0a3b9c31986ba5545fa6c68eda775a4d040e264cf6000527f7fd8d2ced0fccd11e450792c18aa5502ec6e59926df193163641376539f4301b60205260006040527f6eea0915c614760dffb89669fd77b21a3c54fbec96445e381999801282c7fe6660605260206000608060006000600161980ff26012556000516013557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f1d889ad783fb93cd8b1a00fafed86ceffb9372869b387e65d0cf149c98f983a06040527f2dee9d460d8207475a3461371307d5a1c982e9e9848afb97b518a4ed17c9fcf4606052602060006080600060006001620178c4f16014556000516015557fb9fd2a1e809c3b7e7d8dfe206432a81de90fa922f4bb7f3adc6a3716abffd3806000527fc6e489e4f2d91554e568b4f959d1f390465e5b1bd23c423774d2dc84c1a9dfb76020527fc8937b5ad7058e304a4e44bbe31cc4efce5ca2dc4500f7b9c697033031f61e6f6040527fc598b13938344c0d6d244599075bd4a602ff4057b041ac5a6b56193d7973861b606052602060006080600060006001612deaf26016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f90c2b4aafe3f6f4d25e37e5ebead359fa69060901a6938be171df655cbfe64af6040527f71f2654408880b6690fe5087cd3c7ca3c5d10131c79b7a5b1e652225060f8a806060526020600060806000600162010ac5fa6018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f40bbb8d71baab2003b987bc5f7ccb66df8b04a5201bc89e2f23bcdb144b810506040527f4f11207e7d336d7075a95f57b4a1b5caa5cb4accc50f9de98df1c555ae05934a6060526020600060806000600161ebebfa601a55600051601b556000600052600060205260006040526000606052602060006080600060006001620170aef1601c55600051601d557f70eb8cc6aa62dee5a1e13e0267b43694aed5d5b09835791a1523c9c11634e33a6000527f52b8ce8f1dbd041192fe3c06f7d0904bd1bbe1f15f2e0d78edd625ca9dd9291d6020527f3a4060d4b707437df0d0f1dca6b6290c0fdb1c79b0846e6b8d595be2ae27d9116040527fb919a3300bcd1dcfbbf72efa726ad1313219f0883bd443411a7ccaa10447eb1c60605260206000608060006000600162017822f1601e55600051601f557f5ced1050fb51c2a94cf987d493b396d4fa3a53e46beea80831a5d7e3d6bb86106000527ffa87751775d77462b6b34be506beb70ab28352c7f8e5e39175f728181074361b60205260006040527fe1d256c5100bcad5d9bbcae86dc22ea1b3e19647919f3effbfbce66d37418ed0606052602060006080600060016001618ccaf16020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f170d4909ec18966d3e28b7ea77e7823b32c23375110257748b80bc9e7a36dc466040527f40c2a1c302838d759b9a86ecdec3807c17f848e30adc4ad730cbf681cb2cde1860605260206000608060006001611e31fa6022556000516023557f2ba1713bcf21b729b7b5bd648fb582a944fa5c55dfeb08b91e8862e360f312ce6000527fc7a148d54f25335eb6da75e95d1604ca4dffcba41fcaeb4e8eb24681443049b36020527f02a55f450ee865c0caf6ddab1690853be92d0316977bc02de3f5dd17b18c2d136040527f25c2390881011d3dfa6c2dc5adf1e375862220f32e3b35766024ff4090122a146060526020600060806000600161904af46024556000516025557f0fb8ca4f71925cd08c671793082e4accd3050f3128ad1e9b4ab1c6d20fc4f0a76000527f1163c9bb92b221466021d2776b0b7613d47a77d9312db4e5e942930ec1ded31b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fa61767fb6b9f736b4962affdfc29347b0730878f841a7c7f78a9b70245bbc7216060526020600060806000600161f490fa6026556000516027556000600052601b602052600160405260016060526020600060806000600161ef81f46028556000516029557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fc8e6348e2c71786d2ccd1c7c967f420855cc839dc19c80f1b578b6d1c322f9096040527f3f5a8673444c55112df70fdfc64dbb5d07da30535a32c60a4d20055155cd1da76060526020600060806000600162018339f4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f8abe932511c6b22f6b28bab5650dc28d63f1981103d26534e1956c84c332fc636040527f133e7abea04d45a26b9300224c462c7705feb578e48cea8b5b40c13006be7460606052602060006080600060006001620163bef2602c55600051602d557f16e1c685844a7fa1b621ef440822eb44512fc2b8bee61e62a5874f912e307e5b6000527f9e4d6d753bcb998f92c39ea58808b75ea82bb0e9089f4cfd95afb7e26087431b60205260006040527fb1ec0f8d39f445a49efab6cf246abc10d7d5477361727498d30f555c2ccc94ad60605260206000608060006001620131d5f4602e55600051602f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f7f8c30c8d71ec097a66757459c78919acca9839d99b4cdc3bb9168f5930ec3f66040527f1d33b7ca4b1d6d2f44c2b98eff781b1f0bee479bada720563ec351345feb046c6060526020600060806000600162013984f4603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x7f40000000fd000000db0000000000000000000000000000000000000000000001671fffffffffffffff901c7d7676767676760000000000760000000000000056000000000000000000007f82000000000000000000000000000000000000000000000000000000000000007cc9700000000000000000023f00c00014ff00000000000000002230080509604f557e40000000fd000000db0000000000000000000040000000fd000000db0000017d76767676767600000000007600000000000000560000000000000000000090116050556005712000110000000d0a300e750a000000090a0a901a126fdac7fff9ffd9e13226262626262626006d0100000000000000000000000000900360515569100000000000000000006f121212121212121212121212121212121d90047ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000600590057e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006101117f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0960525515901517671fffffffffffffff7a010900000000000000000000000000000000000000000000000000901d1860077fffffffffffffffff7effffff800000007effffff800000008000ff00000100001c1a7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006f800000000000000100000000000000009016176780000000000000016f80000000000000010000000000000000100b7f82000000000000000000000000000000000000000000000000000000000000006f12121212121212121212121212121212610111900990077f7effffff8000000000000000000000000000000000000000d900000000000001677fffffffffffffff901d901b7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7702ffffffffffffffffffffffffffffffffff2000000000000217760100000000ffffffffffffffff0000000000002e000000600790057f77676767676760000000000000001002e000000000000040000000e0000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0680100000000000000009008901490187a0109000000000000000000000000000000000000000000000000007f40000000fd000000db000000000000000000000000000000000000000000000167ffffffffffffffff90089001778200000000000000fe000004000000ffff000000fffff7007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000901d90057ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f800000000000000000000000000000000000000000000000000000000000000017900b7d767676767676000000000076000000000000005600000000000000000000682323232323232323231c1015197a0109000000000000000000000000000000000000000000000000007702ffffffffffffffffffffffffffffffffff000000030000900b60535569100000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff061c7f7effffff8000000000000000000000000000000000000000d9000000000000017176767676767676767600000076767676767611027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe778200000000000000fe000004000000ffff000000fffff700777effffff8000000000000000000000000000000000008001099019901b60006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000054": "0x000000000000000000000000000000000000000000000000000000000000000c",
+ "0x0000000000000000000000000000000000000000000000000000000000000055": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000056": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000057": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000058": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x0000000000000000000000000000000000000000000000000000000000000059": "0x0000000000000000000000000000000000000000000000000000000000000004"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xae7D4902083D51fB69147F97f93522A6ACde32e3": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x095113ac45e3fc3d29c686504b49b5bfa2bbb26afa0ff1b5a6e78199e3aef49a",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556002496001554a6002556001600355",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x606d6000526078602052606d6040527f06969cd3d17047a3c033d477a356eb6ebd02814ae1f49088a1a242623dbf28e66060527fa676380fb7aafe0fa248866ce2f4791be20e44bc99d3f2b8e7187fd2e7b99b196080527f7151476f0af990c48816173b5d9051376c9a7f1047d8ba71e7e79d4a704cdacc60a0527f68c95ec18334d106b3d49cb6120000000000000000000020000000000000000060c052600060e0526000610100526000610120527abc6d485cd9b7850ba153b2251675cb64a9f6a9d2a16d1749eeec42610140527f69786eef9e41fc0119f402f45634776e67372649b652bb6d55163dd4a3d2d775610160527f2558f4470a237c93666a43a4090aabd3dbcc17a8871358e6b78de5d7557491936101805260ac6101a053600a6101a15360506101a253605f6101a35360576101a453609e6101a55360a06101a65360c16101a75360296101a85360ff6101a95360616101aa53601d6101ab53606c6101ac5360146101ad53605d6101ae5360126101af5360b06101b05360ad6101b153606d60006101b260006005620b40e0f45a01600055600051600155602051600255604051600355606051600455601060005261036960205260106040527f3bff515c72d1e83825f674d33c3be5a0c3c1b25b39f7fb3760251512fcac16866060527f892e53cad071d7af40e641c2fe62a738cbc10f710f8618b294ddbc910ec2d3ad6080527faef07d5365cf2749714704088599058eaa79452af493312077db847b9dcfdce160a0527fd1d20d50f580d96730f7ed7c22946530e4ce6ca8915d8186fb9dfa5642c916c160c0527f2a95a3141956373fb3ac67da6b0db573908e66113d2ebaebf5ec12f671b7991460e0527f120b1aa07aa1b8f7b8b3c4f486e9af80aadc99d6ae43e9838f280477db763ea0610100527f70d81ce84a0260bb8ffe0d9a61f086ef701c6a74640ca583270c6592c840983a610120527fc654061c1b0f2db6f1c098f605a7f027036200ad189af26ebd01b953ac70ee76610140527f5469ce22aa99d7595f9b76007d57a086fdb3d605e3c9489d26b3b5ee56133d80610160527f809f2cb0cd4f3a325bae5509fa63f6e6f1f7f95195508f341433016f0adf1471610180527f5a7691337c0f92863f4d8629ac6b072979ad8f94606e6b836360755b98852bf96101a0527f0b3334aed8257dc6287043f97db0786cf3aa5a3ba1790bdd8d7a5c46e2a0641c6101c0527fd06e211746f8d26e83202f1b08c0b47cfc354d30e27d47437f5e5fa33eba160e6101e0527f1b33cd83dc4e3f3d25742bce25c6039dccb1f8fd75c37f12bbec7130f668f36d610200527f7627ebcea7518334fd633674da463f583484712a8b08871ad915b3fc5e844229610220527f25efb7329b1117639f9d71a6b1861b406f4818bb8a60ffa98b68c23815ad9946610240527fc6049241e09a0b4c0fc8f6fd23b145ab1f4b2e865c481d2a29897737552fcc9a610260527f6dacd1f325fd6882cecc9f9eff330bd72b1796bf36be740166dc15c20109d157610280527f3b950f339162d4a9b43f4b152ce6118b5e8d3604655a77df348ed2a59a2ad5bd6102a0527f90029bfc8992471aa9c3210ebfc84122bbea32441303367b82a46d5dc871682a6102c0527f330e3d2feaf6388e1036175258eb6a776a76c02ddffa503058abc7c8cbd93f026102e0527f8917b602885d931ebe52636c9d9372b2a11c1933efa77bb538002d9c6082439e610300527f07d1ffcdf19617d783507043df209734d791fee5715dbcfa84cf9fb516be801f610320527f25edb69cf491500089a08307910e7dffc9fbfd9c4c054220235305b6196d6f73610340527fb8a4296a8f918535cc1266917de9d04e44c874b216f981ddefb18f76ca3557d7610360527f5bf7394e83d4ab174b51e4494779e927bb2cec1158c492cf2703d8d439363081610380527f8bb776cf19fab4db9da420097ae0c01c5877361e90c514ab5ad4ec4269d838b56103a0527fd2718ca190840807337574ca501af530e322da9dbc55f02a0296675d8cadee3a6103c052609d6103e05360836103e153603c6103e25360b56103e35360396103e45360ab6103e553605c6103e65360966103e75360e46103e853601060006103e9600060056204afb6f45a016005556000516006556055600052600260205260686040527fb4033714df43444fae7e7442a9bf1e21b29fe93c31eece3ebc21e3c8096a9efe6060527ff1002242cb3925eac55c4b2206a0fe6f232074d14c559a20515d5d963049936a6080527f4540cb4fbca19aeec551174d86f8ef243035d4c11c1c0ed39c4a14bf7254ece560a0527fe2d28870c3c3c4a0de8479bc9e58460ddeed4f85f6320d356c668d5a4395a64960c0527fbce240b2454432a5860fa357e305c52b6e806d84b43a837142187b38389c21a360e05260ca6101005360e161010153603561010253604061010353604f6101045360a361010553607c61010653600e61010753607061010853601061010953608061010a53601e61010b5360dc61010c5360b461010d53605e61010e53607f61010f53603c61011053609a61011153607161011253601b61011353601c6101145360e561011553609e6101165360d96101175360496101185360a66101195360cc61011a53602361011b53605461011c5360ba61011d5360d461011e536068600061011f60006005611196f45a01600755600051600855602051600955604051600a55606051600b55",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x20000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x60000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x",
+ "from": "0xae7D4902083D51fB69147F97f93522A6ACde32e3",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x0"
+ },
+ {
+ "data": "0x",
+ "from": "0x79caC06f747229e9F79FA47049fb37884ec384b1",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0x96"
+ },
+ {
+ "data": "0x8a31d9bb704c555c24f732c6883998e445e86b09be29a2310d87a2a29c1998c1ee667cf95f5686cb613523a0b4fc4025782106b0e8fc299a6054fccb89416257",
+ "from": "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0x62"
+ },
+ {
+ "data": "0x496cc712e00f0f40037adc0b96bea9eadbb3582c856ef10b3211f59e881ef0b332e341b56fac149a8352a5cfd046d4023d4365176ca9d660ae95b5ecefe6e598d4308bc57ee84becc2e6cabf95753a3ce3d7137111f1e265c40a83282f",
+ "from": "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0x0"
+ },
+ {
+ "data": "0x120b3eecdb80166a105dcc8c8ad8afbccf7e6397d125c0e6e9879f2a9edb9f85f646562555777c411d6002282a46f47f3edac617",
+ "from": "0x0b530C4203F212318CE214ae2F1089d2478cb56c",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0xcc7947"
+ },
+ {
+ "data": "0x71268733c98129c80286704a3cae048b4844232d79acac54",
+ "from": "0xae7D4902083D51fB69147F97f93522A6ACde32e3",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0xfc1838"
+ },
+ {
+ "data": "0x2ef88d3dc71b45691876a113f3b1c2faf56158ee3b9d7ea8d047d6a516",
+ "from": "0x79caC06f747229e9F79FA47049fb37884ec384b1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0x8a7e"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x015f55eac6e598ff65cc16149757ffff9074b952549cb8c2dc96901c0f8ff5fe",
+ "0x01ef0c49e7504ae667b0eea1985b80598d05917f150f1f01389e77ed1465287a",
+ "0x01fcaae78c0438d7fb1adda2dc67c3dfd5f6432c5815abeb1a44794182b0b5ef",
+ "0x01670282b0ac787d53c024019bcbefd4765d1477d8136d19f89d3e57ace37d8b",
+ "0x0168f561e7975219eeaab25239746c7763d4664556e226ec728f71d0ca835e5b",
+ "0x0112cfe4c7af4e1114aab612902e7618ce92d004012b326e08e71f430eb80e95"
+ ],
+ "data": "0xa38f",
+ "from": "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 1,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x82c54de5780525f1a6604ee6fb757ef6985d536827009ade100818174b0214906875c07778068d38f75d1aa9f2c4406228317465137727de5471a1c19cf0d028b76c3b32319f8c80afbce3ffd3",
+ "from": "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0xba88"
+ },
+ {
+ "data": "0x",
+ "from": "0x0b530C4203F212318CE214ae2F1089d2478cb56c",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x0"
+ },
+ {
+ "data": "0x2e228bdfae2d5514c42bb144b04f34377ce64d701d349cafb636c2f73698c171e11d318e37c74c95ed9ba1ec8d327e2ace9b1c4ee285f95edea4cbff6b08ce7d88db009b731577f4da3eb9440315739ab72a77d9",
+ "from": "0xae7D4902083D51fB69147F97f93522A6ACde32e3",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x663"
+ },
+ {
+ "data": "0xcb2b6ab7acaa2f0a6f60f06d4e445833b05fad7d4510a06afb5cd57d598df72d5107677f0cc8e3dde712123e6b3a558beb515edc22552315d2eaf7e0c6ad524ba23776fb1bc0c29206702b3b389f2c",
+ "from": "0x79caC06f747229e9F79FA47049fb37884ec384b1",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0xb712a7"
+ },
+ {
+ "data": "0x536553f53b491d18ad280730198d44810c496e91e020daf71f0fc49f3d415244000b5af69206dd69db5edfb6602c20f4c75b644f16e50954833808c0f82665ded9a0df95509974b0ea4799cede017b0aca24eec4ac",
+ "from": "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0x30"
+ },
+ {
+ "data": "0xae5c17fd105f53464bfbad2b3c8c44f988bbc93ab17bf1a48a4320f8eb71ac1cf570fb8fb611afbb6481a1399bc8258b7d0215301229a95f2ec440200581491d48e624a2",
+ "from": "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x0"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x00000000000000000000000000000000000000f7",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x3b9d5e9a36279ed2c81761a8ed35c785cfabca68fe029b9e0462e973c352e857",
+ "s": "0x60dc03ea63ff6c10dd5cafb63cc2e4e531f4642e7f53a805acc94d8f4e952ca9",
+ "v": "0x1"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f4",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x87e3b063ecfe90dad2ba6331723b4772dd08a79e918d494633ff5e332ef3e055",
+ "s": "0x4954a1da6fc047e8ff073b4b1cd5864752a1a00745437319ab7cb91114ab9424",
+ "v": "0x1"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f2",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xeaaaafc5c341208dc8fa74dd76c680d4e70ff4470b5c7be410a95d4eb9063628",
+ "s": "0x682254770ea41bc56cff1d5b47f64ceede0da45e5233ebdc9c60d5c10c7a3e15",
+ "v": "0x0"
+ },
+ {
+ "address": "0x88f9b82462f6c4bf4a0fb15e5c3971559a316e7f",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xbcad8bdc514baf5efab74757cec1366ad303cb086e4fc286650a499aa2c51979",
+ "s": "0x291e47131cefbca9f42434f163e1be4d6fec29160ce5f1ed716b3735e5b01e7f",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000002",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xf005537a1e36922e7a12f79716b304b6eea3c89fd0ccf0f1cb8584cfa67cfbc0",
+ "s": "0x2d5fdfe68d1e9c26f36cf82a0b2f24402991987f75946b99ebcfe13194cfb2f9",
+ "v": "0x1"
+ },
+ {
+ "address": "0x000000000000000000000000000000000000000a",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0xffc1c76933522ee09da5d32efb9514f2fb3fe070c8c9e76ca170222e08b327a",
+ "s": "0x817fd0bbedb965878d16800f47470195839125925937723193f530fed54f818",
+ "v": "0x1"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f3",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0xf6995406f58d828d4dfc5930773f4ab58af7e00305a0753f61a9635684b16be0",
+ "s": "0x1a08f1d43abaeb2604e8d21b0509d4549f468ddb60d9dcf4d5020e7b05f1d718",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f2",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0xa444813984575f38fe02fb696aacae0fcd71866cb02676318f9ed9f0660d42f5",
+ "s": "0xe6b7da27d25b3e6e65c663dfbb9eecbef56a8abd03e8b0bdc1d7c691ced3d34",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000010",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0x28acb6533b497b0c51e4f38162972c9ad4a60edc90e5ce448cf3f84fa070057f",
+ "s": "0x6bc95b9f8bfff6d47a61ec78d3cd9e5f60e6d588eb0016198aab9e09a3664f09",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f2",
+ "chainId": "0x0",
+ "nonce": "0x2",
+ "r": "0x75e27043bd9be44d39a3624a9eb427ef06f12fa9748e33cba70d6aeb7707e1d",
+ "s": "0x5c65fea04d26d8f90a00755fc2375f047922f7b5f2942d9ef13a32b360f7d2dc",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x4b4ccbd62cf795a7b29973b786c3861c7ce8ea6d66b9c4031283c6c5ba16ef10a7e711aaed4d5ca5a531c786b2da665b687197288570ad7b",
+ "from": "0x7c2C923D79B9903f29A71bFAB11B24c30C9FF962",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000010",
+ "type": "0x4",
+ "value": "0xee5bdb"
+ },
+ {
+ "data": "0x00",
+ "from": "0xAff0d1Fad46ff203C5b9FF00F10FE1134862571D",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x00000000000000000000000000000000000000f7",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xf3ff30055a5994e37ff024d18062a0107b978e80c9bebdcb138a0bd916f3396b",
+ "s": "0x35caf50bdf31d7e5d7f1e1062ca6fe150e7c41dd3fea6bf8f8bc3b3e6b665eff",
+ "v": "0x1"
+ }
+ ],
+ "data": "0x4b4ccbd62cf795a7b29973b786c3861c7ce8ea6d66b9c4031283c6c5ba16ef10a7e711aaed4d5ca5a531c786b2da665b687197288570ad7b",
+ "from": "0xB6754926EBc05d33a936ffdE524617F45429CCFC",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000010",
+ "type": "0x4",
+ "value": "0xee5bdb"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/tests/vectors/fuzzer_test_2.json b/packages/tests/src/cli/tests/vectors/fuzzer_test_2.json
new file mode 100644
index 0000000000..ee7cf22e11
--- /dev/null
+++ b/packages/tests/src/cli/tests/vectors/fuzzer_test_2.json
@@ -0,0 +1,440 @@
+{
+ "accounts": {
+ "0x000000000000000000000000000000000000000A": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x00000000000000000000000000000000000000F5": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x071b56102BcF6C36a20a3a16fE48781448B1C274": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x4957f6f5af2d9acc075b694de14765a3ee3ebadd720ffdb0c471fccdeb1999e0",
+ "storage": {}
+ },
+ "0x08d033C61e1E55bF868082cf788a3949f4ea949D": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x18c571b8d627c38e4cd2674ff9e1810ac122de605ad7e36051814279ada15f76",
+ "storage": {}
+ },
+ "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xaa7060c894d60af0152633bd7fb04eec13d565d152895681af06b5aa973faebb",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f13354ab4e7cc72ca20ffac17e9c1b49e6000527fa774be197d572deb808140f315c100d2d5b447c60b80a1b74547997ab198d16f6020526f176dfa0b1b23c9b0aa1559abc0e6b3ac6040527fd5fd9911c96b4c2fb77a3083e58ca209789f9dd34748f8cc98b91778eb66d6466060526f04dec2525331e3a900d26f9872d420af6080527ff94c487bc34b1d01d00cbda233627a06fccf69c89b049796cc085f168248341f60a0526f086324d465d550c6ee843b64c6e7759060c0527f8e48c1fa02fda324d5d1cb956e0aab45de89c5276b228c54d1cb2647317614e260e052608060006101006000600b7f4f98dd185cc2f36c1bd041dd1cc98b487ef9602b0578858b7284310edc62d5d6f46000556000516001556020516002556040516003556060516004556f1a702a96876d961f14157b5ef86e16e86000527fc6a1f44881f0ba5f2b765070a0156cf5c485bcb9786e041fbb5c335aeef73b436020526f04b318655f98855db2f8e004a2aa2e276040527fc4f6237e51f0ba883191ac4eee5bdf35d3dcf8bef33156eb619e577bbb38c8416060527fe3e2461badb2e11a04503bdf8c903cfe43cce07d322703d192c3aac1559f76cb6080526f023f3c470ae026e4b8e7d1c7e7c61a0c60a0527f5e1706597302e07b4e610fb7251c52b545642b421fece660fc17206d89144b6f60c0526f1532e6055e532a60024d0fb15ca6e47960e0527f74110b8a237d86f94cd0b459143c3e0c91ef78a41d05bd52c563b7d166cb7e21610100527fc1eec215a08bb347aeb9a1f5c07361975d64957f0673f20844e48a6a14a169c2610120526f1b4b2fd8fc7e8e13a2c559b2309c6dc3610140527f747996328ddd37eb4b6f36f5730b4503d399d4472b6ee2f6a28416f76b5398ad610160526f0859289d4cdb015254ed20cff2f133e8610180527f8e6cc4b53d2df6446c0ccfee4cd91dabc25bb7bbfa44ea0e39d3c592e30d19ce6101a0527f7376a76efdd3625a9f49bede1c096bcc48ea402836db68a38620c647db77c5b36101c052608060006101e060006040600c7f28825afba0dd595ba78aa61e8b06e00e2a57be0f466af3fb2f62468750701d7cf16005556000516006556020516007556040516008556060516009556f1502253d35ec4177f1766f3b652ce1b06000527fedae07c15f0dd155f2a52e7333f76db8295fea99e31c416139a6f42e594847f36020526f0c77dce05d8c9948df79b990832cb5b96040527f6407068a6d15d290574da434bbffdeeea6bf4492942381fb5880f3cb85262be56060526f10353e65e34115652cac77cf24cf6d7e6080527f883e49eed6eae00340d35609bc807b298675006a9b56d5db1bf6fbc0bdd5c38460a0526f07fdb9d1377264bc6977b8fbf21d3c4960c0527fa65fdc065246f3142a9548b8f44b1a8582a893c180aa0e00351c6669cae7d8a160e0526f024aa2b2f08f0a91260805272dc51051610100527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610120526f13e02b6052719f607dacd3a088274f65610140527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610160526f0ce5d527727d6e118cc9cdc6da2e351a610180527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016101a0526f0606c4a02ea734cc32acd2b02bc28b996101c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6101e052610100600061020060006000600d7f41b1dc95a91c0f63475dce8b84d6a2014ca4859b79b38361bc0180aeb9575b32f1600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f09591d15ccd26715c86df27189606a306000527f1074c0108948ec88e06a37ccc58d4a496b614be8a8c061e1889a53602256c3e76020526e729efe8920b0e6554e3fd8ef3ffdc26040527f6a55705d641bee07f894ff253fd3903b18d320640ef92caca5fe8faa5869a2406060526f0d0fa369916ba32740a28c7ffa522e6e6080527f8ba14f4cbcbf26d66863188eecd54b2acda7f1a5f86bf0fe51c6941342e1000f60a0526f054e66d6c3461adcfe918548ee5f024960c0527f0d4f8ca0cebcdc8a6440b8695ca853f216620435cbad0544528c422b517c6ce760e0527fdebe899263c418bd542bc0d0888519f4c8a933074dca8822676913b20becde7a610100526101006000610120600060b0600e7f16d3ec1f09882e6a724e1115fd966740bfc5a1f97b94514b23a68d1168fb25fff160135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b5560006000526000602052600060405260006060526f0eae09f2030077ef6fb53a86b29a6a836080527ff4a91e12d6b9c378fa5d1646b59b49e685ab915672a872f0ad3878a13e90a5e060a0526f0d202a25256ea37788ce16169dc7dcc660c0527fe043c34aa9fdd992b6fd112ad6c882081b547cb181bf21e63b3a2f9a5c1dacc960e0526e7f6de3ad9f0a3810f6c7b9f1f76709610100527f2a1d06f1ff4b8fee5863ff6b0d85866a6aa55c8c5c57d4c9bb6e7ee5f00bfdf1610120526f150e8e3062f97c80ca5c93876db9080e610140527f5e1985a7e619e2b11823018135870f57db88956447a0ef30ae4442abea98d0af6101605260006101805260006101a052688000000000000000006101c05260006101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527327d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e0526020600061030060006084600f7f4e7f3f831ac0330f4a7145646b2308154f13f0d8b4bd2f4bc1aae77fc58df06ff2601c55600051601d556f164a295a5f96a09041f69ff8b879aaef6000527f1fe370f8797936043fb243918b0bda2342fdc6f8909876cdf648ac35d085a171602052608060006040600060107f543872703925f6e15c6fbf2e92b7b23be4b78a893cb54ce637e9c72526019a8bf4601e55600051601f556020516020556040516021556060516022556f0129250bc1e499805c6dad0c4fb11f786000527f2f344cd82754b3b5a9f23d6d22ae7d8ca47d620ecc6f2cce2e4c5cb4de8441606020526f1385ee97b39f8fa20cfadf1a4ce4a4c86040527f98ef7fe9a5173caa1560c95365d28545e68b8989a184193ea29aaf7855138da460605261010060006080600060117f5c4a5e0205f85cf2e772f816575e415e19d7fc5a03e0772aa7e47f0a54fe8051fa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x603b6082603c608660b760a260fb1c1b50171b8a7a77a04378111b39537669943377621a046c4702433e163310157615680b7e9256347b650737367662391736f29b3a696f3c779a109910ff7a7a6605355c46599e0a78534a8375767776643e7a6e765c7f1446816797437b7e91541211505a5b96115491741243397a7011196d436e5e7b97166e026a85057445a1f032099f815b936b570359570905136d626f208c9f807477fd7ffe0201523f4a5f611c996e5a683e406978651e54747e571756937f027e3aa4757c705e705c5798534548807d92414953427c195d1477796f5042175d7c678c34a4606868750380440883416e6e596b786e7c016511056104068a3613351539900473f087f45c81463b3581417b3095939852634a3f36358d7a7f657f76024800133479446c6045844403ff60393c1110716604791b086963106ba362fd047286704a63460635648ca159316176040444536a3e0802931d4a306ea2393f50384118313e53407c3d541c67054949045155455c3ff456935f3b323c1733407469f16d7978203d1c707d865753483b056f445662623b801a35fe967c536b695749787e110833709f5719483a8c80013af4a4041c10525b1b6048531d9e66526c00193e4654093b63741d1d5545715d05181e13657a5860443c8b819313124784f4454338556b3b7f407659581d6d4250385c90441290771a58385736664595338175507d72747d505042f57017805630083a7f44455fa208949e5453579c953e4549659a07520a8836206c4a59115f40977c886815a2ff661817fd6695814342918d6c917670569f983e9e150a396b673c7c717a8b5c509c6e3d8b721c3e209f1e497d47739af233175e121a796f3e496f8f3f8f61195af55a803c3219a416a46af33e0b6f1637a234337ff197361d718e7ef1fd606e786982121b886c627a4917003163325d8c5d5e67a33e620a476c7531967f5e8b18ff4719118945577b485d54145e480b636330726b613e89427745811850464966663933fd44655f3798456d1e906079208780676686068d942015663941681087118d413da19e3a5274919e410a69778d5934a018889e058e054814427674f11d84753d9e5b7c30684577701001483c8e705770328247ff6c163556373984005043143f8a766e58313f8802419e4072193e189c727a123c1d6167757e524a3b9007556f5072578111a2006b3997a079738c783605718356363b5734423e737359190047434320990532483f1b31098a476801807b977e0232436f44956a053a5e207d601b08fe79a0665b077b69413e403d9d3a687173616b50995a7a14475a575e3a4976033c757d1b73109083647a7c96175582701b1d3a76381d981d52ff3f393f57004344613b3668a1374214123034715049474291040b8077539d025f064644",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000f"
+ }
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x8d257f6000545060005450600054507f7fead49cfc66cdca062385ae79f051a4390c576000527fd0d9f7f94f1cc8d2fd223482c46000527f7b6000527f5f60d6e582f439f6716f6020527f60774d948fe1acdaceefe862a6e54c11916020527f58621fd1396020527fcca36040527f9191262e95001a15c1ac5065aad0fe33e29b8430636040527f9c0b8a9954d9176060527f3db16040527fdef46cde2c90ad6b23e39f070b2bc52f0998a86060527f833a636080527f75c9f692892ad391dbcf6060527f1d53b2784812f66e0e1531e8e1fc9660805260a0527f7f74c2597d5b8d9ba46d859159d12ad0e6d96080527f337fe7f3d3873486dcf460c0527f1560a0527f911710de8b38999cab6c3cfbd9b05044dc01de196d60a0527f082360e0527fc318899bbf60c0527febd2d6571e07174702ee55c0eebf40af20ce122b5b6a16610100527f1da060c0527fdf45d760e0527fd355a93d2c44e97ddcd60f845e1dcadc66d619610120527f59d8c48fff68ccba6cc660e052610100527f7f79cc531dd20f90521804c1993c610140527f9b331c646cbac8115fa7853cc99df36716c8610120527f656101005260406000610160527f610120600060007fce44c9eaccfe6bf206096f6aa158bb610140527f80e53ca3610180527fac327874562502b099b83df12efa6000556000516001556020516002610160526101a05260606101c05360556101c15360616101c25360016101c35360806101c45360536101c55360616101c65360016101c75360816101c85360606101c95360006101ca5360f36101cb537fc83d61127eefb10b62467c07424b431e4f8ffa2374b5b952590a757fee068d086101e0527f36c5a642e314a4206a0cce31007a78b3461a7631153367453e98bf676c2a3e83610200527f1c7678339b71b6afa89bf3853f130165a3310929c58f73c998cf12d16cf9cb4f610220527f0498e16f982b920f187b7075776fa525caaf69ba2d3b8539975374d24e95864c610240527f1bcd63bc8bc2529377f7892fd3a05a974d09b4763a0db31b795f05e1cd7873e8610260527fe924913b79c49c0f25233620ee249266b4dd373db8c7b3abd7a0af61352325c7610280527fea4f3b8eaaef65564a6f7eed3d44a3b2b8a1e1338a58ca32d0f1c37bafd788e46102a0527f19ad295516b5fda6e2b0525bb1792a8c3854f9ea8b005e02bc1d93c055decad86102c0527feccd32ce7ebb6ed22eb0d8aa38649067c4ba771b38416e9197ca1885a3a6bf906102e0527f1669bb286e4d3fd981a471ef98c077899365e07cb0ae637bf5a983bcbfaaf141610300527fcc64326653b1d5d095a16fea028ee0352ae85d218e177cdf19fbbfe99d12c4dd610320527f87a0bd590fe290637473b63898b5f26aae2d07420714e0eb7b6e0c4c561fe33d6103405260006101cc60006000f5604060006101806101e06000855af2600355600051600455602051600555600655",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000008"
+ }
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7f4b26560b2d940791740f8b3d018c1a3deaabe12c90b03eb180940437763140ed6000527f33b5de51493a0e79ac2eda2a932d7f6bbc34084b6634d25b81144e6980dd08e06020527f80cbaad461f9baa6cc07de7dec06dcbce0affccb02c772280fbab222907284fd6040527fea90ab16040b2db45d81d72fe566035ecdccb3746ba69b0fa0dded372834089f6060527ffbdb9232445406128d083228db41c0a5b67e230e9c014b30781ecb9de3cf5d646080527ff17aa266e879f8b4f50075f700c4b8ff08c0bea32f1c1905cb9a014b410efe4960a0527f8b86bf12b97a6ef8cd94a36eeec0f11605acc64103bc508300b3e50b042d6d1260c0527fa01cd36922eb2caecc22d580c276b849d7f72116e0d157d409d0d08735b60c9660e0527fb3ef17372c4cb5e0e2f4320df85b1423272cd53ddf0a5553cda29dd4e72712a8610100527fc674b6383e153fdb3c0cbc8458196402a7a077f550f21ae53fdbf2c1820a5f7c61012052608060006101406000600c7f48fcd75d2eb0a07a402d6f458c2dc521ec8a9d47ae55aae11ff8a2d5ba81b818fa600055600051600155602051600255604051600355606051600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x60d2610320fd",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x8b7f60ff6000536060600153600060025360546003536050600453606060055360f16000527f60065360ff60075360606008536001600953605c600a536050600b536060600c6020527f536008600d536060600e536000600f536055601053604e60115360606012536060405260206060536060606153601360625360536063536060606453606060655360606066536014606753605360685360606069536000606a536060606b536015606c536053606d536060606e5360fd606f53606060705360166071536053607253606060735360176074536060607553600060765360f36077537faf893e4163047c05289d407b9a702a25aa8e1fdbcbb6e6d94f2f9274e8c305886080527fe0b62d82842386d246eb69a810abdb2809726f7cbe2fa885968c3ce805a1bf0560a0527fc2d94f6ee30e0dfe8fcf22f0144f7bcb976c742351bbbeaf48e4b52bb3ed637f60c0527fd7544f4031d7cd44745ac4b19dd3227e94241ce359463d356f8fd78c9fcf47cf60e0527fbe8dd296d74032dbf63b373f0e10f29ce12bf743a77d052c335f51d21f82349c610100527fba69a74988c5676412c71650f0d069dd1122209f7ba2d0b857b925e14f237b44610120527f8a537da9e5559e3fd686eca7ffa7da09dda8d061e093b8bbd78aaab215a0bd17610140526000607860006000f56040600060e06080845af4600155600051600255602051600355600455",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000e"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7d03c760c325f8cdc4daaae014b8e32d6408fa8ee3ec3f283b6a30d7d42ba56000527f679d181529ad318d93556d9a0101109a11bbbf2d186cec7944fbaf2dbf14d8c96020527ff86ebbcca7ef069f796ba132dd561970ab8492cf0f43f8328d0c0aa98f9655116040527f676b7bb4ea0d4899b02941302abfa653b1f05e9c35e662d65f98c5bebab42c146060527f580da6c9840e9a73a9aba2cfc092f5c4851adb6961d0871abea94ea51c0c938a6080527f908136bad625f9d78e4a032b7f8b99b6a10021a1d0f79e78e176410c918191b960a052605e60c053608060c153605160c253605160c35360a660c453608c60c55360e160c65360d560c753604e60c853606960c953601960ca53601060cb5360cd60cc53607f60cd5360f360ce53604f60cf5360da60d05360f760d153608960d253604160d353600060d4536040600060d5600060f260097fcd3346af51c7b5bac45c869077565dea47dfc7724dcfc2de6f737ef73e779518f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xd13202f0930bfa690a45b6c2831829395d15c95781714271a8054dfb2074dd1b",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x7ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000067800000000000000190136000556fdac7fff9ffd9e13226262626262626007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff05600155637fffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11677fffffffffffffff7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7f820000000000000000000000000000000000000000000000000000000000000009901590127d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf96f800000000000000100000000000000001d6c100000000000000000000000007f8200000000000000000000000000000000000000000000000000000000000000712000110000000d0a300e750a000000090a0a08901d90046002557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb019777effffff800000007effffff800000008000ff00000100007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb090071d6003557fffffffffffffffff7effffff800000007effffff800000008000ff00000100007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a009016778200000000000000fe000004000000ffff000000fffff7007f40000000fd000000db00000000000000000000000000000000000000000000011d901a6005600704600455778200000000000000fe000004000000ffff000000fffff7007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee10777effffff80000000000000000000000000000000000080016910000000000000000000682100000000000000229009600555901c671fffffffffffffff7f800000000000000180000000000000008000000000000000800000000000000002107f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56b10000000000000000000000090131676013590cab83b779e708b533b0eef3561483ddeefc841f56801fffffffffffffffe9010901660065563800000017cc9700000000000000000023f00c00014ff0000000000000000223008051b6007556b1000000000000000000000007f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001901a6d01000000000000000000000000007176767676767676767600000076767676767690131990036008557f7effffff8000000000000000000000000002000044000000000000000000000168010000000000000000900b15717676767676767676760000007676767676766f800000000000000000000000000000011b1b19712000110000000d0a300e750a000000090a0a760fffc000000000000767676240000000000002b057604790131a762900760076761e0002007676000000007676767600000060059007901a6009557e40000000fd000000db0000000000000000000040000000fd000000db00000168066aa0a5319bcf5cb4678000000000000001087f8000000000000000000000000000000000000000000000000000000000000000762900760076761e000200767600000000767676760000000a901c63800000007e40000000fd000000db0000000000000000000040000000fd000000db000001901814712000110000000d0a300e750a000000090a0a7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0901a901d600a556f80000000000000000000000000000000196c100000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff1b651ce97e1ab91a7f7effffff800000000000000000000000000200004400000000000000000000017f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000010860006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527ff1f6f7815b1d9ab2d0116ea5cfd5513777f85a9e0ea98319ed1f93327545dd596060527fe993da5edb8e12b4b9ebbbcb94b5a7a01be8606d6e04a2d69fda74e39a6877da6080526020600060a060006001610100611b15f16000556000516001557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611c5af26002556000516003557fe6a85b19d7a91a47c412085e4e7e26e410e36a13b93a9f901a4e60ba32ffbdae6000527fe8c2ec339609ac230d0366063a6ae492ac251168ba0396d62c885d068e80d3986020527f211f80b4b063ea7b9ccc5158fe4bdb99f4b7eeb5c02a953cea6bc82d1f72e4236040527f9ece146764964f6cc5179913a7ea94fc67941932299548b23330f407200a6fc96060527f4874f78b335ce37e6aaf920457ab92bec58d03030fe0dbb8e1c3dbe2fce49c376080526020600060a060006000610100611c7df26004556000516005557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffdfffffffffffffffffffeffffffefefffffffffffffffffffffffd6020527fffffffffffdfffffffffffffffffffeffffffefefffffffffffffffffffffffd6040527f929a627f76294e7041dc0d74d9c3c9ac2cc7ce336a28023405d93aa03834d0bd6060527ff3d7a84534ee20597f4dc1fc9c44744f75a880989f14d24199c6be5490fb24a86080526020600060a06000610100611ca3fa6006556000516007557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527fc6ff4b3f7a863bead987f1963f6b0aaff9e4951bbc26d6176a825a3d669e30c96060527fa8e431bfa6a9a58e352038b93bd3f670a9f41d16d64391fbfcf0c53e8af119cc6080526020600060a06000600061010061197df26008556000516009557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b97f2600a55600051600b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb5600052634000000060205263400000006040527f06af349be1401d5693cd9897ff18f24b75c8961730a7fb42f7b8c05adb7ae4aa6060527ffd86c3aefeedf5bd733562eb1c287e20505f7257275d65a3203da7df67d2cfb06080526020600060a060006001610100611b72f1600c55600051600d557f26a77edafe02e595da4fd28a5b12e58f35631825b42942ac45f741a3cc48235d6000527fa813b95c8f745c9e8c74835e6d7294a1f18d8c0223dd9de2195f6fb80e87df1b6020527f729ac1c416279c26f6ef1880807d14fb9e5b59dd04284967b886b763ee3e531f6040527fd55891b3eae94b9d31603841e0a506f4f1ca9707f1e396a1357d03cb7d4874766060527fd5eb98bbd949f52c9202a47ec52b8fd5ffa9e407b3597ee9264794de43fe58726080526020600060a060006000610100611aecf1600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b52f26010556000516011557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6020527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a060006000610100611c9ef2601255600051601355600060005260006020526000604052600060605260006080526020600060a06000610100611abcfa6014556000516015557f91e80dcf2d1c4a9016fb27e21dae230fcf796b906a147329d2299c61e9fd016d6000527f4ab4bf536ecf5c53a5292fdfb6f790ac1ab2fa939c88c011dc458ae9d1c314336020527fccd9f0d9daff86a998d359e6d8590640cda3fd0c02ed358dd62c67ac9a599cb06040527f4b9e55f8048a5156261d796f0735f5322225ad150751c79cd050e054baf0f9716060527fc44c1988e80d316cc9fd2f484030ff014b9009644ead59d37f7d13ac09aef2766080526020600060a060006001610100611a33f16016556000516017557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c26f46018556000516019557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffffffffffffffffffffffffffffffffffffbfffffbff7fffffffffffff6020527ffffffffffffffffffffffffffffffffffffffffffbfffffbff7fffffffffffff6040527f1ce4cc2c6c9b4ef10f826805726283048e38decfa349b69274668dd196cf20c66060527f280ae8f2a302694e423a2310d8ee05b84f6b34cbd87645bf90e8a7da9bea4f636080526020600060a06000610100611960f4601a55600051601b55600060005260006020526000604052600060605260006080526020600060a060006001610100611910f1601c55600051601d557fda7ec96c9e839e42b8502b8626c53235c48e9901e9914849d7dd107de28f7f806000527f0d654e9e3f27b46f31641cc06966bc91038240c335ee08f569b19900af4ceaf76020527fdfdb06c0fc565ca8fe717ce893796e2262cc4432fffdb3cb183cfd03b3197b696040527f8a38b7e8c499eed9961f8b9275549450ce253c0becb777723bc6cd3f37d2f8c26060527f10650f82e1b46cb015b7f392f549113a19c32649de943a7d5f36f3f71b92962e6080526020600060a06000610100611969f4601e55600051601f557f07e55549b656864ada291099acf04498baecec4ee9e5ffabe3be06ca7f2d70d36000527fc961b86e7fc4b49ed3ab2e9abb290c42b3d4937a8c61ef808daa683ec9ece2496020527f33b1bdb31c143cd58de8752b610d54f1ac4366a83d50554bd881b9fded16c1bb6040527f97a6f2dec960870eb0946d725d0952a0f856a3d049ffae0b49505a16b358f0fe6060527f0b04637614be1f3492cb13ba35138d31672126f91d4fcbc49fa9a7b897d3c9eb6080526020600060a060006001610100611ab4f26020556000516021557fda2564d83aad64c14d0d9ff48b1b1a1a4e6389abfc88b1a84699d5bb46e9a43a6000527f79a5c9ee5f65ad10c9802d3eb05326854a4c7f1daf119125e85193871c192a846020527fc9349f26cb6c3d621a4819dc7abd4552b0d40262ed60c5f4de04966d34d306966040527ff5580e84b736cac1404b9f4653d9d02d99040364e727902bdb7541d9ae3a1ee26060527fbe39d7d06a2a38e968acc2fa53fc55b5816ebed7ca643a55f01e98ac1305c5736080526020600060a060006001610100611b80f26022556000516023557f8fccb068b531ac17d393ea08148715ab1898c1221e597564e77c2c9e78a9cdef6000527f4dc2cfb84a8455b0236d18ce80926abd45467af811f56e6272415193751cdae86020527fc4dcf859a68077f23f823233bf677414fd9590e2a65a24bd19e631b2684c01456040527fa776aedfa3736ca6866a41294f89dc4782ac275121732a97aecb822ff59306586060527fcdc5b3065863cb5d3cf03470e91aafedcb274e4f5d0848f68d2567ee7a9ddfba6080526020600060a06000610100611aedf46024556000516025557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffdfffffffffff7fffffffffffffffffffffffffffffffffffffffffdffff6020527ffffffdfffffffffff7fffffffffffffffffffffffffffffffffffffffffdffff6040527fe6fe5af4014fae1b8838a671bfa6509acddb8d61778b223aff75fe49ae234a236060527f7d4bca4cd977976c41986214a10be7463b36bd73e7283a7b62d15d454a9ddc9e6080526020600060a060006001610100611b36f16026556000516027557fc5929fdb9b2ea2f7717901114528523cce282c9958e34dfe1dd97e8b9faefdfd6000527f90785ad69d68434f9be9d6fc656043bf9372b65357822817086c2f06ccdb10666020527fc8e51af9578a30cf291bb0cde19d503d4a75c24ad8becff0d5314c630c30906c6040527f6adac970a61bfac29951187862ce1f66f90ee923742656bd076677d87469b7f16060527f03bec49c0bf8bd2c77dcba46118716009eb49cd098c538b7a4e5db94357441cf6080526020600060a06000610100611a4af4602855600051602955",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x600060005260006020527f0cffdcad2364bf800d4f8ecad5acedf0975a3bd851fd9571673aa9351f5e95306040527f21d1fdc3e210bbb02f211da9de4a47a662b545dce50e4aa7af30a23003201e7d6060526040600060806000604260067fc66e5fe04ae9124419d32a64cd9d5cf2b3f445692192c5fc79b7b49fc73286eaf2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f015822aed75630376d37386f3799b27ec63cb07f30e4659a3b7d9cece811d5a26000527f67c06c3a98df4007b07860fa901efbb50ff143e42809fe2041fa24c02026c1126020527f63ad3f11f2f2eb2478505506675eff6e83f3867ff066fc991f5fe25980c389816040527fb70e5bd3f9e9428c3cbbd6d663f8e3feeb70b54c9197a0de4c49f0b7438466b56060527e14d252daa3180c5e0d1de5f5669551984adcfd0e36d90e1bc29ffdf06696f66080527fe38950d11fd574dad1ad6bd2456121fba6fb6895ac76aebb386b7a98ad76570e60a0526040600060c06000600a7f5c693deea99ec3065d08bb3bbbf8992574d560bcabcbdc8781ecb8dc228efa9bf4600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x600060005260006020526000604052600060605260206000608060006001617c22f46000556000516001557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f3bee45b3eb35ba25ddf514daba65fef3f327a2ab836025e69585f1a903c7c86f6040527f4499a1a179f672d04a0b2fec1bd260ddda493c524f1b9e513592d2f476b963f560605260206000608060006001620160eef46002556000516003557fd9c84e1cff4c078bf9679ea5bf23592805f37ea1ec5fcd75c1a6e8a3fd66e44c6000527f3d0a9c3803840519f5701b12bc8ba1cf5f5bfd079dcef891120fcfbdc9c2911b60205260006040527fca06c9e53a2cbfab1d6050b4ea989e98b4fa84f2d19c7594b0073962de4e18ae60605260206000608060006001620110befa6004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f3154834094fb37ba975716f3970bad6297c47c172e7384670a4ce1f93cd344066040527f1cdaf53e7a35ca88126674601fa2b335be2920986a3cf316840aea84dc1b4a696060526020600060806000600162014802fa6006556000516007557f63efb6cfb44bb2963a13fd5e3fdaffc6fbc619559964acf4e8614e1d15f3ed086000527f024652b7aecaba2bb5d6fd3da04180ba0ae2e2c6ef618fabc25b49581db73b766020527f4421f056c8b311d1c0461d9e241c010377ee025a6aaaa218980a1e8a03b0f4666040527fe19e0855afb14158ae4bafec2480565d839a784cf5fb30ecb1d425b74a8d4503606052602060006080600060016146e9fa6008556000516009557fce846eb15af7598f7fefd78f0efce96830f71a5fa9f360b4c32c546e82fbe9c36000527f0bb1573c8bbd32e2cf127adcbfbc0cfa59330ddd44f22eb7a18aee283001ce1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fef7a75d0b606ceb4a6a8c83052578514aabc80200cf0e965247e40869b01cb7160605260206000608060006001600161fe07f2600a55600051600b556000600052601b602052600160405260016060526020600060806000600161e8e5fa600c55600051600d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f4c23edb3269c38a2b71f2dac376ef96277b30deb4b8b5f4b0a446894fb0434e26040527f4f5320eb658715ac23b12693f7b736660643a49f7bdfc12aa58368387856f7bd606052602060006080600060016201039efa600e55600051600f557f16ec952430685ceab67971d69ba453c0f7c7ace8ced2b2ad05fdbe8855b966856000527f16e01e4b4546a40674fc3e4afa205f32a99e0e0361e1a5bdca14dcba1f4be01d6020527f58e5f30ed3f01bdf0ce96e36e0e18f0ab1f5f4dc441853b7a0a05013eb0588866040527fffda7608c1228a1efb7030695d5d5c52e8b71938f0006be285d3fd45e9548e9660605260206000608060006001600161a448f26010556000516011557f52e92aaab476abc19ccfb6001e47185d032d199e483ade94021701640b96dbd46000527f67fb34f376fa286f69b858fda0aef9dfc878cd3d45a1b4731b602dc8a423181b60205260006040527fd264e88a16f0b0b8fb3baf7a9de435ebe24a3b00d37e02a4502743901910c8ff60605260206000608060006001600161fb2df26012556000516013557f689298d3c55f4a07506ffb08203a915568fb1992f0dbe5265e8311236232b9bc6000527f85d6554f4cca60914a02671b5008cd2328a23b7a20e71f72b30e1ba3bc59071c6020527f6d0ccc79ed8dcd74c3db310a39119e23b2ed6c3352076c9b46a56b00bd9f941b6040527fffffc98dd3b5e04804879b2857f1f05896ea2569f79e81684978dfeea6b19b4060605260206000608060006001600162011fb6f26014556000516015557f1ddd145d47aa6659d09a487fc08ef28ca0370d45a533849285ba2e335ec271ef6000527fab376704c96d23f843cb7095fcb0ef36f74800a5d2f6d015c8a11cb637030d196020527f9f16a0d1950efed2986a574875a2312ee9862b0472eb497682c5f77de39c427b6040527f0de7d8686e5461ec3acb8012d977ed0b685b39152060460c6986d7b60191d5576060526020600060806000600060016201629af26016556000516017557f52c42577ba6da35a6dc6926eea25f40ce638bd287d51880e62587aef56ed476e6000527fdf8f7cac41b8d9d41c8e98eb22e2d3ba333466a3499e6c4f0e3b55c29be7461b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f2e2603f500a5f34360299f4688039a58e69f5ab3f2bf7e7c168b4fd950ab278d606052602060006080600060006001612aa1f26018556000516019556000600052601b60205260016040526001606052602060006080600060016001618b52f1601a55600051601b55600060005260006020526000604052600060605260206000608060006001619b41f4601c55600051601d557fb2b76192badb0847f3b2457590b2d44c9f96bc0abe182d87456e2767ffc40aeb6000527f2c96e9ba9df964f2b4008771c04941993e39156445d70d0f5dbe25cc9d4ffe1d6020527f305608b33c90faa5662c24c23d12e422f3cc849466213be9363d66eeea9991026040527f67c8fa634bf5d705e990f5cb32d9ef356bf4a7145cd2c740b4b1dc56d6cfb9e56060526020600060806000600161eb8efa601e55600051601f557f926d59808b2bc3e14e0fcbcc631dda2f8b3aa372cb37b1423679e598184dc3d06000527fc427b2c4b667b24ee990d36a0ac61c6e6d707f3e3e416d2005a83e3e536f961b60205260006040527f16b4650305fd17eae244c1d693639579d47c538233c2533e3e6f5b86f0089220606052602060006080600060016170f5f46020556000516021557f930e1fd7f9271151fd26823a99c889ecb4ab61546feec146368da7d21f44fb776000527f5fe6d43e7f98243463ac5569776be9e12fcbede7659966ca47a9234bc7bc8f1c6020527f4d27a9cf036879918194afbbb5f7646c0f03e28236cd38973db762b324e04ba86040527fffff287e5f9bd1b2ccf4e8b875aa7c72eb70c51b3b18e3a276736815060f85b360605260206000608060006001600161880af16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f8bb7ad38f2ccc549cfa98226ed03f00b3542544ff46096e94c69af6ca1ec73be6040527f22ae7721a3f4730a9f09cf0e1f575bccd94ab337cdcef1c3123e4825ba1dd4266060526020600060806000600060016174bef26024556000516025557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f45185c6e5ddd78b586155caf4751ef3969268f7d012d07be817c7cc632a983476040527f20be2543f6125e7806400f8db64d7c1c70894861c08da888f41ddb4b5dbf539f60605260206000608060006001611661fa6026556000516027557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fd8b851bfdafa7d90d5eae79c1db25287222016d88bae4b7856987cd1ab81e81e6040527f6f84238d15c5c049dae779bbef02ba59571258bda10b458cf71b95d1640c26716060526020600060806000600161d66efa60285560005160295560006000526000602052600060405260006060526020600060806000600161aa00f4602a55600051602b557f846458ba17478612f4be17db5ca7c4ee8e2397557a844b612713350a519ec8296000527f21bd55e20abce4ae2cb70e577a3cf541f028abb57b1334e4cd7f7ce8f302941d6020527f044d78e3b2dedc78e77d3faf1685dbc361495122ebcfc719b1cfe48a34c11fcb6040527fbaa38fd4409479113a08882a5d3e16007be8e1d49f5a4697fbffa9ce4b3f599160605260206000608060006000600162014c64f2602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2bbcad12919eecfc432da299104a72f9ee012e14503b95473f5536f52a89e0f16040527f5b44246c8e7a5314f17fe500b90f6a99c01e8991b0a07d85a1adfd7d10d6e3876060526020600060806000600161ea1efa602e55600051602f557fb3d5b41474c8858089f3b75559e94169729a884e468b01ca05af199455c760446000527fda0114f5d7b57def6f3bfe8a9c943e56cd80622a5b4c9243f448fe62990af71c6020527f6ac9cae3220f21ad35a896c09f219bde9068fd977b67d310fd5ed2521817a6336040527fffff16473d4bb2613dad0ec379c4ad2b99fd5dc294a4978087252621228daa0460605260206000608060006001620170a8fa603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x68066aa0a5319bcf5cb47f7effffff800000000000000000000000000200004400000000000000000000019011610107557fffffffffffffffff7effffff800000007effffff800000008000ff00000100007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000900b638000000067fffffffffffffffe90019002610108557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7cc9700000000000000000023f00c00014ff000000000000000022300805901b712000110000000d0a300e750a000000090a0a6fdac7fff9ffd9e1322626262626262600901a900a777effffff80000000000000000000000000000000000080017ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb090016101095567ffffffffffffffff67ffffffffffffffff9010901d6101117bc9700000000000000000023f00c00014ff002c0000000000002231081b684783921454358970526a010000000000000000000060000861010a551b677fffffffffffffff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff096001717676767676760000000000760000007600006c10000000000000000000000000089006901a15686d5adef08547abf7eb7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a001c7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd67d0212626262626267f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe900861010b551b61010c557bc9700000000000000000023f00c00014ff002c000000000000223108762900760076761e000200767600000000767676760000009007777effffff80000000000000000000000000000000000080016c01000000000000000000000000900114157fffffffffffffffff7effffff800000007effffff800000008000ff00000100007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1790187f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd61011190046101116901000000000000000000760fffc000000000000767676240000000000002b0576047900990137e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0712000110000000d0a300e750a000000090a0a089018901561010d557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90050b7f40000000fd000000db00000000000000000000000000000000000000000000017ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a009011901a6f8000000000000000000000000000000167b368d219438b7f3f7f8200000000000000000000000000000000000000000000000000000000000000900861010e557a010900000000000000000000000000000000000000000000000000717676767676767676760000007676767676760b9001777effffff8000000000000000000000000000000000008001682100000000000000229006901276013590cab83b779e708b533b0eef3561483ddeefc841f57f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000011611778200000000000000fe000004000000ffff000000fffff70067800000000000000102900761010f55760fffc000000000000767676240000000000002b0576047638000000116610110556007600190066c1000000000000000000000000067ffffffffffffffff677fffffffffffffff90081860006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000012": "0x000000000000000000000000000000000000000000000000000000000000000f",
+ "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000013",
+ "0x0000000000000000000000000000000000000000000000000000000000000014": "0x000000000000000000000000000000000000000000000000000000000000000c",
+ "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000016": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000017": "0x0000000000000000000000000000000000000000000000000000000000000004"
+ }
+ },
+ "0xF0AB5055e5Bdac80D061b1E7f2bA766d0498b697": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2629e617faf4ae81683157df0e0b4f967666ca88b6f2e41be40c619288f76ac4",
+ "storage": {}
+ },
+ "0xFb4bfba6610Aa9869db78F7c6b8f28b166CC8674": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xce939f993ef29fe9f18cd2fa2ce7ea2d51b23c6b808b850b33226f40d4cf9a86",
+ "storage": {}
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xab20700d44a6cb18e72347969198ce9e297e3f58b62c60f9a2450c93eab96240",
+ "storage": {}
+ },
+ "0xd51fA0De3ccd210D4cCA7f9D739f305CfCAe9117": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x579dd91bd24f9287c7fd47e0eb7b407c83dcbf3217e11f245153ebe0c1136d83",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556001496001556003496002554a6003556002600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x60e360005261020060205260e36040527ffaae07a3a2b9fa3a20602d0e9afc484992acae594db6cdb5c5e970b01fe1d2fd6060527ff0b069f3fd126ae60edc9f8fd44e79165d533dd418f68f4df72271a1e4693cd76080527f1bf6cd9b8e4f6ea9eda97e449785f31c52a4b2d56e06a30160ed96a6feb4cd2260a0527fd593551965f337f92ad2ef16ea5fbd47af7fab77720e2b5d1f1431187bd1266960c0527f10f80389536469944c05ecb9e0e5815ecce9aaa8fba0b6df40e4e4ea824c466160e0527f7c62cd4b1aa3e55e1c53163efd4767bf340c7bcfe799823dd813c299eaa43452610100527f8f165b90caebe259b370266184e1f0cafd9d42b37a5d3e888f5ef09dfc54032c610120527f0bd6defa6b5381c9428fafda0fb74a9df34db1d8d695d8810a9622b83b75ec4b610140527fd67130e95cf510a562e00a1b65ef39fa2c8a71008af6243bc382d06bb393a2e2610160527f15184ebac4fa806cd9a59b5a5e7067552acf594b687582fb26d45cef67b04f17610180527f5ceebd64fe9bd9e8440bee276ac5342a3b8a4126fcd137f2b03911c4694e5c436101a0527fe6c897f9f07892811764a8afc441bc4ab2dd353220874dca6ba859a9cbf6bc036101c0527f28e95ae07a5eaedc49a861dd0d89e2d310589d3c1af7c21816c4090909fde9e26101e0527f1d05d29d378a36206ae4f3abae31e26899315180a1c586771cb16fe4ef257361610200527f552b6cd8377b3231d5f955e9ca0933bfe0c900d568852407088d3b3a154aa685610220527fad10605210435009fe1b0bbd13347c8d44107b90c8c8a6e71a9055b33c46e3ac610240527f4a0eb5c400a314152caafd8cb2399e459c06c26804f4a72275d8820f905dd7d5610260527f35257277817de1ec1dc26cd00ebb54e7bdcd2727a93f6ad18c1ff2a3fe058eaf610280527f26014895171a3fbc54327a922b6baa6008f188409b7a057a20f369d1a31082ba6102a0527f8b733a0ea3de93de3edfd4d6cd75704f0705fa00d25ae45d125edd24d74a983d6102c0527f1e8478e4dbc47704425a059f02d999f16d754e5830a451fbef62831e891154816102e0527fdd64f93827ed6c86190fbcdfb861b25832bc7ade533ce7b745e7f09724bc5a66610300527f2e9892e7834d12e6fdddc6f459a787bf624ff3c9491f78b87d15f687a6f1171d610320527f3f730fdc84ebaeddaca539e147900f45f6fe6e685df79cdb6ab2459d03ccbc70610340527fcca041875600703836086de20840d1183317a3fa577890ce6fe82039476a09cd610360527f75c64f3414ce2e4e9db92b2faed2c5e36cb0564e6085f6b418b6d5dabdd3304a610380527fccbd8a35b466aaa12f730b6c5fd79b506ad023e8796db42af39ab5ac6d67697b6103a0527fb01d6cecf3b1e6668744c46db1be303ed3d4efa65f5c8082406f1fda81ece65a6103c0527f978144fee5e0eb04f5a06ec8c5e05581c3d1d41b29036103f04645beec00e0316103e0527f6db832109438b66e4481c69f387825932055264bcac0880659388926223732e161040052607c6104205360846104215360866104225360716104235360236104245360526104255360e360006104266000600562ea33befa5a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556103e2600052600f6020526103e26040527f248028ef9455230bd7f522958ecaaf82bed59d3e3eb33fa958cf0c9d2f60238b6060527f44943b2e4e40cd93d6d2ec3967500767d5ec8ee835418743f0fd6408287e85d86080527f2f8a7437b7d241a054f1be704da4945e6ee1ca560dc96ce512f583a06bf7530560a0527f36dc00a8c881ce08a5517e4993dc6cf55671ea731e281a652349c8de444a279860c0527f368250dcb2fa909e2f75221837413ff1594aca10c381d3212a0341095705c1c660e0527f45c68c9fdee5d1700940d43b61c26dbb413c7ce32a43135b5e608580f659df19610100527f6ec18e46edb7feaef4f2ef79d14eed52c1a33ce66e7d7100d3e599fa93d5a487610120527f6bf749dfc1147cfc81c360b7d9ddbf818620bc1cb69935fb1aa0968b0341d1e6610140527f7003abd30fd7aab20dc02a2cf219ee4e3370dc944614bf11fc9d7e7b5afe2b64610160527f5230dca1e5154963a38a471021d87e08c4b019a62e4a78077a49d9910aa210b9610180527f74455d43ebb593133cc60bf92750661d4466929d1e33223b808e7830144c0a8d6101a0527f4adeaf27275c0641d2bd7cd987d333c2babd0a1d6dadd4bde27bf7b9f5c756066101c0527f15f2e9a6302c609edaeb3c327366fc0ee173ac89d092cdce9938a64137b1a9096101e0527fb0c77bb621770478ba149ef8bdb5cac919eaac04ebb1b93988ea1fe2d08db09c610200527fd962c98a7b2b0fbf426a137b0c1da1ae9e26b04d9a1120cbdd75aae7d1e347b9610220527f98cc876b2e0c67b1cfc529ec6b905d8fb2c92cb667150f6cf55ad01be28e9db6610240527f0fe3ff0b7067a1584d2c13d2e0d88eaf0d92cf20ccf2069c9adeae3c1935c343610260527f0813c163bf3165486c863aba88cdda635910d0a67a6257fc797900c9d823fede610280527f996247e75b775207a98afd38a3922af9f856572d8611e3bb02881db07ec2b0386102a0527fc1c01ace26be91fb5f4f5a1f40d9d4e08e8467f04cfe3ebb27f896d5aaa295876102c0527f46f445787484e54524c9dee743ed2c7421ff13520859c9845bd48bcfeb277ef16102e0527f08e8f600d4a48ee8c71deea2f511053da84489af32e4b8909fc90f79052cc605610300527f7cd12f8c3ba6650410f01559b8bc869f70ff721ce334d8ee19e1e7bbd52258b2610320527f1a38ddc7183eac35aa6f1d444063379ec52a85c60bef447d6df20b22a35ec846610340527ffc2819284a26887c7dc9eead9ad44d4a685cb048c42bfa434286a776c898ea67610360527f01bafafac3bb3f73f6b2ec355422a65e8f453701d18e6602febc266c88a7c792610380527fa2dd5015e81fda79bb08c408f2ab994a7d30ac41eb14e2a264d9252f473c60776103a0527f31df7fa21fe0a305e3e308ed5dd4ab3707cf2c36f550eb36d06127a44e8079ab6103c0527fff9acf8767e66237a69bea82986cf67e395fedb7cc0f9b313c71e43f15b0cb996103e0527f71ee952eb352d50ca60c38c05359196881e5c92b9b255d3db87f5d049b8dd2dd610400527f9124e3c8a00153bc22ceff34179e0701f387f47ceea3bc39f395ef7bed9882c3610420527f6bd8000000000000000000000000000001f1fc721aaa4119207ef47ad8eb122f610440527ff9d42abb6e626b18641b3106800eb0533016cf48e6c16156c8709b9a715db426610460527f8acde410f5e3406e1903da96d312a40b664c7739273db7c6ed6648239e040a20610480527f2cabadd704d468f241dd904a6632fec62f396418f691553246991f86235783a36104a0527fafa27b738831fe4b18682241410d87fbe96a0e5fb9956bde3405e8f06a6ee1be6104c0527f9b811b69d55cd62936c12b36a8905681f95baa73e38c804f0dd9ce859418aec96104e0527fe6cd0e199631c5561acfdb0f4775dd26f5730c5625fe2799f96cb1d030284499610500527fa9afc4207868c6d5b86a8dcc23c4acd8ad6ab431f4780031f72f810cd7fa74d9610520527f34625a5e5161695cc029dce6569f4d787bc0fc318a8099d6dec7411e96d2ed59610540527f52174be74808d4f3bde58dc2b44ef99a1bba5b5ad5cdf5549f049fe0b184d7d8610560527fc8f06e1de0809d1ac202556892c6596f6da699d61bf9218cede09d49f402de94610580527f6ba89081a0a1e0c3b5e1d2510c1bef2c773952f1628539dc9cf83dc1b70bccbc6105a0527fe4dfa2deb3d771e6f98a8ae4138a8283092ed48bbdd7e25ae6deffe7be3bdecc6105c0527f7a7741900ef61b99f257f3f78b3c4bf782d1d386b38cb7ef1e39f0b5b094e0206105e0527fe7364d03a262655301265f05019b07c401c6a1216daa542f8b9af7063aee8012610600527f7caace2fae0bc642701a9e68679af1edaa352de7b266807cf9ed1f4183c7109f610620527f55d3fd38ba1e4615050ad6b85977898606251555166540ddebb6a2edbec026b5610640527fac02c66f1ab04dbcbfdecbe4b45b23e88b47cea22aa6f9fe54cf5566ee5c8233610660527f076dbad8993743658ec20a6b08011b7e963e84267da8c37973bd60e9575959bc610680527f425c6ab015129cc0ea6630fc7044e458aabd48b9c72f9ab49cd4bc431704395f6106a0527f9a7a1ef1ca5040473b5cbb69b5a5b1b335d56098cc4e21a66b28359a7d7a3d836106c0527f08bda3f52af64cfb832c3d5c1b6c8e6c1c30efde970c00767b0613df6bd551e46106e0527f335ab482163dbaf64f21514e2261607cf8faf45345760c9eb208c07d00605a5d610700527f20c1360ef4857065a011a48e0edf602a97ee036d03c04778c2294588259a62b8610720527f583bd4fe66b6af52f1d2ab8c694e7af74fd1756a98ef0388aa3e04004c3b888e610740527f38a6b73740b97b303554dd7ac963234b5d13c612920018e0f43540afcb50f748610760527f99b3a4b63e7c9548c08bf23821ef55a5a5a1f7a5d8b54294fba52551166c320b610780527f3476912286595061f76abfde7b82d6b37bdc511082ff700c7c0374946e87303a6107a0527fe367d1c0f8d4728b996355f936b87588f9b3119896e75dfed07fec08c7a883066107c0527fd3b5804babc1a6f9dc98f1994d8e3d0ea45c10e164df92a05dca65c1508680856107e0527fe1eecc21fd182df2d3dbf79a9e66a5f9a2117fb9b6455cca7ee8ff3dd35f958a6108005260e161082053606461082153600c6108225360af61082353600461082453600e6108255360c46108265360f361082753601e61082853605f6108295360b761082a5360b761082b53609b61082c53606161082d53604461082e5360cc61082f53603661083053608f6108315360b7610832536103e260006108336000600561927cf45a01600955600051600a55602051600b55604051600c55606051600d55608051600e5560a051600f5560c05160105560e05160115561010051601255610120516013556101405160145561016051601555610180516016556101a0516017556101c0516018556101e05160195561020051601a5561022051601b5561024051601c5561026051601d5561028051601e556102a051601f556102c0516020556102e05160215561030051602255610320516023556103405160245561036051602555610380516026556103a0516027556103c0516028556103e051602955",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x20000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0xe0000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x35",
+ "from": "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0xfe"
+ },
+ {
+ "data": "0x",
+ "from": "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0xc4"
+ },
+ {
+ "data": "0xdf92ac04706765a4e274839cf32f84312e756a6a88f9571ad2cc4b6bde369fb6e1eec69f223fb3a373b720e2c04b3cf6975cac6b07a5db676b54bef65a0542e123d14e1b2a6609d159c733c586",
+ "from": "0x08d033C61e1E55bF868082cf788a3949f4ea949D",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0x598d"
+ },
+ {
+ "data": "0x0fbede1cda5ea094f3d336e7086c33f03a60",
+ "from": "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0x0"
+ },
+ {
+ "data": "0x185adb1cbf8c55587a099e646bd7b247a0567c03924be159636e",
+ "from": "0xd51fA0De3ccd210D4cCA7f9D739f305CfCAe9117",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0xdd"
+ },
+ {
+ "data": "0x74186378b78937c2e7cf7cd7d6404c8a4dcfc5e5d727",
+ "from": "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0x33a7"
+ },
+ {
+ "data": "0xe02e8207ba2827e4a98f8a5fca6a6a2485896b4f1e120e0990f8f1abde4f14c7d175fec00dbe69d167e0ca48333b99214cd6fd665cebaa7f1e9e6e1f16abd9",
+ "from": "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0x7ffb"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x012c1fb205d2aba4cdc7b1da451737a4496f61db6a9404f086443a9ad6adc41d",
+ "0x019f3411a7a4978373a8718d07d80152b457d6167e6b2e00eaabb75d23005fb8",
+ "0x014d775ca00a525bdfd432f7bdcde8821b7434e7d6d041181b009c9ad14767fc",
+ "0x012063c494734e4905ac1a882e1da4b41dac3c6f4d88165279a5ea3a4e1e65b4",
+ "0x01d404619f4f9383cbf624a616734f4f13bd4c2e778c5c32f8b9d3205963629f",
+ "0x01fe71124eeaa9afbcd2c70a0092c0bc8c71738e958c75d896e546304f5f665d"
+ ],
+ "data": "0xcae6",
+ "from": "0x08d033C61e1E55bF868082cf788a3949f4ea949D",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 1,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x7fabc0867b153544d0a7a6917649213ea389d9fbb8d2cf1d31a4921c2d19383080dc1752efb642d761d03a87ab3e5fba43e6b5bb9d55e6c3454977c539d55e32c00c02207b00c2ba56c3d800c2716df020f56948eed77d629bb629f6812e9908d3e1e5846faa3ddb00a4eec063222bcddecb516dfd85543169209e07727b860ef2d540c3a60529b836baa37caa3253bf76cee4b2da73884961397d8208303f7aca875b83ab8f0458ad54306d435dabe741380930e4f72130433408dc99c1fdb46503e08b2afaa43fdcaf9d69cc64d45a4763464acb0cd4a8ebdc421c7c4eb55b6870b824732294d4da57b9fd93d9af41676c9ea38eb4d94305582f2ded7fa8ef6de9770a7cdc5e36c879074bed19d32057ac3afb62b016bc42ab1a8631ae96f991cec8d9b55a4078ba3e115e7f1bbe3a1a59b1d25dbca7f12d4aa49f89ba7acf15e72a210fdb6bcc820e0e51ad73169c35c91c5ec53a9d80206d2c911cf72909c56ffdd464e9cad124ddcd09624a27e49454e4240996cf05795d9c80c6de9f5057f0e693b1790e7c1241dd43c4b2171b753eb0e1ce4d03dee9533e0138b6a7ccb3bd963918fae9b528ec34f4bcd0a24766da",
+ "from": "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0x432c"
+ },
+ {
+ "data": "0x73",
+ "from": "0xd51fA0De3ccd210D4cCA7f9D739f305CfCAe9117",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0xbf"
+ },
+ {
+ "data": "0x8cf9e1e7ecaf9c7fdba7e4e5ce437b3475a6722752a6eda1a5f6f3f8d073f7d854b4b8043d502b0f3d560708cb912bd4d954727b06c1998c31476653936c81544b5398a43189252c1cc1d14280684fab74271fbf4e43b4cf0199d1c322",
+ "from": "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0xbc"
+ },
+ {
+ "data": "0xaed6c0af2a3b780d8f64283222061e3546f17c8f89432dd88300ad877a6f3cded23eeff09e65eda5e1d3dc07612d5a4d104957d44ddf8875f1c21cbde16f05683e0889ea62cc5614981f91006165b8298ddc6c16572aa9c4eab011880f81",
+ "from": "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0x81ce"
+ },
+ {
+ "data": "0x131f100b936e782a5a",
+ "from": "0x08d033C61e1E55bF868082cf788a3949f4ea949D",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0x7ee2"
+ },
+ {
+ "data": "0x77fd456d2b161715b9d91df9a7b38ba3a2697ec0db03ca7bbd44d4768850060e6b0f14724a7240c8f89ad2645f00eaae2846a4815c675c5af4feb83052eb5c05d0856eb1fe0631c3ca5d7295d26fa4e4ca5378c417",
+ "from": "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x0"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x000000000000000000000000000000000000000a",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xfcc66a95eb000258ec04458ea3e7c3fbda47d4e513fb50bd91302c17eb758f9c",
+ "s": "0x16061ffffa1c3a815c757cb500b5989dddace00fdb3d6d90b93ae38f3b2591c7",
+ "v": "0x0"
+ },
+ {
+ "address": "0x8fd379246834eac74b8419ffda202cf8051f7a03",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x62957cb32907e1636ea9fe81e4b5c4b343cb341b9031e0b1cfb757e581726714",
+ "s": "0x7631afc54a3a4824e975d7817b97a58c48c4b4ee6115c092dc1b8e3902d39baa",
+ "v": "0x0"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f9",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xbce2fa378f0a346de227333da920658ec00165a3d868a08e24820aa5d661c66f",
+ "s": "0x79434caa34fd81d2fd6a72e4c37328423b859ba9699db8070eb8cf6cb62ecb5f",
+ "v": "0x1"
+ },
+ {
+ "address": "0x88f9b82462f6c4bf4a0fb15e5c3971559a316e7f",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x135760c8d007349409e2e9e91d1920717096e5c322a09fd57aec337e9d45a0f9",
+ "s": "0x51b01163736696657476c58c28dd1c64611ba807f95d9bf08e498f0a3ff136f0",
+ "v": "0x1"
+ },
+ {
+ "address": "0x8fd379246834eac74b8419ffda202cf8051f7a03",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0x9a99690542fb5529e0939ad8f6249b224f006b5abe02d6b1266092586d9473da",
+ "s": "0xeab54e0e8d555a5052579dc28758792ec2ab9811ad89bd74f8ead90f1d0f20a",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x275bd835384724a426a222f96df619961766984861b90e",
+ "from": "0x071b56102BcF6C36a20a3a16fE48781448B1C274",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x00000000000000000000000000000000000000F5",
+ "type": "0x4",
+ "value": "0x1e"
+ },
+ {
+ "data": "0x00",
+ "from": "0xF0AB5055e5Bdac80D061b1E7f2bA766d0498b697",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x000000000000000000000000000000000000000A",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xa57450a9f1a11d34fcd9161c926b59b6a49fa5c410ba426f4653d8d5b1efc7d9",
+ "s": "0x7f32774d49271f17179ff7fca61536e2bdba3e13c5f4935e4249b5d51a6908a3",
+ "v": "0x1"
+ }
+ ],
+ "data": "0x275bd835384724a426a222f96df619961766984861b90e",
+ "from": "0xFb4bfba6610Aa9869db78F7c6b8f28b166CC8674",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x00000000000000000000000000000000000000F5",
+ "type": "0x4",
+ "value": "0x1e"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/tests/vectors/fuzzer_test_3.json b/packages/tests/src/cli/tests/vectors/fuzzer_test_3.json
new file mode 100644
index 0000000000..a099937177
--- /dev/null
+++ b/packages/tests/src/cli/tests/vectors/fuzzer_test_3.json
@@ -0,0 +1,451 @@
+{
+ "accounts": {
+ "0x0000000000000000000000000000000000000003": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x00000000000000000000000000000000000000F5": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x6517fa85aafd83a02f88fe864d93249c357cce975bd1f35d0b0430a901613f76",
+ "storage": {}
+ },
+ "0x18665208d71eAF07c959cB6d2b263aCE3eF24042": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xaf09231cd0ab58828b41ee0ba14866d944b955fbc80243a5bf0bc8c86c664552",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f16e24b8def199c4faf4b0de6ce2c63e66000527fe7791b7fabc464b9917b8670c24bd789323ae58b0f592f02ed3d06e79ecbcffa6020526f1206832c56ded76311a0db4a5bc0b47a6040527f377a7b0ecaf5f702f0a97545192bdf9048a284141d8ec65c40d673bb507d61e26060526f164f4218ce14fdcca1a3917b8352c0836080527ffd2305f25eb90f9195ac522e4f6cd88e81545fb7f10562a26e1aa6d1466bbdc760a0526f144a6f62df019666d40f23c29262f4ec60c0527ffb087c5672a2296e370e37d9978dd2fbe48b2a672b2c4cdca1044065048f4cac60e0526080600061010060006030600b7f21a070d9db735f0bf7584a27bb2989cf7e5394856980d1ba9e331f287f809f76f26000556000516001556020516002556040516003556060516004557bc700000000000000000000000186661c6cb8c557683f3956179418be6000527ffee89013185ca411ac3c1d013761ece59171c177ba2b3ea4a5ba57fd23132bb56020526f1972ee1d32f075d8afbb8bcfe83ae8886040527ff1af141241fe7a10d277654ccee3d1ae5a920045671bc866bbc2fde1d7fd5bda6060527ff6806c397759dafe04362b30bb4cecee2f2c7ad27c5ca85c9a9ee5c0631b82fe6080526e6359ecffaf804508e2133f4cec6fb460a0527fc0af6115166ef142b6955aa1210eeb62ad00eb163ec6f4a136a0433055fe382b60c0526f06218d0729b50ed2c4bb39e9bdd0ef6460e0527fe76fa18f7bd8bcae67625fccaf814b691414b9ae8faab635f5f26a69a5bc39c1610100527f54aefece91198aef0f6aeff12c5bbeee9ac4b7f53e5b0b3df5d18a0b4d883b27610120526f0ea17c12bbe9b722a199f015cd765e30610140527f839f0cc89472d1544db8f1e5a7cdc6cb55a244294ce0927a8cba0bab057482b5610160526f0783e9c6f15f9a5545069dc92d2804e5610180527f49a0323eef45d535d31de25f11bfae9a2232c8ea963eed91a947ac24057774816101a0527fd6487c7c52f985b8fee0c9fe74e2d52126f0cc94bcf6d03a821ca3081e1694e56101c052608060006101e060006099600c7f4322102205f887a7635767bbf3bb40eff62346a24993b2dbd48340d613bd7c1af16005556000516006556020516007556040516008556060516009556e375c316e62646db2c8786a8b0c99f96000527f73c5d11ce498ea04903d444de4db21f1859032a2222b3a1398e989ff66038e1d6020526f02bb1e1e9aa44652a3d2f90cbadff6e26040527fdc4c58d923744044fe05eb40315de822e830e55f24b67b74c7e3fcbe85bc13846060526f169e9504cbdd505e5e011a09319dd5976080527f4c5efd999ccb14045319553f51ac1be0b40789940f1f7b060288d5ddc22f7b3f60a0526f11917a01e6cb9dfb309d424e92ad637260c0527fd7386bca15ce9cc8365ffd362adbc5126f52d6c3d3802bd05684ce68d5e344af60e0526f13cc36e82da85504b9394234ba7bc0ae610100527fd19a92d065480cc7d89463d00a86f3207b514b7e0c10b2ffd4ef7011e2752666610120526f0355c0f12e9ce247869f07f4b25e8ce5610140527fa16eb6a8fb9d1fd3bf2fd16518d276396888965053f66bf8557ca90f269cca90610160526f08ec0da76cc6750ccc460296d791ea40610180527f2284637750bea945d7ec2425afb94b3efbe4813a31be1ae9ca7ae586cdd744d26101a0526f098827f98c92126deea2d037fa4c14bf6101c0527fd26774d199c337ea4c1d1f975598147fd0f7adb7fb3e7c7769c84c44c02d1a4a6101e05261010060006102006000602c600d7fb04339addce3f2e532cf21af244ab062b26ecd058004437c40a04087afb86cb6f1600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f175f42faa24a4f636d8a463f7941f13c6000527f38b53dbe8af42d72270c1b541da8c8dac472f7ec9e9028bb34ffb68635c3567a6020526f0b60ea582837a3b6397096913eaedf266040527f85d30f905969403d9c6012f333d90bf3e8eba0a38a2e20d4775f27f6d5a7aee56060526f0e0730b9d76b6ff1207a7168f9609dcd6080527f5ce106c8a7242d425fe3b4a07db65789e0dbadcc841d04711be513d73fdbeae760a0526f133c63b3f316edf9dd452d522258b39260c0527f280dcfba6160d56f8b6d0a9bf26e733efa882535efac1f7c2c9c7d1806a33b1560e0527fa7e33087160b56e50927d53a940543fcca6ff669cb04d671cad0ee2988ab0bc8610100526e1ff24610aeaef59ecf547fe2708be7610120527f4537ce6a7678ba6967a76907697eb0c0b768f91beac5c6221e030226138b32b9610140526f0e3eba81018c856b86d941a40f26b0e1610160527f561a85f883f1dfa49f1ac2aab5925080417f16b289cccd87aa640a57c207ce61610180526f0874daaffb648d8ef8d8b1d65424d4376101a0527f802f3f60cc6b221a8454783135350b75ccce251abf1ab4e228c0958077318da16101c0526f052493beffc1839977c746f2286a8ae96101e0527f67ea09233649b696976e68f8e89c7faf312eca402b85ab9bb3a8875651457a87610200527f86e1c5c45c73587ab24a91612d97087d0cb17ca75aba181bb3933849dea20d6a6102205261010060006102406000600e7f5966d656a872091de7969b3c78cdc26b8fa86c98472016fee4b05524d116ace2fa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f10c60cab79bbd0a1ca7fee24970273266000527fc50134494b67160faa9d01d31c35f964f553dfc570139af84ce9f94aada1a56c6020526f0e7c6cb18834163ab4ec76c3fac369606040527f4f07721b1bdb858d2eaeb30eba516910f4ff3f809a9d602cb037623bed28d4be6060526f070e5834f155e738b226330f1e1f234d6080527fd2606e390b318f44d0ad923604b18ccd4cebe13edc7516af7be5f4fba545aa3560a0526f1394b964d3fe51eb280a1187c1a03f7960c0527f303da872bdbb83bbf0f52691d6632d205894bd069779fb6096cfc341c208233e60e0526f0b8d5e4b35400bf719728979a7a2e7d4610100527f5c6df065931a258ebbce660eaeb09db3501f7b18756d2dda21351deeede9a097610120526f0947daa09c50d095cc7adc0ed7b362c3610140527fdada2c430295e6c4e859180f93d88a833fe623ae81da2229ea24ff2c18396b056101605270011166b9f441df607c05545f4969139c6b610180527f29a50b35c35ef7369642e91ad7fbbb322fefe41aaff8903e7b3a68a86a3c527b6101a0526f107152bc657840de46821e92d790caa06101c0527fb268c147a995053433215c2d41d31440cdce54c6ce630113d1c8fe0e4aa1a1c16101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527727d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e052602060006103006000600f7f9535deee52630252dd81819eebd7046936470694754f1b4d92dab7b1e1b1bb11f4601c55600051601d556f175bca4cccc7ffe99528de9434a6ebc36000527ffcfb65055ce6f814efdc8dd4e229be05322f80d17f96ce7d8bd95a093f4d8f3c602052608060006040600060107ff92f99086b528dbda48f43e7514a2ad225b845afd0fd0ccb91c137a3c89b847ff4601e55600051601f556020516020556040516021556060516022556f08237a9d0ac1a6af0eb791d36cb179d96000527f2cbf3a95e85134eac54bf8e4b91f809740e3880368c63d0a85bbd86007f246d06020526f16ca20640460923b84fd15033ddd83ce6040527fbb8d51f9079bad29ee8b31b1f8a8f9cce34475bb87a852916f1d9000b1122167606052610100600060806000600060117f9daaee1428029ce3842e234b0a1727116151bb0f9a60c83187ad9e3413b92621f160235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x606160d1606b6053609a609a60e44534857912774a1016438a38fd47785815431c5f10056985333736916b885974f56c7cfe063c369c5b5c363e120b826d1b83a349787b193f1a8d717075746a577d005264f06a461a3ca242087c6bf412183f5014013ca2021a0a1b5b647f449f7b10a1577a6367fe5d135140143e9e529c9686387e57766f7d533c05355a1155125a8d66068170a300704807f140687c3e793e308b0a767b0714776a16791477423159053b31433e850a5c487f1766175b1d40183a81676800981d33427f366d3d5334163a39546f550699200973367d42677e31a11d33686738020233f58805530804a415324977333e077a364217f29c321e6e6119336c90317f081e460a8058183c9404742068346315638c3291fe8d443b56310b7cf0746c3e4a6fa17f77ffff3968377345f25762755f9f6a8e8ffa57367b747264156168609c5a1d307d7b736c475b887a7f1a6143116a83407a765216093ef402450100438b385c485c3e3b7683117139a13b545b806819168a3c1b5f0184031774a20065093ef1430170123b1d4416815646413872033302783306561c5e43534016531488937e533b54495331f31d1a11378e1b86630270166e680b13030b097d7a42128657306af54219009d5e11516ea2a13967550936866a9401160a3e1432427e48994a756a1a05f21a3a511b341e3354207a04a243788b8d3ff26609904a905737854442386d8c92f456468a567304076273663e986d020a6902193b4587650615a4123e367a7915156f3438429b6d133593597c597d0b33779d5150163449206e7602555c9c6341117580f1399d3973010148958117331373151493988ca3536f663b31151714600b8344459b5d085d3e5b02470553916a496e7b7815a1755c1211621414127b08975e463d47603a38927e8f63908c47705e12193e14a3626d34376b7df2743a695f83a0541b663b345682ff343e176b6c63485d653178330a67618870161966353d8314119878418e791781015e0070635a6f424191301145547c884543964434fa6c1c357b7f57713f8017a31c001e6d4935073238546a5e9c6939a35a6b9df4083c5e7a17113e30034605330b9d89790012406175709ef062758f7c3a3a4a4200647508328042687f865f883f4543421956083f9a39841b5ea3995b0662427a15571c0367847b813115fd147b0603876a0b743c4468a120459f3f546595304a815e527a5a5a1995fe1cf105350b659e01015b4806085e0b443a40f47e377b5b5508a36d6880fd7379a48d4539108c333f3b17a05cf25b34920186a38804f1196b3b1282708a58034746771130076c496c605654319c0a3259a03206807613759d3a524634716ea170627e6d8d93fa7635183337395f1960173932545e3187301a7654a4494993949c7665563573f07b",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000002"
+ }
+ },
+ "0x2837fE6BCdADEa40e14E73df3101847267659772": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2bc9eb16f330b5d3764d1e508af3bcbb84786071e249bad6f91ac38553464bf4",
+ "storage": {}
+ },
+ "0x35F694E45962Ab9eD665971FdF51A45A3b109c62": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x2ac7d0629b3a39ccca4afd80b787edeccd0f9ceb5a83595c0f6a0e1cff0ebc7e",
+ "storage": {}
+ },
+ "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xd5b187a1488a0211288f3d420de324151455a6fa819850303f62bd25582b7cf6",
+ "storage": {}
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x3d20e47e079e7b696d7f7f600054506001600055600060015560015450319675d11a4a3d869a257f60016000527f606000527f0255600260035560026004556000600555600154506004545060016020527f60066000526020527f7f55600354507f60026007557f977910ced1e5f2611cf16040527f0fd10cca0c0c2201606040527ff26020527f5cf3c0a7bfa76000527fa09027936060527f1fe16000527ffc2e808841d1cb6060527f1011f4fc5c6040527f991d19f4c0a46080527f0aa9d8cc6020527fc56caf7348595e1e256080527f3b6020527fec9e2b08606060a0527f527f121d91ed66a56b3990e7f55479fd6040527fed60a0527f2693f7eeb9302260c0527f1a445683aff26080527f6040527f37f16d2e0764318bda8a2060c0527f172f8a60e0527f6060527f26b7d98bb236ce7cd1f260a0527f90920f631a99cc0f60605260e052610100527f7f6040600060806000600360608052609b60a05360f460c0527f60a153606060610120527fa2610100527f53600860a353605560a453606060a553600060a653605160a760610140527fe0527f536060610120527f60a853600960a953605560aa53606060ab53602060610160527fac53605160ad5360610100610140527f5260606101205360606101215360ae61610180527f01225360536101235360606101245360610160527f0a610125536060610126536101a0527f60af61012753605361012853606061012953605561610180527f012a536060616101c0527f012b5360b061012c53605361012d53606061012e5360b161012f6101a0527f536101e0527f60606101305360006101315360f3610132537f295db4d10d457703fac4a58461610200527f01c0527f5763d8ad4f7fe25d383340a63bd007f1d0fac745610140527f18503e610220527fd067c38b6101e0527f3f15a2db16b993db65b52be1c3751292ab7f726556cc6f610240527f3db861016052610133610200527f60006000f0604060006040610140845afa60610260527f0b55600051600c55602051600d5561022052606061024053600e6102415360556102805260616102a05360026102a15360426102a25360536102a35360616102a45360026102a55360436102a65360606102a75360006102a85360f36102a9537fe3ee942ad25b25369be2c1688b613d779c81839be45594d5fdf66ebe02c5884d6102c0527fc1b8cb2dec124ef66d8514616b19425f8306a7c25ec7319547379c3e2f2a3e716102e0527f676bf6ab4f90e5802f11842312f6c3105ceadcd6e9ec7ff7104e40318837c13b610300527fdd597bf102dd9bacfcb320224a9cf7d69219ebf4ca46e02ffa66876002035be1610320527f101d91264e2f2011201db863853ce65852eded02898b6c2ac970dd990634d17b610340527fe466b225771c74493685be8ca2589a6fc0874cf8930b5ff07c738b703aae0a37610360527fcb08dfbd742c633520a90d3202b758a4cb65f2980cba0d6c0cb75b9723a2cfea610380527fa490bff0e3a32a3bdb0e0858f6d25d043b8d79a6b329c8fd02df2804e4b692e06103a0527f968ce172991a8531da24600abb8747b66d8af0db1cdd002c528eb0354ffdfc166103c0527f37e4358b26718085b990b595281654dfc84ff24aaa257a641bc8be1422fe301c6103e0526102aa60006000f0604060006101406102c0845af4600f55600051601055602051601155601255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000014": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000007"
+ }
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7fb8bc210a6b2898ba233c41ca9920618eea79fc8a5ace79aadeab519a3eb9189d6000527f7bd79287ffc0ffeacb8b778efd44ad58fc6a6488b608dba69d1eee3d4a9799226020527fd4d0115c7dd08822f919c6315ae2984950ef08a85b6a35418de93190b37753b26040527f656124ca0102959f7bd6da4d2d951456a260354d75b4e5c40557336af6dedd656060527f5e7c42f565141777662f033b988197a41247e27f98a46e5f89718064f2c028d76080527f2200c204b98c10e05e544c20f2ac26512806695a083f9c5363e9aaf60521fe5f60a0527fa59326cbfc0ef56563909e19e3ff88d59af8aa304da4daa68122ddfb4356549960c0527f838059777f4f4b14043f7d2938256813a4f66317e40697d62c1060f5476e513260e0527f4c4f97ec8ecbfa1c0c8d31fc2f3ece52614034e18c9c914872f0cc37c6b865fd6101005260406000610120600060fe60077f8828d27885159dda6056c70a602676114dc2ebbaa89240614ab73a567597ccd8f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x6102a051606060e0fd",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x6888bf43c6b0a7bd72d3d4f360efc2fcf781b746e6de54a559882e71c4ac43a2",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x600560005536841b5f80ee6fee60206000fd",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000005"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7d0819c8cc03a05cd0bb060c4679208c3a385feac991407fe30f137f7abedc6000527ffa5f14bbc34be0fb36e1b8577b662d2b5528b6152cfff1e62805a23d072b964c6020527f4f4b6af3709c8fa80e946e07e0e869608fb689b23498972d172a770d2afa11b96040527ff723c9c9e48eddc4e1fcee8bb6b5df3e184634701681fe9a1fd71f1fbf15bdb26060527f2920d94fa1b64095d1ea56ef0447587309ca666fffb9cdb23ebe6f71235965046080527fa3a2f686f7eaa89c2611a8c33be8bbe053a8db8ffc762b7f3df68dd98a84d5c960a052609c60c053602260c15360ab60c25360e260c353601560c453605960c553608260c653602e60c753607260c853605560c953607460ca5360c560cb53603960cc5360dd60cd53603f60ce53607360cf53600260d05360bc60d15360c260d253600660d353600160d4536040600060d560007ff34c1f709738770ff7d63376077de9f459c1ac7cb882e82c5b41a39530ddb14960097f7742ed7e48cde6954062a5df6b187eb254afb4f65652c8529d1cbc9318db63b7f1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xbc501cdb0096cc68817e5b2aa2eb7e97fcf45a56dbd22b6e2de2b234b51f12d5",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x7f80000000000000000000000000000000000000000000000000000000000000006380000000077d7676767676760000000000760000000000000056000000000000000000006801000000000000000090051c686d5adef08547abf7eb7f800000000000000000000000000000000000000000000000000000000000000218026d01000000000000000000000000006fdac7fff9ffd9e132262626262626260018901d6000557d7676767676760000000000760000000000000056000000000000000000007176767676767600000000007600000076000090171960076f8000000000000000000000000000000007046001557cc9700000000000000000023f00c00014ff000000000000000022300805712000110000000d0a300e750a000000090a0a901d762900760076761e000200767600000000767676760000007f7effffff80000000000000000000000000020000440000000000000000000001638000000190096f800000000000000100000000000000006b010000000000000000000000778200000000000000fe000004000000ffff000000fffff70009901590156002550267ffffffffffffffff7702ffffffffffffffffffffffffffffffffff20000000000090146003557bc9700000000000000000023f00c00014ff002c0000000000002231087f8200000000000000000000000000000000000000000000000000000000000000901d600455671fffffffffffffff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee901390027cc9700000000000000000023f00c00014ff00000000000000002230080567b368d219438b7f3f901890167cc9700000000000000000023f00c00014ff0000000000000000223008056b010000000000000000000000901c177f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9651ce97e1ab91a0960055576fffff716b61616160b0b0b2b0b230b000008010d0a2b007f7effffff8000000000000000000000000000000000000000d9000000000000011290187a01090000000000000000000000000000000000000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f5079015901b6006557f40000000fd000000db0000000000000000000000000000000000000000000001600790037feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c901c6007557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd677fffffffffffffff1315717676767676760000000000760000007600007bc9700000000000000000023f00c00014ff002c0000000000002231081d9004196b0100000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200009007046c100000000000000000000000006c1000000000000000000000000090141a6008556b1000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a017f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001712000110000000d0a300e750a000000090a0a0390067f7effffff8000000000000000000000000000000000000000d9000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900b1460095577800000000000000080000000000000008000000000000000610111900260006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xe0f8e02e171a2ef7eae37783ecfa6acb82cbacaaff229a4a403134ff420cb4c4",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7f24f22a99128cbb4069321393f9093db47175e6518c6edab11963f47871842cfa6000527fa61ad2bf4623a058055dace5152373ce44495781636acbe3ade530c5bfa9e5af6020527f7702525974eabd05751ab013a42162794531ce19b964f523964b3817d73176ff6040527f5e6fe05bbf97827bb85dcad5765d014fc49a1048dd49a38c5c129d14cceb5e5e6060527fbb34b9ba02153c30be036a074e2ee9de7c4095e3467085526207f898f43c1a3e6080526020600060a060006000610100611c35f26000556000516001557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff000000010000000000000000000000010000000000000000000000006020527fffffffff000000010000000000000000000000010000000000000000000000006040527f895720069413cf1ab863112e6e45727bb5f1c2c16cf0cba09c5d3ab527bc9f5a6060527f8aaa289b7cf77196387ce801aea3bd400dbd39fe82bbcf55a0b1539de66c51336080526020600060a060006001610100611a42f26002556000516003557f73d209ac0034eeb9d245ee28c3be7b453ba868e124cf417fa4c2a5edbc1bad0c6000527f7d615e95d2679a60eb6a42bb6936ed3e4b9c3af745c179c9cdcb397a9e0eddcb6020527f79a0d10de0e554431ff1b7a031488a932a16e97adb6dff5b846029ff4bdaf9c86040527fcf3b86e95a2b957d5fafe6d42538c850e5b289c4c840927b96bbaaa7832574a46060527f9799e25d757bf3b4b91a2031d6eaf3071f5b6740c4b286e66d35284f2bcf25a36080526020600060a0600061010061192efa6004556000516005557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611bd4f46006556000516007557fe80484665b6066eb796e789f98f98024c94a8e878a5620a2a923de0de7dd8f8d6000527fc33f0ec09eead991e48c2643432e991bf54fc9d6afb1df86b056a50d440d99576020527f7bc425d87efee0e6a7c0c00568b9422672819241248357dcaa9f50b6905282976040527f98dffe076ad2841ba6059c56b4298f096d2b86fe82e14db2537577accc27e6146060527f5617e88f40eb2d34db4f13618b14b70caf308e786bb8366754c6faa2dabd52406080526020600060a060006001610100611c6af16008556000516009557fba785b717818648aee59b3103ec60111f90bac454a0ddb0fc5aaa0f707b28da26000527fd5fbf36a78b82aa814da906c18a3e1d53105b6c1ad663321f3f37076c67d0a366020527f4773528ced0406f3fe44dc0143bd6b8d6e5064d0883a90abe3d72910c69ec1d06040527f042543aa4843fce3150c493370a49b2d0da36d8f7cc87adf82a646dc04b6133c6060527f698f88f6a07cfcae3dca22cae162e62c3207bc1c03864eeaf0c90247292c24506080526020600060a060006001610100611bd1f2600a55600051600b55600060005260006020526000604052600060605260006080526020600060a06000610100611a31fa600c55600051600d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527e020000000000000001002000000000000000000000000000000002000000006020527e020000000000000001002000000000000000000000000000000002000000006040526d80400000004000000002000000006060526d80400000004000000002000000006080526020600060a0600061010061190ef4600e55600051600f557fb3190ee410789186a46f6acca8928b7987838124aab0cf04395162654b379ed56000527f4a848ae1352d38ce207566762aefe8bbea9bf9667ade78e72f01eca11387fba06020527fb16d9714b0ddd01921237b52ad1e735062dce5fe414f89be9098276b147320696040527f3860ec3d8c9efd14d66eb591d97c61531183a3be527c7c606ff73bf0b19faaa76060527f4984d660600f9a521431e3a2ff3009dfabaa2358e5bee9d3fc55133b0eaf58ab6080526020600060a060006001610100611bb6f16010556000516011557ffea57daec4e67954a917ca0ca921a7d64b7a7580804f8eabdfbbbc9e5db1eaea6000527f6c10fba5e186af4aea14587dc5041422cbc7c9f58cfb2468e8af8814efd6a65c6020527ff819e8802e912c907cf2812dd18523a351685e22ea1b25dbb7156d673ecc5dba6040527f3e29a7314665829e5e743c8d6823e1d1311a03704729f2082b5f16d38a19f5916060527ff1996c6f05e983b4441ecb4e3c6615c0fd538e03b4911e9169bd3ee3ba1805356080526020600060a060006101006119a4fa6012556000516013557ffa0417bc6bb9511e1eaede67a3f0cd0c23526c4fa155ae1f161365cbe7a7c5546000527f5082ad3a8e669637f9c253d0fc6154de372e5724288c6c6ba0db8b1a6ae06a8a6020527f3d7d7e02a4883006d8fde8284540b369de3dc7a908360c9ac5379430f68d3d1e6040527fb30536063c756ed27e2a7fbabc35a07eb30a617e50d1d6e92242ecaafe5de8146060527f7df7b8c33652dc5761a6faa091b947de9c364989a3388badc71b647fcb68da306080526020600060a060006000610100611929f26014556000516015557fc8fbd3a0d4db90baf77610bc0a31e949fe9356e526a918b2f82bb1f6ce61089f6000527fe902d0b4dd1630eb6e7f693e2f562bb3838e042ca9a40a825d0fc7eb5d095c6c6020527fc40851aa6c579e19e95fc3701838e91160c980e1e2bf27c4e54da3459d99dc9b6040527f5f39da4826bdfee74335689bd009e01c2605433ed6d960a1e019ad1048a85cfa6060527f1520e3d42f5e6d3922fec41e56dc4bafd302ac4c21b4c81e8afaa5de4514ed5d6080526020600060a060006001610100611b67f16016556000516017557f57e1ed957a14c920e7fb86e3355392c5b1e7abb074f8794028b65667f3776bcc6000527f72484872ce77a8fc6e2f3b7ac4ffee8ae7445ef5ed95a78f9215843048b0e8516020527f14f85bb2ce9c577d1ec44cc1fbc698b509f8cb88cf21507be3b317ba7291e44f6040527f50d89afab90ece340df275c0ddbf7f44551c0e872e962fa67727c07b904da71d6060527f5df66416387efc11bbb44a582e139ebbb7a845355ebcca8a51ffdc7c09f1d5386080526020600060a060006101006119cffa6018556000516019557f1589a7c2fb3c896ceded91944be7fddd82c9d2ea37a4caca5661d7c2cbef7f876000527f033f2a9f387a627e26801569d57fc81547cc9434efe65707ae704ac40dacdb9c6020527fe1acaa5075ab21193805eb461a0d3aa9ecf269b5575562178705dd9dffe5d9366040527fdbfc6b49c65ed133eabc6deac7c816dd9d8700d2b013e63c3c61d0b2bfbde4c66060527f1ce4cd3a3b18f7c5dc690b84a9d838cbcd78392bfc23a61e360bb09435591bb26080526020600060a06000610100611b5bfa601a55600051601b557f476936d377e6238e1e6695e302f97be55b9d7a2a3f5795413e6b0cfe7e4b9b0d6000527f3490fd4cb7e398858c30422ec621f0f5f9b4a0a1e0f59cef74e89dacd93bc67a6020527fc7cd4f1f41ebb14d6a5edd9c48d1a4ac8e9faf07e0959bb668374656a8df03626040527f6a1b0f2a71e0c54661665393aee5413d3711df2ed7c11063a47e10750b0843106060527fe389a29310062d1b2a1cee6aaa3d52c534103f82c91996a3e5302dedc5dcbfb26080526020600060a060006101006119d9fa601c55600051601d557f81909aa98db980581d2313e9537b40d40fd5bc2283327173c50d9f585890cdb76000527f41df2169692501f171a7025053b6b3394e3b7750ef97776d085642ef689bf2fb6020527f7049ab6516a6c677ab10becb220399208c891f42f4c12637fe12c5f8448b77be6040527f68147c0912a54642d919f3c546463633d4683b604d2511ec9d142721555965176060527fae65a35ea73220c5e6642676c8491dcdd2d7306e1018c3a139d9efa9eedc55736080526020600060a060006001610100611c89f1601e55600051601f557f38a54a3b9d8f4b3778c2786c9d5b46881ef409236eac1eae02d0a7af3fb5f67c6000527fddf6765e882ab5bc19cba477f16eb56cf1c6f07bf716e3fa80ee4d7cbc3124ec6020527f2b43c572d2373b0f41fbd54d4257495b9a4c6ea0868757558224fd0119f7e1fd6040527f99f5e2f02cfe6af231a6b8174da83b100f76d3b806418fbcc1bc0c773dda61846060527f02ad258ba26f93ba475b3703faa3519fa8c925d25aecba4dcf98e775ff2042446080526020600060a06000610100611c03f46020556000516021557f1d9b9559392a4601e49eaf3d2c6f2708d59befbcd026250f87f62dcd0d99c97c6000527f7772672be8d32fdaf0489d79b2f14ca620605f1861f5ab05efaf9db867cc6ccc6020527fdc414270ffb5cf3cd7d0bf86558a2276f9144dd39178538d87f98c46fca8d67c6040527f2c1da6ca558e5e84fe8a5a6ab830b35d99697af70da38e1f71cadab5d8b82be56060527fc9a8ed8582c16b0ea8762a83768f0bb9c25967717f277505025abd6d719200b26080526020600060a06000600161010061193af16022556000516023557fa266ef6b4f35ffff1ef9dadfa0c17bf9f62fe328ab99aaf9205f58883ac6ad046000527f63bb80afe81c5bde0d2bc0311fb485ad8287c0a32376d71382537518ff801aad6020527f662dd6de566229f71084d4c22ef95abec502f28e55697b08cccccf61f67d25466040527fa70c99d9c9e70aa825b4b3a1856bcb069a84df0abd2aca3d3652e5583e9a29026060527ff5e7061cd7157b7cf70218942f152a98995bb89ae95948ad7fd26472badba80b6080526020600060a06000610100611bc3f46024556000516025557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f08cfb1ec9f681f021a9a321e1041afa50858597c6e86340ecd0fb90f27f61a4e6060527ffebba51fc691c0be204421998b1c53bf8d3165645147e40c5620574faeec2f8a6080526020600060a06000610100611cb8f4602655600051602755600060005260006020526000604052600060605260006080526020600060a060006000610100611a4bf26028556000516029557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611c3cf2602a55600051602b557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611a57f2602c55600051602d557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6020527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6040527f705161ba0fb15c41c92b6c48b38f1fd5e12b90733dd1c11ec0a208ff086c7b506060527f1020c461213478ad81d5eecfa1094cabc38bdf59de6af3bef80fab3ac4b08db56080526020600060a060006000610100611ac3f1602e55600051602f557f371ce4e482f494f3938fd93de481a0d4820065968e4826d6404d74e3566cf1996000527f5ce4d043ee558c86a1de059c01cd16158fc549744b61e4182f6a36beece695506020527f52d031db960e606eae783e2b27ad53cb7b5d873074740c0842394604c8abdffd6040527f0dc01fd75abb6644da18665c8c698aac22b63f217dc5491fc3cb2f627b6012706060527fdbc4fa2816249ec4667cbaba1264fde39a1107ad4afe4591a9ebdd0db08257496080526020600060a06000610100611940fa6030556000516031557faabb230926d8306560b7c62f8832294e1c0c5d209a4659fd5e5ca6333f08f3446000527f7d0690e61f42b511937ecb62af7a531b52fcc1e07615ce2a46f4469fbd68cdeb6020527f2e790ce409877cbe56126873b63dd08122b74d2a650a0d5d8bb8788eb4c409596040527fd165b6bca6885a2cbcc2ee024f79f009353b6e194e5fb7e507ea0995ac2b6f316060527fc2c0f5098f1d1250c4faafd7634d99f84032fc1ca82cadc510e33bebe31e03b86080526020600060a060006000610100611a44f26032556000516033557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a060006000610100611a6bf26034556000516035557f809256c854c346a04981f0a94fcaa3ae1b8b71512532ea1cc13b0d21d51dad5c6000527f65667e28754d2e803604c0d975bfd9a6d472f87e70c9c0be5128a2c4da97b32e6020527f89c17692aa4e75158d30ad930bcfbac8cc9ec0a049b937370153dc532cc54e646040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611a63f2603655600051603755600060005260006020526000604052600060605260006080526020600060a0600060006101006119d6f26038556000516039557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffbffffffffffffffffffffffffffbffffffffffffffff7ffffffffffffffffff6020527ffbffffffffffffffffffffffffffbffffffffffffffff7ffffffffffffffffff6040527fad576651d42159e575055dbf913fd5300fe5fe05ab7479d2c303c3941b8bb8e66060527f6c4ea7e65e464d36dce6615b4ea9ed764115aaf547ebd9a74f1b95b298de24e56080526020600060a06000610100611c7bf4603a55600051603b557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611cc0f2603c55600051603d557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f918074fe4165eb12758053d8eba7ac089d81b90c36299d6ab39b3b707a5e0fcf6060527f6d540c78a7d397143840c1f9c22dfd833eb6f7770adbff9950c607f2d0f312746080526020600060a06000610100611ad4fa603e55600051603f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611afcf16040556000516041557f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605d6000526003602052600660405260036060527f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605e6080526020600060a06000610100611a57f46042556000516043557fc9bbf15b2b036c73bfc676544843010312bdb57034b38abc9867e5505717005e6000527f7e3ec609f4d61528ca15971fee344ba38c878bec7d8a75d820e65a931bde81676020527f47af354cd5d49248c895a78e1cef37058971d0b2793a0940054f2630347799c96040527f15bef465d01428155949805c60b1bf0d1e09f2fdfda7bc0d288f29d89bb179c86060527f5da47bf878cffb792df65ae4a2f58f165296f4ea9b955a795d951493db6c85906080526020600060a060006001610100611beaf16044556000516045557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b00fa6046556000516047557f38bf718bdef500d5c9ae22839f7c55c17c14a0849333ac36f652c15136d91db16000527f74db2fe4a60c76266c1cfd63b78e408d94162304ca9cf24eb33d436d69e58ca26020527f844aa5b7c8ca635b15fc539d99a61639d2f75e1b100d0e0d45515b71dba25a9f6040527f7ee37e25805f4df98db6a971f1c4de08fc34a8352adefdab0a6424fa84aa60e86060527fb048966cdd28e69e7b2adb1ec3503b307ae6e69efcb14ae0d6ff186f1caf0aa16080526020600060a06000610100611c78f46048556000516049557f4f164b8627de3ff73865693b11f9d0fd85ea984f8edea3630faf222b31351c226000527f80d9020d250b0fbdf449a90bbfe680601d3a0cf7ba1e0817db7a5613813895886020527fba4c2114e9e626617daced22efa372833c2621fe45cb90829145083e6238e8686040527f9e09b68f458677a0b740474cd2f51f978f48aa23ecbd434325a0049fa48b267a6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611ad5fa604a55600051604b557fe28e01f7ab4d68377a0c8dd04a71e554936cebfa0b1a221c7f65dda575a430f06000527f18598e385d456428d422835ad545c5639c3c26bda4eefcdcca37aed404c3a4d86020527fcae8afc37833bddbd450cba85f70457da0041ff1414a2452244eea56e6c423f06040527f3758338a77ce7169edeacc42f470480579d9ce05cfeaa2a589b40d8595bfa6dc6060527f9c4763bc6f8166ee9161c90e1ca11dcdbe9d9c3f5e7cdc67ffcb671e1464348c6080526020600060a060006000610100611a7bf1604c55600051604d557f5c5752487c7f609e4c694a8255725847fb6320c4886f2bd0986648b2594b8ad46000527f5e7a594934a521e064fe3695ece89bd6dacc48781b32137710802aa2047de5d96020527f94cf7f556a6634100e5d8871937fb9ce3a44975bd68a3ad9e04b4aa862fb07196040527ffb69bab7c49313344e670f4a2dd309cbdba320299e12ab41dfa359bcf1cdbb4f6060527f03fe4c023ad93ba440a72195a294a6fb506997e23e40c3caedcdff14ba0860386080526020600060a060006001610100611ac6f2604e55600051604f55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x7f296d88c89256e71631f0d1524276ff9d231ab3be039daf0ea05a4356743dd4ce6000527f0b1e8bb4741355b5b69ef8b1da4df3a3c725a14e058d99ea50bcf0e10ebda84f6020527f039bbbba49263eb8698845477f0ccb82d126e1ae3f62d12ea6facbb93b91c5726040527ee36156f58424254b022769a1970fd4e554fc49545fa15b7470f6b45e70db1d6060526040600060806000605c60067fe9659779482f376fc6349ac9b9caf0bd66415accf29f680c0441b10e2180b935f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f0131c9766fb600722dc74563bd8ba29a43be4c5a49060e5daaebf7699b4aac476000527f3dcee1a37ddc037617ff8ea6061586a9d600e3ae87fe6b6d42298e3edda1c74d6020527f67e97fc31e12647905e772d643a356899814c796bc17dbbbaff2346b0b9b334c6040527f885d73b14042129e020ba96e83afea37742e1189efa8222db0271a16b639b5996060527f80d83e6166169d6575d6887b1a9d8578930aa2e4b5198bf1aa7a2d8981e075a36080527fff922a7c650f764f9114f76aa4879bb40c846a782e3511b782942c6a13170efe60a0526040600060c06000604a600a7f39f3690c995440fa1457ede1998ed7b63fd2bc2ab9fcd69aeb9b82d940143d45f2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x7fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f05481a72441b413311d9e023471501901968ff54670bac9177e34b92768d60236040527f506d26538692fcacdf676c86516565c93c421f674012822428e7b92e1d7608d56060526020600060806000600160016164b5f16000556000516001557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f1948af26618c1372d65b161c9ce762997b9ebf6739db422b974f29d299b9a3c86040527f5247bfcc87a7ebeb877fc32269be5d0c049d7b91dcc7f89f8ef30bc8010c366260605260206000608060006000600161e8b3f16002556000516003557f79cdac2dc9e317f476c790aebb192b2958148dc5f37d7bc9f96e69a58378243e6000527fd16ad000a3ba445815dd1bb1cefbf56c0ccb0eb66645faddff179670549b621b60205260006040527f745814686ba9a68fe557eb7604922746db8d8ec7577b71208c5470e7146ef3396060526020600060806000600161f980fa6004556000516005557f47fc344cfa7c6a8aac5db665145c55f2a0d14b2fb0e4aa79b6f5557781f504116000527fb0524ed83e0c191094263d88dbb6179a006fa408eead78668a895f953e424d1c6020527fb24e73007edb60ee591c13a4287edc95ae58ad0d0f1622cea7e99e2771ccc4986040527fffff06bf638525444daf275c7c1681da80cae3176d6a9576752929f49a4b26ea606052602060006080600060006001620130d4f26006556000516007557fec5df8eb6e576fcbc7d4d8247f95f349431beb2fab76e18e79c23d6e267c8fe36000527f43ce1e70b5fb2b68d12e2619861f204fe4c6c294e64fe0a01823e6b8eafc06316020527feb97b042568e35acb0174dc8b90faf9e286ebd5d3a6ac97113dad1d21bc254a16040527f500b416077bc121d7373eabf41ed2d1dfec2dfebfa3cb6543b52765cf164994b606052602060006080600060006001616ea6f26008556000516009557fd2af5d12a95280894d384ec024ff17dced446e7a51d9b64ad34ac76f811e17086000527f53d14f9e1df39e0bcab0dc8485ea2fc899205859e9298af772f8a6667ce0a51b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fb21c9e4123e6bfd748b695714b221218a961617cf03f2095e6b2f1a36c47a7b960605260206000608060006001600161cf23f2600a55600051600b556000600052601b602052600160405260016060526020600060806000600161ccf0fa600c55600051600d5560006000526000602052600060405260006060526020600060806000600161a413fa600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f4e6da5d59214b04b4a4fb5069920a5ddbb2635283449a2bc8f9eb069cb02df706040527f2500a4266329b135c80f8510e259e9ff3c1fd0404b97a0323ab1ed89b5b6ff846060526020600060806000600060016178a2f26010556000516011557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f8340a4510c346990bc1f00b0200459dbd2f314235adfba65a5a464737edfc7296040527f328cb0a5547ad2273b55921846b72ca8b2523a34cce1cc0c9086db5fc4ee6b2b60605260206000608060006000600161f086f16012556000516013557fbf1cab3d0133c7ff1421bfae14ff400136b060a437544994e461436ce817b9ce6000527fc5c8b84ef06d2d65f6b076b7ad3f13e69a571b276542f6dd377d8713cdb5b81c6020527f70f8a8bafe48a680de156ac5df8241caaea7a27fb453ae041ec593922b84191b6040527fffff0340eb7e0dfee5b1eb7ff3b2aadd6ff3e76e0ba5fe94301736ad0dd5e2cf6060526020600060806000600161162af46014556000516015557eb4d602e526f3e38e75e652f4794a75ca60a643972d06a7d3ea46f8930edfc06000527f3250cbefada8ffebf4875231d6b24a45233e7b258ea836346578bb30aaf153366020527fcde890d5c10086ef523115dd117fdd54bdff7d83842fa8cc5abe5d1aea3f71786040527f77cce59f97949c3337b8d05ce5e994eac3bf9bb0d7d608a1f6567b83f9693a5960605260206000608060006001600162018676f16016556000516017557f1abfd23db143fbf30c2a330c89c999d3ac92ed3b0f951f2d1fedf136039f4f156000527f7fe1c1baced0905ef34741728c5b5df9193fc357db7b7bb9c13d27b5e4435d1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fc02d8d05f4336334605ea09251078997838f9e8004d71041a2e8dcf2d10e402060605260206000608060006000600161364df16018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f0893e72dba7736bd67ab257bbe123fc06c51beb7d5aecb3631350329826596796040527f39392105de20bb1b0cb2ae0782ec9d6c780f699b978d4a91da2b4f93fe8c75f160605260206000608060006000600161e389f1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fb833dddbccefb4daff2ca2a4fcaf03352bca480798cb44e76725905d4cbf631a6040527f25b3809abaf1bb899b5acb5dbc84bdda737616ea1a923f487597f717bf370a6d6060526020600060806000600060016110fdf2601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f2efc8a47cd06df64fae4cb6b1d379210fc5a355e5f1eb1ba3d8797d44634995e6040527f20f1f25732c41f47db7af98fa4791d3fff9e49fb3da22f5c3c8f53601852db3960605260206000608060006000600161cf50f2601e55600051601f557fad8ad8904b42bee56ed2262bbe546f80c26c1c6c74b58637561934703107ba586000527f51ae5344d1b8b53533cb4cc722b20607ae0606e0cbcdba8146cc4bfe5800c91b60205260006040527ffc6356cb022ccb259b5a91c78478968c553a2d86e90867ef5cbaa6d57beb13f86060526020600060806000600161d7d1fa6020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fbb4a74ef35898ff872ed1bd09c5d2a25414f2678b0c841f923f012f07e6f56936040527f60c14815f38abdff046136207b551435e62faf2066ac61a7074c11669b2991dc6060526020600060806000600161dd9dfa6022556000516023557fb651d6d571f7000ec99082187b9206672cbbeeab1b7587d77c1a53be74b603de6000527f38dec10dce0dc826e580b03a7c53b12ae62131ad4ffb44d6375f4c5a6327dee16020527f97dc665ed5a9725aa3e90ca16b7979b1751ca070534574ed035713d6e1da48406040527fdf5ef8d5bff2b3738b1e617d8e9862ff6c57cb95379243f58c079db83557d648606052602060006080600060006001619a09f26024556000516025557ff15606ec5436a07d10e7992d466e0c33dab03fe98276dcf3c57489c227e184396000527fd100c67b168a79443d9777124f556c8664bb0e525c64a2cb8a01f958295f871b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fa36dbfffbf8eb96234bc9a22c8ae309618f769f422769267f086cd7dbb5779cb6060526020600060806000600161895bf46026556000516027556000600052601b602052600160405260016060526020600060806000600161e276fa60285560005160295560006000526000602052600060405260006060526020600060806000600161268df4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f5fd135840c6524ee72ed6252a676bb5e0a0f7b8ba4819a449f2763cf257c7fb96040527f2c0c965e6c195010dd71ea433ee350d39257b120b9e6753be7bf6acb8a95a32160605260206000608060006001600161da5df2602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f808254cd9c8636fa7c6ebb01e4c53dac6216238b5e6adfc44a764930acfc3c036040527f1c7c06b1317ca8ea1aab730112c0caa17eed03ddb3154044924b2af728696b416060526020600060806000600161c598f4602e55600051602f557efebc31529d174d3f62ddd8f7d3f28b512398b67e78161c745910eedc58fd136000527f9d8ccdfadce68c55781a69a6de9b9c7365b7af5bd23e9d7bf4221b3a95b6391c6020527fbba630c1b560bc6696a101e85f80c2dc00748170fefd572e4e5eb719b186eb5b6040527fffffbb1be56746c953840183bbb009d6a2dd218758eedb043b7e06922d10e9b660605260206000608060006001600162018420f1603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x7f80000000000000000000000000000000000000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb6b01000000000000000000000009760100000000ffffffffffffffff0000000000002e0000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff070763800000016fdac7fff9ffd9e13226262626262626001d760fffc000000000000767676240000000000002b05760477ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9008900a90046051557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5677fffffffffffffff90026c01000000000000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1a1b1968066aa0a5319bcf5cb46f8000000000000000000000000000000118017f7effffff8000000000000000000000000000000000000000d90000000000000177800000000000000080000000000000008000000000000000901c6052557e40000000fd000000db0000000000000000000040000000fd000000db000001760100000000ffffffffffffffff0000000000002e0000000b6c100000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0915171a76fffff716b61616160b0b0b2b0b230b000008010d0a2b0068478392145435897052901b6053557f77676767676760000000000000001002e000000000000040000000e000000000681000000000000000006780000000000000009008605455157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb01611684783921454358970527ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a90086055556f800000000000000100000000000000006f121212121212121212121212121212121b774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a6f80000000000000010000000000000000691000000000000000000090086056557ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff800000000000000000000000000200004400000000000000000000017f40000000fd000000db00000000000000000000000000000000000000000000019009190b6057556f80000000000000010000000000000000682323232323232323230190126b0100000000000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900803762900760076761e000200767600000000767676760000006f800000000000000100000000000000001a60585568010000000000000000681000000000000000001c056059557e1f0000000000000000000000000000002000000001000000000000000000007a010900000000000000000000000000000000000000000000000000900b680100000000000000007cc9700000000000000000023f00c00014ff00000000000000002230080590021468100000000000000000777effffff800000007effffff800000008000ff0000010000901d027f8000000000000000000000000000000000000000000000000000000000000002778200000000000000fe000004000000ffff000000fffff7001a605a55197f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56005121a7f80000000000000000000000000000000000000000000000000000000000000027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe900103605b556101116f8000000000000000000000000000000117605c5560006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000005d": "0x0000000000000000000000000000000000000000000000000000000000000008",
+ "0x000000000000000000000000000000000000000000000000000000000000005e": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0x000000000000000000000000000000000000000000000000000000000000005f": "0x000000000000000000000000000000000000000000000000000000000000000b",
+ "0x0000000000000000000000000000000000000000000000000000000000000060": "0x0000000000000000000000000000000000000000000000000000000000000000"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556002496001554a6002556001600355",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x60a860005261037a60205260a86040527ff0b88e202b842bc58b3e815c216d48d84ffe677a97b4b392d471b92b504d42626060527f2e3e9fc17fbb4395780ccb489363f6a76b01c5626f1a0ff7dae0bea0c88160716080527f472bbafef0b8b8a2654644dd363c21b889170b91d27182d2960184d1407317f560a0527f3f66bfa4fa0df97f228c32bc0a7d4ccd9e24dc3e58bb9500450c1d253df7dfe260c0527f5d85b4513acf5957ccaec4fa3b1ca5c79c56233d41178661f2565bb4f3dfecdb60e0527f628017dd1a398d5e6081d6509bc1535415988569f6b54701c5c2e52eded4dddc610100527fca083ca4ecc78090c36a5b030c061d6fd0720c1fe5aaf9e4f7203a09abfba64f610120527fc85664ff0e0ba2b7c7203012ca0b87d26162f8d12a068d16e6de9e7472c8e0c8610140527f818be57ac614b53ac018f3b1abec6beb23aaa243703b29945db6700960d3a57d610160527f6b97cc84054092f03e46b9ce8d59529fbc61433da0c57f02a9015dd145c11239610180527f7cd50d6659f3066fe9ce05dca12dec6f44c6268c0287ef999d2f64203a7e58e76101a0527fefbb4dc4e91263c47883ce938701d055d5142f5a374d7e5abbc4f89f802c36076101c0527f0ade979482d5dd71e56717c4bb687a4bbb441903958aa9497272683c45410cd16101e0527fb8e23e6eca344102dddb6feaecdf8fb7cc61e61a98752af02b7c780cbb126cde610200527f3cf9e0f86b3126b8bf99585ca41c87a6ceb413430620b1dd907eacf1e3c81625610220527f547b197bf80a32546989e6d27686ba6c0db3333878ba2536dd2e39e15491c928610240527fb199565628b92a4296d600c8f7cede07a185f0834751d314ee0fd99285c49532610260527f20e48ccaa106397744ffc78009aceec6b8afd8e580c85b63d349e9d50398fdf9610280527f1a4c8a878e928742b5f12e185a32b9ac3ce6206ab006c6d51357643efc94b7ec6102a0527fcd3d5c364345276b855df411904b5aee514da2d7dc46550d56c42513dc6e08d36102c0527f796f00b0f45871e0c998ac55fd6d3dd3b6ff7591ffe3fecc2b72e119295dfd046102e0527fbb5f3e820145401cc6430008a54825714a6adcbd0e6d46cb5c5de250948f20b5610300527ff6f72b52677448c5f4997844b7826a265165d210bfa1da95598dd6b91c568036610320527ffa84b89fdcc08cb305c15491a494202df904bfc37b6f446b922df1c34f7d1062610340527f7a5be6a14a294e2229a304140fd9529db21972857cf9622787992e187a802ae7610360527fc8e8fe14c21926fcb10c0c839a8f4fb0293df25e8426b822587d139529692706610380527ff53f9f99ed50a968c9a3ac636d913c4c93d581a4ef3ec06fe4e30cb67d5a8fdb6103a0527f082185cdd7a608dd7f877f858586dc9e9427a5cbd1b46f38a0be135473fc8af96103c0527f545b0921bddd426e0dd05d73f14cd230fc805b0d8e1e13ac941749ca5bb6287a6103e0527f953a898d2cc35277bf0dd2baa7c5a43be4b86cce8e0d54fb1637d549c96b4eff610400527f5a17bf9dc9e9b62866dcc92aa7b74be64048d40fc82757e8bd7229a4c2a8026f610420527fee16eef5c6844ea4345fcbd8cb0fb8330e53e9e9e568b04253a0578b70cbb22b610440527f9378fb903c6f3b0de425669e7b20275b73241c415f3607018efdb79db118c75a610460527f3057e1a48556655448f0080f9394012dfedf80ea22f5c20600a9b088abb957b2610480527f952e5c01afc58257bfd0fd991075edc9a78ebc574d362372714543506ccaced76104a0527f21efc898ca581be8cf766c8cc047a3a4f1d3066a3d351fec5d0506beee85ab1f6104c0527f56f0ee109cc0a31cf55c52037d4764010284a22440a75752b22ddaecf9d7443e6104e0527fe0eed74f524258c6853312232de13c93a80fd6f5296dd4392f3e8b11579389466105005260b76105205360ab6105215360fd61052253602c61052353606a6105245360e36105255360e461052653605b6105275360b861052853601a6105295360a8600061052a6000600562fe08aff45a0160005560005160015560205160025560405160035560605160045560805160055560a051600655606160005261046560205260616040527f6d0d399beee8791c6a12d890598a300f54ffb91c84b86ac27e21c4ffb10d23436060527f61a0479c2a20f3aa130387323166dec8acfcc5be6cbd59a01690dc61a79ca5fc6080527f129b38d0b055ac4d468496a6400b7e78df076275ca6a0f9f5215b40d1994090760a0527fa0b42c23f247024472be573d76fbbd3b40a7291aaf2cf6236a94e137c263204360c0527fe5f21f3a6e26ed1ecffc39e3b4e250e001694de663a52bfd06b687e38ec3211c60e0527fc8e4569a7baada911cd0ebfb9e34982ddf119bba8b6e53b0f17172f03ac9f686610100527f3a0750db630493cb3c82cf86db5f5321072a2e60868c7bc4df77e990aacd864f610120527fe0541732d6c098cdfca0976eed34dedacc8768b4043de91670b46c2998c9ea1a610140527fab0908635f7a0a521b03f9bdd8e439c26493e073284f31a8c94931596d289495610160527f0d9d4f8228b6fb8786fd0ddc8fb9779754f0afbac231d34e0418c1ff15abda2c610180527f6aeb3c4deff9c782536072981a5f5a5f903f0e8d0919bb88988dfd8297548e316101a0527f471af342e540a99e087b966a29f07248bf746b5257a16c3ea3a6ae729199e03f6101c0527fb1ad70289609ee0de9757af4b42816ff1bb84cbfda4ec6812f14fda504936d906101e0527f0579d01de02618a658f31969293c363c88ea85d1eaa8f0173937c9ef74065ffa610200527f0b6db5e353bf88c1868df5518eb79ecb617638968c4bc7dc7aebeadfaba1af98610220527f5a1e2dc0080f4c72c3dfa0980914c7f166bbccd9611bacebc509945373d9eeeb610240527f3508e014ded76cf0547184270633449ff62c26448b77d06f76d293bcbcf0c5a2610260527fc33faa90573d5dd05b297c0e7a361d233f1787c0fc4a7efa54a8c2e21a7dbf9c610280527fee8b7c788b2c846438503d8e84336c0f61afad8843fbc52677753b5f9ccfcd1b6102a0527f566ff8c1a89def377278f892bb270509902298f7ff66090013f6aa0862666a3e6102c0527fd503bd8cda6a85fcd498e2a1f16c25b858d0ef09fe3f2e2701ee197ecca5388a6102e0527ff0c272de44e15d8be23e624e18776bf2d69a2fafd5451ae5195dccba6816ffa6610300527fb6548978b6aaf7bf9ae5f550acccfef9fd56060d29f571b16eff18633929c31f610320527f7ac51a0456b86ad28e2dc1754b3026c299b7483e0363c366409d0692b63ad89c610340527faf22c08ac2a3a0b837ad7d46b7a8410dbe0be22b87a50048ae477e2e5cd6da96610360527fde1096331201adc7cae8259ab737babfa2678f30d9c8a8ebb36a5bae9d0ae362610380527f96c2db37b400fc68d4bf4824ad0976b2ce6054a4f9cd54b0003988f4c0e5a7346103a0527fd0d1c7c23cc73ca0855106aee34299f8005bd20686eea573f58085f8881b5bd36103c0527f9e973851996421f3ab73032a59a965d2815ed45cdd437e2b2e6a109661b9c4ca6103e0527f1b90e608fb4e09ccb7a4cfa1bc2233aa5474dc16f1237ded95afb56713277dd4610400527f61029aa3589b65c7c6625b3e6cc158e9bc68367ed43ea5ea9c1a1c1cd5ad25c5610420527fb207f5644f04965dbf58c2f9da104dcb0fe657cbac9d3675cdde01c628e131c3610440527f47f1b5e3d4aaf4e45cabfa8e7426e73f49ffbc783702d717ab128812f85b0e0f610460527f2e9e786806d106d7b3548fa3880074c55f6f7b12dd5901f62487882b93ab9c70610480527f493c591847872925f5f6f1467567b46ae1b20fcc504e819aa9892824a061226c6104a0527f7ad3ba3a65506f470f57477e9da43014a6d8154367618e1c55ea7887b087c2f66104c0527f3287255cfbc00bc6da86e07aabd37fe1d03ed9b54eb3ff2d8dd73048a913b0a36104e0527fd7c9ac374404002a4d5d41fba312a8ff0d8fb258b819b9ff9e4bfefce482e068610500527fd33944395dc8cb85e9fa82211d0087cf9996de1669f3121c2342c7058e554261610520527f9529bcd34e669b11a75a78fb3d5a1451ff26542208e72d7828ca7e21ad3637be610540527f2b9cef530ca7dcaa5a469eb3c7d6ede8e79588a03d498c11ae37b71d164ef3e56105605260b76105805360916105815360436105825360f761058353609a61058453603761058553603b61058653606160006105876000600060056278cab8f25a01600755600051600855602051600955604051600a55606051600b5560626000526020602052606c6040527f6ea6afa40b5f1b4cb48214b6e6e56a074998a201aa82cdc81c35ad2910e854bb6060527f86fa21730be4ecf2263dbadc0d79eb07e2f4e198ae4aa6201b0a09b17926cabe6080527fbce1ed98b86b6bc3e0a97b3b1fcb42588f27206ca558b452731218d72a0c86a760a0527f740100000000000000000000000000000000000000000000000000000000000060c0527fe3dc8cc642df7e9cf4934a539c46233788e41b60e1f2973cce7e9bde05035cb160e0527ffe1e90f891a5cf105592e9a10b833dc27f5919384201ec73b7ce2302e421d15e610100527f3b5d135d2bce73f8c15ba3166326ab20c33f2dbd2e473aa649e6c3ee9e62d22761012052603361014053606c6101415360556101425360346101435360366101445360726101455360d16101465360706101475360b76101485360d461014953608461014a5360a761014b53606e61014c53606a61014d53606c600061014e60006005611ec7fa5a01600c55600051600d55602051600e55604051600f55606051601055",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x20000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x0",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x",
+ "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x0"
+ },
+ {
+ "data": "0x",
+ "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0xcc12"
+ },
+ {
+ "data": "0xe4004233f44dbea05485b3167d58bbc59a9a573470d1a4c7450ce35894a0eb4ba4a064b4c6cb7d6146a1bc57c774763287c2237c897a1f0ceab9e2fab9",
+ "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0x0"
+ },
+ {
+ "data": "0xccd57cc53461a4b792f7818d9c44db35ca7fd3edb10166e251d4b47bec0dde2c",
+ "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0x2966eb"
+ },
+ {
+ "data": "0xc299908efb3fdb12835d4bff2d03ca4bcbac3e714a83",
+ "from": "0x2837fE6BCdADEa40e14E73df3101847267659772",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0x90"
+ },
+ {
+ "data": "0xbefba71d7b677d6ba980c878f996e35911521fa11e5f0d025547ba7ef825d03dff687fd67e8fe13d4f8b1d115679b79b7bbaab18c4868ddec15c5b7c73578ca4d29b",
+ "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0xdafb"
+ },
+ {
+ "data": "0x9b547c7fc5eb3aa918193db18544aa183ec027ec89abc23a36dcbc401c10882abb1a226c81be965e293e938c4239998475",
+ "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0x1519"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x01abafda8405600f28850c93d20702b19b16786a43e7df7be3ca5769524f5d6c",
+ "0x010d7a9df5c5c8a68be7cc36e1628e87af4bdb9e79bc12efe485461bc7b9baf0",
+ "0x0134705ed50ee98f42b7c4be013bd5c99a190d95f488f6c71e4056f1db2dc9ad",
+ "0x014f220702bf4565e1674e56b6176d45a43f946512c80c0f8a5674be0a884047",
+ "0x012c8fc983035a94a2908a0a67e0cfe1d9ad034da6393984ea89f73c85bb3a04",
+ "0x01be52509c6f3022057f374ceb77216c6484bad1aa601a35f3f31948cbcc1fbd"
+ ],
+ "data": "0x6f",
+ "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 1,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0xbdf020dc94ecf8f9a12512749beacb34358916f7bafd7d82ff8e836bd3ae5c17fadcf0992e",
+ "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0x28"
+ },
+ {
+ "data": "0x",
+ "from": "0x2837fE6BCdADEa40e14E73df3101847267659772",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0xcf"
+ },
+ {
+ "data": "0x73c35e6653df1732e0ecd546054542f4299cdae4527f4f0c5399288d0e18644143fc6b378981c0ae2e62a9d9a57a8ca0fad3feb8e1cef68b0ffeb86504376cd0656c481753042411dfd2c4e5f2cd8526724ba4",
+ "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x3a"
+ },
+ {
+ "data": "0xa86e7b43393bb964f0fca6abebff173b079ac1db5f651547b7a31e09267f0e5ea231dd424360a641d7315d1e31665e14895b475f5d43e10baa63e63a1dd67d66853f8777e7f41eccb134162096495d652eff05cbaab7ad7bb0",
+ "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0xae53b5"
+ },
+ {
+ "data": "0xc102d4b975649d4af883da0f6dc25ffea3bb27906faef989181963d5a9aac717dfddfd84320087cc8b22c8f63d04e7034c856251101093eab6677a15b5b11abb439b",
+ "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0xe3ac41"
+ },
+ {
+ "data": "0x3a70fdbd",
+ "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x2e"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000003",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xb5619cbffc861bbfdaa3e64f9b355f8fdabb9d799849d2dabb2f25876c145292",
+ "s": "0x66361779b642b5632ef692bc04337f9bca791762c47ae2baeef6773fb592c46",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000005",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x138340166a399b49c1f7edde6c633a453e0ba59e46c413194fb91008e79799bd",
+ "s": "0x39ce8b301d482b43275473f83a2fcbcbfc4c99cfdd53e96cd5b3323cfa0f6ce9",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000005",
+ "chainId": "0xdee1f5da8e288cc6d27740ced28df1110000000000000000e2d5020464d553c5",
+ "nonce": "0x0",
+ "r": "0xcf969060aaa8dd8e52c23a2226e67dc4f5f97d38798bbbc038f173dea5a9c7f8",
+ "s": "0x6ee5755aa86f2f8117d761d592bd100610f120ca66c0bacae2bc973ec88adf0a",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000010",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x9a71a0c0c44a05d8a2471cb0262241ee69c28d156d6f34ba485db33f00a42f8c",
+ "s": "0x4945d99f7b2bc60ffd4e45936413244b2107ba059d6bb8ec9ce9f0962f8924a6",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000004",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x431784db736d7a7b32afa2a06f9b2dd9b7947510fcfe270ea15c2ae08af9c7fc",
+ "s": "0x780ae64313ba535e023075c4b6ba0b292377005a380b83e0483cb71d70cdf9d1",
+ "v": "0x1"
+ },
+ {
+ "address": "0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0x58ad4fc6a48d58600a99e258dadf774ccf993a35dca2c92822d103e988d77aae",
+ "s": "0x69054ccea2f3364fe4ded44910d741d4ed75cde286fd5c7fab299322fc9869f0",
+ "v": "0x1"
+ },
+ {
+ "address": "0x00000000000000000000000000000000000000f7",
+ "chainId": "0x0",
+ "nonce": "0x1",
+ "r": "0xea81c59ad4c4ab86d403d72e88317f89cc3f886d5b730baec3ad01ae5f29b54f",
+ "s": "0x4bae176e31ff39b38a35bd67cab30312129402ce912094b173cb131933f6849e",
+ "v": "0x0"
+ }
+ ],
+ "data": "0xe964b68a16dfccb7300e2a3cfe8b30",
+ "from": "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x00000000000000000000000000000000000000F5",
+ "type": "0x4",
+ "value": "0x76"
+ },
+ {
+ "data": "0x00",
+ "from": "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000003",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0xb69e5f919d0b7c265606ddcc668583ef819323ff6b65b9f0485cbadb495e5bae",
+ "s": "0x7296df3d02e403899fbe72a1676027a5216c5bf1f0891d945a992eaaf8b9b614",
+ "v": "0x0"
+ }
+ ],
+ "data": "0xe964b68a16dfccb7300e2a3cfe8b30",
+ "from": "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0x00000000000000000000000000000000000000F5",
+ "type": "0x4",
+ "value": "0x76"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/packages/tests/src/cli/tests/vectors/fuzzer_test_4.json b/packages/tests/src/cli/tests/vectors/fuzzer_test_4.json
new file mode 100644
index 0000000000..420a52ebe3
--- /dev/null
+++ b/packages/tests/src/cli/tests/vectors/fuzzer_test_4.json
@@ -0,0 +1,427 @@
+{
+ "accounts": {
+ "0x0000000000000000000000000000000000000011": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": {
+ "balance": "0x989680",
+ "code": "0x6f02ff392a51880045bd81679eaa49a4616000527f56254cd73afb65c9cabbf00635edb003b0949a8d90b534a408dd40a52b34b53a6020526f154e9920deee06460b9f0155c2178bd96040527eaf16581576839c74614c7c797feb90a61c78e9ac32794649c5ddb41e71b0376060526f165ce2d026e3030555255bc02de9e0456080527f5cbba50b5838eef82ad2c62559770709e2eec3e33fc262b93031d1e1310571e460a0526f0f1b05c33731af7afba9d1ecc2633dca60c0527fa4bd69106c11f78a81e0ed331499740a2c373f32c0d4a4267294c6eef012768560e0526080600061010060006012600b7fca8a3de5474d7684781187c350d780ba82382a44e9fb4fbf62ff85135be18d01f16000556000516001556020516002556040516003556060516004556f15b4a62d16dc800c53d56be3fe06e5316000527ffc90983d1670ea4e0a1c6734c84842961f48ba265b9d1f297db1f6e8f02dbaf06020526f08b2357993c3e46c6df5b4b2a46ac5a86040527f70ed033e5811dbc949080863278cd9ad5a82cd548c03631e9ec7399a196eb72f6060527f6770676283a7b8efb208baaa6360e7408e14ea5b7bc2f32cb27e1a7c6778b5a46080526f064e8898ba5c5a5bab9094b07da7f20960a0527f1d1afd7e9359a3f426001184ed645999406a94095f4393e1133e4ec2f6b5679660c0526f0bc360809709f9fd2972058c40fab13c60e0527f9bd8951b6b7471dccbe0badc90f293e13a0f86fa61eeb656aa287156aed92b14610100527fa7861e47dc4e8f93552ff56950ea7503df311f304aeb00d1a11ce0d96349cb32610120526f100d8556b514febe4262aae2072804ff610140527f1f56cfa643f61c69f8c51986e8526dbf4193b0ba16ebea15e9778c5f1b4bec67610160526f1091ec443cba26cff31f1414be3fc9e4610180527f974fe0473b7aa7f82dcd9c2b16fc28604ba37c5df7834fb62b89dd833fc8a16f6101a0527fe7b8359329021c4595683ceab94e844edc3620b0a5ad0d2e1910ecb9ad4131346101c052608060006101e06000600c7fd2b9d1379879bffa5e6922a3da5bab4c1a1db97b7871f9954a7c0bd550e0964cfa6005556000516006556020516007556040516008556060516009556f11b16d7904cc71ed898cc1c837e83b676000527f7df1a142b4deaa7b27e13ca689d3aa5629ef7aa71f8a535b5f05f61382fff4166020526f0d1425bf71bcdd58e3b2f9914d8203246040527fe26477573206e5cd968229b997c0eb7af9c71cf2a99ea24e76cf6c19b78f9c376060526f032e55ce5592c38376c764bc8f50fab96080527f61b56efce5109366bd037ddcc414886fae97bbf829386ff2b354139814411e0060a0526f06beaaa166ca6f8314d26c9e5220b1ff60c0527f8c0c6d18cb69ab15622a53440dc2548cdcb7161010462636ecaf0a5b7b25fc3560e0526f0c39133f125c1317b348aaa704bfddd0610100527fc158523af83cc3a8c71ce7a6477b60e1218e739286dee601ba70ae924e4bebbb610120526f172f256ab753ee1a075825541bf23515610140527fccf3abc52005fbf9f40147337ed5fd1e8183fad8fae8de4e326b8a3d34479685610160526f1342b383357d50e943731ac03588e0c7610180527f941b16c9474f96dc1f3c4aa50a19bf5aa9e537ad16feec31fddd7595bb0cc88c6101a0526f0f62618f6bccb765aac5e98264e350426101c0527f8c697823eb1f8a342b70e07ed1261be43bdb9a0954ea3195d04885ebd8205d686101e05261010060006102006000600d7f13b55944bab9533cf4f2f8d302aa5ec0ee3e3be0eca70f1520ef656175d872fef4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f150f4d385f70db4c9e1b2977950b224f6000527f104d3d0064de56ce97739c57d661fe0663c04d4c8f8816a6016770b4c93b81816020526f015253a3b2d98f552647a63c85ded9686040527fc5144b738ad3405c03569364a92f376af88484d19f9fdf9ae6aaccf9180f126460605277080000000000000002bf1a30168165233e0e3bc3f108cdd36080527fe367f4d86aa54962114ebc46bc2eb9697cba0fc2a1aa62765904fea31e6ef4c660a0526f12eb730a67099dc608a80aa528055ab660c0527f7613de79580ff064e76deaa2db26900b01162044f9f17fd27916efbf36e5456c60e0527f7157e40f7328332c6e934963ef8716bb4bfb82203d7909c4d848619d33dc87d96101005261010060006101206000600e7f78dbccfa9a44f1f9e4d26170fbb1d4707811b1586c31bf00a64736db763bd820f460135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556e25e6908c41d058bae0017a22c624e56000527fca389a0bd0d682c2d9523b96e2265831a615b249655b882f7327d32d6fdcb4676020526f0749a3da8fa5121b3bade706cd9e74986040527f518e511fa24c4de40f7fa3a8f369b509709d827a2b08bbfe1bdbd78d7ada85126060526f05e128d52c8948aa1e315fa887ea40126080527f89fc5c7803f60a919634a0666f433b6763c075e2a084e43ffcf9602f0c2d622160a0526f0156a0880d3a086e087f0f33c704ef5e60c0527f6154dbc43cb1b72c1d0cf6e695a89e7ef190110fb2b3d72ab3d081a70a9a9c7160e0526f19c0137ba6b2d34a3a4ddd3cfb730005610100527f893413c417397764cb18e8f851ac7e9efe0f32fc5e008af9358a1de973ae70ca610120526f0bf891fd97111ff31ec86b7ebdf60e3c610140527feec4c2cef82e2d5a06fb56d48ae79d725ce304bfe329062db6ff2822b6345c75610160526f02d7185ac827392f6f5127315c7b9b60610180527f4d5d8710dac6bf4d8654423061f924c13d4689da8a8cb6bef7aa5f8f45094ad76101a0526f0db900a3ffe0a9be8ad5edc61ceebfac6101c0527faa7a11a5a505cefe702ab37b37c43d6b1fe5ca8b9ca2012fab0a152a1160de506101e0526f0c0997f6859be162aca94558bb3ce1d4610200527fc58e587162b3f3629996decc96cc0d918a0e395f20be8e2bb1a16597fafe3fa8610220526f04dee2da3a3c4a817130ac1f22b5a05e610240527f7106c5dd497df5d7db92507eb51753e09ff6b50bc798f6a8033ac094b6fd3b57610260526f19a6e21f439afad2d66027984e4644b1610280527fb6532e8789ad68199ea946b511bd18d07a8ad353d87eb3c9f66a6864f33d2e5e6102a0526f18224c9c69a95343548571e650ca96876102c0527f0d274959a9a9b4e4f1c0720df7c3d81d5e51e9b5aa67e73acbb15d4f226aa8726102e0526f09e4e495fe4d9ccf8dbf0c1395c7c0a1610300527f6cc855f92121ea0e801b429f738bc248f336b85d2f59c1effaa5921c60adb623610320526f0f702fb07c66ec3b44e3dd9cbcb1df9d610340527fbaf5e0cf6c415ee9a88ab176719b7e4084e0959372263c7db8c6628a9f3eb81d610360526f10dbea22d2d12eb07ab7af782790af68610380527f94f388250be3c9f7de80db50891202df1daffdfdea2903b846de9d1d169e2d4d6103a0526f04f13c07b6e8530d51bf79111f7e2dcc6103c0527f85bbaf3bb101d1e24e01d687a0967188def03b25e5a01c2e14b7d0191df125456103e0526f195ff16e04a35c0e19cd8621a7d7714f610400527f2eeb11becd22c4397d009144245d468f1c68c8ea68c6570ca3b9ad65f8c7e616610420526f18601dd1f89f6e8ffaa613d4ce374221610440527fb2fc0db4e405c63a3db6f9a63b3ac72306f3231603455fe0cc93f92121439df8610460526f19e867999b3fc03c51d71fe28c5bdd00610480527f185c4e8caf0665f2cb756351e4ce123168280765cd122e935466919ae78e7c946104a0526f0b4b6e440e9a6fe52f0f6f44c72641126104c0527f5e2d9ee84a1f4fcde2a8a1fbb5e131774369605abf5aee5a8d1700297727d73c6104e0526f024aa2b2f08f0a91260805272dc51051610500527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610520526f13e02b6052719f607dacd3a088274f65610540527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610560526f0ce5d527727d6e118cc9cdc6da2e351a610580527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016105a0526f0606c4a02ea734cc32acd2b02bc28b996105c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6105e052602060006106006000600f7f247aa40947a72170799d532697899c366999c2aa400acb85f59c4d0f57266768f4601c55600051601d556f13570d9fd2db4959dfec409d4638602b6000527fa3f04941f45ec554899c4d0f7f53d70e03f9693ce01d037edf011b17ca8493f16020526080600060406000600060107faa336809d445eb5793ca323cca0116b6f90884cd2de24e968c4f3030b348a955f1601e55600051601f556020516020556040516021556060516022556f0e27e5e11d58e678c11a040fd27bf27f6000527f06effaa3b77f09e1fa12a5d8d26b8638a0f01afed29e75150e2b492eae4db9be6020526f0439d0327c8d1b43a20fd7bd2404a90b6040527f47a0cbda67c8dafb13c10143dd6c9c0e4dd5a91f91d57a4947d5b6076927f74f606052610100600060806000604d60117f9ebcee41df8ac99bc589009f8a7e47e4299477856793e1dc9392bcc167dacf74f260235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": {
+ "balance": "0x0",
+ "code": "0x60ef6049609660136040602a60d38a0a3e1a640b08a05400315960423c0b435609f4f0107e701d17667e534a9f037c6757f3123d399535661dfd6c159149611532178e727e57fd72491260941a1347056c885d1c5d006a1145307e82739310116e3e018b769515f373137b37461d0b193e397b7343063416301a34116657f598755a9e6413025a7356181a81623b683a55357f1967458d140a7831445c5f5f7f0a409b3e76071702fe3d55408879751c55ff6ef01e3d54193c6b75485c3a1d678e4005175d047a5d54007a8bf13e549751590b7d672091323e7d303299697a4464f03b9a89377c9d0b716e0467143720101179516509537c0a510a59f44962586873067960036a5d3f85f29c721039556c7206137b7108955a5d94fd0702867b6d65fa79456219863611705a404533430a40597b3055ff0596835d5337619a007e7a513d7866f1653115447341f44a1c6a3bf2676272333a666c7f666f445303738d3c3a8960925474586b5b5607025772568c6b1d095d368737066264663e334a7495068d097974879c6f30101699744217925d53924147625574a04049411804806e7c5c7d40505e3d7659141094736c523f7d3d02fd466134626830004a791e643b163e807a75798e817366945c5360663e5c01727b881d8e191cfd047f043e81936e5ff54a8e3f97657cfe3c49038c171e6f8b55094104202000699d497a527d1c127b7311587014f24687717d0966503f5d016f371d4000083900a36b50601c941e521a6c5fa37c54a23450063b42961e73844407327a6a06341c1d671b62111c061b694540643340a23b798961f10b627135653e123e373d3f576251675717186b71009d148e56581e1d0943097d005c408c0430951365011b8600649e7a7c673f8b718c49194047073530315a115019fa329bf0a16834fd62908536f535193579047b3a9f32184174a3ff9e03850670680810158e10470a333298674a716a769d204919065367207b53fa6843555906677f159e81797a9a9f1e417b721931a0629d1c7b3e50101690715e007f8a187716107a803d864983585b6931080246547b585b8efe599246610811573e487833507a57a28c5b676b6a353b619c7e65523514744095774060f01d06f258481eff6e940516550811633936144a377d6b11786f94817a360b093310856b98f29f18666c9e901d08a08aa07c5c5b1757425e9a12433e6548495c785d661a90710b3f619f7839047c6c1b3317806a94610862688d1007865648123241919f206e7a060773735234a4755a11149a03199d570a65a2883d6c71f27b1998957d5e75425b8f457906460b66395f395e7e0942ff436a180a20857f491537866e5b80395a6b4689803507590661651c50331a8a7e0550905d8161890637848f9c96726d061c7544ff8c593d486431980b5d19",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000c",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000006",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000007",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000005"
+ }
+ },
+ "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": {
+ "balance": "0x0",
+ "code": "0x60f9ff08e55301a405600aff7f838f432b398d67edd79d315dc36a90f8b6cec82cc931e9902c1977c41d815a1f6000527f13fe905749a9fa23e5e6d19d6bc2b116647971e33108b06569f3c5102c60c73f6020527ffbebb93b018b3214b7fb132b27e4a482ef0bc3108d1e7476fa9ae8145a0d52a36040527fff9e5a128ba578caf9dfbb892ca6ff783f8dd7c48389a16d315843dd7dfc0aec6060527f615846a2a8d4ff72d120c18d25778080fafb47fd942cb8db3deb30f9225c81f06080527f16b22134b6bbea2a3fd6fc5ea7ca4ee2626ce45e18265fa072a6b0afd3209a1f60a0527fe83451f442f5180389a5f9dfc9aa2255be1c74faf6f88d95c533cf1457d2362a60c0527f53337028167932cf8acca7e83f755d4d30e80aa033d0bb8511efe8b19cf49fba60e0527fe1535d12c7bb0a7718f875d946d90792b1aa54e135e91d644933763ca1148aec610100527ff79ad2a22352e9ca9a0c445ab02dd151fb08b251275b4171b0fe073dfdce154f610120527fecfd9d2f7e17b9b598ea4fdc1a1a136bc133371fceca1c2375b10c728b75b1a4610140527ff2c027a65ba4bce87721c1e22be423e68594d156ac2ed671ee49a1a6d1810d22610160527ffdf921a8aeba249b30de81ff9b7044ae3be7067e9c15100c3825745121a0373961018052604060006101a0600060037f39a0f0e5a3034ddab629963f71f3a2c805d5de5e485f50470c4788b609891297fa600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000010",
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000003",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000007"
+ }
+ },
+ "0x4133B3E532cC750d0a4691c8Bb0B03fba51707FC": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xdcaa7645870b9ff21dc74c437d77781b7366c4f352caa0c0f1e7acec0c780181",
+ "storage": {}
+ },
+ "0x538A8474EeaB43d5a960164c554A20400151D479": {
+ "balance": "0x989680",
+ "code": "0x7f5cff5e24ab538a91033a6503871ae05abcafe0d859c02f011b73a34fc3c9268d6000527f05c734d437bfc67f9c0201fc5ad0440d2160361d66a5b9e740fac13f2e8053966020527fe5261c43f657361f90396c96da8dfddf51d4e1006fcf030c38272acd6e9cd5226040527f9f354515f0fe58d09aad2b4e7533ed7ba3fedc12996bf860f5f4ba6bb743c2a96060527fd042e4df018e59bc0f575f146560fc50879d525e5bc1b7816fa66a650a6be0fe6080526020600060a0600060566101007f70ded0da3434e4d08343f854a5d5ff9af5b6f2a0a45d505487bd115d5a95dfd2f2600055600051600155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x641602bAD4A323C49629d45338d79A2bb984A3fb": {
+ "balance": "0x989680",
+ "code": "0x602060006103803e60056003607439602a60246103a0376080600661028039602760276103a03760006102802060c760006103203e6001610380fd",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x6EB54E66856fD47bd539A986B19F0Bc9B7B4dA9F": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x38b446fe4e737b60383040233f4e9d2a40598cc6da8bcd879c52501b7bd413c9",
+ "storage": {}
+ },
+ "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": {
+ "balance": "0x0",
+ "code": "0x7f60065c507f60045c507f3f4a6783e043cade83e3efd7c036b5517630586e70666000527ff745609afc6000527f26ac0c300b6000527f1ae979211aef9d5b178c50b254496020527fc94746f9c9f4bc902c6020527f748b1677bd0ef214ce6020527f0547200a26736040527f78956e009667fa7cdcbafee1fe6040527fff58301e64554c7d0f22aff66460406060527f527fc0e58badd643e78e6951c18212baac6060527f8b47d9ec7813b1b2c134086080527f698364dbe21e6060527fabd6c4319461b934544dc06080527fbe25ee574dee9260a0527f8da0cb487ef89497954aa30e26a86080526040600060a0600060a0527f60446060c0527ff67f02548193b632f42d7037186903e461b65d592b996f244819ec079f60c05260e0527f606560e053605160e153606260e25360fb60e353606760e45360f160e5536060610100527f60e653600060e753605560e853606060e953600060ea53605160eb53606060ec610120527f53600160ed53605560ee53606060ef53602060f053605160f153606060f253606101405260026101605360606101615360f36101625360536101635360606101645360556101655360606101665360f46101675360536101685360606101695360f561016a53606061016b53600061016c5360f361016d537f4176702b63bcdc4cb9c73abfc785e626a5d48ed79834c65870dc6b076df773ae610180527fe514ce5369e1515e7c76205f39dc50325f5524af55385127fb99708a160791a06101a0527f540f9745ee262948be29f7c4ff39b29f069012ca8d661cfe500180d47866523d6101c0527f3d871f52edc9e5ee936538aba6b1a574f8c6df1bfe2a4bcf7793bc0bb008b1336101e0527f848fb85541568fc4035f73bf00ab79eb687773ea0878b4b25e4f443b23673b22610200527ffb6a3205053e9cfe09d60513da475141b7102e6c775fc1afd88244e30f98216f610220527fa3a57f172d51608c8a4082a4eb4089f513d89a7916a000af45ecebd20b6b4590610240527f261600b57bee20a830b2b5dff7a02f640cb410fefe2aee2cdfd7cff007f6da3b610260527fe537919b87b961f6f0e06e0b95989a4c4c7976613994af296b67c727e9417099610280527f5cdc062258c2642c1153b1f4ec9d3ec1cf7966d3fb1874d8274863c4c0c4320a6102a0527fa1fc3931caa764bebd3c7d05743c9887f9a7371bb9ad17d5a3c117cf769b54806102c0527f282edeb064f32937da73d7ce692146aed14888fa10e4ff12a005651a41c4b07b6102e0527f91e02452a5a0f1672757344255aec5842f69a3635046e560bc1b54d606c42af8610300527f6bab911858f883ce4f4d0838210ebfd5ae7ffd75d46a9637908e78e4d1943ff4610320527f5a0ef79ffff9ff5f8bef33a8b8eda6a9189ac5eab77d636deeb93c8474a458e0610340527f5fc5680e125bfee5991675741d0e5604667a26970dd8f0ce4753a7209a0b67996103605261016e60006000f060406000610200610180845af4600355600051600455602051600555600655",
+ "nonce": "0x0",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000e",
+ "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000001"
+ }
+ },
+ "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": {
+ "balance": "0x989680",
+ "code": "0x7c30094d9e93c6538447c7f71879ebc33171319acae4d27701c7b3fed94c6000527f28c7989c23b52e07b22635abfda126cf1a14981ede6fef9a9ef409d36ad639bf6020527f1f4dab7bac2a1d1205e2d552299144f2724e1e071a3c937dd0651aee95d859d36040527ff57bf8b81daa6cbae4959a13988b1e8fcc9bdb8be682a8a6f7fe0707d1ddeda46060527f0fc1f5ad1138e3d799bbae17dd28fcca35a3ec19c8bcd49b4b3338610d9429656080527f693bb5ee5c4320832b5134056658e570f5341a8cf1b5d6051c15367ff473fdc360a052604360c053606060c153604f60c25360d260c35360f760c45360ba60c553606f60c65360ca60c753606460c853608060c95360c160ca5360df60cb5360d260cc53608160cd53603a60ce5360cd60cf53602860d05360a360d153604260d25360bd60d353600160d4536040600060d5600060d560097f63823a27ea3a21fe353b0124ab9c852fd4ba8cb0c2dff0e45e1a17c15378f7bcf1600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x78011f4E10a54C02296EfeB11034d561320e8949": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x8260476d5e5d66360702af75fbb09e6db415c6663c7ca092e358bfea4448f770",
+ "storage": {}
+ },
+ "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xd8681c573cfe16cd18cac8fb006983725de8f2b9bf2044cf8d122b7c6aa02822",
+ "storage": {}
+ },
+ "0x94b690A97d429F297d32b8fED10213e759861599": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xad696fc9e254151c47bf314c3d113e3d6f61dbae1a524f30bc67772429681ff1",
+ "storage": {}
+ },
+ "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": {
+ "balance": "0x989680",
+ "code": "0x760100000000ffffffffffffffff0000000000002e0000007e40000000fd000000db0000000000000000000040000000fd000000db0000d3901a7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200006fdac7fff9ffd9e13226262626262626009005900b6c10000000000000000000000000762900760076761e00020076760000000076767676000000901a13778200000000000000fe000004000000ffff000000fffff70060071a05671fffffffffffffff7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a117ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7e40000000fd000000db0000000000000000000040000000fd000000db0000d368066aa0a5319bcf5cb40906901d6a01000000000000000000007f8000000000000000000000000000000000000000000000000000000000000001056000557f80000000000000000000000000000000000000000000000000000000000000017f7effffff80000000000000000000000000020000440000000000000000000001901c900b7f80000000000000000000000000000000000000000000000000000000000000026c01000000000000000000000000900290037d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9682323232323232323230305197780000000000000008000000000000000800000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0017901a6001557f40000000fd000000db00000000000000000000000000000000000000000000017806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9012777effffff8000000000000000000000000000000000008001717676767676760000000000760000007600007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a0990066002557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1a678000000000000000762900760076761e00020076760000000076767676000000011b6a1000000000000000000000637fffffff1d90176003557cc9700000000000000000023f00c00014ff00000000000000002230080567ffffffffffffffff90147f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6801000000000000000010126fdac7fff9ffd9e1322626262626262600778200000000000000fe000004000000ffff000000fffff7009018166004557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd900b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe101a7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff901b037f80000000000000018000000000000000800000000000000080000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff90116005557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6f80000000000000000000000000000000901290177f7effffff8000000000000000000000000000000000000000d90000000000000168210000000000000022774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a08196006557f80000000000000000000000000000000000000000000000000000000000000006f800000000000000100000000000000009007900760075568066aa0a5319bcf5cb467800000000000000190177f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f800000000000000000000000000000000000000000000000000000000000000190050b7fffffffffffffffff7effffff800000007effffff800000008000ff000001000067700000000000000017901c7702ffffffffffffffffffffffffffffffffff0000000300007f82000000000000000000000000000000000000000000000000000000000000000b600855686d5adef08547abf7eb6c100000000000000000000000007f7effffff8000000000000000000000000000000000000000d90000000000000190091d7702ffffffffffffffffffffffffffffffffff200000000000677fffffffffffffff070b686d5adef08547abf7eb7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd900b600955762900760076761e00020076760000000076767676000000777effffff800000000000000000000000000000000000800190139006777effffff8000000000000000000000000000000000008001760fffc000000000000767676240000000000002b0576047181b7cc9700000000000000000023f00c00014ff0000000000000000223008057bc9700000000000000000023f00c00014ff002c0000000000002231089013057f77676767676760000000000000001002e000000000000040000000e0000000007702ffffffffffffffffffffffffffffffffff200000000000901090016a01000000000000000000006a01000000000000000000009005900a67d02126262626262661011103137ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f82000000000000000000000000000000000000000000000000000000000000000b600a556780000000000000016780000000000000016801000000000000000008901d197e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007e1f0000000000000000000000000000002000000001000000000000000000000204600b557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006fdac7fff9ffd9e132262626262626260090137ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000760100000000ffffffffffffffff0000000000002e0000009004176101117f80000000000000000000000000000000000000000000000000000000000000000a06677fffffffffffffff7f77676767676760000000000000001002e000000000000040000000e000000000900390137f80000000000000000000000000000000000000000000000000000000000000016b1000000000000000000000001c151c712000110000000d0a300e750a000000090a0a774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a9004027ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000190101b7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a6000900b0468478392145435897052637fffffff109016760fffc000000000000767676240000000000002b05760477feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1890027ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff637fffffff9010900b682323232323232323237f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd68478392145435897052900904600c557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd197d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd1d107f77676767676760000000000000001002e000000000000040000000e00000000063800000019016076823232323232323232376013590cab83b779e708b533b0eef3561483ddeefc841f5181b778000000000000000800000000000000080000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9018027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe67ffffffffffffffff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee900890166fdac7fff9ffd9e13226262626262626007f7effffff8000000000000000000000000000000000000000d90000000000000104901c600d557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006b10000000000000000000000090107e40000000fd000000db0000000000000000000040000000fd000000db0000d361011190071a6b01000000000000000000000063800000011b600e556b0100000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000010b1d7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb901b901c7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7a0109000000000000000000000000000000000000000000000000007702ffffffffffffffffffffffffffffffffff200000000000081a7f7effffff8000000000000000000000000000000000000000d90000000000000160071b9012600f556101117f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001900b6010557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a677fffffffffffffff1d601155778200000000000000fe000004000000ffff000000fffff7007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf90560125569100000000000000000007f7effffff8000000000000000000000000000000000000000d9000000000000019006600067700000000000000016900315601355678000000000000000677000000000000000187f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a567fffffffffffffffe90139005778000000000000000800000000000000080000000000000007176767676767676767600000076767676767690181d760100000000ffffffffffffffff0000000000002e0000007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a57e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0009901819760100000000ffffffffffffffff0000000000002e000000638000000003057f80000000000000000000000000000000000000000000000000000000000000017f40000000fd000000db00000000000000000000000000000000000000000000011c1c76013590cab83b779e708b533b0eef3561483ddeefc841f5610111901113671fffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff137e1f000000000000000000000000000000200000000100000000000000000000777effffff80000000000000000000000000000000000080017e1f00000000000000000000000000000020000000010000000000000000000008050360016780000000000000007cc9700000000000000000023f00c00014ff00000000000000002230080509900563800000007702ffffffffffffffffffffffffffffffffff000000030000111c7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007d76767676767600000000007600000000000000560000000000000000000090176014556c100000000000000000000000006847839214543589705207900b67fffffffffffffffe77800000000000000080000000000000008000000000000000901c901a19712000110000000d0a300e750a000000090a0a7fffffffffffffffff7effffff800000007effffff800000008000ff0000010000171a778200000000000000fe000004000000ffff000000fffff7006a10000000000000000000009016901a7f40000000fd000000db00000000000000000000000000000000000000000000016a010000000000000000000090121a6770000000000000006910000000000000000000131469010000000000000000006380000001777effffff800000007effffff800000008000ff00000100009008900a67fffffffffffffffe760fffc000000000000767676240000000000002b0576047901890101960056f80000000000000010000000000000000901c90190667b368d219438b7f3f7a0109000000000000000000000000000000000000000000000000009010900a7d7676767676760000000000760000000000000056000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff90179007196015556a10000000000000000000006a010000000000000000000090067702ffffffffffffffffffffffffffffffffff20000000000068232323232323232323119016638000000067b368d219438b7f3f180268232323232323232323600790061c6801000000000000000067800000000000000090177f8000000000000001800000000000000080000000000000008000000000000000778000000000000000800000000000000080000000000000007a010900000000000000000000000000000000000000000000000000900990016016557f7effffff800000000000000000000000000200004400000000000000000000017a01090000000000000000000000000000000000000000000000000007116c1000000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b000a900160006000f3",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": {
+ "balance": "0x989680",
+ "code": "0x7f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff000000010000000000000000000000010000000000000000000000006020527fffffffff000000010000000000000000000000010000000000000000000000006040527fe9d59270783f28e43ddf8f1b6a232fe86e59f3d054ae7056d7dc642d51f14a406060527f9d34ef22e83586115f72b401b9910edf0a3d4eb5ab5842d6526bab09d77e14c06080526020600060a06000610100611c68fa6000556000516001557f7b94c577a72510ad55418281ad7a8629f5b63bf1147d5268283b11beafd9ebe26000527f7810b9459c76111c880ea84e8499a26242792c36ba27d395c41b9c95359bfdea6020527f59b4f9fa4df5b677ff6e52720980987d5fba33171483e8c5cf862cabc2c24d646040527fc47f208c959f2304a9fa862623380053810c0d0ff750736436ac6d0b3fee66996060527f7905e517823b66df754c53a4f041cc1779a861eca59dad07955b10b697346eab6080526020600060a06000610100611a68fa6002556000516003557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f19f6370259c54b5fe9d70769e1d13b5cd7de9174704c0b751ae8c05c2a24ab2b6060527f4ccf54ccc3a23c5051da573be9703d9a2aa6a80862da9de38493d2ef63d024a46080526020600060a060006000610100611b8ef16004556000516005557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611aeef46006556000516007557f27a75fd0382a000f4435415fb07c1ebc1443135f515ea0f1fa570cff63ebbd136000527fcb22c16ad640faaf88f97a84294e8e0bcdb706d94619e821ab82353b7c42fdca6020527f1f5d30fd6961f15a5a77fe525068e0fa278a2787045863e42a69dd24ac1550e46040527f0f306538f795f5bdad7d2beee3c7e75663965997393b690b437411d0d58ce9f26060527f065cbb1784b9a5c653bcc54a914fa50fe730b23528518fc9bd2aec4b27fa2f436080526020600060a060006000610100611cd3f16008556000516009557f36c057851467b4e8f1d9f625862e82538302e0fd975d1cb4e0d516b96ca8b6626000527f4889a3454be76415ccdcce4678704e94af7a3b11985f7a5ae34bd43fb8a4e12c6020527f657224d9b3bb1f69b7c751ec64b612f9f6d5e41737b172cb0e28557eda13a0996040527f3b1e2febeff11f1197266d1574cb00e7924937cddfe0e81a9a6ab5c06abb13536060527fd6e7449ca1278aabfb488a187b82f0a2cc8696575c88932f02ac052d7891a82a6080526020600060a060006001610100611badf1600a55600051600b557f61952ed2690b680aa593a089363d056da851c37e412c53b8d4a5c900876eae886000527f5364c572df38b3eb57d39a9adedddb179a6af9903ab70e6024a8413b13aeb2746020527fc1bc39d8e0c8c05f94a2bb6e9452586003a72b77e2958d07e005d29cb50cdbf96040527f7118c768a2994569c1f71c8e428ee1ed44f13fe0941b16b118765b562713c0196060527f2585a6698c187ea3ed93f12ee13ebd03987d8cba11438973a54406babe0d49326080526020600060a060006001610100611aa3f2600c55600051600d557f9a894ef20b37c1057182fbe7e5f59a3c42f177d9d152ed9dd344d15dec691d956000527f17b51769636e3661b9b0aed1d13c16a50a9f2dfbd79812686b89c6cbd4c8d0e36020527fe66b4011bdad92cf17219c9b80d87e927c7fcc9401922e85ad16260161ed20356040527ff29286409619dc0318eed274c26b87091ec9ccfb3fcbece8a9b326d534030e716060527f31b58bc996aa65a72a9deda0cb19b05a763c26bacd130fdb58c01574d2d6445d6080526020600060a060006001610100611babf1600e55600051600f557fa2f800b0138f1ceb4099b6db46869088b058b877995906229851f3a1ed4a6c566000527fb92bf3b0ddfe9442002c2906fcda67052525a68d54dfdcd18c5697079c4b621f6020527f7d8194ac1768fa99ce3ec308ee5b6b738fde4d07efc44f391e20b8e31233d43b6040527fa35bbb2e53209d4b742d108ce5c643e2520939e5c40f41eb4b5ca6987d1efd9f6060527f0aa9f8e9bbbeacd8362f094f3c4eac043400c457e9d342d8096098542f2c1dc26080526020600060a060006001610100611c89f16010556000516011557ffd5c529bd322eebcca73bba55ad93fcf1663423e06074af41f0ca99575cb32b16000527f458837808d6a6e287bd424bff26bb52a73246b8fb8a142ef523e607e3e84d9f56020527f362b527afb3224b47e0754b3b56dcc24c34874f1936a3db1852ce6c2a717e0786040527f75a34b8ae705ac9a5d79ebd92742c1b18c71e84e3541ba8dd078faff04ba50546060527fc1bdb57d01a87b6ddcdcadd5e40b36ed2d4bafb5a59867821ff95f42b3d7069f6080526020600060a06000610100611c91fa6012556000516013557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f68019add2e307b5807330d28d8577e078bcb965e9a852103a79d25185ee01a0a6060527fd9d79438bcd4e05d060c8b02c7ceba7abebe01846516257cb85e50c2c41d37746080526020600060a060006001610100611bcaf16014556000516015557f3e866a7b7a4024f8e07421be8291c5cc80bed4659564367fd2aa1e2d17a757156000527f5c1803812b8dceaf1d1aeb67107579a1586b07d8033d0772a644c89c9eecfc8960205260436040527f931c499350eb57b965618a1770ad601ee72b1d2f7534572e57bdc2a16e08d1266060527f22d032db5ab09081ca16ebddf3475c04c59a08252e57f318e87c122e64f439d36080526020600060a060006101006119bafa6016556000516017557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f1a52172d34aa8c12e27afd17916b4a3dd4e4767bae7d5f499df89c7d0b6bd0936060527f8da714fb1068cd61fda3cf511ecde05e8345471ac198dd02cef0dbe4526c132d6080526020600060a06000610100611b06fa6018556000516019557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b67fa601a55600051601b557f309481fc9139adcdc6f07820b3cf6426f6dcec887e1769ee0b31007ea4a28e616000527f82da988b9dae706975a53b1b941c835a17cbb087efcd65fef9888ef4002a6c3e6020527fbb0672091ddf44a9a90202fb492ecd36f7d2b00be1096d6b372de353f60825296040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527f1d4df86c05e1b0aa40f4b2bb71876cb83d620ed52c608a990bcea20ccb20a61f6080526020600060a06000610100611b47f4601c55600051601d557f60fe3ec609d65041e5ac55b70de7281992889ad1786a60708710789a275d184c6000527f6789ee5622bbe61476741d925215c89c6ec90fb1c030fe2b7fc9115c5de4c1676020527f81ed559065083889f9b510aca63d4cc839c788991a3285d66434a2a930253cb96040527f6d6625dab4ff1516dc694b2a75ca0ae67105db20b29ffb26be51727f188e0ecb6060527f831fbde00ea788aa911818c1ffe8770c231214487e24ee209f533fccbc5f8f0a6080526020600060a060006000610100611c63f2601e55600051601f557f2b4d344ca37e370e6bce4d4d1b1f362d461709d8d7c676af6e6baaedb7947f136000527f2a9fcf851669dfb57aa0da70d5ad9e172dfdf89100ce9c6a034600b81211f8e56020527f6f0c3598071c216d471205667642f6b6d92a6c67b3deed518623c24e14f29ea76040527f5492389cd1891859b4afda3b89f99f8728c4491e2c7d05ab64317008276d843e6060527f31311a9f1858beecc762365d6b5980f9aaa889f9b34759fad1e0ab0a38f4597b6080526020600060a060006001610100611a13f16020556000516021557f86f5d8b49ceba7aeaf63e9c713c820dd8ed3f6852dc6bda135eb1849be189b4e6000527f3681867bcb7d33e72ffcb95310886698ef860db22b38607ed8adf05b13b828416020527f360a8074d67de629bfa3f8b3446f858878e201c1dfa90903a4aea5eca61146c06040527f392f90a658a4cdf01da2dd1ed687654b201f922d0d02e50618376cab335427db6060527f94c0e5df352182e7a2644cb07c5e8fbfd4f3873470f134a0bb0ba8ad48a32a596080526020600060a06000610100611960f46022556000516023557f2187e0b39b0602365f1a0d76868183a38cb1fd0f2a4d730ce4f6045c2d4926756000527f16fcabc35bf48a06b56b00493dffd9509f6c383a908754774922e9bcc4a8f7a46020527fd9420df2f0b941a7d9c8fe403ff0260b7c0af26ea3eda679cdbb4349eabf8b6f6040527fe10adfc7e992b0511b40fcc442e48e8898ec157cf51935d8dce8a05bf352c63f6060527fd22d191a8791b292932694ddf0a872e5ade42ed3419e15c2019a3684d222d9dc6080526020600060a060006001610100611bbaf26024556000516025557f5b0f9dbb43cdd626807517c7312f503bbdac76dfa29cc22cdd222b22a11adaad6000527fa119ba6510ea446dd9eaaa0bfc98392e23c4ec578498f33681ab6165e634aade6020527f26c16c5fd456933738accd67d30266854cabc2c87913f739b00596f6df3b47326040527f9203ea28df657ce09a406539e155680e09ced0b0bc312920ac2cb4d9820338036060527f27476b844dd0dcd6257f8e279f5f4bd9f79af95ec1054e9e38be7e4fe95f580b6080526020600060a060006000610100611be3f26026556000516027557fd833cd561af31de9949b67669b99be4e9d1c65b71a0dc822bac620e8627909c46000527ff273e568887d5c7c232c3b5b80cbb4304e12edec490de12f8ad1be8aa058ba7c6020527f845589edc62021e0437125910ed1cea3800c60f231c82dd049e462b0e58c3f52604052600060605260006080526020600060a06000610100611ba2f4602855600051602955600060005260006020526000604052600060605260006080526020600060a06000610100611c4cf4602a55600051602b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a06000610100611a4bfa602c55600051602d557f18edc615251fb19db1799d1e0d9cc499707553d6f7e75fdef32e177a9c198ce76000527fc23b9c3d62f717841e0b1a251b772c1f286991f41bf6c2b6744c4d5db0c6c44f6020527f1642cc67c1202959cd38dca27c57aba75579fb113eb38759c4a5fcc46fb435ca6040527f445a1575344053415bed4619d4be1c958b6e61971073fc08d3830216443b02196060527ff5b127e67009d3373f5b7c9b4fcaf785eccb823da9d09f984b2d16a2fa3e05836080526020600060a06000610100611bd3f4602e55600051602f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb560005274800000000000000000000000000000000000000000602052748000000000000000000000000000000000000000006040527f9dcd2d2e205014181bcce7fa788a0ef7fa1dd6dcf1ae31bd0e6d4bee41a918cb6060527f126e9db6839b8c9f27aec5a6ac351952146ac9dc3f4b2b09f7849eb92bfe363c6080526020600060a06000600061010061199af1603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xB9A8D444BbCDFb9a6b19f59e0024184fbe10761c": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x8ffb0595345154a7a19e50c98c725ce7ae2231b522d58776a3f4472f3d622ca0",
+ "storage": {}
+ },
+ "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": {
+ "balance": "0x989680",
+ "code": "0x7f26cc064393e356f34a892dd1815dc54437b2b669f31eb4c62b4903c08aabedc86000527f25ea1cdb71917d07e3f0d2620379e0a5ba2c4061bd663b291e619e795631b07a6020527f1ba0e01f911e12cbdd641b6b387876d2c45db434f342280af8cb43c45b5afd8d6040526040600060606000608860077fc71d868d71d0d82d13bf3293e7fc8a8e17e400ed0bf8ff4ab65cebe1ad753cfbf2600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xD74CFe323387aE2fd070CD046173026716D8D649": {
+ "balance": "0x989680",
+ "code": "0x7f0120d0aeeaa75bcae6522020acde356d3b204cfda02419322a0b875bbe21490a6000527f1a200d4e4f07055a7de7507ea7be401aea666dae89de07142f8023e2b9ec5d966020527edc46c0113055cb6d18d48c6e1b46c188afb53373ed78cbd52ce8fa11f4e4a76040527fae9fb4d83a16077a020981dad4912dad522e8014117fa49408095016742564fd6060527ffd3879f9d9e46f2314c33e39b5cf41608395bc00161da71e3a3cbcf1c173165c6080527f437d18c6fbb60f851752e0bd2c44c8f59618faadcf06117915fbc0f0f620d60860a0526040600060c06000600a7f2c6d339c3f6418873266d0bdde127282b35741c9b47c522d30ce2ddb992b8dd6fa600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": {
+ "balance": "0x989680",
+ "code": "0x600060005260006020526000604052600060605260206000608060006000600161265ef16000556000516001557f8ffba10a0017ca5f8219909e128d511f31ba382b0d16f2df9c188d675ec691606000527f1d1f6dc7fd280f0613985080dd8712abfb86f6ab501331c2f76b1b75b41fd81d6020527f6ebbe1a2bf52d21e98477f1c849c68c5bc869cea5747e2b63272a8acdb0567866040527fd187e3992461b86080fe2d5de2844e395df602593ebb1821b20e0172daca8b7760605260206000608060006000600161d949f26002556000516003557f66b4f6e8a92f3f16280310feed70a2566d9af4d89434c564a3b6c581cfc62c7c6000527fafc59625004fd16e389059faef7927f7d6d1da75b445daa3d07c4baba821051b60205260006040527fbf941c82a54c09c167606a6efae9306aafbbe0ab3da162f92e97f389f62abc5060605260206000608060006001616c4cfa6004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f9d2ea85682769dce1d8d837360f17bed8c18f08157e7e3c75cd02d43e22d18156040527f641af4a62533813dc42df075c1d56e12c49a0b15e76d6673984a966904c8718160605260206000608060006001600161a349f26006556000516007557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2281e311cea2cfa2d47a95ecc920d2fd303025a731594cb63b341fab784f7f976040527f551dca8bd75d4b9a7a70c580fe2bd64c1645051a27764a1a0be26835a0a6c35760605260206000608060006000600162016959f26008556000516009557fd11c4a1918b16339575c493b5e703a275f0c72dfa9c48ecb2a5634f8c37929a16000527fe44db503c9eb138b141d8aa54cd48df9539d966001850963446a57b1f51bdb1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f13e1f66edabdc35841c531fb7387f640116df72c4e24f7d40050819e5ed7bedc60605260206000608060006000600162011544f1600a55600051600b556000600052601b60205260016040526001606052602060006080600060016001614b65f1600c55600051600d556000600052600060205260006040526000606052602060006080600060016201687ef4600e55600051600f557f9cae8ac6460c880a4245cc665db1bec3a711ede7de8cff6b374e70395b86dd256000527f27181ce37efb15fa507728635acef6bc88447cae85aade5709d5b66ed6705a1d6020527f8e2b295c578c6c3efa1980162d62733e54afd977da407669c1599acd1fe7d25a6040527f3a4e3ec1e15a60d4031f9067a24376f9e28c6857c9718c62a89886bde764466360605260206000608060006000600162010f56f16010556000516011557fefe4130c9e6b6fe6e37733bb46c25753aac68618489ce41ae0624e14d40363976000527ff874b185f1f225860aab85b3d4963966b9171cfaa46622db6e0782b59e8d1e1b60205260006040527fc9a2d0e35763f3dbd99acb56fb534c350ee000a65f9fdca5474f1aa0f1b31ec060605260206000608060006001620160f3f46012556000516013557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fe436034a72ef7c34b9b1f2c3eac91192cb84b22d087e5884dacdd8696ff34b726040527f48803a6ed19bfc202f898a085136dd3ee4a918fdb3835663bdd96a50975e1745606052602060006080600060006001620142c7f26014556000516015557fd5042e3ec2ca8fde8b18909f94d7348e8b438a7263d2feeb2c422cb60f83bad86000527f55584a92ed548e75f6dcd3b25f48c5703fb8f0a85d772d8f587599b93f87fad46020527ffb1ced138fd8af5f88a6dcb089edafd1d2908513ef25ee480fdeadb2e83695146040527fa453d375eba08e416c4b97217f65e0b9307d4f5d3eaa7da79fdabe8e0f49bda6606052602060006080600060016001611401f26016556000516017557f82f33cf000118e725f5eed0187c8b6095a051ddbac8ded15de0d3c8928a808636000527fb8bc86053e103bb2549c3ff06a84d902e514c7e1ba1393502217d68a4aadb31b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f08011bce289447868d688b9973ae2bbe9d8ad6c143ecfdc6b9b70fe282a496b860605260206000608060006001600161e1eff16018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fbe6d8c84796ce695fa00e4d0b0ac7132b50632ad157af5b1adc7c6702e9599d06040527f35381b299c20c4ba894596a0db9caddf538a0074684b690560e95be04a190d5e606052602060006080600060016001614ffdf1601a55600051601b556000600052600060205260006040526000606052602060006080600060016155c8f4601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fb0b5271225f035633edd33399f0913cbbef801313afb172c5fcd0590a94cf7b16040527f7e21e99a654ff21645693c71c11b776d4a9b61b7d9f15e5d97566f3eee5e60d3606052602060006080600060016001616deff2601e55600051601f557fb0e50afc95032ef3f21c5a95297c0d938886cb86da733009ef3d5e07193b7e1b6000527f4b48a05eb03d69aceb85b68608beebbd4bc578adf27f3b74091f5fc5df9df01b60205260006040527f2f9b55f0a732315697939e9d44523bf9b0c939ebc9a0e21edd2739a5923d0bcd60605260206000608060006001620182effa6020556000516021557fc39046a1193d18e62e84969d1a188a1c607d8ebfcef95072b96c7949676dd76f6000527f81726196fb4b59c1ba65eaefd21a431f9a3558de6d72087a82ed3563f0fc411c6020527f8f2ba33d42cb6bce63318886374c1fa956f1057cd6d529e2265874d75c5f35356040527fffffa2299df57260c1cbf85ea7379f90a3d546b6a4ad568d4935acd69a34db3c60605260206000608060006001600161af20f16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527ffe374920b47cf11a7b5da58393d25c34e5fe6e82b0d51d4a6e5c21b034e56ca86040527f17095694c8d8c9c8d28ac82b2f9df8f6618bacfc76c11d46b4d0c9e430f331ae606052602060006080600060006001620162acf26024556000516025557f15f24e505d16ac34cff2135dff87c71c10e11b65a33116164024b27cf27d1d006000527f536998cc03c326a9be90624f39787d5a14f9d5ebb2fd3b64823dd60f217fab1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f28dd42754fe747224d3095cd4d4a4107df952a05789098d2eca919073b149b9d60605260206000608060006001616d36fa6026556000516027557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fd293fff8f5adb1cde1fc86abd0c24f5649eca393b7808fa635e4c0732457dd346040527f2fcb00f81dad8b140cc9cd948c7d3065911f8b07b23fdcfd558a7bfcb435cde860605260206000608060006001619593fa6028556000516029556000600052600060205260006040526000606052602060006080600060016123d8fa602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fbe7c2cdd179b62736e7d27dc41b00d66b0676aaf1416229f58f93c229be4d6d96040527f45419dc3d82bf0241483c47de0c38aea663dfb4e2fd3dd5db35155e4c582fd5f60605260206000608060006001600161897bf1602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fbd5cd8a674673281e0ba3b891773dd48b80608999a9e6d2957f489e195854d4e6040527f1d3cb422a300a1292e963d0c85300794e42c3f57378ec436be9c331c88d600016060526020600060806000600161a560f4602e55600051602f557fdecd52e420acf17cc0d451565b7c67671329e510c8c62ad03a95cc7351c043cb6000527f8f9991901996d733ef224cedc1826d06918df3f6ed4588cb2736e2e0f50d891c6020527f3e03b0ff538af2ccc877e59141b53a07bf3942b8078713a07900276f3cd33f9f6040527fffff38e35ae5b3c57a64627f66b4e44d6f0e38a593eee27710ae85a61ab95310606052602060006080600060016192a2f4603055600051603155",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": {
+ "balance": "0x0",
+ "code": "0x671fffffffffffffff6b10000000000000000000000090187ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff800000000000000000000000000200004400000000000000000000019014901c6000557d76767676767600000000007600000000000000560000000000000000000060006380000001097ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0681000000000000000009006901767d02126262626262667b368d219438b7f3f187702ffffffffffffffffffffffffffffffffff000000030000638000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b009008600155901c7702ffffffffffffffffffffffffffffffffff2000000000007f77676767676760000000000000001002e000000000000040000000e000000000900a901590191871767676767676767676000000767676767676690100000000000000000060070890187ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb09011196002557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100067ffffffffffffffff020b6780000000000000006fdac7fff9ffd9e1322626262626262600901a712000110000000d0a300e750a000000090a0a7f8000000000000000000000000000000000000000000000000000000000000002691000000000000000000009076003556b1000000000000000000000007bc9700000000000000000023f00c00014ff002c000000000000223108901190047cc9700000000000000000023f00c00014ff0000000000000000223008057feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee9012901590046d01000000000000000000000000007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90179004681000000000000000006f80000000000000010000000000000000177d767676767676000000000076000000000000005600000000000000000000760fffc000000000000767676240000000000002b05760477ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9009901960045504762900760076761e000200767600000000767676760000007702ffffffffffffffffffffffffffffffffff2000000000009010901c156005556c1000000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0003778200000000000000fe000004000000ffff000000fffff7006fdac7fff9ffd9e132262626262626260013027f40000000fd000000db0000000000000000000000000000000000000000000001637fffffff90106006556fdac7fff9ffd9e13226262626262626006847839214543589705216900260075577800000000000000080000000000000008000000000000000681000000000000000000a7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee016008557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a677fffffffffffffff1390106f800000000000000100000000000000006001121c7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007bc9700000000000000000023f00c00014ff002c000000000000223108901860095560006000f3",
+ "nonce": "0x0",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000a",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000009",
+ "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000012",
+ "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000011",
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000008"
+ }
+ },
+ "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": {
+ "balance": "0xffffffffff",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "storage": {}
+ },
+ "0xe1fAE9b4fAB2F5726677ECfA912d96b0B683e6a9": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xe583e10A46B183759EBdA6b6C9F4c5c8Bac3f93B": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0xd04de6bff05c8224a456b8903e1eccc90b0536886d56e39545afdebcfd03bed3",
+ "storage": {}
+ },
+ "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": {
+ "balance": "0x989680",
+ "code": "0x6000496000556001496001556003496002554a6003556002600455",
+ "nonce": "0x0",
+ "storage": {}
+ },
+ "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D": {
+ "balance": "0x8ac7230489e80000",
+ "code": "0x",
+ "nonce": "0x0",
+ "privateKey": "0x7b323b16770a849a484590f9b4bba2c1f64d350b326633d6d120bfca55a11efd",
+ "storage": {}
+ },
+ "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": {
+ "balance": "0x989680",
+ "code": "0x60216000526103f260205260216040527f3623fd54cd06b75de7239ccf1b2449a0c9fd70c16f144a6bd2c9b0ac1fbfa8426060527f5d682940046b0afaf1eb7c6108fc0c970b258534d91d98209d333897b4b59b846080527f4c11a995c208cf5b0d4a29d98e5febda07077f48c48e29111a22442dee68cb9460a0527f950bef146802e0392142abe6ee810af996bea2fb476355f7593642d094ac676260c0527fd0b37c652e6f974b1a3c20664bb531a1e90a07d2d2c72b6115b9688f2002657660e0527ff631350425b8e604137eab399d6197e946a94e944bd07cb999e55efb5e744c94610100527f316b2d67bc1e378311ca594b35b3db4bf9b62cc5c83067a5147007124415f517610120527f1653e592c605857d24772e234ab2688aae83ac8deacdcaa5106fb4af091c8f81610140527f21ea6e72b65e0a16201deb8766050c2bc0612d7777f7b38b865ca773fb5b564c610160527fb69766036db609f36cf7a7c24a8b29254a6f2087ee0d7cccae89c0a3960f3294610180527f3d6a4d27eb848d841c593cac2bfd6f193e1aa156f89786510162d5f9662d49856101a0527f40c0d5118ea194423736359189066377b8195b4659fc3beada17066ba04132a76101c0527f8fc99a206ed6cdac47c088c9b71f4c8ffedb694103f96dddccc1457b7a71318e6101e0527f5649a7fa1ddb7d657a9102f7f5a1a0bd31d21a9388ab01bcf3ff7a0dafc7caeb610200527ffe8d1945e75ffc64e7e1a0e28e6ddab729070484ab13e7b4588eee69fd20980d610220527f06b489907a05480d4bd15c2e811243b0e69483a1759b21dfd02119359c61be16610240527f2476c6aa2b8e075e8c5e60c22223ab7610f7961b88f6f94a35f48ac59c0ccab6610260527fdba179d99abb3d9cb827d031e122f1b6ae6ff0761ce5e62ff2f6b439d7d5c721610280527f3f1ea572872467aac1cea6022193187d39de665fa8eba806cc43f0ab92e5b0816102a0527fb40663f10434fc54da8900ecc24c1ce52254d229603ff06a0a91a393f58c04416102c0527f38cbdf77b1cb1fff9022d5f3ffd04f1ce41442ec8c0086b94aaf2700525f60816102e0527f6beb95bbee2d635427cb55c90edf55323fda330b1709eaf414b391187e096830610300527fe07054ce1cc262cf540e7672266cc70e616c9fcb2b770daa52ee17329a1b3f19610320527fe6c7acff91edb2d66c98f2290c641b4c230f59db3f978964af0549ae58d3a1f4610340527f8537d71840b84339ef799929127470bbe566945ba3600b765fdcc2dd1c1f470e610360527f4dfa8d7e7650e02b28eb62be4eb0c79a718b70e84bf63a10bcb050a0b0db2469610380527f7858ec131355134d102649bfe55ca13bf7812924d28d5851f5c4b1d4ed3c28066103a0527f4668d069b63983dc376dd9940250c84fe5fad561f60c3cccac2ac3d5e79df7666103c0527f4d8520a4c52e2fa81849f4eba861282e70f6fc67ef38d5727bead9bb96432bb26103e0527fa4e584909b998e4926f86f26c61e7dbb2ff97e0ff20fb9cc15afeab67b8ce5ca610400527f616b8111dcb7a9e369eb0fc06366dac06ddc34eb75efe6e8a758d2a46d1deaa1610420527f0dc20600f514db6ef4b5da00e489e2bf64386e4d91b5cdcd3151f98b83ee6ced610440527f2ab02ae3d7f233d2a21d6188b372fad4957220a3c1357422d3902689fb536eef6104605260446104805360c86104815360c96104825360966104835360f36104845360c061048553605661048653604b6104875360836104885360256104895360c861048a5360bf61048b53602561048c53609461048d53602961048e53608d61048f536083610490536078610491536049610492536096610493536021600061049460006005620fe4adf45a01600055600051600155602051600255",
+ "nonce": "0x0",
+ "storage": {}
+ }
+ },
+ "chainId": 1,
+ "env": {
+ "currentBaseFee": "0xa",
+ "currentBlobGasUsed": "0x40000",
+ "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000",
+ "currentDifficulty": "0x20000",
+ "currentExcessBlobGas": "0x40000",
+ "currentGasLimit": "0x11e1a300",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x3e8"
+ },
+ "fork": "Osaka",
+ "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f",
+ "transactions": [
+ {
+ "data": "0x8e",
+ "from": "0x78011f4E10a54C02296EfeB11034d561320e8949",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6",
+ "value": "0x4a"
+ },
+ {
+ "data": "0x",
+ "from": "0x94b690A97d429F297d32b8fED10213e759861599",
+ "gas": "0xf42400",
+ "gasPrice": "0x20",
+ "nonce": 0,
+ "to": "0x538A8474EeaB43d5a960164c554A20400151D479",
+ "value": "0x74402e"
+ },
+ {
+ "data": "0x5fba026aad22ba6d36391ae06cc12b8887c2f8b66741f5c57853e6480826ad6b4fe3bb038561",
+ "from": "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f",
+ "value": "0xa6"
+ },
+ {
+ "data": "0xb9e0c6c06b57302452e876c996345d34e9ad5434bbeacf59e90fff975f1fe072e7f6f3f33266af1aa0ea535d2741ceafaafa745d5d9653008598379dcd69594e00544ffe6c1509c8ff28dd459e1410e61827cd01dc05bef761bdda",
+ "from": "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d",
+ "value": "0x1fe4"
+ },
+ {
+ "data": "0xb88caa18d4de9c90178eecb316248c992f6fc85c57a7970cb37bb1dc781aa8848e011b5a741a61f67e505ee5532d849365395fb740ed631138e9edae986483563d29",
+ "from": "0xB9A8D444BbCDFb9a6b19f59e0024184fbe10761c",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 0,
+ "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3",
+ "value": "0xa8ac92"
+ },
+ {
+ "data": "0x3ef31a11b704ef279b601279a6296bf1039df853abdfc74f36a10522a7af9040a0e907e9fd14cd2e81a5d079e8a723e8aa39956f73387afaa9c1d2eee1ff14",
+ "from": "0x78011f4E10a54C02296EfeB11034d561320e8949",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F",
+ "value": "0x750d9e"
+ },
+ {
+ "data": "0xd4559e7fd8a8496695ae9233914fa1fba8ddb2e4eab01d79d9426299a5",
+ "from": "0x94b690A97d429F297d32b8fED10213e759861599",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c",
+ "value": "0x0"
+ },
+ {
+ "blobVersionedHashes": [
+ "0x01b9a0a66963a7a2735327cbb69cec9c07c2644c444a4a75bb58ae87fe70ec6e",
+ "0x01c0937d94e0a52b9af97df93c6f0d33392f2b3ccdb55c84808a9a29988197d6",
+ "0x01b736808fd4fc140fa4af910c0265186faad28a8a087730a3e71e5bdacad36d",
+ "0x013a1bef93a852ea266538894c417e60875c907875d58766051d3677585a651a",
+ "0x01ea6e6b1e708d9dccabdfa016f94d7f5b18a2bc565b438724634bcc72643927",
+ "0x0145f4cc59d6d83e1a5ff9d4c4171ef8854be73adbca43f41f1dfe53a1f8afb8"
+ ],
+ "data": "0x8c54f5",
+ "from": "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D",
+ "gas": "0xf42400",
+ "maxFeePerBlobGas": "0x100",
+ "maxFeePerGas": "0x20",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 1,
+ "sidecar": {
+ "blobs": 6,
+ "commitments": 6,
+ "proofs": 6
+ },
+ "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89",
+ "type": "0x3",
+ "value": "0x0"
+ },
+ {
+ "data": "0x3139811779e97d51edcca9f0f79b1b2fcd5bc74a1da9a7c90ac6fc1366ade717b52e58e1b0",
+ "from": "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb",
+ "value": "0x0"
+ },
+ {
+ "data": "0x",
+ "from": "0xB9A8D444BbCDFb9a6b19f59e0024184fbe10761c",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 1,
+ "to": "0xD74CFe323387aE2fd070CD046173026716D8D649",
+ "value": "0x92"
+ },
+ {
+ "data": "0x25257c9ea9a05c62de65f6f1613928d3dd9f1694b0ce543c5cf7a4cdd41a21b33053082b2312eb71122e3c5901c4ad7797bc6a98b067e7268da2de8d02d544",
+ "from": "0x78011f4E10a54C02296EfeB11034d561320e8949",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10",
+ "value": "0x47"
+ },
+ {
+ "data": "0x48a095c06665b1190c6653014033badc12021c60193e8eb6e8c8822ec3a5605086f4cee4b39c17abb9b02d1046e5c9e59915bf3968b9529020a499",
+ "from": "0x94b690A97d429F297d32b8fED10213e759861599",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876",
+ "value": "0xf69e"
+ },
+ {
+ "data": "0xfba48342d570d662f5cc18448171f710e934b7",
+ "from": "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190",
+ "value": "0xc920"
+ },
+ {
+ "data": "0xec004e5112fb80f934d824af5b6ae62f5397ca8c95ab9efb09baa7a67524ba3d4c51f4d774715bd442806ef5dc3ec256c3d61f97ded829c8",
+ "from": "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E",
+ "gas": "0xf42400",
+ "gasPrice": "0x10",
+ "nonce": 2,
+ "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce",
+ "value": "0x4cc67"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000011",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xc85231701b4522e30f0612a30f5232b35d33a866a963ade8ff2c5e8852871b63",
+ "s": "0x67cc51220312f0e513ca06ee1923c144e1717f4485ba44ecfd3f5b802cfbbc34",
+ "v": "0x1"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000011",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0xd7fd315f0a21617cbad586fe26272506edb4a08088290683c37dd206e53aaa0e",
+ "s": "0x240d9bc9570a3d1d6a5018dcec493b70620f59f01ec75873f6ecfdd31ae488",
+ "v": "0x1"
+ },
+ {
+ "address": "0x000000000000000000000000000000000000000a",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x9f38d3bef386cc1c61793f5a3eb8642a0df6ec0c0099f6fd390b99a35ad63e5b",
+ "s": "0x7d728242231f8632e0e89861c8053024e3bed6de2e29f47b4e034712b45f3c3d",
+ "v": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000000005",
+ "chainId": "0x0",
+ "nonce": "0x0",
+ "r": "0x2b6bbd42a3b7c53e20e688b857c21ae5ea552e203fb85d173c15bccbb5c1a0b6",
+ "s": "0x11fbe9f4188ebc5c59c80cc65f0d555d41ec0148434d1b37fc348f41b87625bc",
+ "v": "0x0"
+ }
+ ],
+ "data": "0x190b8a4289",
+ "from": "0x6EB54E66856fD47bd539A986B19F0Bc9B7B4dA9F",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0xe1fAE9b4fAB2F5726677ECfA912d96b0B683e6a9",
+ "type": "0x4",
+ "value": "0x0"
+ },
+ {
+ "data": "0x00",
+ "from": "0x4133B3E532cC750d0a4691c8Bb0B03fba51707FC",
+ "gas": "0x30d40",
+ "maxFeePerGas": "0x1e",
+ "maxPriorityFeePerGas": "0x1",
+ "nonce": 0,
+ "to": "0x0000000000000000000000000000000000000011",
+ "type": "0x2",
+ "value": "0x3e8"
+ },
+ {
+ "authorizationList": [
+ {
+ "address": "0x0000000000000000000000000000000000000000",
+ "chainId": "0x1",
+ "nonce": "0x2",
+ "r": "0x5dacfa13af5badbc0d7892ab80bdfb50697fdcf55eda65d933585fff39a52def",
+ "s": "0x1dbc77f20853c92d53095f9e2e5280b3e2565a14ea4a24fb2e9706892d04f236",
+ "v": "0x1"
+ }
+ ],
+ "data": "0x190b8a4289",
+ "from": "0xe583e10A46B183759EBdA6b6C9F4c5c8Bac3f93B",
+ "gas": "0xf42400",
+ "maxFeePerGas": "0x10",
+ "maxPriorityFeePerGas": "0x10",
+ "nonce": 0,
+ "to": "0xe1fAE9b4fAB2F5726677ECfA912d96b0B683e6a9",
+ "type": "0x4",
+ "value": "0x0"
+ }
+ ],
+ "version": "2.0"
+}
\ No newline at end of file
diff --git a/src/ethereum_spec_tests/cli/tox_helpers.py b/packages/tests/src/cli/tox_helpers.py
similarity index 94%
rename from src/ethereum_spec_tests/cli/tox_helpers.py
rename to packages/tests/src/cli/tox_helpers.py
index 7dbe0c26cf..63b4cee668 100644
--- a/src/ethereum_spec_tests/cli/tox_helpers.py
+++ b/packages/tests/src/cli/tox_helpers.py
@@ -2,8 +2,8 @@
CLI commands used by tox.ini.
Contains wrappers to the external commands markdownlint-cli2 and pyspelling
-(requires aspell) that fail silently if the command is not available. The
-aim is to avoid disruption to external contributors.
+(requires aspell) that fail silently if the command is not available. The aim
+is to avoid disruption to external contributors.
"""
import os
@@ -23,10 +23,11 @@ def write_github_summary(title: str, tox_env: str, error_message: str, fix_comma
Write a summary to GitHub Actions when a check fails.
Args:
- title: The title of the check that failed
- tox_env: The tox environment name (e.g., "spellcheck")
- error_message: Description of what went wrong
- fix_commands: List of commands to fix the issue locally
+ title: The title of the check that failed tox_env: The tox
+ environment name (e.g., "spellcheck")
+ tox_env: The tox environment
+ error_message: Description of what went wrong
+ fix_commands: List of commands to fix the issue locally
"""
if not os.environ.get("GITHUB_ACTIONS"):
@@ -70,7 +71,8 @@ def markdownlint(args):
"""
markdownlint = shutil.which("markdownlint-cli2")
if not markdownlint:
- # Note: There's an additional step in test.yaml to run markdownlint-cli2 in GitHub Actions
+ # Note: There's an additional step in test.yaml to run markdownlint-
+ # cli2 in GitHub Actions
click.echo("********* Install 'markdownlint-cli2' to enable markdown linting *********")
sys.exit(0)
@@ -194,7 +196,8 @@ def codespell():
@click.command()
def validate_changelog():
"""
- Validate changelog formatting to ensure bullet points end with proper punctuation.
+ Validate changelog formatting to ensure bullet points end with proper
+ punctuation.
Checks that all bullet points (including nested ones) end with either:
- A period (.) for regular entries
diff --git a/src/ethereum_spec_tests/config/__init__.py b/packages/tests/src/config/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/config/__init__.py
rename to packages/tests/src/config/__init__.py
diff --git a/src/ethereum_spec_tests/config/app.py b/packages/tests/src/config/app.py
similarity index 100%
rename from src/ethereum_spec_tests/config/app.py
rename to packages/tests/src/config/app.py
diff --git a/src/ethereum_spec_tests/config/check_eip_versions.py b/packages/tests/src/config/check_eip_versions.py
similarity index 100%
rename from src/ethereum_spec_tests/config/check_eip_versions.py
rename to packages/tests/src/config/check_eip_versions.py
diff --git a/src/ethereum_spec_tests/config/docs.py b/packages/tests/src/config/docs.py
similarity index 86%
rename from src/ethereum_spec_tests/config/docs.py
rename to packages/tests/src/config/docs.py
index f081e92d15..ac6c7e93cd 100644
--- a/src/ethereum_spec_tests/config/docs.py
+++ b/packages/tests/src/config/docs.py
@@ -2,7 +2,7 @@
A module for managing documentation-related configurations.
Classes:
-- DocsConfig: Holds configurations for documentation generation.
+ DocsConfig: Holds configurations for documentation generation.
"""
from pydantic import BaseModel
@@ -19,5 +19,6 @@ class DocsConfig(BaseModel):
DOCS_BASE_URL: str = "https://eest.ethereum.org"
- # Documentation URLs prefixed with `DOCS_URL__` to avoid conflicts with other URLs
+ # Documentation URLs prefixed with `DOCS_URL__` to avoid conflicts with
+ # other URLs
DOCS_URL__WRITING_TESTS: str = f"{DOCS_BASE_URL}/main/writing_tests/"
diff --git a/src/ethereum_spec_tests/config/env.py b/packages/tests/src/config/env.py
similarity index 76%
rename from src/ethereum_spec_tests/config/env.py
rename to packages/tests/src/config/env.py
index 0e2811b205..f2bf92b2f2 100644
--- a/src/ethereum_spec_tests/config/env.py
+++ b/packages/tests/src/config/env.py
@@ -1,12 +1,14 @@
"""
A module for exposing application-wide environment variables.
-This module is responsible for loading, parsing, and validating the application's
-environment configuration from the `env.yaml` file. It uses Pydantic to ensure that
-the configuration adheres to expected formats and types.
+This module is responsible for loading, parsing, and validating the
+application's environment configuration from the `env.yaml` file. It uses
+Pydantic to ensure that the configuration adheres to expected formats and
+types.
Functions:
-- create_default_config: Creates a default configuration file if it doesn't exist.
+- create_default_config: Creates a default configuration file if it
+ doesn't exist.
Classes:
- EnvConfig: Loads the configuration and exposes it as Python objects.
@@ -32,9 +34,11 @@ class RemoteNode(BaseModel):
Represents a configuration for a remote node.
Attributes:
- - name (str): The name of the remote node.
- - node_url (HttpUrl): The URL for the remote node, validated as a proper URL.
- - rpc_headers (Dict[str, str]): A dictionary of optional RPC headers, defaults to empty dict.
+ name (str): The name of the remote node.
+ node_url (HttpUrl): The URL for the remote node, validated as a
+ proper URL.
+ rpc_headers (Dict[str, str]): A dictionary of optional RPC headers,
+ defaults to empty dict.
"""
@@ -48,7 +52,7 @@ class Config(BaseModel):
Represents the overall environment configuration.
Attributes:
- - remote_nodes (List[RemoteNode]): A list of remote node configurations.
+ remote_nodes (List[RemoteNode]): A list of remote node configurations.
"""
@@ -59,8 +63,8 @@ class EnvConfig(Config):
"""
Loads and validates environment configuration from `env.yaml`.
- This is a wrapper class for the Config model. It reads a config file
- from disk into a Config model and then exposes it.
+ This is a wrapper class for the Config model. It reads a config file from
+ disk into a Config model and then exposes it.
"""
def __init__(self):
diff --git a/src/ethereum_spec_tests/config/templates/env.yaml.j2 b/packages/tests/src/config/templates/env.yaml.j2
similarity index 100%
rename from src/ethereum_spec_tests/config/templates/env.yaml.j2
rename to packages/tests/src/config/templates/env.yaml.j2
diff --git a/src/ethereum_spec_tests/conftest.py b/packages/tests/src/conftest.py
similarity index 97%
rename from src/ethereum_spec_tests/conftest.py
rename to packages/tests/src/conftest.py
index 59fb310c5f..82c42bb48b 100644
--- a/src/ethereum_spec_tests/conftest.py
+++ b/packages/tests/src/conftest.py
@@ -14,7 +14,8 @@
for transition_tool in TransitionTool.registered_tools
if (
transition_tool.is_installed()
- # Currently, Besu has the same `default_binary` as Geth, so we can't use `is_installed`.
+ # Currently, Besu has the same `default_binary` as Geth, so we can't
+ # use `is_installed`.
and transition_tool != BesuTransitionTool
)
]
@@ -32,7 +33,8 @@ def installed_transition_tool_instances() -> Generator[
transition_tool_instance.start_server()
instances[transition_tool_class.__name__] = transition_tool_instance
except Exception as e:
- # Record the exception in order to provide context when failing the appropriate test
+ # Record the exception in order to provide context when failing the
+ # appropriate test
instances[transition_tool_class.__name__] = e
yield instances
for instance in instances.values():
diff --git a/src/ethereum_spec_tests/ethereum_clis/__init__.py b/packages/tests/src/ethereum_clis/__init__.py
similarity index 78%
rename from src/ethereum_spec_tests/ethereum_clis/__init__.py
rename to packages/tests/src/ethereum_clis/__init__.py
index f555cae91e..6fffde82a9 100644
--- a/src/ethereum_spec_tests/ethereum_clis/__init__.py
+++ b/packages/tests/src/ethereum_clis/__init__.py
@@ -1,8 +1,23 @@
-"""Library of Python wrappers for the different implementations of transition tools."""
+"""
+Library of Python wrappers for the different implementations of transition
+tools.
+"""
+from .cli_types import (
+ BlockExceptionWithMessage,
+ Result,
+ Traces,
+ TransactionExceptionWithMessage,
+ TransitionToolOutput,
+)
from .clis.besu import BesuTransitionTool
from .clis.ethereumjs import EthereumJSTransitionTool
-from .clis.evmone import EvmoneExceptionMapper, EvmOneTransitionTool
+from .clis.evmone import (
+ EvmOneBlockchainFixtureConsumer,
+ EvmoneExceptionMapper,
+ EvmOneStateFixtureConsumer,
+ EvmOneTransitionTool,
+)
from .clis.execution_specs import ExecutionSpecsTransitionTool
from .clis.geth import GethFixtureConsumer, GethTransitionTool
from .clis.nethermind import Nethtest, NethtestFixtureConsumer
@@ -10,13 +25,6 @@
from .ethereum_cli import CLINotFoundInPathError, UnknownCLIError
from .fixture_consumer_tool import FixtureConsumerTool
from .transition_tool import TransitionTool
-from .types import (
- BlockExceptionWithMessage,
- Result,
- Traces,
- TransactionExceptionWithMessage,
- TransitionToolOutput,
-)
TransitionTool.set_default_tool(ExecutionSpecsTransitionTool)
FixtureConsumerTool.set_default_tool(GethFixtureConsumer)
@@ -28,6 +36,8 @@
"EthereumJSTransitionTool",
"EvmoneExceptionMapper",
"EvmOneTransitionTool",
+ "EvmOneStateFixtureConsumer",
+ "EvmOneBlockchainFixtureConsumer",
"ExecutionSpecsTransitionTool",
"FixtureConsumerTool",
"GethFixtureConsumer",
diff --git a/src/ethereum_spec_tests/ethereum_clis/types.py b/packages/tests/src/ethereum_clis/cli_types.py
similarity index 82%
rename from src/ethereum_spec_tests/ethereum_clis/types.py
rename to packages/tests/src/ethereum_clis/cli_types.py
index 0d55c63eb2..0cb8389239 100644
--- a/src/ethereum_spec_tests/ethereum_clis/types.py
+++ b/packages/tests/src/ethereum_clis/cli_types.py
@@ -4,7 +4,7 @@
from pathlib import Path
from typing import Annotated, Any, Dict, List, Self
-from pydantic import Field
+from pydantic import Field, PlainSerializer, PlainValidator
from ethereum_test_base_types import (
BlobSchedule,
@@ -29,7 +29,8 @@
Transaction,
TransactionReceipt,
)
-from pytest_plugins.logging import get_logger
+from ethereum_test_vm import Opcode, Opcodes
+from pytest_plugins.custom_logging import get_logger
logger = get_logger(__name__)
@@ -99,8 +100,8 @@ def from_file(cls, trace_file_path: Path) -> Self:
@staticmethod
def remove_gas(traces: List[TraceLine]):
"""
- Remove the GAS operation opcode result from the stack to make comparison possible
- even if the gas has been pushed to the stack.
+ Remove the GAS operation opcode result from the stack to make
+ comparison possible even if the gas has been pushed to the stack.
"""
for i in range(1, len(traces)):
trace = traces[i]
@@ -143,7 +144,9 @@ def print(self):
class Traces(EthereumTestRootModel):
- """Traces returned from the transition tool for all transactions executed."""
+ """
+ Traces returned from the transition tool for all transactions executed.
+ """
root: List[TransactionTraces]
@@ -173,6 +176,40 @@ def print(self):
tx.print()
+_opcode_synonyms = {
+ "KECCAK256": "SHA3",
+}
+
+
+def validate_opcode(obj: Any) -> Opcodes | Opcode:
+ """Validate an opcode from a string."""
+ if isinstance(obj, Opcode) or isinstance(obj, Opcodes):
+ return obj
+ if isinstance(obj, str):
+ if obj in _opcode_synonyms:
+ obj = _opcode_synonyms[obj]
+ for op in Opcodes:
+ if str(op) == obj:
+ return op
+ raise Exception(f"Unable to validate {obj} (type={type(obj)})")
+
+
+class OpcodeCount(EthereumTestRootModel):
+ """Opcode count returned from the evm tool."""
+
+ root: Dict[
+ Annotated[Opcodes, PlainValidator(validate_opcode), PlainSerializer(lambda o: str(o))], int
+ ]
+
+ def __add__(self, other: Self) -> Self:
+ """Add two instances of opcode count dictionaries."""
+ assert isinstance(other, OpcodeCount), f"Incompatible type {type(other)}"
+ new_dict = self.model_dump() | other.model_dump()
+ for match_key in self.root.keys() & other.root.keys():
+ new_dict[match_key] = self.root[match_key] + other.root[match_key]
+ return self.__class__(new_dict)
+
+
class Result(CamelModel):
"""Result of a transition tool output."""
@@ -200,6 +237,7 @@ class Result(CamelModel):
BlockExceptionWithMessage | UndefinedException | None, ExceptionMapperValidator
] = None
traces: Traces | None = None
+ opcode_count: OpcodeCount | None = None
class TransitionToolInput(CamelModel):
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/__init__.py b/packages/tests/src/ethereum_clis/clis/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/clis/__init__.py
rename to packages/tests/src/ethereum_clis/clis/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/besu.py b/packages/tests/src/ethereum_clis/clis/besu.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_clis/clis/besu.py
rename to packages/tests/src/ethereum_clis/clis/besu.py
index b30b205757..833248909f 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/besu.py
+++ b/packages/tests/src/ethereum_clis/clis/besu.py
@@ -19,8 +19,8 @@
)
from ethereum_test_forks import Fork
+from ..cli_types import TransitionToolOutput
from ..transition_tool import TransitionTool, dump_files_to_directory, model_dump_config
-from ..types import TransitionToolOutput
class BesuTransitionTool(TransitionTool):
@@ -289,10 +289,10 @@ class BesuExceptionMapper(ExceptionMapper):
TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: (
r"transaction invalid Transaction gas limit must be at most \d+"
),
- TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: (
- r"Blob transaction has too many blobs: \d+"
- ),
TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: (
- r"Invalid Blob Count: \d+"
+ r"Blob transaction 0x[0-9a-f]+ exceeds block blob gas limit: \d+ > \d+"
+ ),
+ TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: (
+ r"Blob transaction has too many blobs: \d+|Invalid Blob Count: \d+"
),
}
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/erigon.py b/packages/tests/src/ethereum_clis/clis/erigon.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_clis/clis/erigon.py
rename to packages/tests/src/ethereum_clis/clis/erigon.py
index c549d0deb6..b16bcb4b51 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/erigon.py
+++ b/packages/tests/src/ethereum_clis/clis/erigon.py
@@ -45,7 +45,7 @@ class ErigonExceptionMapper(ExceptionMapper):
}
mapping_regex = {
TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: (
- r"invalid block, txnIdx=\d+, gas limit too high"
+ r"invalid block, txnIdx=\d+,.*gas limit too high"
),
BlockException.INCORRECT_BLOB_GAS_USED: r"blobGasUsed by execution: \d+, in header: \d+",
BlockException.INCORRECT_EXCESS_BLOB_GAS: r"invalid excessBlobGas: have \d+, want \d+",
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/ethereumjs.py b/packages/tests/src/ethereum_clis/clis/ethereumjs.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_clis/clis/ethereumjs.py
rename to packages/tests/src/ethereum_clis/clis/ethereumjs.py
index 45e7aed735..59214e00fa 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/ethereumjs.py
+++ b/packages/tests/src/ethereum_clis/clis/ethereumjs.py
@@ -39,13 +39,16 @@ def __init__(
def is_fork_supported(self, fork: Fork) -> bool:
"""
Return True if the fork is supported by the tool.
+
Currently, EthereumJS-t8n provides no way to determine supported forks.
"""
return True
class EthereumJSExceptionMapper(ExceptionMapper):
- """Translate between EEST exceptions and error strings returned by EthereumJS."""
+ """
+ Translate between EEST exceptions and error strings returned by EthereumJS.
+ """
mapping_substring: ClassVar[Dict[ExceptionBase, str]] = {
TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: (
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/ethrex.py b/packages/tests/src/ethereum_clis/clis/ethrex.py
similarity index 87%
rename from src/ethereum_spec_tests/ethereum_clis/clis/ethrex.py
rename to packages/tests/src/ethereum_clis/clis/ethrex.py
index 69cbbfde42..bd3fd6c073 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/ethrex.py
+++ b/packages/tests/src/ethereum_clis/clis/ethrex.py
@@ -48,11 +48,16 @@ class EthrexExceptionMapper(ExceptionMapper):
r"blob versioned hashes not supported|"
r"Type 3 transactions are not supported before the Cancun fork"
),
- # A type 4 Transaction without a recipient won't even reach the EVM, we can't decode it.
+ # A type 4 Transaction without a recipient won't even reach the EVM, we
+ # can't decode it.
TransactionException.TYPE_4_TX_CONTRACT_CREATION: (
r"unexpected length|Contract creation in type 4 transaction|"
r"Error decoding field 'to' of type primitive_types::H160: InvalidLength"
),
+ TransactionException.TYPE_3_TX_CONTRACT_CREATION: (
+ r"unexpected length|Contract creation in type 3 transaction|"
+ r"Error decoding field 'to' of type primitive_types::H160: InvalidLength"
+ ),
TransactionException.TYPE_4_TX_PRE_FORK: (
r"eip 7702 transactions present in pre-prague payload|"
r"Type 4 transactions are not supported before the Prague fork"
@@ -62,7 +67,10 @@ class EthrexExceptionMapper(ExceptionMapper):
),
TransactionException.INTRINSIC_GAS_TOO_LOW: (
r"gas floor exceeds the gas limit|call gas cost exceeds the gas limit|"
- r"Intrinsic gas too low"
+ r"Transaction gas limit lower than the minimum gas cost to execute the transaction"
+ ),
+ TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST: (
+ r"Transaction gas limit lower than the gas cost floor for calldata tokens"
),
TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS: (
r"gas price is less than basefee|Insufficient max fee per gas"
@@ -74,6 +82,7 @@ class EthrexExceptionMapper(ExceptionMapper):
TransactionException.INITCODE_SIZE_EXCEEDED: (
r"create initcode size limit|Initcode size exceeded.*"
),
+ TransactionException.NONCE_IS_MAX: (r"Nonce is max"),
TransactionException.GAS_ALLOWANCE_EXCEEDED: (r"Gas allowance exceeded.*"),
TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: (r"Blob count exceeded.*"),
BlockException.SYSTEM_CONTRACT_CALL_FAILED: (r"System call failed.*"),
diff --git a/packages/tests/src/ethereum_clis/clis/evmone.py b/packages/tests/src/ethereum_clis/clis/evmone.py
new file mode 100644
index 0000000000..1cb71f9096
--- /dev/null
+++ b/packages/tests/src/ethereum_clis/clis/evmone.py
@@ -0,0 +1,378 @@
+"""Evmone Transition tool interface."""
+
+import json
+import re
+import shlex
+import shutil
+import subprocess
+import tempfile
+import textwrap
+from functools import cache
+from pathlib import Path
+from typing import Any, ClassVar, Dict, List, Optional
+
+import pytest
+
+from ethereum_clis.file_utils import dump_files_to_directory
+from ethereum_clis.fixture_consumer_tool import FixtureConsumerTool
+from ethereum_test_exceptions import (
+ EOFException,
+ ExceptionBase,
+ ExceptionMapper,
+ TransactionException,
+)
+from ethereum_test_fixtures.base import FixtureFormat
+from ethereum_test_fixtures.blockchain import BlockchainFixture
+from ethereum_test_fixtures.state import StateFixture
+from ethereum_test_forks import Fork
+
+from ..transition_tool import TransitionTool
+
+
+class EvmOneTransitionTool(TransitionTool):
+ """Evmone `evmone-t8n` Transition tool interface wrapper class."""
+
+ default_binary = Path("evmone-t8n")
+ detect_binary_pattern = re.compile(r"^evmone-t8n\b")
+ t8n_use_stream = False
+
+ binary: Path
+ cached_version: Optional[str] = None
+ trace: bool
+ supports_opcode_count: ClassVar[bool] = True
+
+ def __init__(
+ self,
+ *,
+ binary: Optional[Path] = None,
+ trace: bool = False,
+ ):
+ """Initialize the Evmone Transition tool interface."""
+ super().__init__(exception_mapper=EvmoneExceptionMapper(), binary=binary, trace=trace)
+
+ def is_fork_supported(self, fork: Fork) -> bool:
+ """
+ Return True if the fork is supported by the tool. Currently, evmone-t8n
+ provides no way to determine supported forks.
+ """
+ return True
+
+
+class EvmoneFixtureConsumerCommon:
+ """Common functionality for Evmone fixture consumers."""
+
+ binary: Path
+ version_flag: str = "--version"
+
+ cached_version: Optional[str] = None
+
+ def __init__(
+ self,
+ trace: bool = False,
+ ):
+ """Initialize the EvmoneFixtureConsumerCommon class."""
+ self._info_metadata: Optional[Dict[str, Any]] = {}
+
+ def _run_command(self, command: List[str]) -> subprocess.CompletedProcess:
+ try:
+ return subprocess.run(
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
+ )
+ except subprocess.CalledProcessError as e:
+ raise Exception("Command failed with non-zero status.") from e
+ except Exception as e:
+ raise Exception("Unexpected exception calling evm tool.") from e
+
+ # TODO: copied from geth.py, needs to be deduplicated, but nethermind.py
+ # also has its version
+ def _consume_debug_dump(
+ self,
+ command: List[str],
+ result: subprocess.CompletedProcess,
+ fixture_path: Path,
+ debug_output_path: Path,
+ ):
+ # our assumption is that each command element is a string
+ assert all(isinstance(x, str) for x in command), (
+ f"Not all elements of 'command' list are strings: {command}"
+ )
+ assert len(command) > 0
+
+ # replace last value with debug fixture path
+ debug_fixture_path = str(debug_output_path / "fixtures.json")
+ command[-1] = debug_fixture_path
+
+ # ensure that flags with spaces are wrapped in double-quotes
+ consume_direct_call = " ".join(shlex.quote(arg) for arg in command)
+
+ consume_direct_script = textwrap.dedent(
+ f"""\
+ #!/bin/bash
+ {consume_direct_call}
+ """
+ )
+ dump_files_to_directory(
+ str(debug_output_path),
+ {
+ "consume_direct_args.py": command,
+ "consume_direct_returncode.txt": result.returncode,
+ "consume_direct_stdout.txt": result.stdout,
+ "consume_direct_stderr.txt": result.stderr,
+ "consume_direct.sh+x": consume_direct_script,
+ },
+ )
+ shutil.copyfile(fixture_path, debug_fixture_path)
+
+ def _skip_message(self, fixture_format: FixtureFormat) -> str:
+ return f"Fixture format {fixture_format.format_name} not supported by {self.binary}"
+
+ @cache # noqa
+ def consume_test_file(
+ self,
+ fixture_path: Path,
+ debug_output_path: Optional[Path] = None,
+ ) -> Dict[str, Any]:
+ """
+ Consume an entire state or blockchain test file.
+
+ The `evmone-...test` will always execute all the tests contained in a
+ file without the possibility of selecting a single test, so this
+ function is cached in order to only call the command once and
+ `consume_test` can simply select the result that was requested.
+ """
+ global_options: List[str] = []
+ if debug_output_path:
+ global_options += ["--trace"]
+
+ with tempfile.NamedTemporaryFile() as tempfile_json:
+ # `evmone` uses `gtest` and generates JSON output to a file,
+ # c.f. https://google.github.io/googletest/advanced.html#generating-a-json-report
+ # see there for the JSON schema.
+ global_options += ["--gtest_output=json:{}".format(tempfile_json.name)]
+ command = [str(self.binary)] + global_options + [str(fixture_path)]
+ result = self._run_command(command)
+
+ if result.returncode not in [0, 1]:
+ raise Exception(
+ f"Unexpected exit code:\n{' '.join(command)}\n\n Error:\n{result.stderr}"
+ )
+
+ try:
+ output_data = json.load(tempfile_json)
+ except json.JSONDecodeError as e:
+ raise Exception(
+ f"Failed to parse JSON output from evmone-state/blockchaintest: {e}"
+ ) from e
+
+ if debug_output_path:
+ self._consume_debug_dump(command, result, fixture_path, debug_output_path)
+
+ return output_data
+
+ def _failure_msg(self, file_results: Dict[str, Any]) -> str:
+ # Assumes only one test has run and there has been a failure,
+ # as asserted before.
+ failures = file_results["testsuites"][0]["testsuite"][0]["failures"]
+ return ", ".join([f["failure"] for f in failures])
+
+ def consume_test(
+ self,
+ fixture_path: Path,
+ fixture_name: Optional[str] = None,
+ debug_output_path: Optional[Path] = None,
+ ):
+ """
+ Consume a single state or blockchain test.
+
+ Uses the cached result from `consume_test_file` in order to not
+ call the command every time an select a single result from there.
+ """
+ file_results = self.consume_test_file(
+ fixture_path=fixture_path,
+ debug_output_path=debug_output_path,
+ )
+ if not fixture_name:
+ fixture_hint = fixture_path.stem
+ else:
+ fixture_hint = fixture_name
+ assert file_results["tests"] == 1, f"Multiple tests ran for {fixture_hint}"
+ assert file_results["disabled"] == 0, f"Disabled tests for {fixture_hint}"
+ assert file_results["errors"] == 0, f"Errors during test for {fixture_hint}"
+ assert file_results["failures"] == 0, (
+ f"Failures for {fixture_hint}: {self._failure_msg(file_results)}"
+ )
+
+ test_name = file_results["testsuites"][0]["testsuite"][0]["name"]
+ assert test_name == fixture_path.stem, (
+ f"Test name mismatch, expected {fixture_path.stem}, got {test_name}"
+ )
+
+
+class EvmOneStateFixtureConsumer(
+ EvmoneFixtureConsumerCommon,
+ FixtureConsumerTool,
+ fixture_formats=[StateFixture],
+):
+ """Evmone's implementation of the fixture consumer for state tests."""
+
+ default_binary = Path("evmone-statetest")
+ detect_binary_pattern = re.compile(r"^evmone-statetest\b")
+
+ def __init__(
+ self,
+ binary: Optional[Path] = None,
+ trace: bool = False,
+ ):
+ """Initialize the EvmOneStateFixtureConsumer class."""
+ self.binary = binary if binary else self.default_binary
+ super().__init__(trace=trace)
+
+ def consume_fixture(
+ self,
+ fixture_format: FixtureFormat,
+ fixture_path: Path,
+ fixture_name: Optional[str] = None,
+ debug_output_path: Optional[Path] = None,
+ ):
+ """
+ Execute the appropriate fixture consumer for the fixture at
+ `fixture_path`.
+ """
+ if fixture_format == StateFixture:
+ self.consume_test(
+ fixture_path=fixture_path,
+ fixture_name=fixture_name,
+ debug_output_path=debug_output_path,
+ )
+ else:
+ pytest.skip(self._skip_message(fixture_format))
+
+
+class EvmOneBlockchainFixtureConsumer(
+ EvmoneFixtureConsumerCommon,
+ FixtureConsumerTool,
+ fixture_formats=[BlockchainFixture],
+):
+ """Evmone's implementation of the fixture consumer for blockchain tests."""
+
+ default_binary = Path("evmone-blockchaintest")
+ detect_binary_pattern = re.compile(r"^evmone-blockchaintest\b")
+
+ def __init__(
+ self,
+ binary: Optional[Path] = None,
+ trace: bool = False,
+ ):
+ """Initialize the EvmOneBlockchainFixtureConsumer class."""
+ self.binary = binary if binary else self.default_binary
+ super().__init__(trace=trace)
+
+ def consume_fixture(
+ self,
+ fixture_format: FixtureFormat,
+ fixture_path: Path,
+ fixture_name: Optional[str] = None,
+ debug_output_path: Optional[Path] = None,
+ ):
+ """
+ Execute the appropriate fixture consumer for the fixture at
+ `fixture_path`.
+ """
+ if fixture_format == BlockchainFixture:
+ self.consume_test(
+ fixture_path=fixture_path,
+ fixture_name=fixture_name,
+ debug_output_path=debug_output_path,
+ )
+ else:
+ pytest.skip(self._skip_message(fixture_format))
+
+
+class EvmoneExceptionMapper(ExceptionMapper):
+ """
+ Translate between EEST exceptions and error strings returned by Evmone.
+ """
+
+ mapping_substring: ClassVar[Dict[ExceptionBase, str]] = {
+ TransactionException.SENDER_NOT_EOA: "sender not an eoa:",
+ TransactionException.GAS_ALLOWANCE_EXCEEDED: "gas limit reached",
+ TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS: (
+ "max priority fee per gas higher than max fee per gas"
+ ),
+ TransactionException.NONCE_IS_MAX: "nonce has max value:",
+ TransactionException.TYPE_4_TX_CONTRACT_CREATION: "set code transaction must ",
+ TransactionException.TYPE_4_INVALID_AUTHORITY_SIGNATURE: "invalid authorization signature",
+ TransactionException.TYPE_4_INVALID_AUTHORITY_SIGNATURE_S_TOO_HIGH: (
+ "authorization signature s value too high"
+ ),
+ TransactionException.TYPE_4_EMPTY_AUTHORIZATION_LIST: "empty authorization list",
+ TransactionException.INTRINSIC_GAS_TOO_LOW: "intrinsic gas too low",
+ TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST: "intrinsic gas too low",
+ TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: "blob gas limit exceeded",
+ TransactionException.INITCODE_SIZE_EXCEEDED: "max initcode size exceeded",
+ TransactionException.INSUFFICIENT_ACCOUNT_FUNDS: (
+ "insufficient funds for gas * price + value"
+ ),
+ TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS: (
+ "max fee per gas less than block base fee"
+ ),
+ TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS: (
+ "max blob fee per gas less than block base fee"
+ ),
+ TransactionException.TYPE_4_TX_PRE_FORK: "transaction type not supported",
+ TransactionException.TYPE_3_TX_PRE_FORK: "transaction type not supported",
+ TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH: "invalid blob hash version",
+ TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: "blob gas limit exceeded",
+ TransactionException.TYPE_3_TX_ZERO_BLOBS: "empty blob hashes list",
+ TransactionException.TYPE_3_TX_CONTRACT_CREATION: (
+ "blob transaction must not be a create transaction"
+ ),
+ TransactionException.NONCE_MISMATCH_TOO_LOW: "nonce too low",
+ TransactionException.NONCE_MISMATCH_TOO_HIGH: "nonce too high",
+ # TODO EVMONE needs to differentiate when the section is missing in the
+ # header or body
+ EOFException.MISSING_STOP_OPCODE: "err: no_terminating_instruction",
+ EOFException.MISSING_CODE_HEADER: "err: code_section_missing",
+ EOFException.MISSING_TYPE_HEADER: "err: type_section_missing",
+ # TODO EVMONE these exceptions are too similar, this leeds to ambiguity
+ EOFException.MISSING_TERMINATOR: "err: header_terminator_missing",
+ EOFException.MISSING_HEADERS_TERMINATOR: "err: section_headers_not_terminated",
+ EOFException.INVALID_VERSION: "err: eof_version_unknown",
+ EOFException.INVALID_NON_RETURNING_FLAG: "err: invalid_non_returning_flag",
+ EOFException.INVALID_MAGIC: "err: invalid_prefix",
+ EOFException.INVALID_FIRST_SECTION_TYPE: "err: invalid_first_section_type",
+ EOFException.INVALID_SECTION_BODIES_SIZE: "err: invalid_section_bodies_size",
+ EOFException.INVALID_TYPE_SECTION_SIZE: "err: invalid_type_section_size",
+ EOFException.INCOMPLETE_SECTION_SIZE: "err: incomplete_section_size",
+ EOFException.INCOMPLETE_SECTION_NUMBER: "err: incomplete_section_number",
+ EOFException.TOO_MANY_CODE_SECTIONS: "err: too_many_code_sections",
+ EOFException.ZERO_SECTION_SIZE: "err: zero_section_size",
+ EOFException.MISSING_DATA_SECTION: "err: data_section_missing",
+ EOFException.UNDEFINED_INSTRUCTION: "err: undefined_instruction",
+ EOFException.INPUTS_OUTPUTS_NUM_ABOVE_LIMIT: "err: inputs_outputs_num_above_limit",
+ EOFException.UNREACHABLE_INSTRUCTIONS: "err: unreachable_instructions",
+ EOFException.INVALID_RJUMP_DESTINATION: "err: invalid_rjump_destination",
+ EOFException.UNREACHABLE_CODE_SECTIONS: "err: unreachable_code_sections",
+ EOFException.STACK_UNDERFLOW: "err: stack_underflow",
+ EOFException.STACK_OVERFLOW: "err: stack_overflow",
+ EOFException.MAX_STACK_INCREASE_ABOVE_LIMIT: "err: max_stack_increase_above_limit",
+ EOFException.STACK_HIGHER_THAN_OUTPUTS: "err: stack_higher_than_outputs_required",
+ EOFException.JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS: (
+ "err: jumpf_destination_incompatible_outputs"
+ ),
+ EOFException.INVALID_MAX_STACK_INCREASE: "err: invalid_max_stack_increase",
+ EOFException.INVALID_DATALOADN_INDEX: "err: invalid_dataloadn_index",
+ EOFException.TRUNCATED_INSTRUCTION: "err: truncated_instruction",
+ EOFException.TOPLEVEL_CONTAINER_TRUNCATED: "err: toplevel_container_truncated",
+ EOFException.ORPHAN_SUBCONTAINER: "err: unreferenced_subcontainer",
+ EOFException.CONTAINER_SIZE_ABOVE_LIMIT: "err: container_size_above_limit",
+ EOFException.INVALID_CONTAINER_SECTION_INDEX: "err: invalid_container_section_index",
+ EOFException.INCOMPATIBLE_CONTAINER_KIND: "err: incompatible_container_kind",
+ EOFException.AMBIGUOUS_CONTAINER_KIND: "err: ambiguous_container_kind",
+ EOFException.STACK_HEIGHT_MISMATCH: "err: stack_height_mismatch",
+ EOFException.TOO_MANY_CONTAINERS: "err: too_many_container_sections",
+ EOFException.INVALID_CODE_SECTION_INDEX: "err: invalid_code_section_index",
+ EOFException.CALLF_TO_NON_RETURNING: "err: callf_to_non_returning_function",
+ EOFException.EOFCREATE_WITH_TRUNCATED_CONTAINER: "err: eofcreate_with_truncated_container",
+ }
+ mapping_regex: ClassVar[Dict[ExceptionBase, str]] = {}
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/execution_specs.py b/packages/tests/src/ethereum_clis/clis/execution_specs.py
similarity index 93%
rename from src/ethereum_spec_tests/ethereum_clis/clis/execution_specs.py
rename to packages/tests/src/ethereum_clis/clis/execution_specs.py
index e9d4424b7d..1a97b049b6 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/execution_specs.py
+++ b/packages/tests/src/ethereum_clis/clis/execution_specs.py
@@ -1,14 +1,20 @@
"""
Ethereum Specs EVM Transition Tool Interface.
"""
+
import json
import tempfile
from io import StringIO
from typing import Any, ClassVar, Dict, Optional
+import ethereum
+from ethereum_spec_tools.evm_tools import create_parser
+from ethereum_spec_tools.evm_tools.t8n import T8N
+from ethereum_spec_tools.evm_tools.utils import get_supported_forks
+
+from ethereum_clis.cli_types import TransitionToolOutput
from ethereum_clis.file_utils import dump_files_to_directory
-from ethereum_clis.transition_tool import TransitionTool, model_dump_config
-from ethereum_clis.types import TransitionToolOutput
+from ethereum_clis.transition_tool import model_dump_config
from ethereum_test_exceptions import (
BlockException,
ExceptionBase,
@@ -16,12 +22,6 @@
TransactionException,
)
from ethereum_test_forks import Fork
-from pytest_plugins.logging import get_logger
-
-import ethereum
-from ethereum_spec_tools.evm_tools import create_parser
-from ethereum_spec_tools.evm_tools.t8n import T8N
-from ethereum_spec_tools.evm_tools.utils import get_supported_forks
from ..transition_tool import TransitionTool
@@ -59,9 +59,7 @@ def evaluate(
"""
del slow_request
request_data = transition_tool_data.get_request_data()
- request_data_json = request_data.model_dump(
- mode="json", **model_dump_config
- )
+ request_data_json = request_data.model_dump(mode="json", **model_dump_config)
t8n_args = [
"t8n",
@@ -127,16 +125,17 @@ def evaluate(
)
if self.trace:
- self.collect_traces(
- output.result.receipts, temp_dir, debug_output_path
- )
+ self.collect_traces(output.result.receipts, temp_dir, debug_output_path)
temp_dir.cleanup()
return output
class ExecutionSpecsExceptionMapper(ExceptionMapper):
- """Translate between EEST exceptions and error strings returned by ExecutionSpecs."""
+ """
+ Translate between EEST exceptions and error strings returned by
+ ExecutionSpecs.
+ """
mapping_substring: ClassVar[Dict[ExceptionBase, str]] = {
TransactionException.TYPE_4_EMPTY_AUTHORIZATION_LIST: "EmptyAuthorizationListError",
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/geth.py b/packages/tests/src/ethereum_clis/clis/geth.py
similarity index 88%
rename from src/ethereum_spec_tests/ethereum_clis/clis/geth.py
rename to packages/tests/src/ethereum_clis/clis/geth.py
index a104410923..e8589dd63e 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/geth.py
+++ b/packages/tests/src/ethereum_clis/clis/geth.py
@@ -71,7 +71,7 @@ class GethExceptionMapper(ExceptionMapper):
TransactionException.TYPE_4_TX_PRE_FORK: ("transaction type not supported"),
TransactionException.INITCODE_SIZE_EXCEEDED: "max initcode size exceeded",
TransactionException.NONCE_MISMATCH_TOO_LOW: "nonce too low",
- BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "unable to parse deposit data",
+ TransactionException.NONCE_MISMATCH_TOO_HIGH: "nonce too high",
BlockException.INCORRECT_BLOB_GAS_USED: "blob gas used mismatch",
BlockException.INCORRECT_EXCESS_BLOB_GAS: "invalid excessBlobGas",
BlockException.INVALID_VERSIONED_HASHES: "invalid number of versionedHashes",
@@ -79,6 +79,9 @@ class GethExceptionMapper(ExceptionMapper):
BlockException.SYSTEM_CONTRACT_CALL_FAILED: "system call failed to execute:",
BlockException.INVALID_BLOCK_HASH: "blockhash mismatch",
BlockException.RLP_BLOCK_LIMIT_EXCEEDED: "block RLP-encoded size exceeds maximum",
+ BlockException.INVALID_BAL_EXTRA_ACCOUNT: "BAL change not reported in computed",
+ BlockException.INVALID_BAL_MISSING_ACCOUNT: "additional mutations compared to BAL",
+ BlockException.INVALID_BLOCK_ACCESS_LIST: "unequal",
}
mapping_regex: ClassVar[Dict[ExceptionBase, str]] = {
TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: (
@@ -88,6 +91,23 @@ class GethExceptionMapper(ExceptionMapper):
r"blob gas used \d+ exceeds maximum allowance \d+"
),
BlockException.INVALID_GAS_USED_ABOVE_LIMIT: r"invalid gasUsed: have \d+, gasLimit \d+",
+ BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: (
+ r"invalid requests hash|failed to parse deposit logs"
+ ),
+ # Geth does not validate the sizes or offsets of the deposit
+ # contract logs. As a workaround we have set
+ # INVALID_DEPOSIT_EVENT_LAYOUT equal to INVALID_REQUESTS.
+ #
+ # Although this is out of spec, it is understood that this
+ # will not cause an issue so long as the mainnet/testnet
+ # deposit contracts don't change.
+ #
+ # The offsets are checked second and the sizes are checked
+ # third within the `is_valid_deposit_event_data` function:
+ # https://eips.ethereum.org/EIPS/eip-6110#block-validity
+ #
+ # EELS definition for `is_valid_deposit_event_data`:
+ # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51
}
@@ -196,7 +216,8 @@ def is_fork_supported(self, fork: Fork) -> bool:
"""
Return True if the fork is supported by the tool.
- If the fork is a transition fork, we want to check the fork it transitions to.
+ If the fork is a transition fork, we want to check the fork it
+ transitions to.
"""
return fork.transition_tool_name() in self.help_string
@@ -217,8 +238,8 @@ def consume_blockchain_test(
"""
Consume a single blockchain test.
- The `evm blocktest` command takes the `--run` argument which can be used to select a
- specific fixture from the fixture file when executing.
+ The `evm blocktest` command takes the `--run` argument which can be
+ used to select a specific fixture from the fixture file when executing.
"""
subcommand = "blocktest"
global_options = []
@@ -269,10 +290,10 @@ def consume_state_test_file(
"""
Consume an entire state test file.
- The `evm statetest` will always execute all the tests contained in a file without the
- possibility of selecting a single test, so this function is cached in order to only call
- the command once and `consume_state_test` can simply select the result that
- was requested.
+ The `evm statetest` will always execute all the tests contained in a
+ file without the possibility of selecting a single test, so this
+ function is cached in order to only call the command once and
+ `consume_state_test` can simply select the result that was requested.
"""
subcommand = "statetest"
global_options: List[str] = []
@@ -312,8 +333,8 @@ def consume_state_test(
"""
Consume a single state test.
- Uses the cached result from `consume_state_test_file` in order to not call the command
- every time an select a single result from there.
+ Uses the cached result from `consume_state_test_file` in order to not
+ call the command every time an select a single result from there.
"""
file_results = self.consume_state_test_file(
fixture_path=fixture_path,
@@ -342,7 +363,10 @@ def consume_fixture(
fixture_name: Optional[str] = None,
debug_output_path: Optional[Path] = None,
):
- """Execute the appropriate geth fixture consumer for the fixture at `fixture_path`."""
+ """
+ Execute the appropriate geth fixture consumer for the fixture at
+ `fixture_path`.
+ """
if fixture_format == BlockchainFixture:
self.consume_blockchain_test(
fixture_path=fixture_path,
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/nethermind.py b/packages/tests/src/ethereum_clis/clis/nethermind.py
similarity index 94%
rename from src/ethereum_spec_tests/ethereum_clis/clis/nethermind.py
rename to packages/tests/src/ethereum_clis/clis/nethermind.py
index 13bf2c776f..68c075fbd7 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/nethermind.py
+++ b/packages/tests/src/ethereum_clis/clis/nethermind.py
@@ -96,8 +96,9 @@ def has_eof_support(self) -> bool:
"""
Return True if the `nethtest` binary supports the `--eofTest` flag.
- Currently, nethtest EOF support is only available in nethermind's feature/evm/eof
- branch https://github.com/NethermindEth/nethermind/tree/feature/evm/eof
+ Currently, nethtest EOF support is only available in nethermind's
+ feature/evm/eof branch
+ https://github.com/NethermindEth/nethermind/tree/feature/evm/eof
"""
return "--eofTest" in self.help()
@@ -121,7 +122,8 @@ def _build_command_with_options(
if fixture_format is BlockchainFixture:
command += ["--blockTest", "--filter", f"{re.escape(fixture_name)}"]
elif fixture_format is StateFixture:
- # TODO: consider using `--filter` here to readily access traces from the output
+ # TODO: consider using `--filter` here to readily access traces
+ # from the output
pass # no additional options needed
elif fixture_format is EOFFixture:
command += ["--eofTest"]
@@ -144,10 +146,10 @@ def consume_state_test_file(
"""
Consume an entire state test file.
- The `evm statetest` will always execute all the tests contained in a file without the
- possibility of selecting a single test, so this function is cached in order to only call
- the command once and `consume_state_test` can simply select the result that
- was requested.
+ The `evm statetest` will always execute all the tests contained in a
+ file without the possibility of selecting a single test, so this
+ function is cached in order to only call the command once and
+ `consume_state_test` can simply select the result that was requested.
"""
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
@@ -180,8 +182,8 @@ def consume_state_test(
"""
Consume a single state test.
- Uses the cached result from `consume_state_test_file` in order to not call the command
- every time an select a single result from there.
+ Uses the cached result from `consume_state_test_file` in order to not
+ call the command every time an select a single result from there.
"""
file_results, stderr = self.consume_state_test_file(
fixture_path=fixture_path,
@@ -203,9 +205,6 @@ def consume_state_test(
for test_result in file_results
if test_result["name"].removesuffix(nethtest_suffix)
== f"{fixture_name.split('/')[-1]}"
- # TODO: the following was required for nethermind's feature/evm/eof branch
- # nethtest version: 1.32.0-unstable+025871675bd2e0839f93d2b70416ebae9dbae012
- # == f"{fixture_name.split('.py::')[-1]}"
]
assert len(test_result) < 2, f"Multiple test results for {fixture_name}"
assert len(test_result) == 1, f"Test result for {fixture_name} missing"
@@ -254,7 +253,8 @@ def consume_eof_test_file(
pattern = re.compile(r"^(test_.+?)\s+(PASS|FAIL)$", re.MULTILINE)
test_results = {
- match.group(1): match.group(2) == "PASS" # Convert "PASS" to True and "FAIL" to False
+ match.group(1): match.group(2) == "PASS" # Convert "PASS" to True
+ # and "FAIL" to False
for match in pattern.finditer(result.stdout)
}
@@ -297,7 +297,10 @@ def consume_fixture(
fixture_name: Optional[str] = None,
debug_output_path: Optional[Path] = None,
):
- """Execute the appropriate geth fixture consumer for the fixture at `fixture_path`."""
+ """
+ Execute the appropriate geth fixture consumer for the fixture at
+ `fixture_path`.
+ """
command = self._build_command_with_options(
fixture_format, fixture_path, fixture_name, debug_output_path
)
@@ -340,7 +343,7 @@ class NethermindExceptionMapper(ExceptionMapper):
"InvalidMaxPriorityFeePerGas: Cannot be higher than maxFeePerGas"
),
TransactionException.GAS_ALLOWANCE_EXCEEDED: "Block gas limit exceeded",
- TransactionException.NONCE_IS_MAX: "nonce overflow",
+ TransactionException.NONCE_IS_MAX: "NonceTooHigh",
TransactionException.INITCODE_SIZE_EXCEEDED: "max initcode size exceeded",
TransactionException.NONCE_MISMATCH_TOO_LOW: "wrong transaction nonce",
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS: (
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/nimbus.py b/packages/tests/src/ethereum_clis/clis/nimbus.py
similarity index 96%
rename from src/ethereum_spec_tests/ethereum_clis/clis/nimbus.py
rename to packages/tests/src/ethereum_clis/clis/nimbus.py
index 6c0960774c..a1f167c363 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/nimbus.py
+++ b/packages/tests/src/ethereum_clis/clis/nimbus.py
@@ -57,13 +57,16 @@ def is_fork_supported(self, fork: Fork) -> bool:
"""
Return True if the fork is supported by the tool.
- If the fork is a transition fork, we want to check the fork it transitions to.
+ If the fork is a transition fork, we want to check the fork it
+ transitions to.
"""
return fork.transition_tool_name() in self.help_string
class NimbusExceptionMapper(ExceptionMapper):
- """Translate between EEST exceptions and error strings returned by Nimbus."""
+ """
+ Translate between EEST exceptions and error strings returned by Nimbus.
+ """
mapping_substring: ClassVar[Dict[ExceptionBase, str]] = {
TransactionException.TYPE_4_TX_CONTRACT_CREATION: (
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/reth.py b/packages/tests/src/ethereum_clis/clis/reth.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_clis/clis/reth.py
rename to packages/tests/src/ethereum_clis/clis/reth.py
index 6eae2b7fe4..ad6d986967 100644
--- a/src/ethereum_spec_tests/ethereum_clis/clis/reth.py
+++ b/packages/tests/src/ethereum_clis/clis/reth.py
@@ -58,7 +58,7 @@ class RethExceptionMapper(ExceptionMapper):
r"transaction gas limit \w+ is more than blocks available gas \w+"
),
TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: (
- r"transaction gas limit \(\d+\) is greater than the cap \(\d+\)"
+ r"transaction gas limit.*is greater than the cap"
),
BlockException.SYSTEM_CONTRACT_CALL_FAILED: r"failed to apply .* requests contract call",
BlockException.INCORRECT_BLOB_GAS_USED: (
diff --git a/src/ethereum_spec_tests/ethereum_clis/ethereum_cli.py b/packages/tests/src/ethereum_clis/ethereum_cli.py
similarity index 87%
rename from src/ethereum_spec_tests/ethereum_clis/ethereum_cli.py
rename to packages/tests/src/ethereum_clis/ethereum_cli.py
index d08d11b529..6bdbf646ea 100644
--- a/src/ethereum_spec_tests/ethereum_clis/ethereum_cli.py
+++ b/packages/tests/src/ethereum_clis/ethereum_cli.py
@@ -8,7 +8,7 @@
from re import Pattern
from typing import Any, List, Optional, Type
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
logger = get_logger(__name__)
@@ -20,7 +20,9 @@ class UnknownCLIError(Exception):
class CLINotFoundInPathError(Exception):
- """Exception raised if the specified CLI binary is not found in the path."""
+ """
+ Exception raised if the specified CLI binary is not found in the path.
+ """
def __init__(self, message="The CLI binary was not found in the path", binary=None):
"""Initialize the exception."""
@@ -49,11 +51,14 @@ class EthereumCLI:
cached_version: Optional[str] = None
def __init__(self, *, binary: Optional[Path] = None):
- """Abstract initialization method that all subclasses must implement."""
+ """
+ Abstract initialization method that all subclasses must implement.
+ """
if binary is None:
binary = self.default_binary
else:
- # improve behavior of which by resolving the path: ~/relative paths don't work
+ # improve behavior of which by resolving the path: ~/relative paths
+ # don't work
resolved_path = Path(os.path.expanduser(binary)).resolve()
if resolved_path.exists():
binary = resolved_path
@@ -75,10 +80,12 @@ def set_default_tool(cls, tool_subclass: Type[Any]):
@classmethod
def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any:
"""
- Instantiate the appropriate CLI subclass derived from the CLI's `binary_path`.
+ Instantiate the appropriate CLI subclass derived from the CLI's
+ `binary_path`.
- This method will attempt to detect the CLI version and instantiate the appropriate
- subclass based on the version output by running the CLI with the version flag.
+ This method will attempt to detect the CLI version and instantiate the
+ appropriate subclass based on the version output by running the CLI
+ with the version flag.
"""
assert cls.default_tool is not None, "default CLI implementation was never set"
@@ -114,8 +121,8 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any:
logger.debug(f"Successfully located the path of the t8n binary: {binary}")
binary = Path(binary)
- # Group the tools by version flag, so we only have to call the tool once for all the
- # classes that share the same version flag
+ # Group the tools by version flag, so we only have to call the tool
+ # once for all the classes that share the same version flag
for version_flag, subclasses in groupby(
cls.registered_tools, key=lambda x: x.version_flag
):
@@ -134,7 +141,9 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any:
if result.returncode != 0:
logger.debug(f"Subprocess returncode is not 0! It is: {result.returncode}")
- continue # don't raise exception, you are supposed to keep trying different version flags # noqa: E501
+ continue
+ # don't raise exception, you are supposed to keep
+ # trying different version flags
if result.stderr:
logger.debug(f"Stderr detected: {result.stderr}") # type: ignore
@@ -143,10 +152,6 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any:
binary_output = ""
if result.stdout:
binary_output = result.stdout.decode().strip()
- # e.g. 1.31.10+f62cfede9b4abfb5cd62d6f138240668620a2b0d should be treated as 1.31.10 # noqa: E501
- # if "+" in binary_output:
- # binary_output = binary_output.split("+")[0]
-
logger.debug(f"Stripped subprocess stdout: {binary_output}")
for subclass in subclasses:
@@ -169,7 +174,10 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any:
@classmethod
def detect_binary(cls, binary_output: str) -> bool:
- """Return True if a CLI's `binary_output` matches the class's expected output."""
+ """
+ Return True if a CLI's `binary_output` matches the class's expected
+ output.
+ """
assert cls.detect_binary_pattern is not None
return cls.detect_binary_pattern.match(binary_output) is not None
@@ -187,7 +195,10 @@ def is_installed(cls, binary_path: Optional[Path] = None) -> bool:
return binary is not None
def version(self) -> str:
- """Return the name and version of the CLI as reported by the CLI's version flag."""
+ """
+ Return the name and version of the CLI as reported by the CLI's version
+ flag.
+ """
if self.cached_version is None:
result = subprocess.run(
[str(self.binary), self.version_flag],
diff --git a/src/ethereum_spec_tests/ethereum_clis/file_utils.py b/packages/tests/src/ethereum_clis/file_utils.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/file_utils.py
rename to packages/tests/src/ethereum_clis/file_utils.py
diff --git a/src/ethereum_spec_tests/ethereum_clis/fixture_consumer_tool.py b/packages/tests/src/ethereum_clis/fixture_consumer_tool.py
similarity index 92%
rename from src/ethereum_spec_tests/ethereum_clis/fixture_consumer_tool.py
rename to packages/tests/src/ethereum_clis/fixture_consumer_tool.py
index 1f958e2c13..3391c49a9c 100644
--- a/src/ethereum_spec_tests/ethereum_clis/fixture_consumer_tool.py
+++ b/packages/tests/src/ethereum_clis/fixture_consumer_tool.py
@@ -9,8 +9,8 @@
class FixtureConsumerTool(FixtureConsumer, EthereumCLI):
"""
- Fixture consumer tool abstract base class which should be inherited by all fixture consumer
- tool implementations.
+ Fixture consumer tool abstract base class which should be inherited by all
+ fixture consumer tool implementations.
"""
registered_tools: List[Type["FixtureConsumerTool"]] = []
diff --git a/src/ethereum_spec_tests/ethereum_clis/py.typed b/packages/tests/src/ethereum_clis/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/py.typed
rename to packages/tests/src/ethereum_clis/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/alloc.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/alloc.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/alloc.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/1/alloc.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/env.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/env.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/env.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/1/env.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/exp.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/exp.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/exp.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/1/exp.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/txs.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/txs.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/txs.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/1/txs.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/alloc.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/alloc.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/alloc.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/3/alloc.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/env.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/env.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/env.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/3/env.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/exp.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/exp.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/exp.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/3/exp.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/readme.md b/packages/tests/src/ethereum_clis/tests/fixtures/3/readme.md
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/readme.md
rename to packages/tests/src/ethereum_clis/tests/fixtures/3/readme.md
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/txs.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/txs.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/txs.json
rename to packages/tests/src/ethereum_clis/tests/fixtures/3/txs.json
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/test_execution_specs.py b/packages/tests/src/ethereum_clis/tests/test_execution_specs.py
similarity index 89%
rename from src/ethereum_spec_tests/ethereum_clis/tests/test_execution_specs.py
rename to packages/tests/src/ethereum_clis/tests/test_execution_specs.py
index 410c58a831..a748c9a5b3 100644
--- a/src/ethereum_spec_tests/ethereum_clis/tests/test_execution_specs.py
+++ b/packages/tests/src/ethereum_clis/tests/test_execution_specs.py
@@ -12,7 +12,7 @@
from ethereum_clis import ExecutionSpecsTransitionTool, TransitionTool
from ethereum_test_base_types import to_json
-from ethereum_test_forks import Berlin, Fork, Istanbul, London
+from ethereum_test_forks import Berlin
from ethereum_test_types import Alloc, Environment, Transaction
FIXTURES_ROOT = Path(os.path.join("src", "ethereum_clis", "tests", "fixtures"))
@@ -22,10 +22,11 @@
@pytest.fixture(autouse=True)
def monkeypatch_path_for_entry_points(monkeypatch):
"""
- Monkeypatch the PATH to add the "bin" directory where entrypoints are installed.
+ Monkeypatch the PATH to add the "bin" directory where entrypoints are
+ installed.
- This would typically be in the venv in which pytest is running these tests and fill,
- which, with uv, is `./.venv/bin`.
+ This would typically be in the venv in which pytest is running these tests
+ and fill, which, with uv, is `./.venv/bin`.
This is required in order for fill to locate the ethereum-spec-evm-resolver
"binary" (entrypoint) when being executed using pytester.
@@ -34,9 +35,8 @@ def monkeypatch_path_for_entry_points(monkeypatch):
monkeypatch.setenv("PATH", f"{bin_dir}:{os.environ['PATH']}")
-@pytest.mark.parametrize("fork", [London, Istanbul])
@pytest.mark.parametrize(
- "alloc,base_fee,expected_hash",
+ "alloc,expected_hash",
[
(
{
@@ -47,7 +47,6 @@ def monkeypatch_path_for_entry_points(monkeypatch):
"storage": {},
},
},
- 7,
bytes.fromhex("51e7c7508e76dca0"),
),
(
@@ -56,7 +55,6 @@ def monkeypatch_path_for_entry_points(monkeypatch):
"balance": "0x0BA1A9CE0BA1A9CE",
},
},
- None,
bytes.fromhex("51e7c7508e76dca0"),
),
(
@@ -68,7 +66,6 @@ def monkeypatch_path_for_entry_points(monkeypatch):
"storage": {},
},
},
- None,
bytes.fromhex("37c2dedbdea6b3af"),
),
(
@@ -80,25 +77,15 @@ def monkeypatch_path_for_entry_points(monkeypatch):
},
},
},
- None,
bytes.fromhex("096122e88929baec"),
),
],
)
def test_calc_state_root(
- default_t8n: TransitionTool,
- fork: Fork,
alloc: Dict,
- base_fee: int | None,
expected_hash: bytes,
) -> None:
"""Test calculation of the state root against expected hash."""
-
- class TestEnv:
- base_fee: int | None
-
- env = TestEnv()
- env.base_fee = base_fee
assert Alloc(alloc).state_root().startswith(expected_hash)
@@ -112,7 +99,8 @@ def test_evm_tool_binary_arg(evm_tool, binary_arg):
elif binary_arg == "path_type":
evm_bin = which(DEFAULT_EVM_T8N_BINARY_NAME)
if not evm_bin:
- # typing: Path can not take None; but if it is None, we may as well fail explicitly.
+ # typing: Path can not take None; but if it is None, we may as well
+ # fail explicitly.
raise Exception("Failed to find `{DEFAULT_EVM_T8N_BINARY_NAME}` in the PATH via which")
evm_tool(binary=Path(evm_bin)).version()
return
@@ -157,7 +145,9 @@ def test_evm_t8n(
env: Environment,
test_dir: str,
) -> None:
- """Test the `evaluate` method of the `ExecutionSpecsTransitionTool` class."""
+ """
+ Test the `evaluate` method of the `ExecutionSpecsTransitionTool` class.
+ """
expected_path = Path(FIXTURES_ROOT, test_dir, "exp.json")
with open(expected_path, "r") as exp:
@@ -176,8 +166,9 @@ def test_evm_t8n(
)
assert to_json(t8n_output.alloc) == expected.get("alloc")
if isinstance(default_t8n, ExecutionSpecsTransitionTool):
- # The expected output was generated with geth, instead of deleting any info from
- # this expected output, the fields not returned by eels are handled here.
+ # The expected output was generated with geth, instead of deleting
+ # any info from this expected output, the fields not returned by
+ # eels are handled here.
missing_receipt_fields = [
"root",
"status",
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tool.py b/packages/tests/src/ethereum_clis/tests/test_transition_tool.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tool.py
rename to packages/tests/src/ethereum_clis/tests/test_transition_tool.py
index 40884de027..01c2c1bb10 100644
--- a/src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tool.py
+++ b/packages/tests/src/ethereum_clis/tests/test_transition_tool.py
@@ -67,9 +67,11 @@ def __init__(self, stdout):
self.returncode = 0
def mock_which(self):
+ del self
return which_result
def mock_run(args, **kwargs):
+ del args, kwargs
return MockCompletedProcess(read_result.encode())
monkeypatch.setattr(shutil, "which", mock_which)
diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tools_support.py b/packages/tests/src/ethereum_clis/tests/test_transition_tools_support.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tools_support.py
rename to packages/tests/src/ethereum_clis/tests/test_transition_tools_support.py
index 3c6fd625c1..8c6f94278b 100644
--- a/src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tools_support.py
+++ b/packages/tests/src/ethereum_clis/tests/test_transition_tools_support.py
@@ -31,8 +31,8 @@
Withdrawal,
add_kzg_version,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types import Alloc
+from ethereum_test_vm import Opcodes as Op
BLOB_COMMITMENT_VERSION_KZG = 1
@@ -44,7 +44,9 @@ def test_ci_multi_t8n_support(
installed_transition_tool_instances: Dict[str, TransitionTool | Exception],
running_in_ci: bool,
):
- """Check that the instances of t8n we expect in CI environment were found."""
+ """
+ Check that the instances of t8n we expect in CI environment were found.
+ """
names = set(installed_transition_tool_instances.keys())
expected_names = {"ExecutionSpecsTransitionTool"}
if running_in_ci:
diff --git a/src/ethereum_spec_tests/ethereum_clis/transition_tool.py b/packages/tests/src/ethereum_clis/transition_tool.py
similarity index 89%
rename from src/ethereum_spec_tests/ethereum_clis/transition_tool.py
rename to packages/tests/src/ethereum_clis/transition_tool.py
index 58d66424dc..f141f3ff70 100644
--- a/src/ethereum_spec_tests/ethereum_clis/transition_tool.py
+++ b/packages/tests/src/ethereum_clis/transition_tool.py
@@ -24,9 +24,8 @@
from ethereum_test_forks.helpers import get_development_forks, get_forks
from ethereum_test_types import Alloc, Environment, Transaction
-from .ethereum_cli import EthereumCLI
-from .file_utils import dump_files_to_directory, write_json_file
-from .types import (
+from .cli_types import (
+ OpcodeCount,
Traces,
TransactionReceipt,
TransactionTraces,
@@ -35,25 +34,29 @@
TransitionToolOutput,
TransitionToolRequest,
)
+from .ethereum_cli import EthereumCLI
+from .file_utils import dump_files_to_directory, write_json_file
model_dump_config: Mapping = {"by_alias": True, "exclude_none": True}
-# TODO: reduce NORMAL_SERVER_TIMEOUT back down to 20 once BLS timeout issue is resolved:
-# https://github.com/ethereum/execution-spec-tests/issues/1894
+# TODO: reduce NORMAL_SERVER_TIMEOUT back down to 20 once BLS timeout issue is
+# resolved: https://github.com/ethereum/execution-spec-tests/issues/1894
NORMAL_SERVER_TIMEOUT = 600
SLOW_REQUEST_TIMEOUT = 600
def get_valid_transition_tool_names() -> set[str]:
- """Get all valid transition tool names from deployed and development forks."""
+ """
+ Get all valid transition tool names from deployed and development forks.
+ """
all_available_forks = get_forks() + get_development_forks()
return {fork.transition_tool_name() for fork in all_available_forks}
class TransitionTool(EthereumCLI):
"""
- Transition tool abstract base class which should be inherited by all transition tool
- implementations.
+ Transition tool abstract base class which should be inherited by all
+ transition tool implementations.
"""
traces: List[Traces] | None = None
@@ -69,6 +72,7 @@ class TransitionTool(EthereumCLI):
t8n_use_server: bool = False
server_url: str | None = None
process: Optional[subprocess.Popen] = None
+ supports_opcode_count: ClassVar[bool] = False
supports_xdist: ClassVar[bool] = True
@@ -80,7 +84,9 @@ def __init__(
binary: Optional[Path] = None,
trace: bool = False,
):
- """Abstract initialization method that all subclasses must implement."""
+ """
+ Abstract initialization method that all subclasses must implement.
+ """
assert exception_mapper is not None
self.exception_mapper = exception_mapper
super().__init__(binary=binary)
@@ -112,7 +118,9 @@ def reset_traces(self):
self.traces = None
def append_traces(self, new_traces: Traces):
- """Append a list of traces of a state transition to the current list."""
+ """
+ Append a list of traces of a state transition to the current list.
+ """
if self.traces is None:
self.traces = []
self.traces.append(new_traces)
@@ -127,7 +135,10 @@ def collect_traces(
temp_dir: tempfile.TemporaryDirectory,
debug_output_path: str = "",
) -> Traces:
- """Collect the traces from the t8n tool output and store them in the traces list."""
+ """
+ Collect the traces from the t8n tool output and store them in the
+ traces list.
+ """
traces: Traces = Traces(root=[])
temp_dir_path = Path(temp_dir.name)
for i, r in enumerate(receipts):
@@ -194,7 +205,10 @@ def _evaluate_filesystem(
t8n_data: TransitionToolData,
debug_output_path: str = "",
) -> TransitionToolOutput:
- """Execute a transition tool using the filesystem for its inputs and outputs."""
+ """
+ Execute a transition tool using the filesystem for its inputs and
+ outputs.
+ """
temp_dir = tempfile.TemporaryDirectory()
os.mkdir(os.path.join(temp_dir.name, "input"))
os.mkdir(os.path.join(temp_dir.name, "output"))
@@ -236,6 +250,13 @@ def _evaluate_filesystem(
"--state.chainid",
str(t8n_data.chain_id),
]
+ if self.supports_opcode_count:
+ args.extend(
+ [
+ "--opcode.count",
+ "opcodes.json",
+ ]
+ )
if self.trace:
args.append("--trace")
@@ -256,14 +277,16 @@ def _evaluate_filesystem(
t8n_call = t8n_call.replace(
os.path.dirname(file_path), os.path.join(debug_output_path, "input")
)
- t8n_call = t8n_call.replace( # use a new output path for basedir and outputs
+ # use a new output path for basedir and outputs
+ t8n_call = t8n_call.replace(
temp_dir.name,
t8n_output_base_dir,
)
t8n_script = textwrap.dedent(
f"""\
#!/bin/bash
- rm -rf {debug_output_path}/t8n.sh.out # hard-coded to avoid surprises
+ # hard-coded to avoid surprises
+ rm -rf {debug_output_path}/t8n.sh.out
mkdir -p {debug_output_path}/t8n.sh.out/output
{t8n_call}
"""
@@ -294,6 +317,20 @@ def _evaluate_filesystem(
output = TransitionToolOutput.model_validate(
output_contents, context={"exception_mapper": self.exception_mapper}
)
+ if self.supports_opcode_count:
+ opcode_count_file_path = Path(temp_dir.name) / "opcodes.json"
+ if opcode_count_file_path.exists():
+ opcode_count = OpcodeCount.model_validate_json(opcode_count_file_path.read_text())
+ output.result.opcode_count = opcode_count
+
+ if debug_output_path:
+ dump_files_to_directory(
+ debug_output_path,
+ {
+ "opcodes.json": opcode_count.model_dump(),
+ },
+ )
+
if self.trace:
output.result.traces = self.collect_traces(
output.result.receipts, temp_dir, debug_output_path
@@ -355,7 +392,9 @@ def _evaluate_server(
debug_output_path: str = "",
timeout: int,
) -> TransitionToolOutput:
- """Execute the transition tool sending inputs and outputs via a server."""
+ """
+ Execute the transition tool sending inputs and outputs via a server.
+ """
request_data = t8n_data.get_request_data()
request_data_json = request_data.model_dump(mode="json", **model_dump_config)
@@ -424,7 +463,10 @@ def _evaluate_stream(
t8n_data: TransitionToolData,
debug_output_path: str = "",
) -> TransitionToolOutput:
- """Execute a transition tool using stdin and stdout for its inputs and outputs."""
+ """
+ Execute a transition tool using stdin and stdout for its inputs and
+ outputs.
+ """
temp_dir = tempfile.TemporaryDirectory()
args = self.construct_args_stream(t8n_data, temp_dir)
@@ -460,15 +502,16 @@ def _evaluate_stream(
output.result.traces = self.collect_traces(
output.result.receipts, temp_dir, debug_output_path
)
- temp_dir.cleanup()
+ temp_dir.cleanup()
return output
def safe_t8n_args(
self, fork_name: str, chain_id: int, reward: int, temp_dir=None
) -> List[str]:
"""Safely construct t8n arguments with validated inputs."""
- # Validate fork name against actual transition tool names from all available forks
+ # Validate fork name against actual transition tool names from all
+ # available forks
valid_forks = get_valid_transition_tool_names()
if fork_name not in valid_forks:
raise ValueError(f"Invalid fork name: {fork_name}")
@@ -528,7 +571,9 @@ def dump_debug_stream(
args: List[str],
result: subprocess.CompletedProcess,
):
- """Export debug files if requested when interacting with t8n via streams."""
+ """
+ Export debug files if requested when interacting with t8n via streams.
+ """
if not debug_output_path:
return
@@ -539,8 +584,11 @@ def dump_debug_stream(
t8n_script = textwrap.dedent(
f"""\
#!/bin/bash
- rm -rf {debug_output_path}/t8n.sh.out # hard-coded to avoid surprises
- mkdir {debug_output_path}/t8n.sh.out # unused if tracing is not enabled
+ # hard-coded to avoid surprises
+ rm -rf {debug_output_path}/t8n.sh.out
+
+ # unused if tracing is not enabled
+ mkdir {debug_output_path}/t8n.sh.out
{t8n_call} < {debug_output_path}/stdin.txt
"""
)
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/__init__.py b/packages/tests/src/ethereum_test_base_types/__init__.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_base_types/__init__.py
rename to packages/tests/src/ethereum_test_base_types/__init__.py
index 3bb8c6a370..6562a2e848 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/__init__.py
+++ b/packages/tests/src/ethereum_test_base_types/__init__.py
@@ -18,6 +18,7 @@
Wei,
ZeroPaddedHexNumber,
)
+from .base_types_json import to_json
from .composite_types import (
AccessList,
Account,
@@ -38,7 +39,6 @@
TestPrivateKey2,
)
from .conversions import to_bytes, to_hex
-from .json import to_json
from .pydantic import CamelModel, EthereumTestBaseModel, EthereumTestRootModel
from .reference_spec import ReferenceSpec
from .serialization import RLPSerializable, SignableRLPSerializable
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/base_types.py b/packages/tests/src/ethereum_test_base_types/base_types.py
similarity index 92%
rename from src/ethereum_spec_tests/ethereum_test_base_types/base_types.py
rename to packages/tests/src/ethereum_test_base_types/base_types.py
index d50155ac38..8900eafd8a 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/base_types.py
+++ b/packages/tests/src/ethereum_test_base_types/base_types.py
@@ -24,15 +24,18 @@
class ToStringSchema:
"""
- Type converter to add a simple pydantic schema that correctly
- parses and serializes the type.
+ Type converter to add a simple pydantic schema that correctly parses and
+ serializes the type.
"""
@staticmethod
def __get_pydantic_core_schema__(
source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call the class constructor without info and appends the serialization schema."""
+ """
+ Call the class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
source_type,
serialization=to_string_ser_schema(),
@@ -80,13 +83,15 @@ def __new__(cls, input_number: NumberConvertible | Self):
base, exp = value_str.split("**")
value = float(base) ** int(exp)
else:
- value = float(value_str)
+ value = int(value_str) if value_str.isdecimal() else float(value_str)
return super(Number, cls).__new__(cls, value * multiplier)
return super(Number, cls).__new__(cls, to_number(input_number))
@staticmethod
def _get_multiplier(unit: str) -> int:
- """Return the multiplier for the given unit of wei, handling synonyms."""
+ """
+ Return the multiplier for the given unit of wei, handling synonyms.
+ """
match unit:
case "wei":
return 1
@@ -117,7 +122,10 @@ def __str__(self) -> str:
def __get_pydantic_core_schema__(
source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call the class constructor without info and appends the serialization schema."""
+ """
+ Call the class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
source_type,
serialization=to_string_ser_schema(),
@@ -143,7 +151,10 @@ def hex(self) -> str:
def __get_pydantic_core_schema__(
source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call the class constructor without info and appends the serialization schema."""
+ """
+ Call the class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
source_type,
serialization=to_string_ser_schema(),
@@ -197,7 +208,10 @@ def sha256(self) -> "Hash":
def __get_pydantic_core_schema__(
source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call the class constructor without info and appends the serialization schema."""
+ """
+ Call the class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
source_type,
serialization=to_string_ser_schema(),
@@ -256,7 +270,10 @@ def hex(self) -> str:
def __get_pydantic_core_schema__(
cls: Type[Self], source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call the class constructor without info and appends the serialization schema."""
+ """
+ Call the class constructor without info and appends the serialization
+ schema.
+ """
pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$"
return no_info_plain_validator_function(
source_type,
@@ -341,7 +358,10 @@ def __ne__(self, other: object) -> bool:
def __get_pydantic_core_schema__(
cls: Type[Self], source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call the class constructor without info and appends the serialization schema."""
+ """
+ Call the class constructor without info and appends the serialization
+ schema.
+ """
pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$"
return no_info_plain_validator_function(
source_type,
@@ -351,7 +371,9 @@ def __get_pydantic_core_schema__(
class ForkHash(FixedSizeBytes[4]): # type: ignore
- """Class that helps represent the CRC config hashes and identifiers of a fork."""
+ """
+ Class that helps represent the CRC config hashes and identifiers of a fork.
+ """
pass
@@ -391,7 +413,8 @@ class StorageKey(FixedSizeBytes[32]): # type: ignore
def __new__(cls, value, **kwargs):
"""Create a new StorageKey with automatic left padding."""
- # Always apply left_padding for storage keys unless explicitly set to False
+ # Always apply left_padding for storage keys unless explicitly set to
+ # False
if "left_padding" not in kwargs:
kwargs["left_padding"] = True
return super().__new__(cls, value, **kwargs)
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/json.py b/packages/tests/src/ethereum_test_base_types/base_types_json.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_base_types/json.py
rename to packages/tests/src/ethereum_test_base_types/base_types_json.py
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/composite_types.py b/packages/tests/src/ethereum_test_base_types/composite_types.py
similarity index 91%
rename from src/ethereum_spec_tests/ethereum_test_base_types/composite_types.py
rename to packages/tests/src/ethereum_test_base_types/composite_types.py
index 035bfb2a88..63fbe534ff 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/composite_types.py
+++ b/packages/tests/src/ethereum_test_base_types/composite_types.py
@@ -41,7 +41,9 @@ class Storage(EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueTyp
@dataclass(kw_only=True)
class InvalidTypeError(Exception):
- """Invalid type used when describing test's expected storage key or value."""
+ """
+ Invalid type used when describing test's expected storage key or value.
+ """
key_or_value: Any
@@ -90,8 +92,8 @@ def __str__(self):
@dataclass(kw_only=True)
class KeyValueMismatchError(Exception):
"""
- Test expected a certain value in a storage key but value found
- was different.
+ Test expected a certain value in a storage key but value found was
+ different.
"""
address: Address
@@ -101,7 +103,10 @@ class KeyValueMismatchError(Exception):
hint: str
def __init__(self, address: Address, key: int, want: int, got: int, hint: str = "", *args):
- """Initialize the exception with the address, key, wanted and got values."""
+ """
+ Initialize the exception with the address, key, wanted and got
+ values.
+ """
super().__init__(args)
self.address = address
self.key = key
@@ -183,14 +188,17 @@ def items(self):
return self.root.items()
def set_expect_any(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType):
- """Mark key to be able to have any expected value when comparing storages."""
+ """
+ Mark key to be able to have any expected value when comparing storages.
+ """
self._any_map[StorageKeyValueTypeAdapter.validate_python(key)] = True
def store_next(
self, value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool, hint: str = ""
) -> StorageKeyValueType:
"""
- Store a value in the storage and returns the key where the value is stored.
+ Store a value in the storage and returns the key where the value is
+ stored.
Increments the key counter so the next time this function is called,
the next key is used.
@@ -208,10 +216,9 @@ def peek_slot(self) -> int:
def contains(self, other: "Storage") -> bool:
"""
- Return True if self contains all keys with equal value as
- contained by second storage.
- Used for comparison with test expected post state and alloc returned
- by the transition tool.
+ Return True if self contains all keys with equal value as contained by
+ second storage. Used for comparison with test expected post state and
+ alloc returned by the transition tool.
"""
for key in other.keys():
if key not in self:
@@ -222,11 +229,10 @@ def contains(self, other: "Storage") -> bool:
def must_contain(self, address: Address, other: "Storage"):
"""
- Succeeds only if self contains all keys with equal value as
- contained by second storage.
- Used for comparison with test expected post state and alloc returned
- by the transition tool.
- Raises detailed exception when a difference is found.
+ Succeeds only if self contains all keys with equal value as contained
+ by second storage. Used for comparison with test expected post state
+ and alloc returned by the transition tool. Raises detailed exception
+ when a difference is found.
"""
for key in other.keys():
if key not in self:
@@ -283,8 +289,9 @@ def must_be_equal(self, address: Address, other: "Storage | None"):
def canary(self) -> "Storage":
"""
- Return a canary storage filled with non-zero values where the current storage expects
- zero values, to guarantee that the test overwrites the storage.
+ Return a canary storage filled with non-zero values where the current
+ storage expects zero values, to guarantee that the test overwrites the
+ storage.
"""
return Storage({key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0})
@@ -294,22 +301,15 @@ class Account(CamelModel):
nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
"""
- The scalar value equal to a) the number of transactions sent by
- an Externally Owned Account, b) the amount of contracts created by a
- contract.
+ The scalar value equal to a) the number of transactions sent by an
+ Externally Owned Account, b) the amount of contracts created by a contract.
"""
balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
- """
- The amount of Wei (10-18 Eth) the account has.
- """
+ """The amount of Wei (10-18 Eth) the account has."""
code: Bytes = Bytes(b"")
- """
- Bytecode contained by the account.
- """
+ """Bytecode contained by the account."""
storage: Storage = Field(default_factory=Storage)
- """
- Storage within a contract.
- """
+ """Storage within a contract."""
NONEXISTENT: ClassVar[None] = None
"""
@@ -329,7 +329,9 @@ class NonceMismatchError(Exception):
got: int | None
def __init__(self, address: Address, want: int | None, got: int | None, *args):
- """Initialize the exception with the address, wanted and got values."""
+ """
+ Initialize the exception with the address, wanted and got values.
+ """
super().__init__(args)
self.address = address
self.want = want
@@ -348,8 +350,8 @@ def __str__(self):
@dataclass(kw_only=True)
class BalanceMismatchError(Exception):
"""
- Test expected a certain balance for an account but a different
- value was found.
+ Test expected a certain balance for an account but a different value
+ was found.
"""
address: Address
@@ -357,7 +359,9 @@ class BalanceMismatchError(Exception):
got: int | None
def __init__(self, address: Address, want: int | None, got: int | None, *args):
- """Initialize the exception with the address, wanted and got values."""
+ """
+ Initialize the exception with the address, wanted and got values.
+ """
super().__init__(args)
self.address = address
self.want = want
@@ -376,8 +380,8 @@ def __str__(self):
@dataclass(kw_only=True)
class CodeMismatchError(Exception):
"""
- Test expected a certain bytecode for an account but a different
- one was found.
+ Test expected a certain bytecode for an account but a different one was
+ found.
"""
address: Address
@@ -385,7 +389,9 @@ class CodeMismatchError(Exception):
got: bytes | None
def __init__(self, address: Address, want: bytes | None, got: bytes | None, *args):
- """Initialize the exception with the address, wanted and got values."""
+ """
+ Initialize the exception with the address, wanted and got values.
+ """
super().__init__(args)
self.address = address
self.want = want
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/constants.py b/packages/tests/src/ethereum_test_base_types/constants.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_base_types/constants.py
rename to packages/tests/src/ethereum_test_base_types/constants.py
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/conversions.py b/packages/tests/src/ethereum_test_base_types/conversions.py
similarity index 87%
rename from src/ethereum_spec_tests/ethereum_test_base_types/conversions.py
rename to packages/tests/src/ethereum_test_base_types/conversions.py
index e99743ba24..84fbb77895 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/conversions.py
+++ b/packages/tests/src/ethereum_test_base_types/conversions.py
@@ -60,12 +60,16 @@ def to_fixed_size_bytes(
"""
Convert multiple types into fixed-size bytes.
- :param input_bytes: The input data to convert.
- :param size: The size of the output bytes.
- :param left_padding: Whether to allow left-padding of the input data bytes using zeros. If the
- input data is an integer, padding is always performed.
- :param right_padding: Whether to allow right-padding of the input data bytes using zeros. If
- the input data is an integer, padding is always performed.
+ Args:
+ input_bytes: The input data to convert.
+ size: The size of the output bytes.
+ left_padding: Whether to allow left-padding of the input data bytes
+ using zeros. If the input data is an integer, padding is
+ always performed.
+ right_padding: Whether to allow right-padding of the input data bytes
+ using zeros. If the input data is an integer, padding
+ is always performed.
+
"""
if isinstance(input_bytes, int):
return int.to_bytes(input_bytes, length=size, byteorder="big", signed=input_bytes < 0)
diff --git a/packages/tests/src/ethereum_test_base_types/mixins.py b/packages/tests/src/ethereum_test_base_types/mixins.py
new file mode 100644
index 0000000000..d5c1d4cf5f
--- /dev/null
+++ b/packages/tests/src/ethereum_test_base_types/mixins.py
@@ -0,0 +1,92 @@
+"""Provides various mixins for Pydantic models."""
+
+from typing import Any, Literal
+
+from pydantic import BaseModel
+
+
+class ModelCustomizationsMixin:
+ """
+ A mixin that customizes the behavior of pydantic models. Any pydantic
+ configuration override that must apply to all models should be placed here.
+
+ This mixin is applied to both `EthereumTestBaseModel` and
+ `EthereumTestRootModel`.
+ """
+
+ def serialize(
+ self,
+ mode: Literal["json", "python"],
+ by_alias: bool,
+ exclude_none: bool = True,
+ ) -> dict[str, Any]:
+ """
+ Serialize the model to the specified format with the given parameters.
+
+ Args:
+ mode: The mode of serialization. If mode is 'json', the output
+ will only contain JSON serializable types. If mode is
+ 'python', the output may contain non-JSON-serializable
+ Python objects.
+ by_alias: Whether to use aliases for field names.
+ exclude_none: Whether to exclude fields with None values,
+ default is True.
+
+ Returns:
+ dict[str, Any]: The serialized representation of the model.
+
+ """
+ if not hasattr(self, "model_dump"):
+ raise NotImplementedError(
+ f"{self.__class__.__name__} does not have 'model_dump' method."
+ "Are you sure you are using a Pydantic model?"
+ )
+ return self.model_dump(mode=mode, by_alias=by_alias, exclude_none=exclude_none)
+
+ def __repr_args__(self):
+ """
+ Generate a list of attribute-value pairs for the object representation.
+
+ This method serializes the model, retrieves the attribute names, and
+ constructs a list of tuples containing attribute names and their
+ corresponding values. Only attributes with non-None values are included
+ in the list.
+
+ This method is used by the __repr__ method to generate the object
+ representation, and is used by `gentest` module to generate the test
+ cases.
+
+ See:
+ https://pydantic-docs.helpmanual.io/usage/models/
+ #custom-repr
+
+ and
+
+ https://github.com/ethereum/execution-spec-tests/pull/
+ 901#issuecomment-24432968 35
+
+ Returns:
+ List[Tuple[str, Any]]: A list of tuples where each tuple
+ contains an attribute name and its
+ corresponding non-None value.
+
+ """
+ attrs_names = self.serialize(mode="python", by_alias=False).keys()
+ attrs = ((s, getattr(self, s)) for s in attrs_names)
+
+ # Convert field values based on their type. This ensures consistency
+ # between JSON and Python object representations. Should a custom
+ # `__repr__` be needed for a specific type, it can added in the match
+ # statement below. Otherwise, the default string representation is
+ # used.
+ repr_attrs = []
+ for a, v in attrs:
+ match v:
+ # Note: The `None` case handles an edge case with transactions
+ # see: https://github.com/ethereum/execution-spec-tests/pull/
+ # 901#discussion_r1828491918
+ case list() | dict() | BaseModel() | None:
+ repr_attrs.append((a, v))
+ case _:
+ repr_attrs.append((a, str(v)))
+ return repr_attrs
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/py.typed b/packages/tests/src/ethereum_test_base_types/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_base_types/py.typed
rename to packages/tests/src/ethereum_test_base_types/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/pydantic.py b/packages/tests/src/ethereum_test_base_types/pydantic.py
similarity index 86%
rename from src/ethereum_spec_tests/ethereum_test_base_types/pydantic.py
rename to packages/tests/src/ethereum_test_base_types/pydantic.py
index 6471fe07fa..6d58f1fcf9 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/pydantic.py
+++ b/packages/tests/src/ethereum_test_base_types/pydantic.py
@@ -27,7 +27,9 @@ class CopyValidateModel(EthereumTestBaseModel):
"""Model that supports copying with validation."""
def copy(self: Self, **kwargs) -> Self:
- """Create a copy of the model with the updated fields that are validated."""
+ """
+ Create a copy of the model with the updated fields that are validated.
+ """
return self.__class__(**(self.model_dump(exclude_unset=True) | kwargs))
@@ -35,8 +37,8 @@ class CamelModel(CopyValidateModel):
"""
A base model that converts field names to camel case when serializing.
- For example, the field name `current_timestamp` in a Python model will be represented
- as `currentTimestamp` when it is serialized to json.
+ For example, the field name `current_timestamp` in a Python model will be
+ represented as `currentTimestamp` when it is serialized to json.
"""
model_config = ConfigDict(
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/__init__.py b/packages/tests/src/ethereum_test_base_types/reference_spec/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/__init__.py
rename to packages/tests/src/ethereum_test_base_types/reference_spec/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/git_reference_spec.py b/packages/tests/src/ethereum_test_base_types/reference_spec/git_reference_spec.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/git_reference_spec.py
rename to packages/tests/src/ethereum_test_base_types/reference_spec/git_reference_spec.py
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/reference_spec.py b/packages/tests/src/ethereum_test_base_types/reference_spec/reference_spec.py
similarity index 81%
rename from src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/reference_spec.py
rename to packages/tests/src/ethereum_test_base_types/reference_spec/reference_spec.py
index 96a0f49392..3bf3611352 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/reference_spec.py
+++ b/packages/tests/src/ethereum_test_base_types/reference_spec/reference_spec.py
@@ -36,7 +36,10 @@ def name(self) -> str:
@abstractmethod
def has_known_version(self) -> bool:
- """Return true if the reference spec object is hard-coded with a latest known version."""
+ """
+ Return true if the reference spec object is hard-coded with a latest
+ known version.
+ """
pass
@abstractmethod
@@ -46,7 +49,9 @@ def known_version(self) -> str:
@abstractmethod
def api_url(self) -> str:
- """Return the URL required to poll the version from an API, if needed."""
+ """
+ Return the URL required to poll the version from an API, if needed.
+ """
pass
@abstractmethod
@@ -64,13 +69,19 @@ def is_outdated(self) -> bool:
@abstractmethod
def write_info(self, info: Dict[str, Dict[str, Any] | str]):
- """Write info about the reference specification used into the output fixture."""
+ """
+ Write info about the reference specification used into the output
+ fixture.
+ """
pass
@staticmethod
@abstractmethod
def parseable_from_module(module_dict: Dict[str, Any]) -> bool:
- """Check whether the module's dict contains required reference spec information."""
+ """
+ Check whether the module's dict contains required reference spec
+ information.
+ """
pass
@staticmethod
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/serialization.py b/packages/tests/src/ethereum_test_base_types/serialization.py
similarity index 92%
rename from src/ethereum_spec_tests/ethereum_test_base_types/serialization.py
rename to packages/tests/src/ethereum_test_base_types/serialization.py
index 35aeaaf233..f0f18f5084 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/serialization.py
+++ b/packages/tests/src/ethereum_test_base_types/serialization.py
@@ -36,26 +36,29 @@ class RLPSerializable:
def get_rlp_fields(self) -> List[str]:
"""
- Return an ordered list of field names to be included in RLP serialization.
+ Return an ordered list of field names to be included in RLP
+ serialization.
Function can be overridden to customize the logic to return the fields.
By default, rlp_fields class variable is used.
- The list can be nested list up to one extra level to represent nested fields.
+ The list can be nested list up to one extra level to represent nested
+ fields.
"""
return self.rlp_fields
def get_rlp_signing_fields(self) -> List[str]:
"""
- Return an ordered list of field names to be included in the RLP serialization of the object
- signature.
+ Return an ordered list of field names to be included in the RLP
+ serialization of the object signature.
Function can be overridden to customize the logic to return the fields.
By default, rlp_signing_fields class variable is used.
- The list can be nested list up to one extra level to represent nested fields.
+ The list can be nested list up to one extra level to represent nested
+ fields.
"""
return self.rlp_signing_fields
@@ -69,7 +72,8 @@ def get_rlp_prefix(self) -> bytes:
def get_rlp_signing_prefix(self) -> bytes:
"""
- Return a prefix that has to be appended to the serialized signing object.
+ Return a prefix that has to be appended to the serialized signing
+ object.
By default, an empty string is returned.
"""
@@ -117,8 +121,9 @@ def to_list(self, signing: bool = False) -> List[Any]:
field_list = self.get_rlp_signing_fields()
else:
if self.signable:
- # Automatically sign signable objects during full serialization:
- # Ensures nested objects have valid signatures in the final RLP.
+ # Automatically sign signable objects during full
+ # serialization: Ensures nested objects have valid signatures
+ # in the final RLP.
self.sign()
field_list = self.get_rlp_fields()
@@ -136,7 +141,9 @@ def rlp(self) -> Bytes:
class SignableRLPSerializable(RLPSerializable):
- """Class that adds RLP serialization to another class with signing support."""
+ """
+ Class that adds RLP serialization to another class with signing support.
+ """
signable: ClassVar[bool] = True
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/tests/__init__.py b/packages/tests/src/ethereum_test_base_types/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_base_types/tests/__init__.py
rename to packages/tests/src/ethereum_test_base_types/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/tests/test_base_types.py b/packages/tests/src/ethereum_test_base_types/tests/test_base_types.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_base_types/tests/test_base_types.py
rename to packages/tests/src/ethereum_test_base_types/tests/test_base_types.py
index c53ff13898..719b2a5633 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/tests/test_base_types.py
+++ b/packages/tests/src/ethereum_test_base_types/tests/test_base_types.py
@@ -5,8 +5,8 @@
import pytest
from ..base_types import Address, Hash, Wei
+from ..base_types_json import to_json
from ..composite_types import AccessList
-from ..json import to_json
@pytest.mark.parametrize(
@@ -163,6 +163,9 @@ def test_address_padding():
("1e18", 10**18),
("1 ether", 10**18),
("2 ether", 2 * 10**18),
+ ("70000 ether", 70000 * 10**18),
+ ("123456 ether", 123456 * 10**18),
+ ("123456.789 ether", 123456.789 * 10**18),
("2.1 ether", 2.1 * 10**18),
("2.1 Ether", 2.1 * 10**18),
("2.1 ETHER", 2.1 * 10**18),
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/tests/test_reference_spec.py b/packages/tests/src/ethereum_test_base_types/tests/test_reference_spec.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_base_types/tests/test_reference_spec.py
rename to packages/tests/src/ethereum_test_base_types/tests/test_reference_spec.py
index c7aedbc5fb..dbb15d89cc 100644
--- a/src/ethereum_spec_tests/ethereum_test_base_types/tests/test_reference_spec.py
+++ b/packages/tests/src/ethereum_test_base_types/tests/test_reference_spec.py
@@ -8,7 +8,8 @@
from ..reference_spec.git_reference_spec import GitReferenceSpec
from ..reference_spec.reference_spec import NoLatestKnownVersionError
-# the content field from https://api.github.com/repos/ethereum/EIPs/contents/EIPS/eip-100.md
+# the content field from
+# https://api.github.com/repos/ethereum/EIPs/contents/EIPS/eip-100.md
# as of 2023-08-29
response_content = "LS0tCmVpcDogMTAwCnRpdGxlOiBDaGFuZ2UgZGlmZmljdWx0eSBhZGp1c3Rt\
ZW50IHRvIHRhcmdldCBtZWFuIGJsb2NrIHRpbWUgaW5jbHVkaW5nIHVuY2xl\
@@ -63,6 +64,8 @@ def test_git_reference_spec(monkeypatch):
"""Test Git reference spec."""
def mock_get(self, headers=None):
+ del self, headers
+
class Response:
content = (
'{"content": "'
diff --git a/packages/tests/src/ethereum_test_benchmark/__init__.py b/packages/tests/src/ethereum_test_benchmark/__init__.py
new file mode 100644
index 0000000000..fb8b71a207
--- /dev/null
+++ b/packages/tests/src/ethereum_test_benchmark/__init__.py
@@ -0,0 +1,16 @@
+"""
+Benchmark code generator classes for
+creating optimized bytecode patterns.
+"""
+
+from .benchmark_code_generator import (
+ BenchmarkCodeGenerator,
+ ExtCallGenerator,
+ JumpLoopGenerator,
+)
+
+__all__ = (
+ "BenchmarkCodeGenerator",
+ "ExtCallGenerator",
+ "JumpLoopGenerator",
+)
diff --git a/packages/tests/src/ethereum_test_benchmark/benchmark_code_generator.py b/packages/tests/src/ethereum_test_benchmark/benchmark_code_generator.py
new file mode 100644
index 0000000000..311b4132c3
--- /dev/null
+++ b/packages/tests/src/ethereum_test_benchmark/benchmark_code_generator.py
@@ -0,0 +1,80 @@
+"""
+Benchmark code generator classes for creating
+optimized bytecode patterns.
+"""
+
+from ethereum_test_forks import Fork
+from ethereum_test_specs.benchmark import BenchmarkCodeGenerator
+from ethereum_test_types import Alloc, Transaction
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm.opcodes import Opcodes as Op
+
+
+class JumpLoopGenerator(BenchmarkCodeGenerator):
+ """Generates bytecode that loops execution using JUMP operations."""
+
+ def deploy_contracts(self, pre: Alloc, fork: Fork) -> None:
+ """Deploy the looping contract."""
+ # Benchmark Test Structure:
+ # setup + JUMPDEST + attack + attack + ... +
+ # attack + JUMP(setup_length)
+ code = self.generate_repeated_code(self.attack_block, self.setup, fork)
+ self._contract_address = pre.deploy_contract(code=code)
+
+ def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transaction:
+ """Generate transaction that executes the looping contract."""
+ if not hasattr(self, "_contract_address"):
+ raise ValueError("deploy_contracts must be called before generate_transaction")
+
+ return Transaction(
+ to=self._contract_address,
+ gas_limit=gas_limit,
+ sender=pre.fund_eoa(),
+ )
+
+
+class ExtCallGenerator(BenchmarkCodeGenerator):
+ """
+ Generates bytecode that fills the contract to
+ maximum allowed code size.
+ """
+
+ def deploy_contracts(self, pre: Alloc, fork: Fork) -> None:
+ """Deploy both target and caller contracts."""
+ # Benchmark Test Structure:
+ # There are two contracts:
+ # 1. The target contract that executes certain operation
+ # but not loop (e.g. PUSH)
+ # 2. The loop contract that calls the target contract in a loop
+
+ max_iterations = min(
+ fork.max_stack_height(), fork.max_code_size() // len(self.attack_block)
+ )
+
+ # Deploy target contract that contains the actual attack block
+ self._target_contract_address = pre.deploy_contract(
+ code=self.attack_block * max_iterations
+ )
+
+ # Create caller contract that repeatedly calls the target contract
+ # attack = POP(
+ # STATICCALL(GAS, target_contract_address, 0, 0, 0, 0)
+ # )
+ #
+ # setup + JUMPDEST + attack + attack + ... + attack +
+ # JUMP(setup_length)
+ code_sequence = Op.POP(Op.STATICCALL(Op.GAS, self._target_contract_address, 0, 0, 0, 0))
+
+ caller_code = self.generate_repeated_code(code_sequence, Bytecode(), fork)
+ self._contract_address = pre.deploy_contract(code=caller_code)
+
+ def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transaction:
+ """Generate transaction that executes the caller contract."""
+ if not hasattr(self, "_contract_address"):
+ raise ValueError("deploy_contracts must be called before generate_transaction")
+
+ return Transaction(
+ to=self._contract_address,
+ gas_limit=gas_limit,
+ sender=pre.fund_eoa(),
+ )
diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/__init__.py b/packages/tests/src/ethereum_test_checklists/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_checklists/__init__.py
rename to packages/tests/src/ethereum_test_checklists/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.py b/packages/tests/src/ethereum_test_checklists/eip_checklist.py
similarity index 96%
rename from src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.py
rename to packages/tests/src/ethereum_test_checklists/eip_checklist.py
index 2fd01ea834..1361965eb7 100644
--- a/src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.py
+++ b/packages/tests/src/ethereum_test_checklists/eip_checklist.py
@@ -1,12 +1,12 @@
"""
EIP Testing Checklist Enum definitions.
-Note: This module includes a companion .pyi stub file that provides mypy type hints
-for making EIPChecklist classes callable. The stub file is auto-generated using:
- uv run generate_checklist_stubs
+Note: This module includes a companion .pyi stub file that provides mypy type
+hints for making EIPChecklist classes callable. The stub file is auto-generated
+using: uv run generate_checklist_stubs
-If you modify the EIPChecklist class structure, regenerate the stub file to maintain
-proper type checking support.
+If you modify the EIPChecklist class structure, regenerate the stub file to
+maintain proper type checking support.
"""
import re
@@ -16,9 +16,11 @@
def camel_to_snake(name: str) -> str:
"""Convert CamelCase to snake_case."""
- # Insert an underscore before any uppercase letter that follows a lowercase letter
+ # Insert an underscore before any uppercase letter that follows a lowercase
+ # letter
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
- # Insert an underscore before any uppercase letter that follows a lowercase letter or number
+ # Insert an underscore before any uppercase letter that follows a lowercase
+ # letter or number
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
@@ -73,8 +75,8 @@ def __repr__(cls) -> str:
def __call__(cls, *args, **kwargs):
"""Return a pytest mark decorator for the checklist item."""
- # If called with a function as the first argument (direct decorator usage)
- # and no other arguments, apply the decorator to the function
+ # If called with a function as the first argument (direct decorator
+ # usage) and no other arguments, apply the decorator to the function
if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
func = args[0]
marker = pytest.mark.eip_checklist(cls._path)
@@ -93,20 +95,21 @@ class EIPChecklist:
"""
Main namespace for EIP testing checklist items.
- This class provides a structured way to reference checklist items for EIP testing.
- The class structure is automatically converted to callable pytest markers.
+ This class provides a structured way to reference checklist items for EIP
+ testing. The class structure is automatically converted to callable pytest
+ markers.
- Note: If you modify this class structure, regenerate the type stub file using:
- uv run generate_checklist_stubs
+ Note: If you modify this class structure, regenerate the type stub file
+ using: uv run generate_checklist_stubs
Examples:
- @EIPChecklist.Opcode.Test.GasUsage.Normal()
- def test_normal_gas():
- pass
+ @EIPChecklist.Opcode.Test.GasUsage.Normal()
+ def test_normal_gas():
+ pass
- @EIPChecklist.Opcode.Test.StackOverflow
- def test_stack_overflow():
- pass
+ @EIPChecklist.Opcode.Test.StackOverflow
+ def test_stack_overflow():
+ pass
"""
@@ -239,8 +242,9 @@ class Even(ChecklistItem):
class DataPortionVariables(ChecklistItem, override_name="data_portion_variables"):
"""
- If the opcode contains variables in its data portion, for each variable `n`
- of the opcode that accesses the nth stack item, test `n` being.
+ If the opcode contains variables in its data portion, for
+ each variable `n` of the opcode that accesses the nth stack
+ item, test `n` being.
"""
class Top(ChecklistItem):
@@ -386,6 +390,11 @@ class OutOfGasMemory(ChecklistItem):
pass
+ class ExtraGas(ChecklistItem):
+ """Extra gas usage tests."""
+
+ pass
+
class OrderOfOperations(ChecklistItem):
"""Order of operations tests."""
@@ -1683,28 +1692,31 @@ class Test(ChecklistItem):
"""Test vectors for the new validity constraint."""
class ForkTransition(ChecklistItem):
- """Tests for the new transaction validity constraint on fork boundary."""
+ """
+ Tests for the new transaction validity constraint on fork
+ boundary.
+ """
class AcceptedBeforeFork(ChecklistItem):
"""
- Verify that a block before the activation fork is accepted even when the new
- constraint is not met.
+ Verify that a block before the activation fork is accepted
+ even when the new constraint is not met.
"""
pass
class AcceptedAfterFork(ChecklistItem):
"""
- Verify that a block after the activation fork is accepted when the new
- validity constraint is met.
+ Verify that a block after the activation fork is accepted
+ when the new validity constraint is met.
"""
pass
class RejectedAfterFork(ChecklistItem):
"""
- Verify that a block after the activation fork is rejected when the new
- validity constraint is not met.
+ Verify that a block after the activation fork is rejected
+ when the new validity constraint is not met.
"""
pass
@@ -1716,36 +1728,41 @@ class Test(ChecklistItem):
"""Test vectors for the modified validity constraint."""
class ForkTransition(ChecklistItem):
- """Tests for the modified transaction validity constraint on fork boundary."""
+ """
+ Tests for the modified transaction validity constraint on fork
+ boundary.
+ """
class AcceptedBeforeFork(ChecklistItem):
"""
- Verify that a block before the activation fork is accepted when the existing
- constraint is met and, ideally, the new constraint is not met.
+ Verify that a block before the activation fork is accepted
+ when the existing constraint is met and, ideally, the new
+ constraint is not met.
"""
pass
class RejectedBeforeFork(ChecklistItem):
"""
- Verify that a block before the activation fork is rejected when the existing
- constraint is not met and, ideally, the new constraint is met.
+ Verify that a block before the activation fork is rejected
+ when the existing constraint is not met and, ideally, the
+ new constraint is met.
"""
pass
class AcceptedAfterFork(ChecklistItem):
"""
- Verify that a block after the activation fork is accepted when the new
- validity constraint is met.
+ Verify that a block after the activation fork is accepted
+ when the new validity constraint is met.
"""
pass
class RejectedAfterFork(ChecklistItem):
"""
- Verify that a block after the activation fork is rejected when the new
- validity constraint is not met.
+ Verify that a block after the activation fork is rejected
+ when the new validity constraint is not met.
"""
pass
diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.pyi b/packages/tests/src/ethereum_test_checklists/eip_checklist.pyi
similarity index 95%
rename from src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.pyi
rename to packages/tests/src/ethereum_test_checklists/eip_checklist.pyi
index 54c2b707da..6dd2653923 100644
--- a/src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.pyi
+++ b/packages/tests/src/ethereum_test_checklists/eip_checklist.pyi
@@ -1,7 +1,8 @@
"""
Type stubs for EIP checklist - auto-generated.
-DO NOT EDIT MANUALLY - This file is generated by `uv run generate-checklist-stubs`
+DO NOT EDIT MANUALLY -
+This file is generated by `uv run generate_checklist_stubs`
"""
from typing import Any, Callable, TypeVar, overload
@@ -89,6 +90,21 @@ class EIPChecklist:
SecondClient: _CallableChecklistItem
TestCoverage: _CallableChecklistItem
+ class ModifiedTransactionValidityConstraint(_CallableChecklistItem):
+ class Test(_CallableChecklistItem):
+ class ForkTransition(_CallableChecklistItem):
+ AcceptedAfterFork: _CallableChecklistItem
+ AcceptedBeforeFork: _CallableChecklistItem
+ RejectedAfterFork: _CallableChecklistItem
+ RejectedBeforeFork: _CallableChecklistItem
+
+ class NewTransactionValidityConstraint(_CallableChecklistItem):
+ class Test(_CallableChecklistItem):
+ class ForkTransition(_CallableChecklistItem):
+ AcceptedAfterFork: _CallableChecklistItem
+ AcceptedBeforeFork: _CallableChecklistItem
+ RejectedAfterFork: _CallableChecklistItem
+
class Opcode(_CallableChecklistItem):
class Test(_CallableChecklistItem):
ExceptionalAbort: _CallableChecklistItem
@@ -138,6 +154,7 @@ class EIPChecklist:
Invalid: _CallableChecklistItem
class GasUsage(_CallableChecklistItem):
+ ExtraGas: _CallableChecklistItem
MemoryExpansion: _CallableChecklistItem
Normal: _CallableChecklistItem
OutOfGasExecution: _CallableChecklistItem
diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/tests/__init__.py b/packages/tests/src/ethereum_test_checklists/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_checklists/tests/__init__.py
rename to packages/tests/src/ethereum_test_checklists/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/tests/test_checklist_template_consistency.py b/packages/tests/src/ethereum_test_checklists/tests/test_checklist_template_consistency.py
similarity index 93%
rename from src/ethereum_spec_tests/ethereum_test_checklists/tests/test_checklist_template_consistency.py
rename to packages/tests/src/ethereum_test_checklists/tests/test_checklist_template_consistency.py
index 1e99199cde..f8a190ae57 100644
--- a/src/ethereum_spec_tests/ethereum_test_checklists/tests/test_checklist_template_consistency.py
+++ b/packages/tests/src/ethereum_test_checklists/tests/test_checklist_template_consistency.py
@@ -32,8 +32,10 @@ def extract_markdown_ids(markdown_content: str) -> Set[str]:
return ids
-def get_all_checklist_ids(obj, current_path="") -> Set[str]:
- """Recursively extract all checklist IDs from EIPChecklist and its children."""
+def get_all_checklist_ids(obj) -> Set[str]:
+ """
+ Recursively extract all checklist IDs from EIPChecklist and its children.
+ """
ids = set()
# Iterate through all attributes of the object
@@ -59,7 +61,9 @@ def get_all_checklist_ids(obj, current_path="") -> Set[str]:
def test_checklist_template_consistency():
- """Test that all IDs in markdown template match EIPChecklist class exactly."""
+ """
+ Test that all IDs in markdown template match EIPChecklist class exactly.
+ """
# Read the markdown template
with open(TEMPLATE_PATH, "r", encoding="utf-8") as f:
markdown_content = f.read()
@@ -135,7 +139,10 @@ def test_id_extraction_functions():
def test_eip_checklist_decorator_usage():
- """Test EIPChecklist items work correctly as decorators both with and without parentheses."""
+ """
+ Test EIPChecklist items work correctly as decorators both with and without
+ parentheses.
+ """
# Test decorator with parentheses
@EIPChecklist.Opcode.Test.StackComplexOperations()
@@ -149,7 +156,8 @@ def test_function_with_parens():
assert len(eip_markers) == 1
assert eip_markers[0].args == ("opcode/test/stack_complex_operations",)
- # Test decorator without parentheses (direct usage - this is the key fix for issue #1)
+ # Test decorator without parentheses (direct usage - this is the key fix
+ # for issue #1)
@EIPChecklist.Opcode.Test.StackOverflow
def test_function_no_parens():
pass
@@ -192,6 +200,7 @@ def test_eip_checklist_pytest_param_usage():
with pytest.raises((TypeError, AssertionError)):
pytest.param(
"test_value",
- marks=EIPChecklist.Opcode.Test.StackOverflow, # Without () should fail
+ # Without () should fail
+ marks=EIPChecklist.Opcode.Test.StackOverflow,
id="should_fail",
)
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/__init__.py b/packages/tests/src/ethereum_test_exceptions/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/__init__.py
rename to packages/tests/src/ethereum_test_exceptions/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/engine_api.py b/packages/tests/src/ethereum_test_exceptions/engine_api.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/engine_api.py
rename to packages/tests/src/ethereum_test_exceptions/engine_api.py
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exception_mapper.py b/packages/tests/src/ethereum_test_exceptions/exception_mapper.py
similarity index 88%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/exception_mapper.py
rename to packages/tests/src/ethereum_test_exceptions/exception_mapper.py
index 43d4d7af66..cf8e7b4e76 100644
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/exception_mapper.py
+++ b/packages/tests/src/ethereum_test_exceptions/exception_mapper.py
@@ -20,9 +20,11 @@ class ExceptionMapper(ABC):
mapping_substring: ClassVar[Dict[ExceptionBase, str]]
"""
- Mapping of exception to substring that should be present in the error message.
+ Mapping of exception to substring that should be present in the error
+ message.
- Items in this mapping are used for substring matching (`substring in message`).
+ Items in this mapping are used for substring matching (`substring in
+ message`).
"""
mapping_regex: ClassVar[Dict[ExceptionBase, str]]
@@ -34,13 +36,14 @@ class ExceptionMapper(ABC):
"""
reliable: ClassVar[bool] = True
"""
- Whether the exceptions returned by the tool are reliable and can be accurately
- mapped to the exceptions in this class.
+ Whether the exceptions returned by the tool are reliable and can be
+ accurately mapped to the exceptions in this class.
"""
def __init__(self) -> None:
"""Initialize the exception mapper."""
- # Ensure that the subclass has properly defined mapping_substring before accessing it
+ # Ensure that the subclass has properly defined mapping_substring
+ # before accessing it
assert self.mapping_substring is not None, "mapping_substring must be defined in subclass"
assert self.mapping_regex is not None, "mapping_regex must be defined in subclass"
self.mapper_name = self.__class__.__name__
@@ -66,8 +69,8 @@ def message_to_exception(
class ExceptionWithMessage(BaseModel, Generic[ExceptionBoundTypeVar]):
"""
- Class that contains the exception along with the verbatim message from the external
- tool/client.
+ Class that contains the exception along with the verbatim message from the
+ external tool/client.
"""
exceptions: List[ExceptionBoundTypeVar]
@@ -86,8 +89,8 @@ def __str__(self):
def mapper_validator(v: str, info: ValidationInfo) -> Dict[str, Any] | UndefinedException | None:
"""
- Use the exception mapper that must be included in the context to map the exception
- from the external tool.
+ Use the exception mapper that must be included in the context to map the
+ exception from the external tool.
"""
if v is None:
return v
@@ -110,17 +113,18 @@ def mapper_validator(v: str, info: ValidationInfo) -> Dict[str, Any] | Undefined
ExceptionMapperValidator = BeforeValidator(mapper_validator)
"""
-Validator that can be used to annotate a pydantic field in a model that is meant to be
-parsed from an external tool or client.
+Validator that can be used to annotate a pydantic field in a model that is
+meant to be parsed from an external tool or client.
-The annotated type must be an union that can include `None`, `UndefinedException` and a
-custom model as:
+The annotated type must be an union that can include `None`,
+`UndefinedException` and a custom model as:
```
class BlockExceptionWithMessage(ExceptionWithMessage[BlockException]):
pass
```
where `BlockException` can be any derivation of `ExceptionBase`.
-The `message` attribute is the verbatim message received from the external tool or client,
-and can be used to be printed for extra context information in case of failures.
+The `message` attribute is the verbatim message received from the external tool
+or client, and can be used to be printed for extra context information in case
+of failures.
"""
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions.py b/packages/tests/src/ethereum_test_exceptions/exceptions.py
similarity index 58%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions.py
rename to packages/tests/src/ethereum_test_exceptions/exceptions.py
index 437b5ad8f2..8de5ac505c 100644
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions.py
+++ b/packages/tests/src/ethereum_test_exceptions/exceptions.py
@@ -25,7 +25,10 @@ def __init_subclass__(cls) -> None:
def __get_pydantic_core_schema__(
cls, source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call class constructor without info and appends the serialization schema."""
+ """
+ Call class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
cls.from_str,
serialization=to_string_ser_schema(),
@@ -104,7 +107,10 @@ def __new__(cls, value: str, *, mapper_name: str | None = None) -> "UndefinedExc
def __get_pydantic_core_schema__(
cls, source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call class constructor without info and appends the serialization schema."""
+ """
+ Call class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
cls,
serialization=to_string_ser_schema(),
@@ -114,195 +120,125 @@ def __get_pydantic_core_schema__(
@unique
class TransactionException(ExceptionBase):
"""
- Exception raised when a transaction is invalid, and thus cannot be executed.
+ Exception raised when a transaction is invalid, and thus cannot be
+ executed.
- If a transaction with any of these exceptions is included in a block, the block is invalid.
+ If a transaction with any of these exceptions is included in a block, the
+ block is invalid.
"""
TYPE_NOT_SUPPORTED = auto()
- """
- Transaction type is not supported on this chain configuration.
- """
+ """Transaction type is not supported on this chain configuration."""
SENDER_NOT_EOA = auto()
- """
- Transaction is coming from address that is not exist anymore.
- """
+ """Transaction is coming from address that is not exist anymore."""
ADDRESS_TOO_SHORT = auto()
- """
- Transaction `to` is not allowed to be less than 20 bytes.
- """
+ """Transaction `to` is not allowed to be less than 20 bytes."""
ADDRESS_TOO_LONG = auto()
- """
- Transaction `to` is not allowed to be more than 20 bytes.
- """
+ """Transaction `to` is not allowed to be more than 20 bytes."""
NONCE_MISMATCH_TOO_HIGH = auto()
- """
- Transaction nonce > sender.nonce.
- """
+ """Transaction nonce > sender.nonce."""
NONCE_MISMATCH_TOO_LOW = auto()
- """
- Transaction nonce < sender.nonce.
- """
+ """Transaction nonce < sender.nonce."""
NONCE_TOO_BIG = auto()
"""
- Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably TransactionTest).
+ Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably
+ TransactionTest).
"""
NONCE_IS_MAX = auto()
"""
- Transaction `nonce` is not allowed to be max_uint64 - 1 (this is StateTests).
+ Transaction `nonce` is not allowed to be max_uint64 - 1 (this is
+ StateTests).
"""
NONCE_OVERFLOW = auto()
- """
- Transaction `nonce` is not allowed to be more than uint64.
- """
+ """Transaction `nonce` is not allowed to be more than uint64."""
GASLIMIT_OVERFLOW = auto()
- """
- Transaction gaslimit exceeds 2^64-1 maximum value.
- """
+ """Transaction gaslimit exceeds 2^64-1 maximum value."""
VALUE_OVERFLOW = auto()
- """
- Transaction value exceeds 2^256-1 maximum value.
- """
+ """Transaction value exceeds 2^256-1 maximum value."""
GASPRICE_OVERFLOW = auto()
- """
- Transaction gasPrice exceeds 2^256-1 maximum value.
- """
+ """Transaction gasPrice exceeds 2^256-1 maximum value."""
GASLIMIT_PRICE_PRODUCT_OVERFLOW = auto()
- """
- Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value.
- """
+ """Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value."""
INVALID_SIGNATURE_VRS = auto()
- """
- Invalid transaction v, r, s values.
- """
+ """Invalid transaction v, r, s values."""
RLP_INVALID_SIGNATURE_R = auto()
- """
- Error reading transaction signature R value.
- """
+ """Error reading transaction signature R value."""
RLP_INVALID_SIGNATURE_S = auto()
- """
- Error reading transaction signature S value.
- """
+ """Error reading transaction signature S value."""
RLP_LEADING_ZEROS_GASLIMIT = auto()
- """
- Error reading transaction gaslimit field RLP.
- """
+ """Error reading transaction gaslimit field RLP."""
RLP_LEADING_ZEROS_GASPRICE = auto()
- """
- Error reading transaction gasprice field RLP.
- """
+ """Error reading transaction gasprice field RLP."""
RLP_LEADING_ZEROS_VALUE = auto()
- """
- Error reading transaction value field RLP.
- """
+ """Error reading transaction value field RLP."""
RLP_LEADING_ZEROS_NONCE = auto()
- """
- Error reading transaction nonce field RLP.
- """
+ """Error reading transaction nonce field RLP."""
RLP_LEADING_ZEROS_R = auto()
- """
- Error reading transaction signature R field RLP.
- """
+ """Error reading transaction signature R field RLP."""
RLP_LEADING_ZEROS_S = auto()
- """
- Error reading transaction signature S field RLP.
- """
+ """Error reading transaction signature S field RLP."""
RLP_LEADING_ZEROS_V = auto()
- """
- Error reading transaction signature V field RLP.
- """
+ """Error reading transaction signature V field RLP."""
RLP_LEADING_ZEROS_BASEFEE = auto()
- """
- Error reading transaction basefee field RLP.
- """
+ """Error reading transaction basefee field RLP."""
RLP_LEADING_ZEROS_PRIORITY_FEE = auto()
- """
- Error reading transaction priority fee field RLP.
- """
+ """Error reading transaction priority fee field RLP."""
RLP_LEADING_ZEROS_DATA_SIZE = auto()
"""
- Error reading transaction data field RLP, (rlp field length has leading zeros).
+ Error reading transaction data field RLP, (rlp field length has leading
+ zeros).
"""
RLP_LEADING_ZEROS_NONCE_SIZE = auto()
"""
- Error reading transaction nonce field RLP, (rlp field length has leading zeros).
+ Error reading transaction nonce field RLP, (rlp field length has leading
+ zeros).
"""
RLP_TOO_FEW_ELEMENTS = auto()
"""
- Error reading transaction RLP, structure has too few elements than expected.
+ Error reading transaction RLP, structure has too few elements than
+ expected.
"""
RLP_TOO_MANY_ELEMENTS = auto()
"""
- Error reading transaction RLP, structure has too many elements than expected.
+ Error reading transaction RLP, structure has too many elements than
+ expected.
"""
RLP_ERROR_EOF = auto()
- """
- Error reading transaction RLP, rlp stream unexpectedly finished.
- """
+ """Error reading transaction RLP, rlp stream unexpectedly finished."""
RLP_ERROR_SIZE = auto()
- """
- Error reading transaction RLP, rlp size is invalid.
- """
+ """Error reading transaction RLP, rlp size is invalid."""
RLP_ERROR_SIZE_LEADING_ZEROS = auto()
- """
- Error reading transaction RLP, field size has leading zeros.
- """
+ """Error reading transaction RLP, field size has leading zeros."""
INVALID_CHAINID = auto()
- """
- Transaction chain id encoding is incorrect.
- """
+ """Transaction chain id encoding is incorrect."""
RLP_INVALID_DATA = auto()
- """
- Transaction data field is invalid rlp.
- """
+ """Transaction data field is invalid rlp."""
RLP_INVALID_GASLIMIT = auto()
- """
- Transaction gaslimit field is invalid rlp.
- """
+ """Transaction gaslimit field is invalid rlp."""
RLP_INVALID_NONCE = auto()
- """
- Transaction nonce field is invalid rlp.
- """
+ """Transaction nonce field is invalid rlp."""
RLP_INVALID_TO = auto()
- """
- Transaction to field is invalid rlp.
- """
+ """Transaction to field is invalid rlp."""
RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_LONG = auto()
- """
- Transaction access list address is > 20 bytes.
- """
+ """Transaction access list address is > 20 bytes."""
RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_SHORT = auto()
- """
- Transaction access list address is < 20 bytes.
- """
+ """Transaction access list address is < 20 bytes."""
RLP_INVALID_ACCESS_LIST_STORAGE_TOO_LONG = auto()
- """
- Transaction access list storage hash > 32 bytes.
- """
+ """Transaction access list storage hash > 32 bytes."""
RLP_INVALID_ACCESS_LIST_STORAGE_TOO_SHORT = auto()
- """
- Transaction access list storage hash < 32 bytes.
- """
+ """Transaction access list storage hash < 32 bytes."""
RLP_INVALID_HEADER = auto()
- """
- Transaction failed to read from RLP as rlp header is invalid.
- """
+ """Transaction failed to read from RLP as rlp header is invalid."""
RLP_INVALID_VALUE = auto()
- """
- Transaction value field is invalid rlp/structure.
- """
+ """Transaction value field is invalid rlp/structure."""
EC_RECOVERY_FAIL = auto()
- """
- Transaction has correct signature, but ec recovery failed.
- """
+ """Transaction has correct signature, but ec recovery failed."""
INSUFFICIENT_ACCOUNT_FUNDS = auto()
"""
Transaction's sender does not have enough funds to pay for the transaction.
"""
INSUFFICIENT_MAX_FEE_PER_GAS = auto()
- """
- Transaction's max-fee-per-gas is lower than the block base-fee.
- """
+ """Transaction's max-fee-per-gas is lower than the block base-fee."""
PRIORITY_OVERFLOW = auto()
"""
Transaction's max-priority-fee-per-gas is exceeds 2^256-1 maximum value.
@@ -313,88 +249,59 @@ class TransactionException(ExceptionBase):
"""
PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS_2 = auto()
"""
- Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas (TransactionTests).
+ Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas
+ (TransactionTests).
"""
INSUFFICIENT_MAX_FEE_PER_BLOB_GAS = auto()
"""
- Transaction's max-fee-per-blob-gas is lower than the block's blob-gas price.
+ Transaction's max-fee-per-blob-gas is lower than the block's blob-gas
+ price.
"""
INTRINSIC_GAS_TOO_LOW = auto()
- """
- Transaction's gas limit is too low.
- """
+ """Transaction's gas limit is too low."""
INTRINSIC_GAS_BELOW_FLOOR_GAS_COST = auto()
- """
- Transaction's gas limit is below the floor gas cost.
- """
+ """Transaction's gas limit is below the floor gas cost."""
INITCODE_SIZE_EXCEEDED = auto()
"""
Transaction's initcode for a contract-creating transaction is too large.
"""
TYPE_3_TX_PRE_FORK = auto()
- """
- Transaction type 3 included before activation fork.
- """
+ """Transaction type 3 included before activation fork."""
TYPE_3_TX_ZERO_BLOBS_PRE_FORK = auto()
- """
- Transaction type 3, with zero blobs, included before activation fork.
- """
+ """Transaction type 3, with zero blobs, included before activation fork."""
TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH = auto()
- """
- Transaction contains a blob versioned hash with an invalid version.
- """
+ """Transaction contains a blob versioned hash with an invalid version."""
TYPE_3_TX_WITH_FULL_BLOBS = auto()
- """
- Transaction contains full blobs (network-version of the transaction).
- """
+ """Transaction contains full blobs (network-version of the transaction)."""
TYPE_3_TX_BLOB_COUNT_EXCEEDED = auto()
- """
- Transaction contains too many blob versioned hashes.
- """
+ """Transaction contains too many blob versioned hashes."""
TYPE_3_TX_CONTRACT_CREATION = auto()
- """
- Transaction is a type 3 transaction and has an empty `to`.
- """
+ """Transaction is a type 3 transaction and has an empty `to`."""
TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED = auto()
- """
- Transaction causes block to go over blob gas limit.
- """
+ """Transaction causes block to go over blob gas limit."""
GAS_ALLOWANCE_EXCEEDED = auto()
- """
- Transaction causes block to go over blob gas limit.
- """
+ """Transaction causes block to go over blob gas limit."""
GAS_LIMIT_EXCEEDS_MAXIMUM = auto()
"""
Transaction gas limit exceeds the maximum allowed limit of 30 million.
"""
TYPE_3_TX_ZERO_BLOBS = auto()
- """
- Transaction is type 3, but has no blobs.
- """
+ """Transaction is type 3, but has no blobs."""
TYPE_4_EMPTY_AUTHORIZATION_LIST = auto()
- """
- Transaction is type 4, but has an empty authorization list.
- """
+ """Transaction is type 4, but has an empty authorization list."""
TYPE_4_INVALID_AUTHORITY_SIGNATURE = auto()
- """
- Transaction authority signature is invalid
- """
+ """Transaction authority signature is invalid"""
TYPE_4_INVALID_AUTHORITY_SIGNATURE_S_TOO_HIGH = auto()
- """
- Transaction authority signature is invalid
- """
+ """Transaction authority signature is invalid"""
TYPE_4_TX_CONTRACT_CREATION = auto()
- """
- Transaction is a type 4 transaction and has an empty `to`.
- """
+ """Transaction is a type 4 transaction and has an empty `to`."""
TYPE_4_INVALID_AUTHORIZATION_FORMAT = auto()
"""
- Transaction is type 4, but contains an authorization that has an invalid format.
+ Transaction is type 4, but contains an authorization that has an invalid
+ format.
"""
TYPE_4_TX_PRE_FORK = auto()
- """
- Transaction type 4 included before activation fork.
- """
+ """Transaction type 4 included before activation fork."""
@unique
@@ -402,202 +309,158 @@ class BlockException(ExceptionBase):
"""
Exception raised when a block is invalid, but not due to a transaction.
- E.g. all transactions in the block are valid, and can be applied to the state, but the
- block header contains an invalid field.
+ E.g. all transactions in the block are valid, and can be applied to the
+ state, but the block header contains an invalid field.
"""
TOO_MANY_UNCLES = auto()
- """
- Block declares too many uncles over the allowed limit.
- """
+ """Block declares too many uncles over the allowed limit."""
UNCLE_IN_CHAIN = auto()
- """
- Block declares uncle header that is already imported into chain.
- """
+ """Block declares uncle header that is already imported into chain."""
UNCLE_IS_ANCESTOR = auto()
- """
- Block declares uncle header that is directly a parent of this block.
- """
+ """Block declares uncle header that is directly a parent of this block."""
UNCLE_IS_BROTHER = auto()
- """
- Block declares two similar uncle headers.
- """
+ """Block declares two similar uncle headers."""
UNCLE_PARENT_INCORRECT = auto()
- """
- Block declares uncle header that is an outdated block to be an uncle.
- """
+ """Block declares uncle header that is an outdated block to be an uncle."""
EXTRA_DATA_TOO_BIG = auto()
- """
- Block header's extra data >32 bytes.
- """
+ """Block header's extra data >32 bytes."""
EXTRA_DATA_INVALID_DAO = auto()
"""
Block header's extra data after dao fork must be a fixed pre defined hash.
"""
UNKNOWN_PARENT = auto()
"""
- Block header's parent hash does not correspond to any of existing blocks on chain.
+ Block header's parent hash does not correspond to any of existing blocks on
+ chain.
"""
UNCLE_UNKNOWN_PARENT = auto()
"""
- Uncle header's parent hash does not correspond to any of existing blocks on chain.
+ Uncle header's parent hash does not correspond to any of existing blocks on
+ chain.
"""
UNKNOWN_PARENT_ZERO = auto()
- """
- Block header's parent hash is zero hash.
- """
+ """Block header's parent hash is zero hash."""
GASLIMIT_TOO_BIG = auto()
- """
- Block header's gas limit > 0x7fffffffffffffff.
- """
+ """Block header's gas limit > 0x7fffffffffffffff."""
INVALID_BLOCK_NUMBER = auto()
- """
- Block header's number != parent header's number + 1.
- """
+ """Block header's number != parent header's number + 1."""
INVALID_BLOCK_TIMESTAMP_OLDER_THAN_PARENT = auto()
- """
- Block header's timestamp <= parent header's timestamp.
- """
+ """Block header's timestamp <= parent header's timestamp."""
INVALID_DIFFICULTY = auto()
"""
- Block header's difficulty does not match the difficulty formula calculated from previous block.
+ Block header's difficulty does not match the difficulty formula calculated
+ from previous block.
"""
INVALID_LOG_BLOOM = auto()
"""
- Block header's logs bloom hash does not match the actually computed log bloom.
+ Block header's logs bloom hash does not match the actually computed log
+ bloom.
"""
INVALID_STATE_ROOT = auto()
"""
- Block header's state root hash does not match the actually computed hash of the state.
+ Block header's state root hash does not match the actually computed hash of
+ the state.
"""
INVALID_RECEIPTS_ROOT = auto()
"""
- Block header's receipts root hash does not match the actually computed hash of receipts.
+ Block header's receipts root hash does not match the actually computed hash
+ of receipts.
"""
INVALID_TRANSACTIONS_ROOT = auto()
"""
- Block header's transactions root hash does not match the actually computed hash of tx tree.
+ Block header's transactions root hash does not match the actually computed
+ hash of tx tree.
"""
INVALID_UNCLES_HASH = auto()
"""
- Block header's uncle hash does not match the actually computed hash of block's uncles.
+ Block header's uncle hash does not match the actually computed hash of
+ block's uncles.
"""
GAS_USED_OVERFLOW = auto()
- """
- Block transactions consume more gas than block header allow.
- """
+ """Block transactions consume more gas than block header allow."""
INVALID_GASLIMIT = auto()
"""
- Block header's gas limit does not match the gas limit formula calculated from previous block.
+ Block header's gas limit does not match the gas limit formula calculated
+ from previous block.
"""
INVALID_BASEFEE_PER_GAS = auto()
- """
- Block header's base_fee_per_gas field is calculated incorrect.
- """
+ """Block header's base_fee_per_gas field is calculated incorrect."""
INVALID_GAS_USED = auto()
"""
Block header's actual gas used does not match the provided header's value
"""
INVALID_GAS_USED_ABOVE_LIMIT = auto()
- """
- Block header's gas used value is above the gas limit field's value.
- """
+ """Block header's gas used value is above the gas limit field's value."""
INVALID_WITHDRAWALS_ROOT = auto()
"""
Block header's withdrawals root does not match calculated withdrawals root.
"""
INCORRECT_BLOCK_FORMAT = auto()
"""
- Block's format is incorrect, contains invalid fields, is missing fields, or contains fields of
- a fork that is not active yet.
+ Block's format is incorrect, contains invalid fields, is missing fields, or
+ contains fields of a fork that is not active yet.
"""
BLOB_GAS_USED_ABOVE_LIMIT = auto()
- """
- Block's blob gas used in header is above the limit.
- """
+ """Block's blob gas used in header is above the limit."""
INCORRECT_BLOB_GAS_USED = auto()
- """
- Block's blob gas used in header is incorrect.
- """
+ """Block's blob gas used in header is incorrect."""
INCORRECT_EXCESS_BLOB_GAS = auto()
- """
- Block's excess blob gas in header is incorrect.
- """
+ """Block's excess blob gas in header is incorrect."""
INVALID_VERSIONED_HASHES = auto()
- """
- Incorrect number of versioned hashes in a payload.
- """
+ """Incorrect number of versioned hashes in a payload."""
RLP_STRUCTURES_ENCODING = auto()
"""
Block's rlp encoding is valid but ethereum structures in it are invalid.
"""
RLP_WITHDRAWALS_NOT_READ = auto()
- """
- Block's rlp encoding is missing withdrawals.
- """
+ """Block's rlp encoding is missing withdrawals."""
RLP_INVALID_FIELD_OVERFLOW_64 = auto()
- """
- One of block's fields rlp is overflow 2**64 value.
- """
+ """One of block's fields rlp is overflow 2**64 value."""
RLP_INVALID_ADDRESS = auto()
- """
- Block withdrawals address is rlp of invalid address != 20 bytes.
- """
+ """Block withdrawals address is rlp of invalid address != 20 bytes."""
RLP_BLOCK_LIMIT_EXCEEDED = auto()
- """
- Block's rlp encoding is larger than the allowed limit.
- """
+ """Block's rlp encoding is larger than the allowed limit."""
INVALID_REQUESTS = auto()
- """
- Block's requests are invalid.
- """
+ """Block's requests are invalid."""
IMPORT_IMPOSSIBLE_LEGACY = auto()
- """
- Legacy block import is impossible in this chain configuration.
- """
+ """Legacy block import is impossible in this chain configuration."""
IMPORT_IMPOSSIBLE_LEGACY_WRONG_PARENT = auto()
"""
- Legacy block import is impossible, trying to import on top of a block that is not legacy.
+ Legacy block import is impossible, trying to import on top of a block that
+ is not legacy.
"""
IMPORT_IMPOSSIBLE_LONDON_WRONG_PARENT = auto()
"""
Trying to import london (basefee) block on top of block that is not 1559.
"""
IMPORT_IMPOSSIBLE_PARIS_WRONG_POW = auto()
- """
- Trying to import paris(merge) block with PoW enabled.
- """
+ """Trying to import paris(merge) block with PoW enabled."""
IMPORT_IMPOSSIBLE_PARIS_WRONG_POS = auto()
"""
Trying to import paris(merge) block with PoS enabled before TTD is reached.
"""
IMPORT_IMPOSSIBLE_LONDON_OVER_PARIS = auto()
- """
- Trying to import london looking block over paris network (POS).
- """
+ """Trying to import london looking block over paris network (POS)."""
IMPORT_IMPOSSIBLE_PARIS_OVER_SHANGHAI = auto()
- """
- Trying to import paris block on top of shanghai block.
- """
+ """Trying to import paris block on top of shanghai block."""
IMPORT_IMPOSSIBLE_SHANGHAI = auto()
- """
- Shanghai block import is impossible in this chain configuration.
- """
+ """Shanghai block import is impossible in this chain configuration."""
IMPORT_IMPOSSIBLE_UNCLES_OVER_PARIS = auto()
"""
Trying to import a block after paris fork that has not empty uncles hash.
"""
IMPORT_IMPOSSIBLE_DIFFICULTY_OVER_PARIS = auto()
- """
- Trying to import a block after paris fork that has difficulty != 0.
- """
+ """Trying to import a block after paris fork that has difficulty != 0."""
SYSTEM_CONTRACT_EMPTY = auto()
"""
- A system contract address contains no code at the end of fork activation block.
+ A system contract address contains no code at the end of fork activation
+ block.
"""
SYSTEM_CONTRACT_CALL_FAILED = auto()
"""
- A system contract call at the end of block execution (from the system address) fails.
+ A system contract call at the end of block execution (from the system
+ address) fails.
"""
INVALID_BLOCK_HASH = auto()
"""
@@ -605,8 +468,8 @@ class BlockException(ExceptionBase):
"""
INVALID_DEPOSIT_EVENT_LAYOUT = auto()
"""
- Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but the layout
- of the event does not match the required layout.
+ Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but
+ the layout of the event does not match the required layout.
"""
@@ -615,218 +478,122 @@ class EOFException(ExceptionBase):
"""Exception raised when an EOF container is invalid."""
DEFAULT_EXCEPTION = auto()
- """
- Expect some exception, not yet known.
- """
+ """Expect some exception, not yet known."""
UNDEFINED_EXCEPTION = auto()
- """
- Indicates that exception string is not mapped to an exception enum.
- """
+ """Indicates that exception string is not mapped to an exception enum."""
UNDEFINED_INSTRUCTION = auto()
- """
- EOF container has undefined instruction in it's body code.
- """
+ """EOF container has undefined instruction in it's body code."""
UNKNOWN_VERSION = auto()
- """
- EOF container has an unknown version.
- """
+ """EOF container has an unknown version."""
INCOMPLETE_MAGIC = auto()
- """
- EOF container has not enough bytes to read magic.
- """
+ """EOF container has not enough bytes to read magic."""
INVALID_MAGIC = auto()
- """
- EOF container has not allowed magic version byte.
- """
+ """EOF container has not allowed magic version byte."""
INVALID_VERSION = auto()
- """
- EOF container version bytes mismatch.
- """
+ """EOF container version bytes mismatch."""
INVALID_NON_RETURNING_FLAG = auto()
- """
- EOF container's section has non-returning flag set incorrectly.
- """
+ """EOF container's section has non-returning flag set incorrectly."""
INVALID_RJUMP_DESTINATION = auto()
- """
- Code has RJUMP instruction with invalid parameters.
- """
+ """Code has RJUMP instruction with invalid parameters."""
MISSING_TYPE_HEADER = auto()
- """
- EOF container missing types section.
- """
+ """EOF container missing types section."""
INVALID_TYPE_SECTION_SIZE = auto()
- """
- EOF container types section has wrong size.
- """
+ """EOF container types section has wrong size."""
INVALID_TYPE_BODY = auto()
- """
- EOF container types body section bytes are wrong.
- """
+ """EOF container types body section bytes are wrong."""
MISSING_CODE_HEADER = auto()
- """
- EOF container missing code section.
- """
+ """EOF container missing code section."""
INVALID_CODE_SECTION = auto()
- """
- EOF container code section bytes are incorrect.
- """
+ """EOF container code section bytes are incorrect."""
INCOMPLETE_CODE_HEADER = auto()
- """
- EOF container code header missing bytes.
- """
+ """EOF container code header missing bytes."""
INCOMPLETE_DATA_HEADER = auto()
- """
- EOF container data header missing bytes.
- """
+ """EOF container data header missing bytes."""
ZERO_SECTION_SIZE = auto()
- """
- EOF container data header construction is wrong.
- """
+ """EOF container data header construction is wrong."""
MISSING_DATA_SECTION = auto()
- """
- EOF container missing data section
- """
+ """EOF container missing data section"""
INCOMPLETE_CONTAINER = auto()
- """
- EOF container bytes are incomplete.
- """
+ """EOF container bytes are incomplete."""
INVALID_SECTION_BODIES_SIZE = auto()
- """
- Sections bodies does not match sections headers.
- """
+ """Sections bodies does not match sections headers."""
TRAILING_BYTES = auto()
- """
- EOF container has bytes beyond data section.
- """
+ """EOF container has bytes beyond data section."""
MISSING_TERMINATOR = auto()
- """
- EOF container missing terminator bytes between header and body.
- """
+ """EOF container missing terminator bytes between header and body."""
MISSING_HEADERS_TERMINATOR = auto()
- """
- Some type of another exception about missing headers terminator.
- """
+ """Some type of another exception about missing headers terminator."""
INVALID_FIRST_SECTION_TYPE = auto()
- """
- EOF container header does not have types section first.
- """
+ """EOF container header does not have types section first."""
INCOMPLETE_SECTION_NUMBER = auto()
- """
- EOF container header has section that is missing declaration bytes.
- """
+ """EOF container header has section that is missing declaration bytes."""
INCOMPLETE_SECTION_SIZE = auto()
- """
- EOF container header has section that is defined incorrectly.
- """
+ """EOF container header has section that is defined incorrectly."""
TOO_MANY_CODE_SECTIONS = auto()
- """
- EOF container header has too many code sections.
- """
+ """EOF container header has too many code sections."""
MISSING_STOP_OPCODE = auto()
- """
- EOF container's code missing STOP bytecode at it's end.
- """
+ """EOF container's code missing STOP bytecode at it's end."""
INPUTS_OUTPUTS_NUM_ABOVE_LIMIT = auto()
- """
- EOF container code section inputs/outputs number is above the limit
- """
+ """EOF container code section inputs/outputs number is above the limit"""
UNREACHABLE_INSTRUCTIONS = auto()
- """
- EOF container's code have instructions that are unreachable.
- """
+ """EOF container's code have instructions that are unreachable."""
UNREACHABLE_CODE_SECTIONS = auto()
- """
- EOF container's body have code sections that are unreachable.
- """
+ """EOF container's body have code sections that are unreachable."""
STACK_UNDERFLOW = auto()
- """
- EOF container's code produces an stack underflow.
- """
+ """EOF container's code produces an stack underflow."""
STACK_OVERFLOW = auto()
- """
- EOF container's code produces an stack overflow.
- """
+ """EOF container's code produces an stack overflow."""
STACK_HEIGHT_MISMATCH = auto()
- """
- EOF container section stack height mismatch.
- """
+ """EOF container section stack height mismatch."""
MAX_STACK_INCREASE_ABOVE_LIMIT = auto()
- """
- EOF container's specified max stack increase is above the limit.
- """
+ """EOF container's specified max stack increase is above the limit."""
STACK_HIGHER_THAN_OUTPUTS = auto()
"""
- EOF container section stack height is higher than the outputs.
- when returning
+ EOF container section stack height is higher than the outputs. when
+ returning
"""
JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS = auto()
"""
- EOF container section JUMPF's to a destination section with incompatible outputs.
+ EOF container section JUMPF's to a destination section with incompatible
+ outputs.
"""
INVALID_MAX_STACK_INCREASE = auto()
"""
- EOF container section's specified max stack increase does not match the actual stack height.
+ EOF container section's specified max stack increase does not match the
+ actual stack height.
"""
INVALID_DATALOADN_INDEX = auto()
- """
- A DATALOADN instruction has out-of-bounds index for the data section.
- """
+ """A DATALOADN instruction has out-of-bounds index for the data section."""
TRUNCATED_INSTRUCTION = auto()
- """
- EOF container's code section has truncated instruction.
- """
+ """EOF container's code section has truncated instruction."""
TOPLEVEL_CONTAINER_TRUNCATED = auto()
- """
- Top-level EOF container has data section truncated
- """
+ """Top-level EOF container has data section truncated"""
ORPHAN_SUBCONTAINER = auto()
- """
- EOF container has an unreferenced subcontainer.
- '"""
+ """EOF container has an unreferenced subcontainer. '"""
CONTAINER_SIZE_ABOVE_LIMIT = auto()
- """
- EOF container is above size limit
- """
+ """EOF container is above size limit"""
INVALID_CONTAINER_SECTION_INDEX = auto()
- """
- Instruction references container section that does not exist.
- """
+ """Instruction references container section that does not exist."""
INCOMPATIBLE_CONTAINER_KIND = auto()
- """
- Incompatible instruction found in a container of a specific kind.
- """
+ """Incompatible instruction found in a container of a specific kind."""
AMBIGUOUS_CONTAINER_KIND = auto()
- """
- The kind of a sub-container cannot be uniquely deduced.
- """
+ """The kind of a sub-container cannot be uniquely deduced."""
TOO_MANY_CONTAINERS = auto()
- """
- EOF container header has too many sub-containers.
- """
+ """EOF container header has too many sub-containers."""
INVALID_CODE_SECTION_INDEX = auto()
- """
- CALLF Operation refers to a non-existent code section
- """
+ """CALLF Operation refers to a non-existent code section"""
UNEXPECTED_HEADER_KIND = auto()
- """
- Header parsing encountered a section kind it wasn't expecting
- """
+ """Header parsing encountered a section kind it wasn't expecting"""
CALLF_TO_NON_RETURNING = auto()
- """
- CALLF instruction targeting a non-returning code section
- """
+ """CALLF instruction targeting a non-returning code section"""
EOFCREATE_WITH_TRUNCATED_CONTAINER = auto()
- """
- EOFCREATE with truncated container
- """
+ """EOFCREATE with truncated container"""
-"""
-Pydantic Annotated Types
-"""
+"""Pydantic Annotated Types"""
ExceptionInstanceOrList = Annotated[
List[TransactionException | BlockException] | TransactionException | BlockException,
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/__init__.py b/packages/tests/src/ethereum_test_exceptions/exceptions/__init__.py
similarity index 95%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/__init__.py
rename to packages/tests/src/ethereum_test_exceptions/exceptions/__init__.py
index 3587b249a1..8434e5f331 100644
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/__init__.py
+++ b/packages/tests/src/ethereum_test_exceptions/exceptions/__init__.py
@@ -3,14 +3,14 @@
from .base import ExceptionBase, UndefinedException, from_pipe_str, to_pipe_str
from .block import BlockException
from .eof import EOFException
-from .transaction import TransactionException
-from .types import (
+from .exceptions_types import (
BlockExceptionInstanceOrList,
EOFExceptionInstanceOrList,
ExceptionBoundTypeVar,
ExceptionInstanceOrList,
TransactionExceptionInstanceOrList,
)
+from .transaction import TransactionException
__all__ = [
"ExceptionBase",
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/base.py b/packages/tests/src/ethereum_test_exceptions/exceptions/base.py
similarity index 93%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/base.py
rename to packages/tests/src/ethereum_test_exceptions/exceptions/base.py
index 96b52929f6..ebfb0d79e9 100644
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/base.py
+++ b/packages/tests/src/ethereum_test_exceptions/exceptions/base.py
@@ -25,7 +25,10 @@ def __init_subclass__(cls) -> None:
def __get_pydantic_core_schema__(
cls, source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call class constructor without info and appends the serialization schema."""
+ """
+ Call class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
cls.from_str,
serialization=to_string_ser_schema(),
@@ -82,7 +85,10 @@ def __new__(cls, value: str, *, mapper_name: str | None = None) -> "UndefinedExc
def __get_pydantic_core_schema__(
cls, source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call class constructor without info and appends the serialization schema."""
+ """
+ Call class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
cls,
serialization=to_string_ser_schema(),
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/block.py b/packages/tests/src/ethereum_test_exceptions/exceptions/block.py
similarity index 58%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/block.py
rename to packages/tests/src/ethereum_test_exceptions/exceptions/block.py
index 033da0bb37..8e7eae0b24 100644
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/block.py
+++ b/packages/tests/src/ethereum_test_exceptions/exceptions/block.py
@@ -10,202 +10,158 @@ class BlockException(ExceptionBase):
"""
Exception raised when a block is invalid, but not due to a transaction.
- E.g. all transactions in the block are valid, and can be applied to the state, but the
- block header contains an invalid field.
+ E.g. all transactions in the block are valid, and can be applied to the
+ state, but the block header contains an invalid field.
"""
TOO_MANY_UNCLES = auto()
- """
- Block declares too many uncles over the allowed limit.
- """
+ """Block declares too many uncles over the allowed limit."""
UNCLE_IN_CHAIN = auto()
- """
- Block declares uncle header that is already imported into chain.
- """
+ """Block declares uncle header that is already imported into chain."""
UNCLE_IS_ANCESTOR = auto()
- """
- Block declares uncle header that is directly a parent of this block.
- """
+ """Block declares uncle header that is directly a parent of this block."""
UNCLE_IS_BROTHER = auto()
- """
- Block declares two similar uncle headers.
- """
+ """Block declares two similar uncle headers."""
UNCLE_PARENT_INCORRECT = auto()
- """
- Block declares uncle header that is an outdated block to be an uncle.
- """
+ """Block declares uncle header that is an outdated block to be an uncle."""
EXTRA_DATA_TOO_BIG = auto()
- """
- Block header's extra data >32 bytes.
- """
+ """Block header's extra data >32 bytes."""
EXTRA_DATA_INVALID_DAO = auto()
"""
Block header's extra data after dao fork must be a fixed pre defined hash.
"""
UNKNOWN_PARENT = auto()
"""
- Block header's parent hash does not correspond to any of existing blocks on chain.
+ Block header's parent hash does not correspond to any of existing blocks on
+ chain.
"""
UNCLE_UNKNOWN_PARENT = auto()
"""
- Uncle header's parent hash does not correspond to any of existing blocks on chain.
+ Uncle header's parent hash does not correspond to any of existing blocks on
+ chain.
"""
UNKNOWN_PARENT_ZERO = auto()
- """
- Block header's parent hash is zero hash.
- """
+ """Block header's parent hash is zero hash."""
GASLIMIT_TOO_BIG = auto()
- """
- Block header's gas limit > 0x7fffffffffffffff.
- """
+ """Block header's gas limit > 0x7fffffffffffffff."""
INVALID_BLOCK_NUMBER = auto()
- """
- Block header's number != parent header's number + 1.
- """
+ """Block header's number != parent header's number + 1."""
INVALID_BLOCK_TIMESTAMP_OLDER_THAN_PARENT = auto()
- """
- Block header's timestamp <= parent header's timestamp.
- """
+ """Block header's timestamp <= parent header's timestamp."""
INVALID_DIFFICULTY = auto()
"""
- Block header's difficulty does not match the difficulty formula calculated from previous block.
+ Block header's difficulty does not match the difficulty formula calculated
+ from previous block.
"""
INVALID_LOG_BLOOM = auto()
"""
- Block header's logs bloom hash does not match the actually computed log bloom.
+ Block header's logs bloom hash does not match the actually computed log
+ bloom.
"""
INVALID_STATE_ROOT = auto()
"""
- Block header's state root hash does not match the actually computed hash of the state.
+ Block header's state root hash does not match the actually computed hash of
+ the state.
"""
INVALID_RECEIPTS_ROOT = auto()
"""
- Block header's receipts root hash does not match the actually computed hash of receipts.
+ Block header's receipts root hash does not match the actually computed hash
+ of receipts.
"""
INVALID_TRANSACTIONS_ROOT = auto()
"""
- Block header's transactions root hash does not match the actually computed hash of tx tree.
+ Block header's transactions root hash does not match the actually computed
+ hash of tx tree.
"""
INVALID_UNCLES_HASH = auto()
"""
- Block header's uncle hash does not match the actually computed hash of block's uncles.
+ Block header's uncle hash does not match the actually computed hash of
+ block's uncles.
"""
GAS_USED_OVERFLOW = auto()
- """
- Block transactions consume more gas than block header allow.
- """
+ """Block transactions consume more gas than block header allow."""
INVALID_GASLIMIT = auto()
"""
- Block header's gas limit does not match the gas limit formula calculated from previous block.
+ Block header's gas limit does not match the gas limit formula calculated
+ from previous block.
"""
INVALID_BASEFEE_PER_GAS = auto()
- """
- Block header's base_fee_per_gas field is calculated incorrect.
- """
+ """Block header's base_fee_per_gas field is calculated incorrect."""
INVALID_GAS_USED = auto()
"""
Block header's actual gas used does not match the provided header's value
"""
INVALID_GAS_USED_ABOVE_LIMIT = auto()
- """
- Block header's gas used value is above the gas limit field's value.
- """
+ """Block header's gas used value is above the gas limit field's value."""
INVALID_WITHDRAWALS_ROOT = auto()
"""
Block header's withdrawals root does not match calculated withdrawals root.
"""
INCORRECT_BLOCK_FORMAT = auto()
"""
- Block's format is incorrect, contains invalid fields, is missing fields, or contains fields of
- a fork that is not active yet.
+ Block's format is incorrect, contains invalid fields, is missing fields, or
+ contains fields of a fork that is not active yet.
"""
BLOB_GAS_USED_ABOVE_LIMIT = auto()
- """
- Block's blob gas used in header is above the limit.
- """
+ """Block's blob gas used in header is above the limit."""
INCORRECT_BLOB_GAS_USED = auto()
- """
- Block's blob gas used in header is incorrect.
- """
+ """Block's blob gas used in header is incorrect."""
INCORRECT_EXCESS_BLOB_GAS = auto()
- """
- Block's excess blob gas in header is incorrect.
- """
+ """Block's excess blob gas in header is incorrect."""
INVALID_VERSIONED_HASHES = auto()
- """
- Incorrect number of versioned hashes in a payload.
- """
+ """Incorrect number of versioned hashes in a payload."""
RLP_STRUCTURES_ENCODING = auto()
"""
Block's rlp encoding is valid but ethereum structures in it are invalid.
"""
RLP_WITHDRAWALS_NOT_READ = auto()
- """
- Block's rlp encoding is missing withdrawals.
- """
+ """Block's rlp encoding is missing withdrawals."""
RLP_INVALID_FIELD_OVERFLOW_64 = auto()
- """
- One of block's fields rlp is overflow 2**64 value.
- """
+ """One of block's fields rlp is overflow 2**64 value."""
RLP_INVALID_ADDRESS = auto()
- """
- Block withdrawals address is rlp of invalid address != 20 bytes.
- """
+ """Block withdrawals address is rlp of invalid address != 20 bytes."""
RLP_BLOCK_LIMIT_EXCEEDED = auto()
- """
- Block's rlp encoding is larger than the allowed limit.
- """
+ """Block's rlp encoding is larger than the allowed limit."""
INVALID_REQUESTS = auto()
- """
- Block's requests are invalid.
- """
+ """Block's requests are invalid."""
IMPORT_IMPOSSIBLE_LEGACY = auto()
- """
- Legacy block import is impossible in this chain configuration.
- """
+ """Legacy block import is impossible in this chain configuration."""
IMPORT_IMPOSSIBLE_LEGACY_WRONG_PARENT = auto()
"""
- Legacy block import is impossible, trying to import on top of a block that is not legacy.
+ Legacy block import is impossible, trying to import on top of a block that
+ is not legacy.
"""
IMPORT_IMPOSSIBLE_LONDON_WRONG_PARENT = auto()
"""
Trying to import london (basefee) block on top of block that is not 1559.
"""
IMPORT_IMPOSSIBLE_PARIS_WRONG_POW = auto()
- """
- Trying to import paris(merge) block with PoW enabled.
- """
+ """Trying to import paris(merge) block with PoW enabled."""
IMPORT_IMPOSSIBLE_PARIS_WRONG_POS = auto()
"""
Trying to import paris(merge) block with PoS enabled before TTD is reached.
"""
IMPORT_IMPOSSIBLE_LONDON_OVER_PARIS = auto()
- """
- Trying to import london looking block over paris network (POS).
- """
+ """Trying to import london looking block over paris network (POS)."""
IMPORT_IMPOSSIBLE_PARIS_OVER_SHANGHAI = auto()
- """
- Trying to import paris block on top of shanghai block.
- """
+ """Trying to import paris block on top of shanghai block."""
IMPORT_IMPOSSIBLE_SHANGHAI = auto()
- """
- Shanghai block import is impossible in this chain configuration.
- """
+ """Shanghai block import is impossible in this chain configuration."""
IMPORT_IMPOSSIBLE_UNCLES_OVER_PARIS = auto()
"""
Trying to import a block after paris fork that has not empty uncles hash.
"""
IMPORT_IMPOSSIBLE_DIFFICULTY_OVER_PARIS = auto()
- """
- Trying to import a block after paris fork that has difficulty != 0.
- """
+ """Trying to import a block after paris fork that has difficulty != 0."""
SYSTEM_CONTRACT_EMPTY = auto()
"""
- A system contract address contains no code at the end of fork activation block.
+ A system contract address contains no code at the end of fork activation
+ block.
"""
SYSTEM_CONTRACT_CALL_FAILED = auto()
"""
- A system contract call at the end of block execution (from the system address) fails.
+ A system contract call at the end of block execution (from the system
+ address) fails.
"""
INVALID_BLOCK_HASH = auto()
"""
@@ -213,6 +169,20 @@ class BlockException(ExceptionBase):
"""
INVALID_DEPOSIT_EVENT_LAYOUT = auto()
"""
- Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but the layout
- of the event does not match the required layout.
+ Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but
+ the layout of the event does not match the required layout.
+ """
+ # --- Block-Level Access Lists (EIP-7928) --- #
+ INVALID_BLOCK_ACCESS_LIST = auto()
+ """Block's access list is invalid."""
+ INVALID_BAL_HASH = auto()
+ """Block header's BAL hash does not match the computed BAL hash."""
+ INVALID_BAL_EXTRA_ACCOUNT = auto()
+ """
+ Block BAL contains an account change that is not present in the computed
+ BAL.
+ """
+ INVALID_BAL_MISSING_ACCOUNT = auto()
+ """
+ Block BAL is missing an account change that is present in the computed BAL.
"""
diff --git a/packages/tests/src/ethereum_test_exceptions/exceptions/eof.py b/packages/tests/src/ethereum_test_exceptions/exceptions/eof.py
new file mode 100644
index 0000000000..0e9c0c5f6c
--- /dev/null
+++ b/packages/tests/src/ethereum_test_exceptions/exceptions/eof.py
@@ -0,0 +1,125 @@
+"""EOF Exceptions."""
+
+from enum import auto, unique
+
+from .base import ExceptionBase
+
+
+@unique
+class EOFException(ExceptionBase):
+ """Exception raised when an EOF container is invalid."""
+
+ DEFAULT_EXCEPTION = auto()
+ """Expect some exception, not yet known."""
+
+ UNDEFINED_EXCEPTION = auto()
+ """Indicates that exception string is not mapped to an exception enum."""
+
+ UNDEFINED_INSTRUCTION = auto()
+ """EOF container has undefined instruction in it's body code."""
+
+ UNKNOWN_VERSION = auto()
+ """EOF container has an unknown version."""
+ INCOMPLETE_MAGIC = auto()
+ """EOF container has not enough bytes to read magic."""
+ INVALID_MAGIC = auto()
+ """EOF container has not allowed magic version byte."""
+ INVALID_VERSION = auto()
+ """EOF container version bytes mismatch."""
+ INVALID_NON_RETURNING_FLAG = auto()
+ """EOF container's section has non-returning flag set incorrectly."""
+ INVALID_RJUMP_DESTINATION = auto()
+ """Code has RJUMP instruction with invalid parameters."""
+ MISSING_TYPE_HEADER = auto()
+ """EOF container missing types section."""
+ INVALID_TYPE_SECTION_SIZE = auto()
+ """EOF container types section has wrong size."""
+ INVALID_TYPE_BODY = auto()
+ """EOF container types body section bytes are wrong."""
+ MISSING_CODE_HEADER = auto()
+ """EOF container missing code section."""
+ INVALID_CODE_SECTION = auto()
+ """EOF container code section bytes are incorrect."""
+ INCOMPLETE_CODE_HEADER = auto()
+ """EOF container code header missing bytes."""
+ INCOMPLETE_DATA_HEADER = auto()
+ """EOF container data header missing bytes."""
+ ZERO_SECTION_SIZE = auto()
+ """EOF container data header construction is wrong."""
+ MISSING_DATA_SECTION = auto()
+ """EOF container missing data section"""
+ INCOMPLETE_CONTAINER = auto()
+ """EOF container bytes are incomplete."""
+ INVALID_SECTION_BODIES_SIZE = auto()
+ """Sections bodies does not match sections headers."""
+ TRAILING_BYTES = auto()
+ """EOF container has bytes beyond data section."""
+ MISSING_TERMINATOR = auto()
+ """EOF container missing terminator bytes between header and body."""
+ MISSING_HEADERS_TERMINATOR = auto()
+ """Some type of another exception about missing headers terminator."""
+ INVALID_FIRST_SECTION_TYPE = auto()
+ """EOF container header does not have types section first."""
+ INCOMPLETE_SECTION_NUMBER = auto()
+ """EOF container header has section that is missing declaration bytes."""
+ INCOMPLETE_SECTION_SIZE = auto()
+ """EOF container header has section that is defined incorrectly."""
+ TOO_MANY_CODE_SECTIONS = auto()
+ """EOF container header has too many code sections."""
+ MISSING_STOP_OPCODE = auto()
+ """EOF container's code missing STOP bytecode at it's end."""
+ INPUTS_OUTPUTS_NUM_ABOVE_LIMIT = auto()
+ """EOF container code section inputs/outputs number is above the limit"""
+ UNREACHABLE_INSTRUCTIONS = auto()
+ """EOF container's code have instructions that are unreachable."""
+ UNREACHABLE_CODE_SECTIONS = auto()
+ """EOF container's body have code sections that are unreachable."""
+ STACK_UNDERFLOW = auto()
+ """EOF container's code produces an stack underflow."""
+ STACK_OVERFLOW = auto()
+ """EOF container's code produces an stack overflow."""
+ STACK_HEIGHT_MISMATCH = auto()
+ """EOF container section stack height mismatch."""
+ MAX_STACK_INCREASE_ABOVE_LIMIT = auto()
+ """EOF container's specified max stack increase is above the limit."""
+ STACK_HIGHER_THAN_OUTPUTS = auto()
+ """
+ EOF container section stack height is higher than the outputs. when
+ returning
+ """
+ JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS = auto()
+ """
+ EOF container section JUMPF's to a destination section with incompatible
+ outputs.
+ """
+ INVALID_MAX_STACK_INCREASE = auto()
+ """
+ EOF container section's specified max stack increase does not match the
+ actual stack height.
+ """
+ INVALID_DATALOADN_INDEX = auto()
+ """A DATALOADN instruction has out-of-bounds index for the data section."""
+ TRUNCATED_INSTRUCTION = auto()
+ """EOF container's code section has truncated instruction."""
+ TOPLEVEL_CONTAINER_TRUNCATED = auto()
+ """Top-level EOF container has data section truncated"""
+ ORPHAN_SUBCONTAINER = auto()
+ """EOF container has an unreferenced subcontainer. '"""
+ CONTAINER_SIZE_ABOVE_LIMIT = auto()
+ """EOF container is above size limit"""
+ INVALID_CONTAINER_SECTION_INDEX = auto()
+ """Instruction references container section that does not exist."""
+ INCOMPATIBLE_CONTAINER_KIND = auto()
+ """Incompatible instruction found in a container of a specific kind."""
+ AMBIGUOUS_CONTAINER_KIND = auto()
+ """The kind of a sub-container cannot be uniquely deduced."""
+ TOO_MANY_CONTAINERS = auto()
+ """EOF container header has too many sub-containers."""
+ INVALID_CODE_SECTION_INDEX = auto()
+ """CALLF Operation refers to a non-existent code section"""
+ UNEXPECTED_HEADER_KIND = auto()
+ """Header parsing encountered a section kind it wasn't expecting"""
+ CALLF_TO_NON_RETURNING = auto()
+ """CALLF instruction targeting a non-returning code section"""
+ EOFCREATE_WITH_TRUNCATED_CONTAINER = auto()
+ """EOFCREATE with truncated container"""
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/types.py b/packages/tests/src/ethereum_test_exceptions/exceptions/exceptions_types.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/types.py
rename to packages/tests/src/ethereum_test_exceptions/exceptions/exceptions_types.py
diff --git a/packages/tests/src/ethereum_test_exceptions/exceptions/transaction.py b/packages/tests/src/ethereum_test_exceptions/exceptions/transaction.py
new file mode 100644
index 0000000000..ee67b0d55e
--- /dev/null
+++ b/packages/tests/src/ethereum_test_exceptions/exceptions/transaction.py
@@ -0,0 +1,192 @@
+"""Transaction Exceptions."""
+
+from enum import auto, unique
+
+from .base import ExceptionBase
+
+
+@unique
+class TransactionException(ExceptionBase):
+ """
+ Exception raised when a transaction is invalid, and thus cannot be
+ executed.
+
+ If a transaction with any of these exceptions is included in a block, the
+ block is invalid.
+ """
+
+ TYPE_NOT_SUPPORTED = auto()
+ """Transaction type is not supported on this chain configuration."""
+ SENDER_NOT_EOA = auto()
+ """Transaction is coming from address that is not exist anymore."""
+ ADDRESS_TOO_SHORT = auto()
+ """Transaction `to` is not allowed to be less than 20 bytes."""
+ ADDRESS_TOO_LONG = auto()
+ """Transaction `to` is not allowed to be more than 20 bytes."""
+ NONCE_MISMATCH_TOO_HIGH = auto()
+ """Transaction nonce > sender.nonce."""
+ NONCE_MISMATCH_TOO_LOW = auto()
+ """Transaction nonce < sender.nonce."""
+ NONCE_TOO_BIG = auto()
+ """
+ Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably
+ TransactionTest).
+ """
+ NONCE_IS_MAX = auto()
+ """
+ Transaction `nonce` is not allowed to be max_uint64 - 1 (this is
+ StateTests).
+ """
+ NONCE_OVERFLOW = auto()
+ """Transaction `nonce` is not allowed to be more than uint64."""
+ GASLIMIT_OVERFLOW = auto()
+ """Transaction gaslimit exceeds 2^64-1 maximum value."""
+ VALUE_OVERFLOW = auto()
+ """Transaction value exceeds 2^256-1 maximum value."""
+ GASPRICE_OVERFLOW = auto()
+ """Transaction gasPrice exceeds 2^256-1 maximum value."""
+ GASLIMIT_PRICE_PRODUCT_OVERFLOW = auto()
+ """Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value."""
+ INVALID_SIGNATURE_VRS = auto()
+ """Invalid transaction v, r, s values."""
+ RLP_INVALID_SIGNATURE_R = auto()
+ """Error reading transaction signature R value."""
+ RLP_INVALID_SIGNATURE_S = auto()
+ """Error reading transaction signature S value."""
+ RLP_LEADING_ZEROS_GASLIMIT = auto()
+ """Error reading transaction gaslimit field RLP."""
+ RLP_LEADING_ZEROS_GASPRICE = auto()
+ """Error reading transaction gasprice field RLP."""
+ RLP_LEADING_ZEROS_VALUE = auto()
+ """Error reading transaction value field RLP."""
+ RLP_LEADING_ZEROS_NONCE = auto()
+ """Error reading transaction nonce field RLP."""
+ RLP_LEADING_ZEROS_R = auto()
+ """Error reading transaction signature R field RLP."""
+ RLP_LEADING_ZEROS_S = auto()
+ """Error reading transaction signature S field RLP."""
+ RLP_LEADING_ZEROS_V = auto()
+ """Error reading transaction signature V field RLP."""
+ RLP_LEADING_ZEROS_BASEFEE = auto()
+ """Error reading transaction basefee field RLP."""
+ RLP_LEADING_ZEROS_PRIORITY_FEE = auto()
+ """Error reading transaction priority fee field RLP."""
+ RLP_LEADING_ZEROS_DATA_SIZE = auto()
+ """
+ Error reading transaction data field RLP, (rlp field length has leading
+ zeros).
+ """
+ RLP_LEADING_ZEROS_NONCE_SIZE = auto()
+ """
+ Error reading transaction nonce field RLP, (rlp field length has leading
+ zeros).
+ """
+ RLP_TOO_FEW_ELEMENTS = auto()
+ """
+ Error reading transaction RLP, structure has too few elements than
+ expected.
+ """
+ RLP_TOO_MANY_ELEMENTS = auto()
+ """
+ Error reading transaction RLP, structure has too many elements than
+ expected.
+ """
+ RLP_ERROR_EOF = auto()
+ """Error reading transaction RLP, rlp stream unexpectedly finished."""
+ RLP_ERROR_SIZE = auto()
+ """Error reading transaction RLP, rlp size is invalid."""
+ RLP_ERROR_SIZE_LEADING_ZEROS = auto()
+ """Error reading transaction RLP, field size has leading zeros."""
+ INVALID_CHAINID = auto()
+ """Transaction chain id encoding is incorrect."""
+ RLP_INVALID_DATA = auto()
+ """Transaction data field is invalid rlp."""
+ RLP_INVALID_GASLIMIT = auto()
+ """Transaction gaslimit field is invalid rlp."""
+ RLP_INVALID_NONCE = auto()
+ """Transaction nonce field is invalid rlp."""
+ RLP_INVALID_TO = auto()
+ """Transaction to field is invalid rlp."""
+ RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_LONG = auto()
+ """Transaction access list address is > 20 bytes."""
+ RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_SHORT = auto()
+ """Transaction access list address is < 20 bytes."""
+ RLP_INVALID_ACCESS_LIST_STORAGE_TOO_LONG = auto()
+ """Transaction access list storage hash > 32 bytes."""
+ RLP_INVALID_ACCESS_LIST_STORAGE_TOO_SHORT = auto()
+ """Transaction access list storage hash < 32 bytes."""
+ RLP_INVALID_HEADER = auto()
+ """Transaction failed to read from RLP as rlp header is invalid."""
+ RLP_INVALID_VALUE = auto()
+ """Transaction value field is invalid rlp/structure."""
+ EC_RECOVERY_FAIL = auto()
+ """Transaction has correct signature, but ec recovery failed."""
+ INSUFFICIENT_ACCOUNT_FUNDS = auto()
+ """
+ Transaction's sender does not have enough funds to pay for the transaction.
+ """
+ INSUFFICIENT_MAX_FEE_PER_GAS = auto()
+ """Transaction's max-fee-per-gas is lower than the block base-fee."""
+ PRIORITY_OVERFLOW = auto()
+ """
+ Transaction's max-priority-fee-per-gas is exceeds 2^256-1 maximum value.
+ """
+ PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS = auto()
+ """
+ Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas.
+ """
+ PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS_2 = auto()
+ """
+ Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas
+ (TransactionTests).
+ """
+ INSUFFICIENT_MAX_FEE_PER_BLOB_GAS = auto()
+ """
+ Transaction's max-fee-per-blob-gas is lower than the block's blob-gas
+ price.
+ """
+ INTRINSIC_GAS_TOO_LOW = auto()
+ """Transaction's gas limit is too low."""
+ INTRINSIC_GAS_BELOW_FLOOR_GAS_COST = auto()
+ """Transaction's gas limit is below the floor gas cost."""
+ INITCODE_SIZE_EXCEEDED = auto()
+ """
+ Transaction's initcode for a contract-creating transaction is too large.
+ """
+ TYPE_3_TX_PRE_FORK = auto()
+ """Transaction type 3 included before activation fork."""
+ TYPE_3_TX_ZERO_BLOBS_PRE_FORK = auto()
+ """Transaction type 3, with zero blobs, included before activation fork."""
+ TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH = auto()
+ """Transaction contains a blob versioned hash with an invalid version."""
+ TYPE_3_TX_WITH_FULL_BLOBS = auto()
+ """Transaction contains full blobs (network-version of the transaction)."""
+ TYPE_3_TX_BLOB_COUNT_EXCEEDED = auto()
+ """Transaction contains too many blob versioned hashes."""
+ TYPE_3_TX_CONTRACT_CREATION = auto()
+ """Transaction is a type 3 transaction and has an empty `to`."""
+ TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED = auto()
+ """Transaction causes block to go over blob gas limit."""
+ GAS_ALLOWANCE_EXCEEDED = auto()
+ """Transaction causes block to go over blob gas limit."""
+ GAS_LIMIT_EXCEEDS_MAXIMUM = auto()
+ """
+ Transaction gas limit exceeds the maximum allowed limit of 30 million.
+ """
+ TYPE_3_TX_ZERO_BLOBS = auto()
+ """Transaction is type 3, but has no blobs."""
+ TYPE_4_EMPTY_AUTHORIZATION_LIST = auto()
+ """Transaction is type 4, but has an empty authorization list."""
+ TYPE_4_INVALID_AUTHORITY_SIGNATURE = auto()
+ """Transaction authority signature is invalid"""
+ TYPE_4_INVALID_AUTHORITY_SIGNATURE_S_TOO_HIGH = auto()
+ """Transaction authority signature is invalid"""
+ TYPE_4_TX_CONTRACT_CREATION = auto()
+ """Transaction is a type 4 transaction and has an empty `to`."""
+ TYPE_4_INVALID_AUTHORIZATION_FORMAT = auto()
+ """
+ Transaction is type 4, but contains an authorization that has an invalid
+ format.
+ """
+ TYPE_4_TX_PRE_FORK = auto()
+ """Transaction type 4 included before activation fork."""
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/py.typed b/packages/tests/src/ethereum_test_exceptions/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/py.typed
rename to packages/tests/src/ethereum_test_exceptions/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/tests/__init__.py b/packages/tests/src/ethereum_test_exceptions/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/tests/__init__.py
rename to packages/tests/src/ethereum_test_exceptions/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/tests/test_exceptions.py b/packages/tests/src/ethereum_test_exceptions/tests/test_exceptions.py
similarity index 96%
rename from src/ethereum_spec_tests/ethereum_test_exceptions/tests/test_exceptions.py
rename to packages/tests/src/ethereum_test_exceptions/tests/test_exceptions.py
index 925d76f9c6..a09381be22 100644
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/tests/test_exceptions.py
+++ b/packages/tests/src/ethereum_test_exceptions/tests/test_exceptions.py
@@ -34,7 +34,10 @@
def test_exceptions_string_conversion(
exception: BlockException | TransactionException, expected: str
):
- """Test that the exceptions are unique and have the correct string representation."""
+ """
+ Test that the exceptions are unique and have the correct string
+ representation.
+ """
assert str(exception) == expected
diff --git a/src/ethereum_spec_tests/ethereum_test_execution/__init__.py b/packages/tests/src/ethereum_test_execution/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_execution/__init__.py
rename to packages/tests/src/ethereum_test_execution/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_execution/base.py b/packages/tests/src/ethereum_test_execution/base.py
similarity index 94%
rename from src/ethereum_spec_tests/ethereum_test_execution/base.py
rename to packages/tests/src/ethereum_test_execution/base.py
index 1bf1d00437..58a3411443 100644
--- a/src/ethereum_spec_tests/ethereum_test_execution/base.py
+++ b/packages/tests/src/ethereum_test_execution/base.py
@@ -44,8 +44,8 @@ class LabeledExecuteFormat:
"""
Represents an execution format with a custom label.
- This label will be used in the test id and also will be added as a marker to the
- generated test case when executing the test.
+ This label will be used in the test id and also will be added as a marker
+ to the generated test case when executing the test.
"""
format: Type[BaseExecute]
@@ -85,8 +85,8 @@ def __eq__(self, other: Any) -> bool:
"""
Check if two labeled execute formats are equal.
- If the other object is a ExecuteFormat type, the format of the labeled execute
- format will be compared with the format of the other object.
+ If the other object is a ExecuteFormat type, the format of the labeled
+ execute format will be compared with the format of the other object.
"""
if isinstance(other, LabeledExecuteFormat):
return self.format == other.format
diff --git a/src/ethereum_spec_tests/ethereum_test_execution/blob_transaction.py b/packages/tests/src/ethereum_test_execution/blob_transaction.py
similarity index 94%
rename from src/ethereum_spec_tests/ethereum_test_execution/blob_transaction.py
rename to packages/tests/src/ethereum_test_execution/blob_transaction.py
index 8be0a25b44..21bedbf4dd 100644
--- a/src/ethereum_spec_tests/ethereum_test_execution/blob_transaction.py
+++ b/packages/tests/src/ethereum_test_execution/blob_transaction.py
@@ -9,10 +9,10 @@
from ethereum_test_base_types.base_types import Bytes
from ethereum_test_forks import Fork
from ethereum_test_rpc import BlobAndProofV1, BlobAndProofV2, EngineRPC, EthRPC
-from ethereum_test_rpc.types import GetBlobsResponse
+from ethereum_test_rpc.rpc_types import GetBlobsResponse
from ethereum_test_types import NetworkWrappedTransaction, Transaction
from ethereum_test_types.transaction_types import TransactionTestMetadata
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
from .base import BaseExecute
@@ -47,8 +47,9 @@ def versioned_hashes_with_blobs_and_proofs(
class BlobTransaction(BaseExecute):
"""
- Represents a test execution format to send blob transactions to the client and then
- use `engine_getBlobsV*` end points to validate the proofs generated by the execution client.
+ Represents a test execution format to send blob transactions to the client
+ and then use `engine_getBlobsV*` end points to validate the proofs
+ generated by the execution client.
"""
format_name: ClassVar[str] = "blob_transaction_test"
@@ -94,16 +95,18 @@ def execute(
version = fork.engine_get_blobs_version()
assert version is not None, "Engine get blobs version is not supported by the fork."
- # ensure that clients respond 'null' when they have no access to at least one blob
+ # ensure that clients respond 'null' when they have no access to at
+ # least one blob
list_versioned_hashes = list(versioned_hashes.keys())
if self.nonexisting_blob_hashes is not None:
list_versioned_hashes.extend(self.nonexisting_blob_hashes)
blob_response: GetBlobsResponse | None = engine_rpc.get_blobs(
list_versioned_hashes, version=version
- ) # noqa: E501
+ )
- # if non-existing blob hashes were request then the response must be 'null'
+ # if non-existing blob hashes were request then the response must be
+ # 'null'
if self.nonexisting_blob_hashes is not None:
if blob_response is not None:
raise ValueError(
@@ -121,8 +124,9 @@ def execute(
assert blob_response is not None
local_blobs_and_proofs = list(versioned_hashes.values())
- assert len(blob_response) == len(local_blobs_and_proofs), "Expected "
- f"{len(local_blobs_and_proofs)} blobs and proofs, got {len(blob_response)}."
+ assert len(blob_response) == len(local_blobs_and_proofs), (
+ f"Expected {len(local_blobs_and_proofs)} blobs and proofs, got {len(blob_response)}."
+ )
for expected_blob, received_blob in zip(
local_blobs_and_proofs, blob_response.root, strict=True
diff --git a/src/ethereum_spec_tests/ethereum_test_execution/transaction_post.py b/packages/tests/src/ethereum_test_execution/transaction_post.py
similarity index 70%
rename from src/ethereum_spec_tests/ethereum_test_execution/transaction_post.py
rename to packages/tests/src/ethereum_test_execution/transaction_post.py
index fce6b2bbcb..a94af44db6 100644
--- a/src/ethereum_spec_tests/ethereum_test_execution/transaction_post.py
+++ b/packages/tests/src/ethereum_test_execution/transaction_post.py
@@ -14,10 +14,15 @@
class TransactionPost(BaseExecute):
- """Represents a simple transaction-send then post-check execution format."""
+ """
+ Represents a simple transaction-send then post-check execution format.
+ """
blocks: List[List[Transaction]]
post: Alloc
+ # Gas validation fields for benchmark tests
+ expected_benchmark_gas_used: int | None = None # Expected total gas to be consumed
+ skip_gas_used_validation: bool = False # Skip gas validation even if expected is set
format_name: ClassVar[str] = "transaction_post_test"
description: ClassVar[str] = (
@@ -31,6 +36,10 @@ def execute(
assert not any(tx.ty == 3 for block in self.blocks for tx in block), (
"Transaction type 3 is not supported in execute mode."
)
+
+ # Track transaction hashes for gas validation (benchmarking)
+ all_tx_hashes = []
+
for block in self.blocks:
signed_txs = []
for tx_index, tx in enumerate(block):
@@ -49,11 +58,31 @@ def execute(
for transaction in signed_txs:
if transaction.error is None:
eth_rpc.send_wait_transaction(transaction)
+ all_tx_hashes.append(transaction.hash)
else:
with pytest.raises(SendTransactionExceptionError):
eth_rpc.send_transaction(transaction)
else:
eth_rpc.send_wait_transactions(signed_txs)
+ all_tx_hashes.extend([tx.hash for tx in signed_txs])
+
+ # Perform gas validation if required for benchmarking
+ # Ensures benchmark tests consume exactly the expected gas
+ if not self.skip_gas_used_validation and self.expected_benchmark_gas_used is not None:
+ total_gas_used = 0
+ # Fetch transaction receipts to get actual gas used
+ for tx_hash in all_tx_hashes:
+ receipt = eth_rpc.get_transaction_receipt(tx_hash)
+ assert receipt is not None, f"Failed to get receipt for transaction {tx_hash}"
+ gas_used = int(receipt["gasUsed"], 16)
+ total_gas_used += gas_used
+
+ # Verify that the total gas consumed matches expectations
+ assert total_gas_used == self.expected_benchmark_gas_used, (
+ f"Total gas used ({total_gas_used}) does not match "
+ f"expected benchmark gas ({self.expected_benchmark_gas_used}), "
+ f"difference: {total_gas_used - self.expected_benchmark_gas_used}"
+ )
for address, account in self.post.root.items():
balance = eth_rpc.get_balance(address)
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/__init__.py b/packages/tests/src/ethereum_test_fixtures/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/__init__.py
rename to packages/tests/src/ethereum_test_fixtures/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/base.py b/packages/tests/src/ethereum_test_fixtures/base.py
similarity index 95%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/base.py
rename to packages/tests/src/ethereum_test_fixtures/base.py
index b4531e4580..e0670b7b34 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/base.py
+++ b/packages/tests/src/ethereum_test_fixtures/base.py
@@ -64,7 +64,10 @@ class BaseFixture(CamelModel):
@classmethod
def output_base_dir_name(cls) -> str:
- """Return name of the subdirectory where this type of fixture should be dumped to."""
+ """
+ Return name of the subdirectory where this type of fixture should be
+ dumped to.
+ """
return cls.format_name.replace("test", "tests")
@classmethod
@@ -161,7 +164,10 @@ def discard_fixture_format_by_marks(
fork: Fork,
markers: List[pytest.Mark],
) -> bool:
- """Discard a fixture format from filling if the appropriate marker is used."""
+ """
+ Discard a fixture format from filling if the appropriate marker is
+ used.
+ """
return False
@@ -169,8 +175,8 @@ class LabeledFixtureFormat:
"""
Represents a fixture format with a custom label.
- This label will be used in the test id and also will be added as a marker to the
- generated test case when filling the test.
+ This label will be used in the test id and also will be added as a marker
+ to the generated test case when filling the test.
"""
format: Type[BaseFixture]
@@ -210,8 +216,8 @@ def __eq__(self, other: Any) -> bool:
"""
Check if two labeled fixture formats are equal.
- If the other object is a FixtureFormat type, the format of the labeled fixture
- format will be compared with the format of the other object.
+ If the other object is a FixtureFormat type, the format of the labeled
+ fixture format will be compared with the format of the other object.
"""
if isinstance(other, LabeledFixtureFormat):
return self.format == other.format
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/blockchain.py b/packages/tests/src/ethereum_test_fixtures/blockchain.py
similarity index 87%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/blockchain.py
rename to packages/tests/src/ethereum_test_fixtures/blockchain.py
index c773b2af3b..e1323efffa 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/blockchain.py
+++ b/packages/tests/src/ethereum_test_fixtures/blockchain.py
@@ -55,10 +55,8 @@ def post_state_validator(alternate_field: str | None = None, mode: str = "after"
"""
Create a validator to ensure exactly one post-state field is provided.
- Args:
- alternate_field: Alternative field name to post_state_hash (e.g., 'post_state_diff').
- mode: Pydantic validation mode.
-
+ Args: alternate_field: Alternative field name to post_state_hash (e.g.,
+ 'post_state_diff'). mode: Pydantic validation mode.
"""
def decorator(cls):
@@ -68,10 +66,12 @@ def validate_post_state_fields(self):
if mode == "after":
# Determine which fields to check
if alternate_field:
- # For engine x fixtures: check post_state vs post_state_diff
+ # For engine x fixtures: check post_state vs
+ # post_state_diff
field1_name, field2_name = "post_state", alternate_field
else:
- # For standard fixtures: check post_state vs post_state_hash
+ # For standard fixtures: check post_state vs
+ # post_state_hash
field1_name, field2_name = "post_state", "post_state_hash"
field1_value = getattr(self, field1_name, None)
@@ -93,8 +93,8 @@ def validate_post_state_fields(self):
class HeaderForkRequirement(str):
"""
- Fork requirement class that specifies the name of the method that should be called
- to check if the field is required.
+ Fork requirement class that specifies the name of the method that should be
+ called to check if the field is required.
"""
def __new__(cls, value: str) -> "HeaderForkRequirement":
@@ -103,7 +103,9 @@ def __new__(cls, value: str) -> "HeaderForkRequirement":
def required(self, fork: Fork, block_number: int, timestamp: int) -> bool:
"""Check if the field is required for the given fork."""
- return getattr(fork, f"header_{self}_required")(block_number, timestamp)
+ return getattr(fork, f"header_{self}_required")(
+ block_number=block_number, timestamp=timestamp
+ )
@classmethod
def get_from_annotation(cls, field_hints: Any) -> "HeaderForkRequirement | None":
@@ -173,7 +175,10 @@ class FixtureHeader(CamelModel):
fork: Fork | None = Field(None, exclude=True)
def model_post_init(self, __context):
- """Model post init method used to check for required fields of a given fork."""
+ """
+ Model post init method used to check for required fields of a given
+ fork.
+ """
super().model_post_init(__context)
if self.fork is None:
@@ -184,8 +189,9 @@ def model_post_init(self, __context):
block_number = self.number
timestamp = self.timestamp
- # For each field, check if any of the annotations are of type HeaderForkRequirement and
- # if so, check if the field is required for the given fork.
+ # For each field, check if any of the annotations are of type
+ # HeaderForkRequirement and if so, check if the field is required for
+ # the given fork.
annotated_hints = get_type_hints(self, include_extras=True)
for field in self.__class__.model_fields:
@@ -234,9 +240,13 @@ def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> "FixtureHead
environment_values["extra_data"] = env.extra_data
extras = {
"state_root": state_root,
- "requests_hash": Requests() if fork.header_requests_required(0, 0) else None,
+ "requests_hash": Requests()
+ if fork.header_requests_required(block_number=0, timestamp=0)
+ else None,
"block_access_list_hash": (
- BlockAccessList().rlp_hash if fork.header_bal_hash_required(0, 0) else None
+ BlockAccessList().rlp_hash
+ if fork.header_bal_hash_required(block_number=0, timestamp=0)
+ else None
),
"fork": fork,
}
@@ -244,7 +254,9 @@ def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> "FixtureHead
class FixtureExecutionPayload(CamelModel):
- """Representation of an Ethereum execution payload within a test Fixture."""
+ """
+ Representation of an Ethereum execution payload within a test Fixture.
+ """
parent_hash: Hash
fee_recipient: Address
@@ -282,8 +294,8 @@ def from_fixture_header(
block_access_list: Bytes | None = None,
) -> "FixtureExecutionPayload":
"""
- Return FixtureExecutionPayload from a FixtureHeader, a list
- of transactions, a list of withdrawals, and an optional block access list.
+ Return FixtureExecutionPayload from a FixtureHeader, a list of
+ transactions, a list of withdrawals, and an optional block access list.
"""
return cls(
**header.model_dump(exclude={"rlp"}, exclude_none=True),
@@ -301,10 +313,12 @@ def from_fixture_header(
Hash,
List[Bytes],
]
+EngineNewPayloadV5Parameters = EngineNewPayloadV4Parameters
-# Important: We check EngineNewPayloadV3Parameters first as it has more fields, and pydantic
-# has a weird behavior when the smaller tuple is checked first.
+# Important: We check EngineNewPayloadV3Parameters first as it has more fields,
+# and pydantic has a weird behavior when the smaller tuple is checked first.
EngineNewPayloadParameters = Union[
+ EngineNewPayloadV5Parameters,
EngineNewPayloadV4Parameters,
EngineNewPayloadV3Parameters,
EngineNewPayloadV1Parameters,
@@ -313,8 +327,8 @@ def from_fixture_header(
class FixtureEngineNewPayload(CamelModel):
"""
- Representation of the `engine_newPayloadVX` information to be
- sent using the block information.
+ Representation of the `engine_newPayloadVX` information to be sent using
+ the block information.
"""
params: EngineNewPayloadParameters
@@ -348,12 +362,23 @@ def from_fixture_header(
**kwargs,
) -> "FixtureEngineNewPayload":
"""Create `FixtureEngineNewPayload` from a `FixtureHeader`."""
- new_payload_version = fork.engine_new_payload_version(header.number, header.timestamp)
+ new_payload_version = fork.engine_new_payload_version(
+ block_number=header.number, timestamp=header.timestamp
+ )
forkchoice_updated_version = fork.engine_forkchoice_updated_version(
- header.number, header.timestamp
+ block_number=header.number, timestamp=header.timestamp
)
assert new_payload_version is not None, "Invalid header for engine_newPayload"
+
+ if fork.engine_execution_payload_block_access_list(
+ block_number=header.number, timestamp=header.timestamp
+ ):
+ if block_access_list is None:
+ raise ValueError(
+ f"`block_access_list` is required in engine `ExecutionPayload` for >={fork}."
+ )
+
execution_payload = FixtureExecutionPayload.from_fixture_header(
header=header,
transactions=transactions,
@@ -362,19 +387,25 @@ def from_fixture_header(
)
params: List[Any] = [execution_payload]
- if fork.engine_new_payload_blob_hashes(header.number, header.timestamp):
+ if fork.engine_new_payload_blob_hashes(
+ block_number=header.number, timestamp=header.timestamp
+ ):
blob_hashes = Transaction.list_blob_versioned_hashes(transactions)
if blob_hashes is None:
raise ValueError(f"Blob hashes are required for ${fork}.")
params.append(blob_hashes)
- if fork.engine_new_payload_beacon_root(header.number, header.timestamp):
+ if fork.engine_new_payload_beacon_root(
+ block_number=header.number, timestamp=header.timestamp
+ ):
parent_beacon_block_root = header.parent_beacon_block_root
if parent_beacon_block_root is None:
raise ValueError(f"Parent beacon block root is required for ${fork}.")
params.append(parent_beacon_block_root)
- if fork.engine_new_payload_requests(header.number, header.timestamp):
+ if fork.engine_new_payload_requests(
+ block_number=header.number, timestamp=header.timestamp
+ ):
if requests is None:
raise ValueError(f"Requests are required for ${fork}.")
params.append(requests)
@@ -436,7 +467,10 @@ def parse_witness_chunks(cls, s: str) -> List["WitnessChunk"]:
class FixtureBlockBase(CamelModel):
- """Representation of an Ethereum block within a test Fixture without RLP bytes."""
+ """
+ Representation of an Ethereum block within a test Fixture without RLP
+ bytes.
+ """
header: FixtureHeader = Field(..., alias="blockHeader")
txs: List[FixtureTransaction] = Field(default_factory=list, alias="transactions")
@@ -458,7 +492,9 @@ def with_rlp(self, txs: List[Transaction]) -> "FixtureBlock":
block = [
self.header.rlp_encode_list,
[tx.serializable_list for tx in txs],
- self.ommers, # TODO: This is incorrect, and we probably need to serialize the ommers
+ # TODO: This is incorrect, and we probably
+ # need to serialize the ommers
+ self.ommers,
]
if self.withdrawals is not None:
@@ -510,15 +546,16 @@ class BlockchainFixtureCommon(BaseFixture):
pre: Alloc
post_state: Alloc | None = Field(None)
post_state_hash: Hash | None = Field(None)
- last_block_hash: Hash = Field(..., alias="lastblockhash") # FIXME: lastBlockHash
+ # FIXME: lastBlockHash
+ last_block_hash: Hash = Field(..., alias="lastblockhash")
config: FixtureConfig
@model_validator(mode="before")
@classmethod
def config_defaults_for_backwards_compatibility(cls, data: Any) -> Any:
"""
- Check if the config field is populated, otherwise use the root-level field values for
- backwards compatibility.
+ Check if the config field is populated, otherwise use the root-level
+ field values for backwards compatibility.
"""
if isinstance(data, dict):
if "config" not in data:
@@ -557,7 +594,8 @@ class BlockchainEngineFixtureCommon(BaseFixture):
fork: Fork = Field(..., alias="network")
post_state_hash: Hash | None = Field(None)
- last_block_hash: Hash = Field(..., alias="lastblockhash") # FIXME: lastBlockHash
+ # FIXME: lastBlockHash
+ last_block_hash: Hash = Field(..., alias="lastblockhash")
config: FixtureConfig
def get_fork(self) -> Fork | None:
@@ -607,7 +645,10 @@ class BlockchainEngineXFixture(BlockchainEngineFixtureCommon):
"""Hash of the pre-allocation group this test belongs to."""
post_state_diff: Alloc | None = None
- """State difference from genesis after test execution (efficiency optimization)."""
+ """
+ State difference from genesis after test execution (efficiency
+ optimization).
+ """
payloads: List[FixtureEngineNewPayload] = Field(..., alias="engineNewPayloads")
"""Engine API payloads for blockchain execution."""
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/collector.py b/packages/tests/src/ethereum_test_fixtures/collector.py
similarity index 91%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/collector.py
rename to packages/tests/src/ethereum_test_fixtures/collector.py
index e13e043125..10606bfefc 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/collector.py
+++ b/packages/tests/src/ethereum_test_fixtures/collector.py
@@ -1,6 +1,6 @@
"""
-Fixture collector class used to collect, sort and combine the different types of generated
-fixtures.
+Fixture collector class used to collect, sort and combine the different types
+of generated fixtures.
"""
import json
@@ -23,9 +23,11 @@ class TestInfo:
"""Contains test information from the current node."""
name: str # pytest: Item.name, e.g. test_paris_one[fork_Paris-state_test]
- id: str # pytest: Item.nodeid, e.g. tests/paris/test_module_paris.py::test_paris_one[...]
+ id: str # pytest: Item.nodeid, e.g.
+ # tests/paris/test_module_paris.py::test_paris_one[...]
original_name: str # pytest: Item.originalname, e.g. test_paris_one
- module_path: Path # pytest: Item.path, e.g. .../tests/paris/test_module_paris.py
+ module_path: Path # pytest: Item.path, e.g.
+ # .../tests/paris/test_module_paris.py
test_prefix: ClassVar[str] = "test_" # Python test prefix
filler_suffix: ClassVar[str] = "Filler" # Static test suffix
@@ -41,11 +43,11 @@ def strip_test_name(cls, name: str) -> str:
def get_name_and_parameters(self) -> Tuple[str, str]:
"""
- Convert test name to a tuple containing the test name and test parameters.
-
- Example:
- test_push0_key_sstore[fork_Shanghai] -> test_push0_key_sstore, fork_Shanghai
+ Convert test name to a tuple containing the test name and test
+ parameters.
+ Example: test_push0_key_sstore[fork_Shanghai] -> test_push0_key_sstore,
+ fork_Shanghai
"""
test_name, parameters = self.name.split("[")
return test_name, re.sub(r"[\[\-]", "_", parameters).replace("]", "")
@@ -91,9 +93,8 @@ def get_module_relative_output_dir(self, filler_path: Path) -> Path:
base ./tests directory) that can be used for output (within the
configured fixtures output path or the base_dump_dir directory).
- Example:
- tests/shanghai/eip3855_push0/test_push0.py -> shanghai/eip3855_push0/test_push0
-
+ Example: tests/shanghai/eip3855_push0/test_push0.py ->
+ shanghai/eip3855_push0/test_push0
"""
basename = self.module_path.with_suffix("").absolute()
basename_relative = basename.relative_to(
@@ -122,8 +123,9 @@ def get_fixture_basename(self, info: TestInfo) -> Path:
"""Return basename of the fixture file for a given test case."""
module_relative_output_dir = info.get_module_relative_output_dir(self.filler_path)
- # Each legacy test filler has only 1 test per file if it's a !state test!
- # So no need to create directory Add11/add11.json it can be plain add11.json
+ # Each legacy test filler has only 1 test per file if it's a !state
+ # test! So no need to create directory Add11/add11.json it can be plain
+ # add11.json
if self.fill_static_tests:
return module_relative_output_dir.parent / info.original_name
@@ -140,7 +142,8 @@ def add_fixture(self, info: TestInfo, fixture: BaseFixture) -> Path:
/ fixture.output_base_dir_name()
/ fixture_basename.with_suffix(fixture.output_file_extension)
)
- if fixture_path not in self.all_fixtures.keys(): # relevant when we group by test function
+ # relevant when we group by test function
+ if fixture_path not in self.all_fixtures.keys():
self.all_fixtures[fixture_path] = Fixtures(root={})
self.json_path_to_test_item[fixture_path] = info
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/common.py b/packages/tests/src/ethereum_test_fixtures/common.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/common.py
rename to packages/tests/src/ethereum_test_fixtures/common.py
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/consume.py b/packages/tests/src/ethereum_test_fixtures/consume.py
similarity index 95%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/consume.py
rename to packages/tests/src/ethereum_test_fixtures/consume.py
index dcec641b3a..b55f35efd4 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/consume.py
+++ b/packages/tests/src/ethereum_test_fixtures/consume.py
@@ -34,7 +34,10 @@ def consume_fixture(
fixture_name: str | None = None,
debug_output_path: Path | None = None,
):
- """Test the client with the specified fixture using its direct consumer interface."""
+ """
+ Test the client with the specified fixture using its direct consumer
+ interface.
+ """
raise NotImplementedError(
"The `consume_fixture()` function is not supported by this tool."
)
@@ -59,7 +62,9 @@ class TestCaseStream(TestCaseBase):
class TestCaseIndexFile(TestCaseBase):
- """The test case model used to save/load test cases to/from an index file."""
+ """
+ The test case model used to save/load test cases to/from an index file.
+ """
json_path: Path
__test__ = False # stop pytest from collecting this class as a test
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/eof.py b/packages/tests/src/ethereum_test_fixtures/eof.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/eof.py
rename to packages/tests/src/ethereum_test_fixtures/eof.py
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/file.py b/packages/tests/src/ethereum_test_fixtures/file.py
similarity index 83%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/file.py
rename to packages/tests/src/ethereum_test_fixtures/file.py
index 2f74e06b37..8679cfabcf 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/file.py
+++ b/packages/tests/src/ethereum_test_fixtures/file.py
@@ -15,13 +15,14 @@
class Fixtures(EthereumTestRootModel):
"""
A base class for defining top-level models that encapsulate multiple test
- fixtures. Each fixture is stored in a dictionary, where each key is a string
- (typically the fixture name) and its corresponding value is a fixture object.
- This is the structure used for blockchain and state JSON fixture files.
-
- This class implements dunder methods and other common functionality to allow
- interaction with the model's fixtures as if they were being accessed directly
- from a dictionary.
+ fixtures. Each fixture is stored in a dictionary, where each key is a
+ string (typically the fixture name) and its corresponding value is a
+ fixture object. This is the structure used for blockchain and state JSON
+ fixture files.
+
+ This class implements dunder methods and other common functionality to
+ allow interaction with the model's fixtures as if they were being accessed
+ directly from a dictionary.
"""
root: Dict[str, SerializeAsAny[BaseFixture]]
@@ -54,8 +55,8 @@ def collect_into_file(self, file_path: Path):
"""
For all formats, we join the fixtures as json into a single file.
- Note: We don't use pydantic model_dump_json() on the Fixtures object as we
- add the hash to the info field on per-fixture basis.
+ Note: We don't use pydantic model_dump_json() on the Fixtures object as
+ we add the hash to the info field on per-fixture basis.
"""
json_fixtures: Dict[str, Dict[str, Any]] = {}
lock_file_path = file_path.with_suffix(".lock")
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/pre_alloc_groups.py b/packages/tests/src/ethereum_test_fixtures/pre_alloc_groups.py
similarity index 94%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/pre_alloc_groups.py
rename to packages/tests/src/ethereum_test_fixtures/pre_alloc_groups.py
index c358b75709..25173760d0 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/pre_alloc_groups.py
+++ b/packages/tests/src/ethereum_test_fixtures/pre_alloc_groups.py
@@ -22,7 +22,8 @@ class PreAllocGroup(CamelModel):
pre-allocation group optimization.
"""
- model_config = {"populate_by_name": True} # Allow both field names and aliases
+ # Allow both field names and aliases
+ model_config = {"populate_by_name": True}
test_ids: List[str] = Field(default_factory=list)
environment: Environment = Field(..., description="Grouping environment for this test group")
@@ -65,9 +66,10 @@ def to_file(self, file: Path) -> None:
else:
new_account = self.pre[account]
if new_account != existing_account:
- # This procedure fails during xdist worker's pytest_sessionfinish
- # and is not reported to the master thread.
- # We signal here that the groups created contain a collision.
+ # This procedure fails during xdist worker's
+ # pytest_sessionfinish and is not reported to the
+ # master thread. We signal here that the groups
+ # created contain a collision.
collision_file_path = file.with_suffix(".fail")
collision_exception = Alloc.CollisionError(
address=account,
@@ -87,7 +89,8 @@ class PreAllocGroups(EthereumTestRootModel):
"""
Root model mapping pre-allocation group hashes to test groups.
- If lazy_load is True, the groups are not loaded from the folder until they are accessed.
+ If lazy_load is True, the groups are not loaded from the folder until they
+ are accessed.
Iterating will fail if lazy_load is True.
"""
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/py.typed b/packages/tests/src/ethereum_test_fixtures/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/py.typed
rename to packages/tests/src/ethereum_test_fixtures/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/state.py b/packages/tests/src/ethereum_test_fixtures/state.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/state.py
rename to packages/tests/src/ethereum_test_fixtures/state.py
index 8d389db57f..3dfb6ba29c 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/state.py
+++ b/packages/tests/src/ethereum_test_fixtures/state.py
@@ -64,7 +64,9 @@ def from_transaction(cls, tx: Transaction) -> "FixtureTransaction":
class FixtureForkPostIndexes(BaseModel):
- """Type used to describe the indexes of a single post state of a single Fork."""
+ """
+ Type used to describe the indexes of a single post state of a single Fork.
+ """
data: int = 0
gas: int = 0
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/__init__.py b/packages/tests/src/ethereum_test_fixtures/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/__init__.py
rename to packages/tests/src/ethereum_test_fixtures/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_base.py b/packages/tests/src/ethereum_test_fixtures/tests/test_base.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_base.py
rename to packages/tests/src/ethereum_test_fixtures/tests/test_base.py
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_blockchain.py b/packages/tests/src/ethereum_test_fixtures/tests/test_blockchain.py
similarity index 99%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_blockchain.py
rename to packages/tests/src/ethereum_test_fixtures/tests/test_blockchain.py
index c2917a2ccf..944f2ece29 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_blockchain.py
+++ b/packages/tests/src/ethereum_test_fixtures/tests/test_blockchain.py
@@ -531,8 +531,9 @@
id="invalid_fixture_block_2",
),
pytest.param(
- False, # Can not be deserialized: A single expect_exception str will not be
- # deserialized as a list and therefore will not match the model_instance definition.
+ False, # Can not be deserialized: A single expect_exception str
+ # will not be deserialized as a list and therefore will not
+ # match the model_instance definition.
InvalidFixtureBlock(
rlp="0x00",
expect_exception=[TransactionException.INTRINSIC_GAS_TOO_LOW],
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_eof.py b/packages/tests/src/ethereum_test_fixtures/tests/test_eof.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_eof.py
rename to packages/tests/src/ethereum_test_fixtures/tests/test_eof.py
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_state.py b/packages/tests/src/ethereum_test_fixtures/tests/test_state.py
similarity index 96%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_state.py
rename to packages/tests/src/ethereum_test_fixtures/tests/test_state.py
index e4b3ab50ce..b1881065b2 100644
--- a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_state.py
+++ b/packages/tests/src/ethereum_test_fixtures/tests/test_state.py
@@ -50,8 +50,9 @@
id="state_fixture_fork_post_exception",
),
pytest.param(
- False, # Can not be deserialized: A single expect_exception str will not be
- # deserialized as a list and therefore will not match the model_instance definition.
+ False, # Can not be deserialized: A single expect_exception str
+ # will not be deserialized as a list and therefore will not
+ # match the model_instance definition.
FixtureForkPost(
state_root=0,
logs_hash=1,
diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/transaction.py b/packages/tests/src/ethereum_test_fixtures/transaction.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_fixtures/transaction.py
rename to packages/tests/src/ethereum_test_fixtures/transaction.py
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/__init__.py b/packages/tests/src/ethereum_test_forks/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/__init__.py
rename to packages/tests/src/ethereum_test_forks/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/base_decorators.py b/packages/tests/src/ethereum_test_forks/base_decorators.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/base_decorators.py
rename to packages/tests/src/ethereum_test_forks/base_decorators.py
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/base_fork.py b/packages/tests/src/ethereum_test_forks/base_fork.py
similarity index 56%
rename from src/ethereum_spec_tests/ethereum_test_forks/base_fork.py
rename to packages/tests/src/ethereum_test_forks/base_fork.py
index 2ce7a89705..a08fc617cd 100644
--- a/src/ethereum_spec_tests/ethereum_test_forks/base_fork.py
+++ b/packages/tests/src/ethereum_test_forks/base_fork.py
@@ -26,15 +26,22 @@
class ForkAttribute(Protocol):
- """A protocol to get the attribute of a fork at a given block number and timestamp."""
+ """
+ A protocol to get the attribute of a fork at a given block number and
+ timestamp.
+ """
def __call__(self, block_number: int = 0, timestamp: int = 0) -> Any:
- """Return value of the attribute at the given block number and timestamp."""
+ """
+ Return value of the attribute at the given block number and timestamp.
+ """
pass
class MemoryExpansionGasCalculator(Protocol):
- """A protocol to calculate the gas cost of memory expansion at a given fork."""
+ """
+ A protocol to calculate the gas cost of memory expansion at a given fork.
+ """
def __call__(self, *, new_bytes: int, previous_bytes: int = 0) -> int:
"""Return gas cost of expanding the memory by the given length."""
@@ -42,7 +49,10 @@ def __call__(self, *, new_bytes: int, previous_bytes: int = 0) -> int:
class CalldataGasCalculator(Protocol):
- """A protocol to calculate the transaction gas cost of calldata at a given fork."""
+ """
+ A protocol to calculate the transaction gas cost of calldata at a given
+ fork.
+ """
def __call__(self, *, data: BytesConvertible, floor: bool = False) -> int:
"""Return the transaction gas cost of calldata given its contents."""
@@ -50,7 +60,9 @@ def __call__(self, *, data: BytesConvertible, floor: bool = False) -> int:
class TransactionDataFloorCostCalculator(Protocol):
- """Calculate the transaction floor cost due to its calldata for a given fork."""
+ """
+ Calculate the transaction floor cost due to its calldata for a given fork.
+ """
def __call__(self, *, data: BytesConvertible) -> int:
"""Return transaction gas cost of calldata given its contents."""
@@ -68,7 +80,10 @@ def __call__(
class BaseFeeChangeCalculator(Protocol):
- """A protocol to calculate the gas that needs to be used to change the base fee."""
+ """
+ A protocol to calculate the gas that needs to be used to change the base
+ fee.
+ """
def __call__(
self,
@@ -82,7 +97,10 @@ def __call__(
class TransactionIntrinsicCostCalculator(Protocol):
- """A protocol to calculate the intrinsic gas cost of a transaction at a given fork."""
+ """
+ A protocol to calculate the intrinsic gas cost of a transaction at a given
+ fork.
+ """
def __call__(
self,
@@ -97,25 +115,32 @@ def __call__(
Return the intrinsic gas cost of a transaction given its properties.
Args:
- calldata: The data of the transaction.
- contract_creation: Whether the transaction creates a contract.
- access_list: The list of access lists for the transaction.
- authorization_list_or_count: The list of authorizations or the count of authorizations
- for the transaction.
- return_cost_deducted_prior_execution: If set to False, the returned value is equal to
- the minimum gas required for the transaction to be valid. If set to True, the
- returned value is equal to the cost that is deducted from the gas limit before
- the transaction starts execution.
-
- Returns:
- Gas cost of a transaction
+ calldata: The data of the transaction.
+ contract_creation: Whether the transaction creates a contract.
+ access_list: The list of access lists for the transaction.
+ authorization_list_or_count: The list of authorizations or the count
+ of authorizations for the transaction.
+ return_cost_deducted_prior_execution: If set to False, the returned
+ value is equal to the minimum
+ gas required for the
+ transaction to be valid. If
+ set to True, the returned
+ value is equal to the cost
+ that is deducted from the gas
+ limit before the transaction
+ starts execution.
+
+ Returns: Gas cost of a transaction
"""
pass
class BlobGasPriceCalculator(Protocol):
- """A protocol to calculate the blob gas price given the excess blob gas at a given fork."""
+ """
+ A protocol to calculate the blob gas price given the excess blob gas at a
+ given fork.
+ """
def __call__(self, *, excess_blob_gas: int) -> int:
"""Return the blob gas price given the excess blob gas."""
@@ -123,7 +148,9 @@ def __call__(self, *, excess_blob_gas: int) -> int:
class ExcessBlobGasCalculator(Protocol):
- """A protocol to calculate the excess blob gas for a block at a given fork."""
+ """
+ A protocol to calculate the excess blob gas for a block at a given fork.
+ """
def __call__(
self,
@@ -134,7 +161,10 @@ def __call__(
parent_blob_count: int | None = None,
parent_base_fee_per_gas: int,
) -> int:
- """Return the excess blob gas given the parent's excess blob gas and blob gas used."""
+ """
+ Return the excess blob gas given the parent's excess blob gas and blob
+ gas used.
+ """
pass
@@ -143,7 +173,10 @@ class BaseForkMeta(ABCMeta):
@abstractmethod
def name(cls) -> str:
- """Return the name of the fork (e.g., Berlin), must be implemented by subclasses."""
+ """
+ Return the name of the fork (e.g., Berlin), must be implemented by
+ subclasses.
+ """
pass
def __repr__(cls) -> str:
@@ -152,12 +185,18 @@ def __repr__(cls) -> str:
@staticmethod
def _maybe_transitioned(fork_cls: "BaseForkMeta") -> "BaseForkMeta":
- """Return the transitioned fork, if a transition fork, otherwise return `fork_cls`."""
+ """
+ Return the transitioned fork, if a transition fork, otherwise return
+ `fork_cls`.
+ """
return fork_cls.transitions_to() if hasattr(fork_cls, "transitions_to") else fork_cls
@staticmethod
def _is_subclass_of(a: "BaseForkMeta", b: "BaseForkMeta") -> bool:
- """Check if `a` is a subclass of `b`, taking fork transitions into account."""
+ """
+ Check if `a` is a subclass of `b`, taking fork transitions into
+ account.
+ """
a = BaseForkMeta._maybe_transitioned(a)
b = BaseForkMeta._maybe_transitioned(b)
return issubclass(a, b)
@@ -167,7 +206,10 @@ def __gt__(cls, other: "BaseForkMeta") -> bool:
return cls is not other and BaseForkMeta._is_subclass_of(cls, other)
def __ge__(cls, other: "BaseForkMeta") -> bool:
- """Compare if a fork is newer than or equal to some other fork (cls >= other)."""
+ """
+ Compare if a fork is newer than or equal to some other fork (cls >=
+ other).
+ """
return cls is other or BaseForkMeta._is_subclass_of(cls, other)
def __lt__(cls, other: "BaseForkMeta") -> bool:
@@ -176,7 +218,10 @@ def __lt__(cls, other: "BaseForkMeta") -> bool:
return cls is not other and BaseForkMeta._is_subclass_of(other, cls)
def __le__(cls, other: "BaseForkMeta") -> bool:
- """Compare if a fork is older than or equal to some other fork (cls <= other)."""
+ """
+ Compare if a fork is older than or equal to some other fork (cls <=
+ other).
+ """
return cls is other or BaseForkMeta._is_subclass_of(other, cls)
@@ -209,7 +254,10 @@ def __init_subclass__(
ignore: bool = False,
bpo_fork: bool = False,
) -> None:
- """Initialize new fork with values that don't carry over to subclass forks."""
+ """
+ Initialize new fork with values that don't carry over to subclass
+ forks.
+ """
cls._transition_tool_name = transition_tool_name
cls._solc_name = solc_name
cls._ignore = ignore
@@ -223,55 +271,55 @@ def __init_subclass__(
# Header information abstract methods
@classmethod
@abstractmethod
- def header_base_fee_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_base_fee_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain base fee."""
pass
@classmethod
@abstractmethod
- def header_prev_randao_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_prev_randao_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain Prev Randao value."""
pass
@classmethod
@abstractmethod
- def header_zero_difficulty_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_zero_difficulty_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must have difficulty zero."""
pass
@classmethod
@abstractmethod
- def header_withdrawals_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_withdrawals_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain withdrawals."""
pass
@classmethod
@abstractmethod
- def header_excess_blob_gas_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_excess_blob_gas_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain excess blob gas."""
pass
@classmethod
@abstractmethod
- def header_blob_gas_used_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_blob_gas_used_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain blob gas used."""
pass
@classmethod
@abstractmethod
- def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_beacon_root_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain parent beacon block root."""
pass
@classmethod
@abstractmethod
- def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_requests_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain beacon chain requests."""
pass
@classmethod
@abstractmethod
- def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_bal_hash_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return true if the header must contain block access list hash."""
pass
@@ -279,162 +327,192 @@ def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) ->
@classmethod
@abstractmethod
- def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts:
+ def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts:
"""Return dataclass with the gas costs constants for the fork."""
pass
@classmethod
@abstractmethod
def memory_expansion_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> MemoryExpansionGasCalculator:
- """Return a callable that calculates the gas cost of memory expansion for the fork."""
+ """
+ Return a callable that calculates the gas cost of memory expansion for
+ the fork.
+ """
pass
@classmethod
@abstractmethod
def calldata_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> CalldataGasCalculator:
"""
- Return callable that calculates the transaction gas cost for its calldata
- depending on its contents.
+ Return callable that calculates the transaction gas cost for its
+ calldata depending on its contents.
"""
pass
@classmethod
@abstractmethod
def base_fee_per_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BaseFeePerGasCalculator:
- """Return a callable that calculates the base fee per gas at a given fork."""
+ """
+ Return a callable that calculates the base fee per gas at a given fork.
+ """
pass
@classmethod
@abstractmethod
def base_fee_change_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BaseFeeChangeCalculator:
"""
- Return a callable that calculates the gas that needs to be used to change the
- base fee.
+ Return a callable that calculates the gas that needs to be used to
+ change the base fee.
"""
pass
@classmethod
@abstractmethod
- def base_fee_max_change_denominator(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def base_fee_max_change_denominator(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base fee max change denominator at a given fork."""
pass
@classmethod
@abstractmethod
- def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def base_fee_elasticity_multiplier(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base fee elasticity multiplier at a given fork."""
pass
+ @classmethod
+ @abstractmethod
+ def max_refund_quotient(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """Return the max refund quotient at a given fork."""
+ pass
+
@classmethod
@abstractmethod
def transaction_data_floor_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionDataFloorCostCalculator:
- """Return a callable that calculates the transaction floor cost due to its calldata."""
+ """
+ Return a callable that calculates the transaction floor cost due to its
+ calldata.
+ """
pass
@classmethod
@abstractmethod
def transaction_intrinsic_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionIntrinsicCostCalculator:
- """Return callable that calculates the intrinsic gas cost of a transaction for the fork."""
+ """
+ Return callable that calculates the intrinsic gas cost of a transaction
+ for the fork.
+ """
pass
@classmethod
@abstractmethod
def blob_gas_price_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BlobGasPriceCalculator:
- """Return a callable that calculates the blob gas price at a given fork."""
+ """
+ Return a callable that calculates the blob gas price at a given fork.
+ """
pass
@classmethod
@abstractmethod
def excess_blob_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> ExcessBlobGasCalculator:
- """Return a callable that calculates the excess blob gas for a block at a given fork."""
+ """
+ Return a callable that calculates the excess blob gas for a block at a
+ given fork.
+ """
pass
@classmethod
@abstractmethod
- def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def min_base_fee_per_blob_gas(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the minimum base fee per blob gas at a given fork."""
pass
@classmethod
@abstractmethod
- def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_gas_per_blob(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the amount of blob gas used per blob at a given fork."""
pass
@classmethod
@abstractmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction at a given fork."""
pass
@classmethod
@abstractmethod
- def supports_blobs(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def supports_blobs(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Return whether the given fork supports blobs or not."""
pass
@classmethod
@abstractmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the target blobs per block at a given fork."""
pass
@classmethod
@abstractmethod
- def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the max blobs per transaction at a given fork."""
pass
@classmethod
@abstractmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the max blobs per block at a given fork."""
pass
@classmethod
@abstractmethod
- def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool:
- """Return whether the fork uses a reserve price mechanism for blobs or not."""
+ def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
+ """
+ Return whether the fork uses a reserve price mechanism for blobs or
+ not.
+ """
pass
@classmethod
@abstractmethod
- def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_cost(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base cost of a blob at a given fork."""
pass
@classmethod
@abstractmethod
- def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
- """Return the version of the full blob transaction wrapper at a given fork."""
+ def full_blob_tx_wrapper_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> int | None:
+ """
+ Return the version of the full blob transaction wrapper at a given
+ fork.
+ """
pass
@classmethod
@prefer_transition_to_method
@abstractmethod
- def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None:
+ def blob_schedule(cls, *, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None:
"""Return the blob schedule up until the given fork."""
pass
@classmethod
@abstractmethod
- def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return expected reward amount in wei of a given fork."""
pass
@@ -442,61 +520,71 @@ def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
@classmethod
@abstractmethod
- def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""Return list of the transaction types supported by the fork."""
pass
@classmethod
@abstractmethod
- def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
- """Return list of the transaction types supported by the fork that can create contracts."""
+ def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ """
+ Return list of the transaction types supported by the fork that can
+ create contracts.
+ """
pass
@classmethod
@abstractmethod
- def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
- """Return the transaction gas limit cap, or None if no limit is imposed."""
+ def transaction_gas_limit_cap(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None:
+ """
+ Return the transaction gas limit cap, or None if no limit is imposed.
+ """
pass
@classmethod
@abstractmethod
- def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
- """Return the maximum RLP size of a block in bytes, or None if no limit is imposed."""
+ def block_rlp_size_limit(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None:
+ """
+ Return the maximum RLP size of a block in bytes, or None if no limit is
+ imposed.
+ """
pass
@classmethod
@abstractmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""Return list pre-compiles supported by the fork."""
pass
@classmethod
@abstractmethod
- def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""Return list system-contracts supported by the fork."""
pass
@classmethod
@prefer_transition_to_method
@abstractmethod
- def pre_allocation(cls) -> Mapping:
+ def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping:
"""
Return required pre-allocation of accounts for any kind of test.
- This method must always call the `fork_to` method when transitioning, because the
- allocation can only be set at genesis, and thus cannot be changed at transition time.
+ This method must always call the `fork_to` method when transitioning,
+ because the allocation can only be set at genesis, and thus cannot be
+ changed at transition time.
"""
pass
@classmethod
@prefer_transition_to_method
@abstractmethod
- def pre_allocation_blockchain(cls) -> Mapping:
+ def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping:
"""
Return required pre-allocation of accounts for any blockchain tests.
- This method must always call the `fork_to` method when transitioning, because the
- allocation can only be set at genesis, and thus cannot be changed at transition time.
+ This method must always call the `fork_to` method when transitioning,
+ because the allocation can only be set at genesis, and thus cannot be
+ changed at transition time.
"""
pass
@@ -504,142 +592,179 @@ def pre_allocation_blockchain(cls) -> Mapping:
@classmethod
@abstractmethod
def engine_new_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
- Return `None` if this fork's payloads cannot be sent over the engine API,
- or the payload version if it can.
+ Return `None` if this fork's payloads cannot be sent over the engine
+ API, or the payload version if it can.
"""
pass
@classmethod
@abstractmethod
- def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def engine_new_payload_blob_hashes(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""
- Return true if the engine api version requires new payload calls to include
- blob hashes.
+ Return true if the engine api version requires new payload calls to
+ include blob hashes.
"""
pass
@classmethod
@abstractmethod
- def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def engine_new_payload_beacon_root(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""
- Return true if the engine api version requires new payload calls to include a parent
- beacon block root.
+ Return true if the engine api version requires new payload calls to
+ include a parent beacon block root.
"""
pass
@classmethod
@abstractmethod
- def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool:
- """Return true if the engine api version requires new payload calls to include requests."""
+ def engine_new_payload_requests(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
+ """
+ Return true if the engine api version requires new payload calls to
+ include requests.
+ """
pass
@classmethod
@abstractmethod
def engine_new_payload_target_blobs_per_block(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> bool:
+ """
+ Return true if the engine api version requires new payload calls to
+ include target blobs per block.
+ """
+ pass
+
+ @classmethod
+ @abstractmethod
+ def engine_execution_payload_block_access_list(
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
"""
- Return true if the engine api version requires new payload calls to include
- target blobs per block.
+ Return `True` if the engine api version requires execution payload to
+ include a `block_access_list`.
"""
pass
@classmethod
@abstractmethod
def engine_payload_attribute_target_blobs_per_block(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
- """Return true if the payload attributes include the target blobs per block."""
+ """
+ Return true if the payload attributes include the target blobs per
+ block.
+ """
pass
@classmethod
@abstractmethod
def engine_payload_attribute_max_blobs_per_block(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
- """Return true if the payload attributes include the max blobs per block."""
+ """
+ Return true if the payload attributes include the max blobs per block.
+ """
pass
@classmethod
@abstractmethod
def engine_forkchoice_updated_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
- """Return `None` if the forks canonical chain cannot be set using the forkchoice method."""
+ """
+ Return `None` if the forks canonical chain cannot be set using the
+ forkchoice method.
+ """
pass
@classmethod
@abstractmethod
def engine_get_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""
- Return `None` if the forks canonical chain cannot build a payload using the engine
- API.
+ Return `None` if the forks canonical chain cannot build a payload using
+ the engine API.
"""
pass
@classmethod
@abstractmethod
- def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]:
- """Return `None` if the fork does not support the engine get blobs version."""
+ def engine_get_blobs_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> Optional[int]:
+ """
+ Return `None` if the fork does not support the engine get blobs
+ version.
+ """
pass
# EVM information abstract methods
@classmethod
@abstractmethod
- def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]:
+ def evm_code_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]:
"""Return list of EVM code types supported by the fork."""
pass
@classmethod
@abstractmethod
- def max_code_size(cls) -> int:
- """Return the maximum code size allowed to be deployed in a contract creation."""
+ def max_code_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ Return the maximum code size allowed to be deployed in a contract
+ creation.
+ """
pass
@classmethod
@abstractmethod
- def max_stack_height(cls) -> int:
+ def max_stack_height(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the maximum stack height allowed in the EVM stack."""
pass
@classmethod
@abstractmethod
- def max_initcode_size(cls) -> int:
- """Return the maximum initcode size allowed to be used in a contract creation."""
+ def max_initcode_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ Return the maximum initcode size allowed to be used in a contract
+ creation.
+ """
pass
@classmethod
@abstractmethod
def call_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
- """Return list of tuples with the call opcodes and its corresponding EVM code type."""
+ """
+ Return list of tuples with the call opcodes and its corresponding EVM
+ code type.
+ """
pass
@classmethod
@abstractmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
pass
@classmethod
@abstractmethod
def create_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
- """Return list of tuples with the create opcodes and its corresponding EVM code type."""
+ """
+ Return list of tuples with the create opcodes and its corresponding EVM
+ code type.
+ """
pass
@classmethod
@abstractmethod
- def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_request_type(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return max request type supported by the fork."""
pass
@@ -650,17 +775,20 @@ def name(cls) -> str:
return cls.__name__
@classmethod
- def fork_at(cls, block_number: int = 0, timestamp: int = 0) -> Type["BaseFork"]:
+ def fork_at(cls, *, block_number: int = 0, timestamp: int = 0) -> Type["BaseFork"]:
"""
- Return fork at the given block number and timestamp.
- Useful only for transition forks, and it's a no-op for normal forks.
+ Return fork at the given block number and timestamp. Useful only for
+ transition forks, and it's a no-op for normal forks.
"""
return cls
@classmethod
@abstractmethod
- def transition_tool_name(cls, block_number: int = 0, timestamp: int = 0) -> str:
- """Return fork name as it's meant to be passed to the transition tool for execution."""
+ def transition_tool_name(cls, *, block_number: int = 0, timestamp: int = 0) -> str:
+ """
+ Return fork name as it's meant to be passed to the transition tool for
+ execution.
+ """
pass
@classmethod
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/__init__.py b/packages/tests/src/ethereum_test_forks/forks/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/__init__.py
rename to packages/tests/src/ethereum_test_forks/forks/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/consolidation_request.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/consolidation_request.bin
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/consolidation_request.bin
rename to packages/tests/src/ethereum_test_forks/forks/contracts/consolidation_request.bin
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/deposit_contract.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/deposit_contract.bin
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/deposit_contract.bin
rename to packages/tests/src/ethereum_test_forks/forks/contracts/deposit_contract.bin
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/history_contract.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/history_contract.bin
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/history_contract.bin
rename to packages/tests/src/ethereum_test_forks/forks/contracts/history_contract.bin
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/withdrawal_request.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/withdrawal_request.bin
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/withdrawal_request.bin
rename to packages/tests/src/ethereum_test_forks/forks/contracts/withdrawal_request.bin
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/forks.py b/packages/tests/src/ethereum_test_forks/forks/forks.py
similarity index 66%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/forks.py
rename to packages/tests/src/ethereum_test_forks/forks/forks.py
index b032354811..a5f44a6734 100644
--- a/src/ethereum_spec_tests/ethereum_test_forks/forks/forks.py
+++ b/packages/tests/src/ethereum_test_forks/forks/forks.py
@@ -33,8 +33,11 @@ class Frontier(BaseFork, solc_name="homestead"):
"""Frontier fork."""
@classmethod
- def transition_tool_name(cls, block_number: int = 0, timestamp: int = 0) -> str:
- """Return fork name as it's meant to be passed to the transition tool for execution."""
+ def transition_tool_name(cls, *, block_number: int = 0, timestamp: int = 0) -> str:
+ """
+ Return fork name as it's meant to be passed to the transition tool for
+ execution.
+ """
if cls._transition_tool_name is not None:
return cls._transition_tool_name
return cls.name()
@@ -47,38 +50,40 @@ def solc_name(cls) -> str:
return cls.name().lower()
@classmethod
- def header_base_fee_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_base_fee_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain base fee."""
return False
@classmethod
- def header_prev_randao_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_prev_randao_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain Prev Randao value."""
return False
@classmethod
- def header_zero_difficulty_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_zero_difficulty_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not have difficulty zero."""
return False
@classmethod
- def header_withdrawals_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_withdrawals_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain withdrawals."""
return False
@classmethod
- def header_excess_blob_gas_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_excess_blob_gas_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain excess blob gas."""
return False
@classmethod
- def header_blob_gas_used_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_blob_gas_used_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain blob gas used."""
return False
@classmethod
- def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts:
- """Return dataclass with the defined gas costs constants for genesis."""
+ def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts:
+ """
+ Return dataclass with the defined gas costs constants for genesis.
+ """
return GasCosts(
G_JUMPDEST=1,
G_BASE=2,
@@ -124,10 +129,13 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts:
@classmethod
def memory_expansion_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> MemoryExpansionGasCalculator:
- """Return callable that calculates the gas cost of memory expansion for the fork."""
- gas_costs = cls.gas_costs(block_number, timestamp)
+ """
+ Return callable that calculates the gas cost of memory expansion for
+ the fork.
+ """
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
def fn(*, new_bytes: int, previous_bytes: int = 0) -> int:
if new_bytes <= previous_bytes:
@@ -144,15 +152,17 @@ def c(w: int) -> int:
@classmethod
def calldata_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> CalldataGasCalculator:
"""
- Return callable that calculates the transaction gas cost for its calldata
- depending on its contents.
+ Return callable that calculates the transaction gas cost for its
+ calldata depending on its contents.
"""
- gas_costs = cls.gas_costs(block_number, timestamp)
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
def fn(*, data: BytesConvertible, floor: bool = False) -> int:
+ del floor
+
cost = 0
for b in Bytes(data):
if b == 0:
@@ -165,30 +175,32 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int:
@classmethod
def base_fee_per_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BaseFeePerGasCalculator:
- """Return a callable that calculates the base fee per gas at a given fork."""
+ """
+ Return a callable that calculates the base fee per gas at a given fork.
+ """
raise NotImplementedError(f"Base fee per gas calculator is not supported in {cls.name()}")
@classmethod
def base_fee_change_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BaseFeeChangeCalculator:
"""
- Return a callable that calculates the gas that needs to be used to change the
- base fee.
+ Return a callable that calculates the gas that needs to be used to
+ change the base fee.
"""
raise NotImplementedError(f"Base fee change calculator is not supported in {cls.name()}")
@classmethod
- def base_fee_max_change_denominator(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def base_fee_max_change_denominator(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base fee max change denominator at a given fork."""
raise NotImplementedError(
f"Base fee max change denominator is not supported in {cls.name()}"
)
@classmethod
- def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def base_fee_elasticity_multiplier(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base fee elasticity multiplier at a given fork."""
raise NotImplementedError(
f"Base fee elasticity multiplier is not supported in {cls.name()}"
@@ -196,22 +208,28 @@ def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int =
@classmethod
def transaction_data_floor_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionDataFloorCostCalculator:
"""At frontier, the transaction data floor cost is a constant zero."""
def fn(*, data: BytesConvertible) -> int:
+ del data
return 0
return fn
@classmethod
def transaction_intrinsic_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionIntrinsicCostCalculator:
- """Return callable that calculates the intrinsic gas cost of a transaction for the fork."""
- gas_costs = cls.gas_costs(block_number, timestamp)
- calldata_gas_calculator = cls.calldata_gas_calculator(block_number, timestamp)
+ """
+ Return callable that calculates the intrinsic gas cost of a transaction
+ for the fork.
+ """
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
+ calldata_gas_calculator = cls.calldata_gas_calculator(
+ block_number=block_number, timestamp=timestamp
+ )
def fn(
*,
@@ -221,6 +239,8 @@ def fn(
authorization_list_or_count: Sized | int | None = None,
return_cost_deducted_prior_execution: bool = False,
) -> int:
+ del return_cost_deducted_prior_execution
+
assert access_list is None, f"Access list is not supported in {cls.name()}"
assert authorization_list_or_count is None, (
f"Authorizations are not supported in {cls.name()}"
@@ -239,117 +259,135 @@ def fn(
@classmethod
def blob_gas_price_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BlobGasPriceCalculator:
- """Return a callable that calculates the blob gas price at a given fork."""
+ """
+ Return a callable that calculates the blob gas price at a given fork.
+ """
raise NotImplementedError(f"Blob gas price calculator is not supported in {cls.name()}")
@classmethod
def excess_blob_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> ExcessBlobGasCalculator:
- """Return a callable that calculates the excess blob gas for a block at a given fork."""
+ """
+ Return a callable that calculates the excess blob gas for a block at a
+ given fork.
+ """
raise NotImplementedError(f"Excess blob gas calculator is not supported in {cls.name()}")
@classmethod
- def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def min_base_fee_per_blob_gas(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the amount of blob gas used per blob at a given fork."""
raise NotImplementedError(f"Base fee per blob gas is not supported in {cls.name()}")
@classmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction at a given fork."""
raise NotImplementedError(
f"Blob base fee update fraction is not supported in {cls.name()}"
)
@classmethod
- def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_gas_per_blob(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the amount of blob gas used per blob at a given fork."""
return 0
@classmethod
- def supports_blobs(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def supports_blobs(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Blobs are not supported at Frontier."""
return False
@classmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the target number of blobs per block at a given fork."""
raise NotImplementedError(f"Target blobs per block is not supported in {cls.name()}")
@classmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the max number of blobs per block at a given fork."""
raise NotImplementedError(f"Max blobs per block is not supported in {cls.name()}")
@classmethod
- def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool:
- """Return whether the fork uses a reserve price mechanism for blobs or not."""
+ def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
+ """
+ Return whether the fork uses a reserve price mechanism for blobs or
+ not.
+ """
raise NotImplementedError(f"Blob reserve price is not supported in {cls.name()}")
@classmethod
- def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_cost(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base cost of a blob at a given fork."""
raise NotImplementedError(f"Blob base cost is not supported in {cls.name()}")
@classmethod
- def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
+ def full_blob_tx_wrapper_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> int | None:
"""Return the version of the full blob transaction wrapper."""
raise NotImplementedError(
f"Full blob transaction wrapper version is not supported in {cls.name()}"
)
@classmethod
- def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the max number of blobs per tx at a given fork."""
raise NotImplementedError(f"Max blobs per tx is not supported in {cls.name()}")
@classmethod
- def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None:
+ def blob_schedule(cls, *, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None:
"""At genesis, no blob schedule is used."""
return None
@classmethod
- def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_requests_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain beacon chain requests."""
return False
@classmethod
- def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_bal_hash_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain block access list hash."""
return False
@classmethod
def engine_new_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""At genesis, payloads cannot be sent through the engine API."""
return None
@classmethod
- def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_beacon_root_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, header must not contain parent beacon block root."""
return False
@classmethod
- def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def engine_new_payload_blob_hashes(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, payloads do not have blob hashes."""
return False
@classmethod
- def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def engine_new_payload_beacon_root(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, payloads do not have a parent beacon block root."""
return False
@classmethod
- def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def engine_new_payload_requests(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At genesis, payloads do not have requests."""
return False
+ @classmethod
+ def engine_execution_payload_block_access_list(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> bool:
+ """At genesis, payloads do not have block access list."""
+ return False
+
@classmethod
def engine_new_payload_target_blobs_per_block(
cls,
+ *,
block_number: int = 0,
timestamp: int = 0,
) -> bool:
@@ -358,39 +396,48 @@ def engine_new_payload_target_blobs_per_block(
@classmethod
def engine_payload_attribute_target_blobs_per_block(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
- """At genesis, payload attributes do not include the target blobs per block."""
+ """
+ At genesis, payload attributes do not include the target blobs per
+ block.
+ """
return False
@classmethod
def engine_payload_attribute_max_blobs_per_block(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
- """At genesis, payload attributes do not include the max blobs per block."""
+ """
+ At genesis, payload attributes do not include the max blobs per block.
+ """
return False
@classmethod
def engine_forkchoice_updated_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
- """At genesis, forkchoice updates cannot be sent through the engine API."""
- return cls.engine_new_payload_version(block_number, timestamp)
+ """
+ At genesis, forkchoice updates cannot be sent through the engine API.
+ """
+ return cls.engine_new_payload_version(block_number=block_number, timestamp=timestamp)
@classmethod
def engine_get_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""At genesis, payloads cannot be retrieved through the engine API."""
- return cls.engine_new_payload_version(block_number, timestamp)
+ return cls.engine_new_payload_version(block_number=block_number, timestamp=timestamp)
@classmethod
- def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]:
+ def engine_get_blobs_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> Optional[int]:
"""At genesis, blobs cannot be retrieved through the engine API."""
return None
@classmethod
- def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""
At Genesis the expected reward amount in wei is
5_000_000_000_000_000_000.
@@ -398,60 +445,64 @@ def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
return 5_000_000_000_000_000_000
@classmethod
- def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At Genesis, only legacy transactions are allowed."""
return [0]
@classmethod
- def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At Genesis, only legacy transactions are allowed."""
return [0]
@classmethod
- def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
+ def transaction_gas_limit_cap(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None:
"""At Genesis, no transaction gas limit cap is imposed."""
return None
@classmethod
- def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
+ def block_rlp_size_limit(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None:
"""At Genesis, no RLP block size limit is imposed."""
return None
@classmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""At Genesis, no pre-compiles are present."""
return []
@classmethod
- def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""At Genesis, no system-contracts are present."""
return []
@classmethod
- def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]:
+ def evm_code_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]:
"""At Genesis, only legacy EVM code is supported."""
return [EVMCodeType.LEGACY]
@classmethod
- def max_code_size(cls) -> int:
- """At genesis, there is no upper bound for code size (bounded by block gas limit)."""
- """However, the default is set to the limit of EIP-170 (Spurious Dragon)"""
+ def max_code_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ At genesis, there is no upper bound for code size (bounded by block gas
+ limit).
+
+ However, the default is set to the limit of EIP-170 (Spurious Dragon)
+ """
return 0x6000
@classmethod
- def max_stack_height(cls) -> int:
+ def max_stack_height(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""At genesis, the maximum stack height is 1024."""
return 1024
@classmethod
- def max_initcode_size(cls) -> int:
+ def max_initcode_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""At genesis, there is no upper bound for initcode size."""
"""However, the default is set to the limit of EIP-3860 (Shanghai)"""
return 0xC000
@classmethod
def call_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
"""Return list of call opcodes supported by the fork."""
return [
@@ -460,9 +511,7 @@ def call_opcodes(
]
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [
Opcodes.STOP,
@@ -598,7 +647,7 @@ def valid_opcodes(
@classmethod
def create_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
"""At Genesis, only `CREATE` opcode is supported."""
return [
@@ -606,12 +655,17 @@ def create_opcodes(
]
@classmethod
- def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_refund_quotient(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """Return the max refund quotient at Genesis."""
+ return 2
+
+ @classmethod
+ def max_request_type(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""At genesis, no request type is supported, signaled by -1."""
return -1
@classmethod
- def pre_allocation(cls) -> Mapping:
+ def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping:
"""
Return whether the fork expects pre-allocation of accounts.
@@ -620,7 +674,7 @@ def pre_allocation(cls) -> Mapping:
return {}
@classmethod
- def pre_allocation_blockchain(cls) -> Mapping:
+ def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping:
"""
Return whether the fork expects pre-allocation of accounts.
@@ -633,7 +687,7 @@ class Homestead(Frontier):
"""Homestead fork."""
@classmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""
At Homestead, EC-recover, SHA256, RIPEMD160, and Identity pre-compiles
are introduced.
@@ -643,36 +697,34 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]
Address(2, label="SHA256"),
Address(3, label="RIPEMD160"),
Address(4, label="ID"),
- ] + super(Homestead, cls).precompiles(block_number, timestamp)
+ ] + super(Homestead, cls).precompiles(block_number=block_number, timestamp=timestamp)
@classmethod
def call_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
"""At Homestead, DELEGATECALL opcode was introduced."""
return [(Opcodes.DELEGATECALL, EVMCodeType.LEGACY)] + super(Homestead, cls).call_opcodes(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
)
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return the list of Opcodes that are valid to work on this fork."""
return [Opcodes.DELEGATECALL] + super(Homestead, cls).valid_opcodes()
@classmethod
def transaction_intrinsic_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionIntrinsicCostCalculator:
"""
At Homestead, the transaction intrinsic cost needs to take contract
creation into account.
"""
super_fn = super(Homestead, cls).transaction_intrinsic_cost_calculator(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
)
- gas_costs = cls.gas_costs(block_number, timestamp)
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
def fn(
*,
@@ -682,6 +734,8 @@ def fn(
authorization_list_or_count: Sized | int | None = None,
return_cost_deducted_prior_execution: bool = False,
) -> int:
+ del return_cost_deducted_prior_execution
+
intrinsic_cost: int = super_fn(
calldata=calldata,
contract_creation=contract_creation,
@@ -717,46 +771,48 @@ class Byzantium(Homestead):
"""Byzantium fork."""
@classmethod
- def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""
- At Byzantium, the block reward is reduced to
- 3_000_000_000_000_000_000 wei.
+ At Byzantium, the block reward is reduced to 3_000_000_000_000_000_000
+ wei.
"""
return 3_000_000_000_000_000_000
@classmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""
- At Byzantium, pre-compiles for bigint modular exponentiation, addition and scalar
- multiplication on elliptic curve alt_bn128, and optimal ate pairing check on
- elliptic curve alt_bn128 are introduced.
+ At Byzantium, pre-compiles for bigint modular exponentiation, addition
+ and scalar multiplication on elliptic curve alt_bn128, and optimal ate
+ pairing check on elliptic curve alt_bn128 are introduced.
"""
return [
Address(5, label="MODEXP"),
Address(6, label="BN254_ADD"),
Address(7, label="BN254_MUL"),
Address(8, label="BN254_PAIRING"),
- ] + super(Byzantium, cls).precompiles(block_number, timestamp)
+ ] + super(Byzantium, cls).precompiles(block_number=block_number, timestamp=timestamp)
@classmethod
- def max_code_size(cls) -> int:
- # NOTE: Move this to Spurious Dragon once this fork is introduced. See EIP-170.
- """At Spurious Dragon, an upper bound was introduced for max contract code size."""
+ def max_code_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ # NOTE: Move this to Spurious Dragon once this fork is introduced. See
+ # EIP-170.
+ """
+ At Spurious Dragon, an upper bound was introduced for max contract code
+ size.
+ """
return 0x6000
@classmethod
def call_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
"""At Byzantium, STATICCALL opcode was introduced."""
return [(Opcodes.STATICCALL, EVMCodeType.LEGACY)] + super(Byzantium, cls).call_opcodes(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
)
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [
Opcodes.REVERT,
@@ -770,7 +826,7 @@ class Constantinople(Byzantium):
"""Constantinople fork."""
@classmethod
- def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""
At Constantinople, the block reward is reduced to
2_000_000_000_000_000_000 wei.
@@ -779,17 +835,15 @@ def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
@classmethod
def create_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
"""At Constantinople, `CREATE2` opcode is added."""
return [(Opcodes.CREATE2, EVMCodeType.LEGACY)] + super(Constantinople, cls).create_opcodes(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
)
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [
Opcodes.SHL,
@@ -810,27 +864,25 @@ class Istanbul(ConstantinopleFix):
"""Istanbul fork."""
@classmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""At Istanbul, pre-compile for blake2 compression is introduced."""
return [
Address(9, label="BLAKE2F"),
- ] + super(Istanbul, cls).precompiles(block_number, timestamp)
+ ] + super(Istanbul, cls).precompiles(block_number=block_number, timestamp=timestamp)
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [Opcodes.CHAINID, Opcodes.SELFBALANCE] + super(Istanbul, cls).valid_opcodes()
@classmethod
- def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts:
+ def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts:
"""
- On Istanbul, the non-zero transaction data byte cost is reduced to 16 due to
- EIP-2028.
+ On Istanbul, the non-zero transaction data byte cost is reduced to 16
+ due to EIP-2028.
"""
return replace(
- super(Istanbul, cls).gas_costs(block_number, timestamp),
+ super(Istanbul, cls).gas_costs(block_number=block_number, timestamp=timestamp),
G_TX_DATA_NON_ZERO=16, # https://eips.ethereum.org/EIPS/eip-2028
)
@@ -846,24 +898,29 @@ class Berlin(Istanbul):
"""Berlin fork."""
@classmethod
- def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At Berlin, access list transactions are introduced."""
- return [1] + super(Berlin, cls).tx_types(block_number, timestamp)
+ return [1] + super(Berlin, cls).tx_types(block_number=block_number, timestamp=timestamp)
@classmethod
- def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At Berlin, access list transactions are introduced."""
- return [1] + super(Berlin, cls).contract_creating_tx_types(block_number, timestamp)
+ return [1] + super(Berlin, cls).contract_creating_tx_types(
+ block_number=block_number, timestamp=timestamp
+ )
@classmethod
def transaction_intrinsic_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionIntrinsicCostCalculator:
- """At Berlin, the transaction intrinsic cost needs to take the access list into account."""
+ """
+ At Berlin, the transaction intrinsic cost needs to take the access list
+ into account.
+ """
super_fn = super(Berlin, cls).transaction_intrinsic_cost_calculator(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
)
- gas_costs = cls.gas_costs(block_number, timestamp)
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
def fn(
*,
@@ -873,6 +930,8 @@ def fn(
authorization_list_or_count: Sized | int | None = None,
return_cost_deducted_prior_execution: bool = False,
) -> int:
+ del return_cost_deducted_prior_execution
+
intrinsic_cost: int = super_fn(
calldata=calldata,
contract_creation=contract_creation,
@@ -892,40 +951,45 @@ class London(Berlin):
"""London fork."""
@classmethod
- def header_base_fee_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_base_fee_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Header must contain the Base Fee starting from London."""
return True
@classmethod
- def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At London, dynamic fee transactions are introduced."""
- return [2] + super(London, cls).tx_types(block_number, timestamp)
+ return [2] + super(London, cls).tx_types(block_number=block_number, timestamp=timestamp)
@classmethod
- def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At London, dynamic fee transactions are introduced."""
- return [2] + super(London, cls).contract_creating_tx_types(block_number, timestamp)
+ return [2] + super(London, cls).contract_creating_tx_types(
+ block_number=block_number, timestamp=timestamp
+ )
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [Opcodes.BASEFEE] + super(London, cls).valid_opcodes()
@classmethod
- def base_fee_max_change_denominator(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_refund_quotient(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """Return the max refund quotient at London."""
+ return 5
+
+ @classmethod
+ def base_fee_max_change_denominator(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base fee max change denominator at London."""
return 8
@classmethod
- def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def base_fee_elasticity_multiplier(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base fee elasticity multiplier at London."""
return 2
@classmethod
def base_fee_per_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BaseFeePerGasCalculator:
"""
Return a callable that calculates the base fee per gas at London.
@@ -938,24 +1002,27 @@ def base_fee_per_gas_calculator(
expected_base_fee_per_gas = parent_base_fee_per_gas
elif parent_gas_used > parent_gas_target:
gas_used_delta = parent_gas_used - parent_gas_target
- base_fee_per_gas_delta = max(
- parent_base_fee_per_gas * gas_used_delta // parent_gas_target \
- // BASE_FEE_MAX_CHANGE_DENOMINATOR,
- 1,
- )
- expected_base_fee_per_gas = parent_base_fee_per_gas + base_fee_per_gas_delta
+ base_fee_per_gas_delta = max( parent_base_fee_per_gas
+ * gas_used_delta // parent_gas_target //
+ BASE_FEE_MAX_CHANGE_DENOMINATOR, 1, )
+ expected_base_fee_per_gas = parent_base_fee_per_gas +
+ base_fee_per_gas_delta
else:
gas_used_delta = parent_gas_target - parent_gas_used
base_fee_per_gas_delta = (
- parent_base_fee_per_gas * gas_used_delta // \
- parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR
- )
- expected_base_fee_per_gas = parent_base_fee_per_gas - base_fee_per_gas_delta
+ parent_base_fee_per_gas * gas_used_delta //
+ parent_gas_target //
+ BASE_FEE_MAX_CHANGE_DENOMINATOR
+ )
+ expected_base_fee_per_gas = parent_base_fee_per_gas -
+ base_fee_per_gas_delta
"""
base_fee_max_change_denominator = cls.base_fee_max_change_denominator(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
+ )
+ elasticity_multiplier = cls.base_fee_elasticity_multiplier(
+ block_number=block_number, timestamp=timestamp
)
- elasticity_multiplier = cls.base_fee_elasticity_multiplier(block_number, timestamp)
def fn(
*, parent_base_fee_per_gas: int, parent_gas_used: int, parent_gas_limit: int
@@ -987,17 +1054,21 @@ def fn(
@classmethod
def base_fee_change_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BaseFeeChangeCalculator:
"""
- Return a callable that calculates the gas that needs to be used to change the
- base fee.
+ Return a callable that calculates the gas that needs to be used to
+ change the base fee.
"""
base_fee_max_change_denominator = cls.base_fee_max_change_denominator(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
+ )
+ elasticity_multiplier = cls.base_fee_elasticity_multiplier(
+ block_number=block_number, timestamp=timestamp
+ )
+ base_fee_per_gas_calculator = cls.base_fee_per_gas_calculator(
+ block_number=block_number, timestamp=timestamp
)
- elasticity_multiplier = cls.base_fee_elasticity_multiplier(block_number, timestamp)
- base_fee_per_gas_calculator = cls.base_fee_per_gas_calculator(block_number, timestamp)
def fn(
*,
@@ -1067,23 +1138,23 @@ class Paris(
"""Paris (Merge) fork."""
@classmethod
- def header_prev_randao_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_prev_randao_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Prev Randao is required starting from Paris."""
return True
@classmethod
- def header_zero_difficulty_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_zero_difficulty_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Zero difficulty is required starting from Paris."""
return True
@classmethod
- def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Paris updates the reward to 0."""
return 0
@classmethod
def engine_new_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""From Paris, payloads can be sent through the engine API."""
return 1
@@ -1093,26 +1164,24 @@ class Shanghai(Paris):
"""Shanghai fork."""
@classmethod
- def header_withdrawals_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_withdrawals_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Withdrawals are required starting from Shanghai."""
return True
@classmethod
def engine_new_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""From Shanghai, new payload calls must use version 2."""
return 2
@classmethod
- def max_initcode_size(cls) -> int:
+ def max_initcode_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""From Shanghai, the initcode size is now limited. See EIP-3860."""
return 0xC000
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [Opcodes.PUSH0] + super(Shanghai, cls).valid_opcodes()
@@ -1124,8 +1193,12 @@ class Cancun(Shanghai):
"FIELD_ELEMENTS_PER_BLOB": 4096,
"BYTES_PER_FIELD_ELEMENT": 32,
"CELL_LENGTH": 2048,
- "BLS_MODULUS": 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001, # EIP-2537: Main subgroup order = q, due to this BLS_MODULUS every blob byte (uint256) must be smaller than 116 # noqa: E501
- # https://github.com/ethereum/consensus-specs/blob/cc6996c22692d70e41b7a453d925172ee4b719ad/specs/deneb/polynomial-commitments.md?plain=1#L78
+ # EIP-2537: Main subgroup order = q, due to this BLS_MODULUS
+ # every blob byte (uint256) must be smaller than 116
+ "BLS_MODULUS": 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001,
+ # https://github.com/ethereum/consensus-specs/blob/
+ # cc6996c22692d70e41b7a453d925172ee4b719ad/specs/deneb/
+ # polynomial-commitments.md?plain=1#L78
"BYTES_PER_PROOF": 48,
"BYTES_PER_COMMITMENT": 48,
"KZG_ENDIANNESS": "big",
@@ -1142,27 +1215,31 @@ def get_blob_constant(cls, name: str) -> int | Literal["big"]:
return retrieved_constant
@classmethod
- def header_excess_blob_gas_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_excess_blob_gas_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Excess blob gas is required starting from Cancun."""
return True
@classmethod
- def header_blob_gas_used_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_blob_gas_used_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Blob gas used is required starting from Cancun."""
return True
@classmethod
- def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_beacon_root_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Parent beacon block root is required starting from Cancun."""
return True
@classmethod
def blob_gas_price_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> BlobGasPriceCalculator:
"""Return a callable that calculates the blob gas price at Cancun."""
- min_base_fee_per_blob_gas = cls.min_base_fee_per_blob_gas(block_number, timestamp)
- blob_base_fee_update_fraction = cls.blob_base_fee_update_fraction(block_number, timestamp)
+ min_base_fee_per_blob_gas = cls.min_base_fee_per_blob_gas(
+ block_number=block_number, timestamp=timestamp
+ )
+ blob_base_fee_update_fraction = cls.blob_base_fee_update_fraction(
+ block_number=block_number, timestamp=timestamp
+ )
def fn(*, excess_blob_gas) -> int:
return fake_exponential(
@@ -1175,11 +1252,16 @@ def fn(*, excess_blob_gas) -> int:
@classmethod
def excess_blob_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> ExcessBlobGasCalculator:
- """Return a callable that calculates the excess blob gas for a block at Cancun."""
- target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp)
- blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp)
+ """
+ Return a callable that calculates the excess blob gas for a block at
+ Cancun.
+ """
+ target_blobs_per_block = cls.target_blobs_per_block(
+ block_number=block_number, timestamp=timestamp
+ )
+ blob_gas_per_blob = cls.blob_gas_per_blob(block_number=block_number, timestamp=timestamp)
target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob
def fn(
@@ -1188,8 +1270,11 @@ def fn(
parent_excess_blobs: int | None = None,
parent_blob_gas_used: int | None = None,
parent_blob_count: int | None = None,
- parent_base_fee_per_gas: int, # Required for Osaka as using this as base
+ # Required for Osaka as using this as base
+ parent_base_fee_per_gas: int,
) -> int:
+ del parent_base_fee_per_gas
+
if parent_excess_blob_gas is None:
assert parent_excess_blobs is not None, "Parent excess blobs are required"
parent_excess_blob_gas = parent_excess_blobs * blob_gas_per_blob
@@ -1204,89 +1289,112 @@ def fn(
return fn
@classmethod
- def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def min_base_fee_per_blob_gas(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the minimum base fee per blob gas for Cancun."""
return 1
@classmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction for Cancun."""
return 3338477
@classmethod
- def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_gas_per_blob(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs are enabled starting from Cancun."""
return 2**17
@classmethod
- def supports_blobs(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def supports_blobs(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""At Cancun, blobs support is enabled."""
return True
@classmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
- """Blobs are enabled starting from Cancun, with a static target of 3 blobs per block."""
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ Blobs are enabled starting from Cancun, with a static target of 3 blobs
+ per block.
+ """
return 3
@classmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
- """Blobs are enabled starting from Cancun, with a static max of 6 blobs per block."""
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ Blobs are enabled starting from Cancun, with a static max of 6 blobs
+ per block.
+ """
return 6
@classmethod
- def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Blob reserve price is not supported in Cancun."""
return False
@classmethod
- def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
- """Pre-Osaka forks don't use tx wrapper versions for full blob transactions."""
+ def full_blob_tx_wrapper_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> int | None:
+ """
+ Pre-Osaka forks don't use tx wrapper versions for full blob
+ transactions.
+ """
return None
@classmethod
- def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int:
- """Blobs are enabled starting from Cancun, with a static max equal to the max per block."""
- return cls.max_blobs_per_block(block_number, timestamp)
+ def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ Blobs are enabled starting from Cancun, with a static max equal to the
+ max per block.
+ """
+ return cls.max_blobs_per_block(block_number=block_number, timestamp=timestamp)
@classmethod
- def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None:
+ def blob_schedule(cls, *, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None:
"""
At Cancun, the fork object runs this routine to get the updated blob
schedule.
"""
parent_fork = cls.parent()
assert parent_fork is not None, "Parent fork must be defined"
- blob_schedule = parent_fork.blob_schedule(block_number, timestamp) or BlobSchedule()
+ blob_schedule = (
+ parent_fork.blob_schedule(block_number=block_number, timestamp=timestamp)
+ or BlobSchedule()
+ )
current_blob_schedule = ForkBlobSchedule(
- target_blobs_per_block=cls.target_blobs_per_block(block_number, timestamp),
- max_blobs_per_block=cls.max_blobs_per_block(block_number, timestamp),
- base_fee_update_fraction=cls.blob_base_fee_update_fraction(block_number, timestamp),
+ target_blobs_per_block=cls.target_blobs_per_block(
+ block_number=block_number, timestamp=timestamp
+ ),
+ max_blobs_per_block=cls.max_blobs_per_block(
+ block_number=block_number, timestamp=timestamp
+ ),
+ base_fee_update_fraction=cls.blob_base_fee_update_fraction(
+ block_number=block_number, timestamp=timestamp
+ ),
)
blob_schedule.append(fork=cls.name(), schedule=current_blob_schedule)
return blob_schedule
@classmethod
- def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At Cancun, blob type transactions are introduced."""
- return [3] + super(Cancun, cls).tx_types(block_number, timestamp)
+ return [3] + super(Cancun, cls).tx_types(block_number=block_number, timestamp=timestamp)
@classmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""At Cancun, pre-compile for kzg point evaluation is introduced."""
return [
Address(10, label="KZG_POINT_EVALUATION"),
- ] + super(Cancun, cls).precompiles(block_number, timestamp)
+ ] + super(Cancun, cls).precompiles(block_number=block_number, timestamp=timestamp)
@classmethod
- def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""Cancun introduces the system contract for EIP-4788."""
return [Address(0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02, label="BEACON_ROOTS_ADDRESS")]
@classmethod
- def pre_allocation_blockchain(cls) -> Mapping:
+ def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping:
"""
- Cancun requires pre-allocation of the beacon root contract for EIP-4788 on blockchain
- type tests.
+ Cancun requires pre-allocation of the beacon root contract for EIP-4788
+ on blockchain type tests.
"""
new_allocation = {
0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02: {
@@ -1300,30 +1408,30 @@ def pre_allocation_blockchain(cls) -> Mapping:
@classmethod
def engine_new_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""From Cancun, new payload calls must use version 3."""
return 3
@classmethod
- def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]:
+ def engine_get_blobs_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> Optional[int]:
"""At Cancun, the engine get blobs version is 1."""
return 1
@classmethod
- def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def engine_new_payload_blob_hashes(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""From Cancun, payloads must have blob hashes."""
return True
@classmethod
- def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def engine_new_payload_beacon_root(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""From Cancun, payloads must have a parent beacon block root."""
return True
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [
Opcodes.BLOBHASH,
@@ -1348,7 +1456,7 @@ class Prague(Cancun):
}
@classmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""
At Prague, pre-compile for BLS operations are added.
@@ -1368,21 +1476,21 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]
Address(15, label="BLS12_PAIRING_CHECK"),
Address(16, label="BLS12_MAP_FP_TO_G1"),
Address(17, label="BLS12_MAP_FP2_TO_G2"),
- ] + super(Prague, cls).precompiles(block_number, timestamp)
+ ] + super(Prague, cls).precompiles(block_number=block_number, timestamp=timestamp)
@classmethod
- def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
+ def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""At Prague, set-code type transactions are introduced."""
- return [4] + super(Prague, cls).tx_types(block_number, timestamp)
+ return [4] + super(Prague, cls).tx_types(block_number=block_number, timestamp=timestamp)
@classmethod
- def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts:
+ def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts:
"""
- On Prague, the standard token cost and the floor token costs are introduced due to
- EIP-7623.
+ On Prague, the standard token cost and the floor token costs are
+ introduced due to EIP-7623.
"""
return replace(
- super(Prague, cls).gas_costs(block_number, timestamp),
+ super(Prague, cls).gas_costs(block_number=block_number, timestamp=timestamp),
G_TX_DATA_STANDARD_TOKEN_COST=4, # https://eips.ethereum.org/EIPS/eip-7623
G_TX_DATA_FLOOR_TOKEN_COST=10,
G_AUTHORIZATION=25_000,
@@ -1390,8 +1498,11 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts:
)
@classmethod
- def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
- """Prague introduces the system contracts for EIP-6110, EIP-7002, EIP-7251 and EIP-2935."""
+ def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ """
+ Prague introduces the system contracts for EIP-6110, EIP-7002, EIP-7251
+ and EIP-2935.
+ """
return [
Address(
0x00000000219AB540356CBB839CBE05303D7705FA,
@@ -1409,22 +1520,25 @@ def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Add
0x0000F90827F1C53A10CB7A02335B175320002935,
label="HISTORY_STORAGE_ADDRESS",
),
- ] + super(Prague, cls).system_contracts(block_number, timestamp)
+ ] + super(Prague, cls).system_contracts(block_number=block_number, timestamp=timestamp)
@classmethod
- def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int:
- """At Prague, three request types are introduced, hence the max request type is 2."""
+ def max_request_type(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ At Prague, three request types are introduced, hence the max request
+ type is 2.
+ """
return 2
@classmethod
def calldata_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> CalldataGasCalculator:
"""
- Return a callable that calculates the transaction gas cost for its calldata
- depending on its contents.
+ Return a callable that calculates the transaction gas cost for its
+ calldata depending on its contents.
"""
- gas_costs = cls.gas_costs(block_number, timestamp)
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
def fn(*, data: BytesConvertible, floor: bool = False) -> int:
tokens = 0
@@ -1441,11 +1555,16 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int:
@classmethod
def transaction_data_floor_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionDataFloorCostCalculator:
- """On Prague, due to EIP-7623, the transaction data floor cost is introduced."""
- calldata_gas_calculator = cls.calldata_gas_calculator(block_number, timestamp)
- gas_costs = cls.gas_costs(block_number, timestamp)
+ """
+ On Prague, due to EIP-7623, the transaction data floor cost is
+ introduced.
+ """
+ calldata_gas_calculator = cls.calldata_gas_calculator(
+ block_number=block_number, timestamp=timestamp
+ )
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
def fn(*, data: BytesConvertible) -> int:
return calldata_gas_calculator(data=data, floor=True) + gas_costs.G_TRANSACTION
@@ -1454,18 +1573,18 @@ def fn(*, data: BytesConvertible) -> int:
@classmethod
def transaction_intrinsic_cost_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> TransactionIntrinsicCostCalculator:
"""
At Prague, the transaction intrinsic cost needs to take the
authorizations into account.
"""
super_fn = super(Prague, cls).transaction_intrinsic_cost_calculator(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
)
- gas_costs = cls.gas_costs(block_number, timestamp)
+ gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp)
transaction_data_floor_cost_calculator = cls.transaction_data_floor_cost_calculator(
- block_number, timestamp
+ block_number=block_number, timestamp=timestamp
)
def fn(
@@ -1496,25 +1615,26 @@ def fn(
return fn
@classmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction for Prague."""
return 5007716
@classmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in Prague, have a static target of 6 blobs per block."""
return 6
@classmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in Prague, have a static max of 9 blobs per block."""
return 9
@classmethod
- def pre_allocation_blockchain(cls) -> Mapping:
+ def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping:
"""
- Prague requires pre-allocation of the beacon chain deposit contract for EIP-6110,
- the exits contract for EIP-7002, and the history storage contract for EIP-2935.
+ Prague requires pre-allocation of the beacon chain deposit contract for
+ EIP-6110, the exits contract for EIP-7002, and the history storage
+ contract for EIP-2935.
"""
new_allocation = {}
@@ -1573,7 +1693,7 @@ def pre_allocation_blockchain(cls) -> Mapping:
return new_allocation | super(Prague, cls).pre_allocation_blockchain() # type: ignore
@classmethod
- def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def header_requests_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""
Prague requires that the execution layer header contains the beacon
chain requests hash.
@@ -1581,22 +1701,26 @@ def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) ->
return True
@classmethod
- def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool:
- """From Prague, new payloads include the requests hash as a parameter."""
+ def engine_new_payload_requests(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
+ """
+ From Prague, new payloads include the requests hash as a parameter.
+ """
return True
@classmethod
def engine_new_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""From Prague, new payload calls must use version 4."""
return 4
@classmethod
def engine_forkchoice_updated_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
- """At Prague, version number of NewPayload and ForkchoiceUpdated diverge."""
+ """
+ At Prague, version number of NewPayload and ForkchoiceUpdated diverge.
+ """
return 3
@@ -1611,28 +1735,30 @@ class Osaka(Prague, solc_name="cancun"):
@classmethod
def engine_get_payload_version(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> Optional[int]:
"""From Osaka, get payload calls must use version 5."""
return 5
@classmethod
- def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]:
+ def engine_get_blobs_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> Optional[int]:
"""At Osaka, the engine get blobs version is 2."""
return 2
@classmethod
- def full_blob_tx_wrapper_version(cls, block_number=0, timestamp=0) -> int | None:
+ def full_blob_tx_wrapper_version(cls, *, block_number=0, timestamp=0) -> int | None:
"""At Osaka, the full blob transaction wrapper version is defined."""
return 1
@classmethod
- def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
+ def transaction_gas_limit_cap(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None:
"""At Osaka, transaction gas limit is capped at 16 million (2**24)."""
return 16_777_216
@classmethod
- def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int | None:
+ def block_rlp_size_limit(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None:
"""From Osaka, block RLP size is limited as specified in EIP-7934."""
max_block_size = 10_485_760
safety_margin = 2_097_152
@@ -1647,16 +1773,14 @@ def is_deployed(cls) -> bool:
return False
@classmethod
- def valid_opcodes(
- cls,
- ) -> List[Opcodes]:
+ def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]:
"""Return list of Opcodes that are valid to work on this fork."""
return [
Opcodes.CLZ,
] + super(Prague, cls).valid_opcodes()
@classmethod
- def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]:
+ def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]:
"""
At Osaka, pre-compile for p256verify operation is added.
@@ -1664,17 +1788,23 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]
"""
return [
Address(0x100, label="P256VERIFY"),
- ] + super(Osaka, cls).precompiles(block_number, timestamp)
+ ] + super(Osaka, cls).precompiles(block_number=block_number, timestamp=timestamp)
@classmethod
def excess_blob_gas_calculator(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> ExcessBlobGasCalculator:
- """Return a callable that calculates the excess blob gas for a block."""
- target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp)
- blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp)
+ """
+ Return a callable that calculates the excess blob gas for a block.
+ """
+ target_blobs_per_block = cls.target_blobs_per_block(
+ block_number=block_number, timestamp=timestamp
+ )
+ blob_gas_per_blob = cls.blob_gas_per_blob(block_number=block_number, timestamp=timestamp)
target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob
- max_blobs_per_block = cls.max_blobs_per_block(block_number, timestamp)
+ max_blobs_per_block = cls.max_blobs_per_block(
+ block_number=block_number, timestamp=timestamp
+ )
blob_base_cost = 2**13 # EIP-7918 new parameter
def fn(
@@ -1694,7 +1824,8 @@ def fn(
if parent_excess_blob_gas + parent_blob_gas_used < target_blob_gas_per_block:
return 0
- # EIP-7918: Apply reserve price when execution costs dominate blob costs
+ # EIP-7918: Apply reserve price when execution costs dominate blob
+ # costs
current_blob_base_fee = cls.blob_gas_price_calculator()(
excess_blob_gas=parent_excess_blob_gas
)
@@ -1716,99 +1847,111 @@ def fn(
return fn
@classmethod
- def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int:
- """Blobs in Osaka, have a static max of 6 blobs per tx. Differs from the max per block."""
+ def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """
+ Blobs in Osaka, have a static max of 6 blobs per tx. Differs from the
+ max per block.
+ """
return 6
@classmethod
- def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool:
+ def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
"""Blob reserve price is supported in Osaka."""
return True
@classmethod
- def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_cost(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the base cost of a blob at a given fork."""
return 2**13 # EIP-7918 new parameter
class BPO1(Osaka, bpo_fork=True):
- """BPO1 fork - Blob Parameter Only fork 1."""
+ """Mainnet BPO1 fork - Blob Parameter Only fork 1."""
@classmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction for BPO1."""
- return 8832827
+ return 8346193
@classmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
- """Blobs in BPO1 have a target of 9 blobs per block."""
- return 9
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """Blobs in BPO1 have a target of 10 blobs per block."""
+ return 10
@classmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
- """Blobs in BPO1 have a max of 14 blobs per block."""
- return 14
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
+ """Blobs in BPO1 have a max of 15 blobs per block."""
+ return 15
class BPO2(BPO1, bpo_fork=True):
- """BPO2 fork - Blob Parameter Only fork 2."""
+ """Mainnet BPO2 fork - Blob Parameter Only fork 2."""
@classmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction for BPO2."""
- return 13739630
+ return 11684671
@classmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in BPO2 have a target of 14 blobs per block."""
return 14
@classmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in BPO2 have a max of 21 blobs per block."""
return 21
class BPO3(BPO2, bpo_fork=True):
- """BPO3 fork - Blob Parameter Only fork 3."""
+ """
+ Pseudo BPO3 fork - Blob Parameter Only fork 3.
+ For testing purposes only.
+ """
@classmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction for BPO3."""
return 20609697
@classmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in BPO3 have a target of 21 blobs per block."""
return 21
@classmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in BPO3 have a max of 32 blobs per block."""
return 32
class BPO4(BPO3, bpo_fork=True):
- """BPO4 fork - Blob Parameter Only fork 4."""
+ """
+ Pseudo BPO4 fork - Blob Parameter Only fork 4.
+ For testing purposes only. Testing a decrease in values from BPO3.
+ """
@classmethod
- def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Return the blob base fee update fraction for BPO4."""
return 13739630
@classmethod
- def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in BPO4 have a target of 14 blobs per block."""
return 14
@classmethod
- def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int:
+ def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int:
"""Blobs in BPO4 have a max of 21 blobs per block."""
return 21
class BPO5(BPO4, bpo_fork=True):
- """BPO5 fork - Blob Parameter Only fork 5 (Required to parse Fusaka devnet genesis files)."""
+ """
+ Pseudo BPO5 fork - Blob Parameter Only fork 5.
+ For testing purposes only. Required to parse Fusaka devnet genesis files.
+ """
pass
@@ -1817,8 +1960,10 @@ class Amsterdam(Osaka):
"""Amsterdam fork."""
@classmethod
- def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
- """From Amsterdam, header must contain block access list hash (EIP-7928)."""
+ def header_bal_hash_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool:
+ """
+ From Amsterdam, header must contain block access list hash (EIP-7928).
+ """
return True
@classmethod
@@ -1826,28 +1971,45 @@ def is_deployed(cls) -> bool:
"""Return True if this fork is deployed."""
return False
+ @classmethod
+ def engine_new_payload_version(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> Optional[int]:
+ """From Amsterdam, new payload calls must use version 5."""
+ return 5
+
+ @classmethod
+ def engine_execution_payload_block_access_list(
+ cls, *, block_number: int = 0, timestamp: int = 0
+ ) -> bool:
+ """
+ From Amsterdam, engine execution payload includes `block_access_list`
+ as a parameter.
+ """
+ return True
+
class EOFv1(Prague, solc_name="cancun"):
"""EOF fork."""
@classmethod
- def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]:
+ def evm_code_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]:
"""EOF V1 is supported starting from Osaka."""
return super(EOFv1, cls).evm_code_types(
- block_number,
- timestamp,
+ block_number=block_number,
+ timestamp=timestamp,
) + [EVMCodeType.EOF_V1]
@classmethod
def call_opcodes(
- cls, block_number: int = 0, timestamp: int = 0
+ cls, *, block_number: int = 0, timestamp: int = 0
) -> List[Tuple[Opcodes, EVMCodeType]]:
"""EOF V1 introduces EXTCALL, EXTSTATICCALL, EXTDELEGATECALL."""
return [
(Opcodes.EXTCALL, EVMCodeType.EOF_V1),
(Opcodes.EXTSTATICCALL, EVMCodeType.EOF_V1),
(Opcodes.EXTDELEGATECALL, EVMCodeType.EOF_V1),
- ] + super(EOFv1, cls).call_opcodes(block_number, timestamp)
+ ] + super(EOFv1, cls).call_opcodes(block_number=block_number, timestamp=timestamp)
@classmethod
def is_deployed(cls) -> bool:
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/helpers.py b/packages/tests/src/ethereum_test_forks/forks/helpers.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/helpers.py
rename to packages/tests/src/ethereum_test_forks/forks/helpers.py
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/transition.py b/packages/tests/src/ethereum_test_forks/forks/transition.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/forks/transition.py
rename to packages/tests/src/ethereum_test_forks/forks/transition.py
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/gas_costs.py b/packages/tests/src/ethereum_test_forks/gas_costs.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_forks/gas_costs.py
rename to packages/tests/src/ethereum_test_forks/gas_costs.py
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/helpers.py b/packages/tests/src/ethereum_test_forks/helpers.py
similarity index 92%
rename from src/ethereum_spec_tests/ethereum_test_forks/helpers.py
rename to packages/tests/src/ethereum_test_forks/helpers.py
index 1cda134e00..3b13834280 100644
--- a/src/ethereum_spec_tests/ethereum_test_forks/helpers.py
+++ b/packages/tests/src/ethereum_test_forks/helpers.py
@@ -13,7 +13,6 @@
ValidatorFunctionWrapHandler,
model_validator,
)
-from semver import Version
from .base_fork import BaseFork
from .forks import forks, transition
@@ -21,7 +20,10 @@
class InvalidForkError(Exception):
- """Invalid fork error raised when the fork specified is not found or incompatible."""
+ """
+ Invalid fork error raised when the fork specified is not found or
+ incompatible.
+ """
def __init__(self, message):
"""Initialize the InvalidForkError exception."""
@@ -55,8 +57,8 @@ def __init__(self, message):
def get_forks() -> List[Type[BaseFork]]:
"""
- Return list of all the fork classes implemented by
- `ethereum_test_forks` ordered chronologically by deployment.
+ Return list of all the fork classes implemented by `ethereum_test_forks`
+ ordered chronologically by deployment.
"""
return all_forks[:]
@@ -86,7 +88,7 @@ def get_parent_fork(fork: Type[BaseFork]) -> Type[BaseFork]:
return parent_fork
-def get_closest_fork(fork: Type[BaseFork], solc_version: Version) -> Optional[Type[BaseFork]]:
+def get_closest_fork(fork: Type[BaseFork]) -> Optional[Type[BaseFork]]:
"""Return None if BaseFork is passed, otherwise return the fork itself."""
if fork is BaseFork:
return None
@@ -178,8 +180,8 @@ def get_selected_fork_set(
transition_forks: bool = True,
) -> Set[Type[BaseFork]]:
"""
- Process sets derived from `--fork`, `--until` and `--from` to return an unified fork
- set.
+ Process sets derived from `--fork`, `--until` and `--from` to return an
+ unified fork set.
"""
selected_fork_set = set()
if single_fork:
@@ -201,8 +203,7 @@ def transition_fork_from_to(
fork_from: Type[BaseFork], fork_to: Type[BaseFork]
) -> Type[BaseFork] | None:
"""
- Return transition fork that transitions to and from the specified
- forks.
+ Return transition fork that transitions to and from the specified forks.
"""
for transition_fork in get_transition_forks():
if not issubclass(transition_fork, TransitionBaseClass):
@@ -232,8 +233,8 @@ def forks_from_until(
fork_from: Type[BaseFork], fork_until: Type[BaseFork]
) -> List[Type[BaseFork]]:
"""
- Return specified fork and all forks after it until and including the
- second specified fork.
+ Return specified fork and all forks after it until and including the second
+ specified fork.
"""
prev_fork = fork_until
@@ -267,13 +268,13 @@ def get_relative_fork_markers(
"""
Return a list of marker names for a given fork.
- For a base fork (e.g. `Shanghai`), return [ `Shanghai` ].
- For a transition fork (e.g. `ShanghaiToCancunAtTime15k` which transitions to `Cancun`),
+ For a base fork (e.g. `Shanghai`), return [ `Shanghai` ]. For a transition
+ fork (e.g. `ShanghaiToCancunAtTime15k` which transitions to `Cancun`),
return [ `ShanghaiToCancunAtTime15k`, `Cancun` ].
- If `strict_mode` is set to `True`, raise an `InvalidForkError` if the fork is not found,
- otherwise, simply return the provided (str) `fork_identifier` (this is required to run
- `consume` with forks that are unknown to EEST).
+ If `strict_mode` is set to `True`, raise an `InvalidForkError` if the fork
+ is not found, otherwise, simply return the provided (str) `fork_identifier`
+ (this is required to run `consume` with forks that are unknown to EEST).
"""
all_forks = set(get_forks()) | set(get_transition_forks())
if isinstance(fork_identifier, str):
@@ -303,7 +304,10 @@ def get_fork_by_name(fork_name: str) -> Type[BaseFork] | None:
class ForkRangeDescriptor(BaseModel):
- """Fork descriptor parsed from string normally contained in ethereum/tests fillers."""
+ """
+ Fork descriptor parsed from string normally contained in ethereum/tests
+ fillers.
+ """
greater_equal: Type[BaseFork] | None = None
less_than: Type[BaseFork] | None = None
@@ -324,8 +328,10 @@ def validate_fork_range_descriptor(cls, v: Any, handler: ValidatorFunctionWrapHa
Validate the fork range descriptor from a string.
Examples:
- - ">=Osaka" validates to {greater_equal=Osaka, less_than=None}
- - ">=Prague=Osaka" validates to {greater_equal=Osaka, less_than=None}
+
+ - ">=PragueB, when filling, and given the from/until markers,
- we expect the following logic:
+ E.g. given transition fork A->B, when filling, and given the from/until
+ markers, we expect the following logic:
Marker Comparison A->B Included
--------- ------------ ---------------
@@ -223,7 +254,8 @@ def test_transition_fork_comparison():
assert BerlinToLondonAt5 >= London
assert BerlinToLondonAt5 <= London
- # Comparisons between transition forks is done against the `transitions_to` fork
+ # Comparisons between transition forks is done against the `transitions_to`
+ # fork
assert BerlinToLondonAt5 < ParisToShanghaiAtTime15k
assert ParisToShanghaiAtTime15k > BerlinToLondonAt5
assert BerlinToLondonAt5 == BerlinToLondonAt5
@@ -264,7 +296,7 @@ class PrePreAllocFork(Shanghai):
"""Dummy fork used for testing."""
@classmethod
- def pre_allocation(cls) -> Dict:
+ def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Dict:
"""Return some starting point for allocation."""
return {"test": "test"}
@@ -273,7 +305,7 @@ class PreAllocFork(PrePreAllocFork):
"""Dummy fork used for testing."""
@classmethod
- def pre_allocation(cls) -> Dict:
+ def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Dict:
"""Add allocation to the pre-existing one from previous fork."""
return {"test2": "test2"} | super(PreAllocFork, cls).pre_allocation()
@@ -353,8 +385,9 @@ class FutureFork(Osaka):
"""
Dummy fork used for testing.
- Contains no changes to the blob parameters from the parent fork in order to confirm that
- it's added to the blob schedule even if it doesn't have any changes.
+ Contains no changes to the blob parameters from the parent fork in order to
+ confirm that it's added to the blob schedule even if it doesn't have any
+ changes.
"""
pass
diff --git a/src/ethereum_spec_tests/ethereum_test_forks/transition_base_fork.py b/packages/tests/src/ethereum_test_forks/transition_base_fork.py
similarity index 96%
rename from src/ethereum_spec_tests/ethereum_test_forks/transition_base_fork.py
rename to packages/tests/src/ethereum_test_forks/transition_base_fork.py
index 83a8b56432..60b43b63a9 100644
--- a/src/ethereum_spec_tests/ethereum_test_forks/transition_base_fork.py
+++ b/packages/tests/src/ethereum_test_forks/transition_base_fork.py
@@ -24,7 +24,9 @@ def transitions_from(cls) -> Type[BaseFork]:
def base_fork_abstract_methods() -> List[str]:
- """Return list of all abstract methods that must be implemented by a fork."""
+ """
+ Return list of all abstract methods that must be implemented by a fork.
+ """
return list(BaseFork.__abstractmethods__)
@@ -66,6 +68,8 @@ def transition_method(
block_number: int = ALWAYS_TRANSITIONED_BLOCK_NUMBER,
timestamp: int = ALWAYS_TRANSITIONED_BLOCK_TIMESTAMP,
):
+ del cls
+
kwargs = {}
if "block_number" in base_method_parameters:
kwargs["block_number"] = block_number
diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/__init__.py b/packages/tests/src/ethereum_test_rpc/__init__.py
similarity index 82%
rename from src/ethereum_spec_tests/ethereum_test_rpc/__init__.py
rename to packages/tests/src/ethereum_test_rpc/__init__.py
index 5e5438a2ca..888cdf3c63 100644
--- a/src/ethereum_spec_tests/ethereum_test_rpc/__init__.py
+++ b/packages/tests/src/ethereum_test_rpc/__init__.py
@@ -1,4 +1,6 @@
-"""JSON-RPC methods and helper functions for EEST consume based hive simulators."""
+"""
+JSON-RPC methods and helper functions for EEST consume based hive simulators.
+"""
from .rpc import (
AdminRPC,
@@ -9,7 +11,7 @@
NetRPC,
SendTransactionExceptionError,
)
-from .types import (
+from .rpc_types import (
BlobAndProofV1,
BlobAndProofV2,
EthConfigResponse,
diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/rpc.py b/packages/tests/src/ethereum_test_rpc/rpc.py
similarity index 77%
rename from src/ethereum_spec_tests/ethereum_test_rpc/rpc.py
rename to packages/tests/src/ethereum_test_rpc/rpc.py
index 61aa05c650..9ea2d279eb 100644
--- a/src/ethereum_spec_tests/ethereum_test_rpc/rpc.py
+++ b/packages/tests/src/ethereum_test_rpc/rpc.py
@@ -1,5 +1,8 @@
-"""JSON-RPC methods and helper functions for EEST consume based hive simulators."""
+"""
+JSON-RPC methods and helper functions for EEST consume based hive simulators.
+"""
+import logging
import time
from itertools import count
from pprint import pprint
@@ -8,12 +11,19 @@
import requests
from jwt import encode
from pydantic import ValidationError
+from tenacity import (
+ before_sleep_log,
+ retry,
+ retry_if_exception_type,
+ stop_after_attempt,
+ wait_exponential,
+)
from ethereum_test_base_types import Address, Bytes, Hash, to_json
from ethereum_test_types import Transaction
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
-from .types import (
+from .rpc_types import (
EthConfigResponse,
ForkchoiceState,
ForkchoiceUpdateResponse,
@@ -30,13 +40,18 @@
class SendTransactionExceptionError(Exception):
- """Represent an exception that is raised when a transaction fails to be sent."""
+ """
+ Represent an exception that is raised when a transaction fails to be sent.
+ """
tx: Transaction | None = None
tx_rlp: Bytes | None = None
def __init__(self, *args, tx: Transaction | None = None, tx_rlp: Bytes | None = None):
- """Initialize SendTransactionExceptionError class with the given transaction."""
+ """
+ Initialize SendTransactionExceptionError class with the given
+ transaction.
+ """
super().__init__(*args)
self.tx = tx
self.tx_rlp = tx_rlp
@@ -51,7 +66,10 @@ def __str__(self):
class BaseRPC:
- """Represents a base RPC class for every RPC call used within EEST based hive simulators."""
+ """
+ Represents a base RPC class for every RPC call used within EEST based hive
+ simulators.
+ """
namespace: ClassVar[str]
response_validation_context: Any | None
@@ -68,7 +86,9 @@ def __init__(
self.response_validation_context = response_validation_context
def __init_subclass__(cls, namespace: str | None = None) -> None:
- """Set namespace of the RPC class to the lowercase of the class name."""
+ """
+ Set namespace of the RPC class to the lowercase of the class name.
+ """
if namespace is None:
namespace = cls.__name__
if namespace.endswith("RPC"):
@@ -76,6 +96,34 @@ def __init_subclass__(cls, namespace: str | None = None) -> None:
namespace = namespace.lower()
cls.namespace = namespace
+ @retry(
+ retry=retry_if_exception_type((requests.ConnectionError, ConnectionRefusedError)),
+ stop=stop_after_attempt(5),
+ wait=wait_exponential(multiplier=0.5, min=0.5, max=4.0),
+ before_sleep=before_sleep_log(logger, logging.WARNING),
+ reraise=True,
+ )
+ def _make_request(
+ self,
+ url: str,
+ json_payload: dict,
+ headers: dict,
+ timeout: int | None,
+ ) -> requests.Response:
+ """
+ Make HTTP POST request with retry logic for connection errors only.
+
+ This method only retries network-level connection failures
+ (ConnectionError, ConnectionRefusedError). HTTP status errors (4xx/5xx)
+ are handled by the caller using response.raise_for_status() WITHOUT
+ retries because:
+ - 4xx errors are client errors (permanent failures, no point retrying)
+ - 5xx errors are server errors that typically indicate
+ application-level issues rather than transient network problems
+ """
+ logger.debug(f"Making HTTP request to {url}, timeout={timeout}")
+ return requests.post(url, json=json_payload, headers=headers, timeout=timeout)
+
def post_request(
self,
*,
@@ -85,7 +133,10 @@ def post_request(
request_id: int | str | None = None,
timeout: int | None = None,
) -> Any:
- """Send JSON-RPC POST request to the client RPC server at port defined in the url."""
+ """
+ Send JSON-RPC POST request to the client RPC server at port defined in
+ the url.
+ """
if extra_headers is None:
extra_headers = {}
if params is None:
@@ -108,8 +159,12 @@ def post_request(
}
headers = base_header | extra_headers
- logger.debug(f"Sending RPC request, timeout is set to {timeout}...")
- response = requests.post(self.url, json=payload, headers=headers, timeout=timeout)
+ logger.debug(
+ f"Sending RPC request to {self.url}, method={self.namespace}_{method}, "
+ f"timeout={timeout}..."
+ )
+
+ response = self._make_request(self.url, payload, headers, timeout)
response.raise_for_status()
response_json = response.json()
@@ -123,8 +178,8 @@ def post_request(
class EthRPC(BaseRPC):
"""
- Represents an `eth_X` RPC class for every default ethereum RPC method used within EEST based
- hive simulators.
+ Represents an `eth_X` RPC class for every default ethereum RPC method used
+ within EEST based hive simulators.
"""
transaction_wait_timeout: int = 60
@@ -137,12 +192,18 @@ def __init__(
transaction_wait_timeout: int = 60,
**kwargs,
):
- """Initialize EthRPC class with the given url and transaction wait timeout."""
+ """
+ Initialize EthRPC class with the given url and transaction wait
+ timeout.
+ """
super().__init__(*args, **kwargs)
self.transaction_wait_timeout = transaction_wait_timeout
def config(self, timeout: int | None = None):
- """`eth_config`: Returns information about a fork configuration of the client."""
+ """
+ `eth_config`: Returns information about a fork configuration of the
+ client.
+ """
try:
response = self.post_request(method="config", timeout=timeout)
if response is None:
@@ -165,7 +226,10 @@ def chain_id(self) -> int:
return int(response, 16)
def get_block_by_number(self, block_number: BlockNumberType = "latest", full_txs: bool = True):
- """`eth_getBlockByNumber`: Returns information about a block by block number."""
+ """
+ `eth_getBlockByNumber`: Returns information about a block by block
+ number.
+ """
block = hex(block_number) if isinstance(block_number, int) else block_number
params = [block, full_txs]
response = self.post_request(method="getBlockByNumber", params=params)
@@ -180,7 +244,9 @@ def get_block_by_hash(self, block_hash: Hash, full_txs: bool = True):
return response
def get_balance(self, address: Address, block_number: BlockNumberType = "latest") -> int:
- """`eth_getBalance`: Returns the balance of the account of given address."""
+ """
+ `eth_getBalance`: Returns the balance of the account of given address.
+ """
block = hex(block_number) if isinstance(block_number, int) else block_number
params = [f"{address}", block]
@@ -200,7 +266,10 @@ def get_code(self, address: Address, block_number: BlockNumberType = "latest") -
def get_transaction_count(
self, address: Address, block_number: BlockNumberType = "latest"
) -> int:
- """`eth_getTransactionCount`: Returns the number of transactions sent from an address."""
+ """
+ `eth_getTransactionCount`: Returns the number of transactions sent from
+ an address.
+ """
block = hex(block_number) if isinstance(block_number, int) else block_number
params = [f"{address}", block]
@@ -223,10 +292,25 @@ def get_transaction_by_hash(self, transaction_hash: Hash) -> TransactionByHashRe
pprint(e.errors())
raise e
+ def get_transaction_receipt(self, transaction_hash: Hash) -> dict | None:
+ """
+ `eth_getTransactionReceipt`: Returns transaction receipt.
+
+ Used to get the actual gas used by a transaction for gas validation
+ in benchmark tests.
+ """
+ response = self.post_request(
+ method="getTransactionReceipt", params=[f"{transaction_hash}"]
+ )
+ return response
+
def get_storage_at(
self, address: Address, position: Hash, block_number: BlockNumberType = "latest"
) -> Hash:
- """`eth_getStorageAt`: Returns the value from a storage position at a given address."""
+ """
+ `eth_getStorageAt`: Returns the value from a storage position at a
+ given address.
+ """
block = hex(block_number) if isinstance(block_number, int) else block_number
params = [f"{address}", f"{position}", block]
@@ -234,7 +318,10 @@ def get_storage_at(
return Hash(response)
def gas_price(self) -> int:
- """`eth_gasPrice`: Returns the number of transactions sent from an address."""
+ """
+ `eth_gasPrice`: Returns the number of transactions sent from an
+ address.
+ """
response = self.post_request(method="gasPrice")
return int(response, 16)
@@ -247,7 +334,7 @@ def send_raw_transaction(
response = self.post_request(
method="sendRawTransaction",
params=[transaction_rlp.hex()],
- request_id=request_id, # noqa: E501
+ request_id=request_id,
)
result_hash = Hash(response)
@@ -263,7 +350,7 @@ def send_transaction(self, transaction: Transaction) -> Hash:
response = self.post_request(
method="sendRawTransaction",
params=[transaction.rlp().hex()],
- request_id=transaction.metadata_string(), # noqa: E501
+ request_id=transaction.metadata_string(),
)
result_hash = Hash(response)
@@ -274,15 +361,18 @@ def send_transaction(self, transaction: Transaction) -> Hash:
raise SendTransactionExceptionError(str(e), tx=transaction) from e
def send_transactions(self, transactions: List[Transaction]) -> List[Hash]:
- """Use `eth_sendRawTransaction` to send a list of transactions to the client."""
+ """
+ Use `eth_sendRawTransaction` to send a list of transactions to the
+ client.
+ """
return [self.send_transaction(tx) for tx in transactions]
def storage_at_keys(
self, account: Address, keys: List[Hash], block_number: BlockNumberType = "latest"
) -> Dict[Hash, Hash]:
"""
- Retrieve the storage values for the specified keys at a given address and block
- number.
+ Retrieve the storage values for the specified keys at a given address
+ and block number.
"""
results: Dict[Hash, Hash] = {}
for key in keys:
@@ -291,7 +381,10 @@ def storage_at_keys(
return results
def wait_for_transaction(self, transaction: Transaction) -> TransactionByHashResponse:
- """Use `eth_getTransactionByHash` to wait until a transaction is included in a block."""
+ """
+ Use `eth_getTransactionByHash` to wait until a transaction is included
+ in a block.
+ """
tx_hash = transaction.hash
start_time = time.time()
while True:
@@ -310,8 +403,8 @@ def wait_for_transactions(
self, transactions: List[Transaction]
) -> List[TransactionByHashResponse]:
"""
- Use `eth_getTransactionByHash` to wait until all transactions in list are included in a
- block.
+ Use `eth_getTransactionByHash` to wait until all transactions in list
+ are included in a block.
"""
tx_hashes = [tx.hash for tx in transactions]
responses: List[TransactionByHashResponse] = []
@@ -345,15 +438,18 @@ def send_wait_transaction(self, transaction: Transaction):
return self.wait_for_transaction(transaction)
def send_wait_transactions(self, transactions: List[Transaction]):
- """Send list of transactions and waits until all of them are included in a block."""
+ """
+ Send list of transactions and waits until all of them are included in a
+ block.
+ """
self.send_transactions(transactions)
return self.wait_for_transactions(transactions)
class DebugRPC(EthRPC):
"""
- Represents an `debug_X` RPC class for every default ethereum RPC method used within EEST based
- hive simulators.
+ Represents an `debug_X` RPC class for every default ethereum RPC method
+ used within EEST based hive simulators.
"""
def trace_call(self, tr: dict[str, str], block_number: str):
@@ -364,8 +460,8 @@ def trace_call(self, tr: dict[str, str], block_number: str):
class EngineRPC(BaseRPC):
"""
- Represents an Engine API RPC class for every Engine API method used within EEST based hive
- simulators.
+ Represents an Engine API RPC class for every Engine API method used within
+ EEST based hive simulators.
"""
jwt_secret: bytes
@@ -389,7 +485,10 @@ def post_request(
request_id: int | str | None = None,
timeout: int | None = None,
) -> Any:
- """Send JSON-RPC POST request to the client RPC server at port defined in the url."""
+ """
+ Send JSON-RPC POST request to the client RPC server at port defined in
+ the url.
+ """
if extra_headers is None:
extra_headers = {}
jwt_token = encode(
@@ -410,7 +509,10 @@ def post_request(
)
def new_payload(self, *params: Any, version: int) -> PayloadStatus:
- """`engine_newPayloadVX`: Attempts to execute the given payload on an execution client."""
+ """
+ `engine_newPayloadVX`: Attempts to execute the given payload on an
+ execution client.
+ """
method = f"newPayloadV{version}"
params_list = [to_json(param) for param in params]
@@ -426,7 +528,10 @@ def forkchoice_updated(
*,
version: int,
) -> ForkchoiceUpdateResponse:
- """`engine_forkchoiceUpdatedVX`: Updates the forkchoice state of the execution client."""
+ """
+ `engine_forkchoiceUpdatedVX`: Updates the forkchoice state of the
+ execution client.
+ """
method = f"forkchoiceUpdatedV{version}"
if payload_attributes is None:
@@ -468,7 +573,9 @@ def get_blobs(
*,
version: int,
) -> GetBlobsResponse | None:
- """`engine_getBlobsVX`: Retrieves blobs from an execution layers tx pool."""
+ """
+ `engine_getBlobsVX`: Retrieves blobs from an execution layers tx pool.
+ """
method = f"getBlobsV{version}"
params = [f"{h}" for h in versioned_hashes]
diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/types.py b/packages/tests/src/ethereum_test_rpc/rpc_types.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_test_rpc/types.py
rename to packages/tests/src/ethereum_test_rpc/rpc_types.py
index 8d874d07fb..d904d441cc 100644
--- a/src/ethereum_spec_tests/ethereum_test_rpc/types.py
+++ b/packages/tests/src/ethereum_test_rpc/rpc_types.py
@@ -55,7 +55,8 @@ class TransactionByHashResponse(Transaction):
transaction_hash: Hash = Field(..., alias="hash")
sender: EOA | None = Field(None, alias="from")
- # The to field can have different names in different clients, so we use AliasChoices.
+ # The to field can have different names in different clients, so we use
+ # AliasChoices.
to: Address | None = Field(..., validation_alias=AliasChoices("to_address", "to", "toAddress"))
v: HexNumber = Field(0, validation_alias=AliasChoices("v", "yParity")) # type: ignore
@@ -64,8 +65,8 @@ class TransactionByHashResponse(Transaction):
@classmethod
def adapt_clients_response(cls, data: Any) -> Any:
"""
- Perform modifications necessary to adapt the response returned by clients
- so it can be parsed by our model.
+ Perform modifications necessary to adapt the response returned by
+ clients so it can be parsed by our model.
"""
if isinstance(data, dict):
if "gasPrice" in data and "maxFeePerGas" in data:
@@ -75,8 +76,8 @@ def adapt_clients_response(cls, data: Any) -> Any:
def model_post_init(self, __context):
"""
- Check that the transaction hash returned by the client matches the one calculated by
- us.
+ Check that the transaction hash returned by the client matches the one
+ calculated by us.
"""
Transaction.model_post_init(self, __context)
assert self.transaction_hash == self.hash
diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/tests/__init__.py b/packages/tests/src/ethereum_test_rpc/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_rpc/tests/__init__.py
rename to packages/tests/src/ethereum_test_rpc/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/tests/test_types.py b/packages/tests/src/ethereum_test_rpc/tests/test_types.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_test_rpc/tests/test_types.py
rename to packages/tests/src/ethereum_test_rpc/tests/test_types.py
index c0a6892e9a..0a42a078b3 100644
--- a/src/ethereum_spec_tests/ethereum_test_rpc/tests/test_types.py
+++ b/packages/tests/src/ethereum_test_rpc/tests/test_types.py
@@ -99,7 +99,9 @@
@pytest.fixture
def eth_config_response() -> EthConfigResponse:
- """Get the `eth_config` response from the client to be verified by all tests."""
+ """
+ Get the `eth_config` response from the client to be verified by all tests.
+ """
return EthConfigResponse.model_validate(eth_config_dict)
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/__init__.py b/packages/tests/src/ethereum_test_specs/__init__.py
similarity index 88%
rename from src/ethereum_spec_tests/ethereum_test_specs/__init__.py
rename to packages/tests/src/ethereum_test_specs/__init__.py
index 790e2b4351..e0baf8c518 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/__init__.py
+++ b/packages/tests/src/ethereum_test_specs/__init__.py
@@ -2,6 +2,7 @@
from .base import BaseTest, TestSpec
from .base_static import BaseStaticTest
+from .benchmark import BenchmarkTest, BenchmarkTestFiller, BenchmarkTestSpec
from .blobs import BlobsTest, BlobsTestFiller, BlobsTestSpec
from .blockchain import (
BlockchainTest,
@@ -23,6 +24,9 @@
__all__ = (
"BaseStaticTest",
"BaseTest",
+ "BenchmarkTest",
+ "BenchmarkTestFiller",
+ "BenchmarkTestSpec",
"BlobsTest",
"BlobsTestFiller",
"BlobsTestSpec",
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/base.py b/packages/tests/src/ethereum_test_specs/base.py
similarity index 91%
rename from src/ethereum_spec_tests/ethereum_test_specs/base.py
rename to packages/tests/src/ethereum_test_specs/base.py
index 45da6fde83..c512028389 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/base.py
+++ b/packages/tests/src/ethereum_test_specs/base.py
@@ -1,4 +1,6 @@
-"""Base test class and helper functions for Ethereum state and blockchain tests."""
+"""
+Base test class and helper functions for Ethereum state and blockchain tests.
+"""
import hashlib
from abc import abstractmethod
@@ -13,6 +15,7 @@
from typing_extensions import Self
from ethereum_clis import Result, TransitionTool
+from ethereum_clis.cli_types import OpcodeCount
from ethereum_test_base_types import to_hex
from ethereum_test_execution import BaseExecute, ExecuteFormat, LabeledExecuteFormat
from ethereum_test_fixtures import (
@@ -43,8 +46,8 @@ def __str__(self):
def verify_result(result: Result, env: Environment):
"""
- Verify that values in the t8n result match the expected values.
- Raises exception on unexpected values.
+ Verify that values in the t8n result match the expected values. Raises
+ exception on unexpected values.
"""
if env.withdrawals is not None:
assert result.withdrawals_root == to_hex(Withdrawal.list_root(env.withdrawals))
@@ -61,7 +64,9 @@ class OpMode(StrEnum):
class BaseTest(BaseModel):
- """Represents a base Ethereum test which must return a single test fixture."""
+ """
+ Represents a base Ethereum test which must return a single test fixture.
+ """
model_config = ConfigDict(extra="forbid")
@@ -71,8 +76,10 @@ class BaseTest(BaseModel):
_operation_mode: OpMode | None = PrivateAttr(None)
_gas_optimization: int | None = PrivateAttr(None)
_gas_optimization_max_gas_limit: int | None = PrivateAttr(None)
+ _opcode_count: OpcodeCount | None = PrivateAttr(None)
expected_benchmark_gas_used: int | None = None
+ skip_gas_used_validation: bool = False
spec_types: ClassVar[Dict[str, Type["BaseTest"]]] = {}
@@ -92,7 +99,10 @@ def discard_fixture_format_by_marks(
fork: Fork,
markers: List[pytest.Mark],
) -> bool:
- """Discard a fixture format from filling if the appropriate marker is used."""
+ """
+ Discard a fixture format from filling if the appropriate marker is
+ used.
+ """
return False
@classmethod
@@ -117,10 +127,12 @@ def from_test(
tag=base_test.tag,
t8n_dump_dir=base_test.t8n_dump_dir,
expected_benchmark_gas_used=base_test.expected_benchmark_gas_used,
+ skip_gas_used_validation=base_test.skip_gas_used_validation,
**kwargs,
)
new_instance._request = base_test._request
new_instance._operation_mode = base_test._operation_mode
+ new_instance._opcode_count = base_test._opcode_count
return new_instance
@classmethod
@@ -130,7 +142,10 @@ def discard_execute_format_by_marks(
fork: Fork,
markers: List[pytest.Mark],
) -> bool:
- """Discard an execute format from executing if the appropriate marker is used."""
+ """
+ Discard an execute format from executing if the appropriate marker is
+ used.
+ """
return False
@abstractmethod
@@ -187,10 +202,11 @@ def is_tx_gas_heavy_test(self) -> bool:
def is_exception_test(self) -> bool | None:
"""
- Check if the test is an exception test (invalid block, invalid transaction).
+ Check if the test is an exception test (invalid block, invalid
+ transaction).
- `None` is returned if it's not possible to determine if the test is negative or not.
- This is the case when the test is not run in pytest.
+ `None` is returned if it's not possible to determine if the test is
+ negative or not. This is the case when the test is not run in pytest.
"""
if self._request is not None and hasattr(self._request, "node"):
return self._request.node.get_closest_marker("exception_test") is not None
@@ -229,7 +245,8 @@ def get_genesis_environment(self, fork: Fork) -> Environment:
"""
Get the genesis environment for pre-allocation groups.
- Must be implemented by subclasses to provide the appropriate environment.
+ Must be implemented by subclasses to provide the appropriate
+ environment.
"""
raise NotImplementedError(
f"{self.__class__.__name__} must implement genesis environment access for use with "
@@ -239,7 +256,10 @@ def get_genesis_environment(self, fork: Fork) -> Environment:
def update_pre_alloc_groups(
self, pre_alloc_groups: PreAllocGroups, fork: Fork, test_id: str
) -> PreAllocGroups:
- """Create or update the pre-allocation group with the pre from the current spec."""
+ """
+ Create or update the pre-allocation group with the pre from the current
+ spec.
+ """
if not hasattr(self, "pre"):
raise AttributeError(
f"{self.__class__.__name__} does not have a 'pre' field. Pre-allocation groups "
@@ -259,7 +279,8 @@ def update_pre_alloc_groups(
group.test_ids.append(str(test_id))
pre_alloc_groups[pre_alloc_hash] = group
else:
- # Create new group - use Environment instead of expensive genesis generation
+ # Create new group - use Environment instead of expensive genesis
+ # generation
genesis_env = self.get_genesis_environment(fork)
pre_alloc = Alloc.merge(
Alloc.model_validate(fork.pre_allocation_blockchain()),
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/base_static.py b/packages/tests/src/ethereum_test_specs/base_static.py
similarity index 81%
rename from src/ethereum_spec_tests/ethereum_test_specs/base_static.py
rename to packages/tests/src/ethereum_test_specs/base_static.py
index cdd60d6164..3dd61bbebc 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/base_static.py
+++ b/packages/tests/src/ethereum_test_specs/base_static.py
@@ -1,4 +1,6 @@
-"""Base class to parse test cases written in static formats."""
+"""
+Base class to parse test cases written in static formats.
+"""
import re
from abc import abstractmethod
@@ -25,8 +27,8 @@ class BaseStaticTest(BaseModel):
@classmethod
def __pydantic_init_subclass__(cls, **kwargs):
"""
- Register all subclasses of BaseStaticTest with a static test format name set
- as possible static test format.
+ Register all subclasses of BaseStaticTest with a static test format
+ name set as possible static test format.
"""
if cls.format_name:
# Register the new fixture format
@@ -55,8 +57,9 @@ def fill_function(self) -> Callable:
This method should be implemented by the subclasses.
- The function returned can be optionally decorated with the `@pytest.mark.parametrize`
- decorator to parametrize the test with the number of sub test cases.
+ The function returned can be optionally decorated with the
+ `@pytest.mark.parametrize` decorator to parametrize the test with the
+ number of sub test cases.
Example:
```
@@ -68,7 +71,7 @@ def test_state_filler(
fork: Fork,
pre: Alloc,
n: int,
- m: int,
+ m: int
):
\"\"\"Generate a test from a static state filler.\"\"\"
assert n == 1
@@ -85,35 +88,46 @@ def test_state_filler(
sender=sender,
)
state_test(env=env, pre=pre, post={}, tx=tx)
-
- return test_state_filler
```
- To aid the generation of the test, the function can be defined and then the decorator be
- applied after defining the function:
+ To aid the generation of the test, the function can be defined and then
+ the decorator be applied after defining the function:
```
def test_state_filler(
- state_test: StateTestFiller,
+ state_test: StateTestFiller,
fork: Fork,
pre: Alloc,
n: int,
m: int,
):
- ...
- test_state_filler = pytest.mark.parametrize("n", [1])(test_state_filler)
- test_state_filler = pytest.mark.parametrize("m", [1, 2])(test_state_filler)
+
+ ...
+
+ test_state_filler = pytest.mark.parametrize("n",
+ [1])(test_state_filler
+ )
+ test_state_filler = pytest.mark.parametrize("m",
+ [1, 2])(test_state_filler
+ )
+
if self.valid_from:
- test_state_filler = pytest.mark.valid_from(self.valid_from)(test_state_filler)
+ test_state_filler = pytest.mark.valid_from(
+ self.valid_from
+ )(test_state_filler)
+
if self.valid_until:
- test_state_filler = pytest.mark.valid_until(self.valid_until)(test_state_filler)
+ test_state_filler = pytest.mark.valid_until(
+ self.valid_until
+ )(test_state_filler)
+
return test_state_filler
```
- The function can contain the following parameters on top of the spec type parameter
- (`state_test` in the example above):
- - `fork`: The fork for which the test is currently being filled.
- - `pre`: The pre-state of the test.
+ The function can contain the following parameters on top of the spec
+ type parameter (`state_test` in the example above): - `fork`: The fork
+ for which the test is currently being filled. - `pre`: The pre-state of
+ the test.
"""
raise NotImplementedError
@@ -143,8 +157,8 @@ def remove_comments_from_model(cls, data: Any) -> Any:
def remove_comments(v: str) -> str:
"""
- Split by line and then remove the comments (starting with #) at the end of each line if
- any.
+ Split by line and then remove the comments (starting with #) at the end of
+ each line if any.
"""
return "\n".join([line.split("#")[0].strip() for line in v.splitlines()])
diff --git a/packages/tests/src/ethereum_test_specs/benchmark.py b/packages/tests/src/ethereum_test_specs/benchmark.py
new file mode 100644
index 0000000000..c6fdd1b644
--- /dev/null
+++ b/packages/tests/src/ethereum_test_specs/benchmark.py
@@ -0,0 +1,269 @@
+"""Ethereum benchmark test spec definition and filler."""
+
+import math
+from abc import ABC, abstractmethod
+from dataclasses import dataclass, field
+from typing import Callable, ClassVar, Dict, Generator, List, Sequence, Type
+
+import pytest
+from pydantic import ConfigDict, Field
+
+from ethereum_clis import TransitionTool
+from ethereum_test_base_types import HexNumber
+from ethereum_test_exceptions import BlockException, TransactionException
+from ethereum_test_execution import (
+ BaseExecute,
+ ExecuteFormat,
+ LabeledExecuteFormat,
+ TransactionPost,
+)
+from ethereum_test_fixtures import (
+ BaseFixture,
+ BlockchainEngineFixture,
+ BlockchainEngineXFixture,
+ BlockchainFixture,
+ FixtureFormat,
+ LabeledFixtureFormat,
+)
+from ethereum_test_forks import Fork
+from ethereum_test_types import Alloc, Environment, Transaction
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm.opcodes import Opcodes as Op
+
+from .base import BaseTest
+from .blockchain import Block, BlockchainTest
+
+
+@dataclass(kw_only=True)
+class BenchmarkCodeGenerator(ABC):
+ """Abstract base class for generating benchmark bytecode."""
+
+ attack_block: Bytecode
+ setup: Bytecode = field(default_factory=Bytecode)
+
+ @abstractmethod
+ def deploy_contracts(self, pre: Alloc, fork: Fork) -> None:
+ """Deploy any contracts needed for the benchmark."""
+ ...
+
+ @abstractmethod
+ def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transaction:
+ """Generate a transaction with the specified gas limit."""
+ ...
+
+ def generate_repeated_code(
+ self, repeated_code: Bytecode, setup: Bytecode, fork: Fork
+ ) -> Bytecode:
+ """
+ Calculate the maximum number of iterations that
+ can fit in the code size limit.
+ """
+ assert len(repeated_code) > 0, "repeated_code cannot be empty"
+ max_code_size = fork.max_code_size()
+
+ overhead = len(setup) + len(Op.JUMPDEST) + len(Op.JUMP(len(setup)))
+ available_space = max_code_size - overhead
+ max_iterations = available_space // len(repeated_code)
+
+ code = setup + Op.JUMPDEST + repeated_code * max_iterations + Op.JUMP(len(setup))
+ self._validate_code_size(code, fork)
+
+ return code
+
+ def _validate_code_size(self, code: Bytecode, fork: Fork) -> None:
+ """Validate that the generated code fits within size limits."""
+ if len(code) > fork.max_code_size():
+ raise ValueError(
+ f"Generated code size {len(code)} exceeds maximum allowed size "
+ f"{fork.max_code_size()}"
+ )
+
+
+class BenchmarkTest(BaseTest):
+ """Test type designed specifically for benchmark test cases."""
+
+ model_config = ConfigDict(extra="forbid")
+
+ pre: Alloc
+ post: Alloc = Field(default_factory=Alloc)
+ tx: Transaction | None = None
+ blocks: List[Block] | None = None
+ block_exception: (
+ List[TransactionException | BlockException] | TransactionException | BlockException | None
+ ) = None
+ env: Environment = Field(default_factory=Environment)
+ expected_benchmark_gas_used: int | None = None
+ gas_benchmark_value: int = Field(default_factory=lambda: int(Environment().gas_limit))
+ code_generator: BenchmarkCodeGenerator | None = None
+
+ supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [
+ BlockchainFixture,
+ BlockchainEngineFixture,
+ BlockchainEngineXFixture,
+ ]
+
+ supported_execute_formats: ClassVar[Sequence[LabeledExecuteFormat]] = [
+ LabeledExecuteFormat(
+ TransactionPost,
+ "benchmark_test",
+ "An execute test derived from a benchmark test",
+ ),
+ ]
+
+ supported_markers: ClassVar[Dict[str, str]] = {
+ "blockchain_test_engine_only": "Only generate a blockchain test engine fixture",
+ "blockchain_test_only": "Only generate a blockchain test fixture",
+ }
+
+ @classmethod
+ def pytest_parameter_name(cls) -> str:
+ """
+ Return the parameter name used in pytest
+ to select this spec type.
+ """
+ return "benchmark_test"
+
+ @classmethod
+ def discard_fixture_format_by_marks(
+ cls,
+ fixture_format: FixtureFormat,
+ fork: Fork,
+ markers: List[pytest.Mark],
+ ) -> bool:
+ """
+ Discard a fixture format from filling if the
+ appropriate marker is used.
+ """
+ if "blockchain_test_only" in [m.name for m in markers]:
+ return fixture_format != BlockchainFixture
+ if "blockchain_test_engine_only" in [m.name for m in markers]:
+ return fixture_format != BlockchainEngineFixture
+ return False
+
+ def get_genesis_environment(self, fork: Fork) -> Environment:
+ """Get the genesis environment for this benchmark test."""
+ return self.env
+
+ def split_transaction(self, tx: Transaction, gas_limit_cap: int | None) -> List[Transaction]:
+ """
+ Split a transaction that exceeds the gas
+ limit cap into multiple transactions.
+ """
+ if gas_limit_cap is None:
+ tx.gas_limit = HexNumber(self.gas_benchmark_value)
+ return [tx]
+
+ if gas_limit_cap >= self.gas_benchmark_value:
+ tx.gas_limit = HexNumber(self.gas_benchmark_value)
+ return [tx]
+
+ num_splits = math.ceil(self.gas_benchmark_value / gas_limit_cap)
+ remaining_gas = self.gas_benchmark_value
+
+ split_transactions = []
+ for i in range(num_splits):
+ split_tx = tx.model_copy()
+ split_tx.gas_limit = HexNumber(remaining_gas if i == num_splits - 1 else gas_limit_cap)
+ remaining_gas -= gas_limit_cap
+ split_tx.nonce = HexNumber(tx.nonce + i)
+ split_transactions.append(split_tx)
+
+ return split_transactions
+
+ def generate_blocks_from_code_generator(self, fork: Fork) -> List[Block]:
+ """Generate blocks using the code generator."""
+ if self.code_generator is None:
+ raise Exception("Code generator is not set")
+
+ self.code_generator.deploy_contracts(self.pre, fork)
+ gas_limit = fork.transaction_gas_limit_cap() or self.gas_benchmark_value
+ benchmark_tx = self.code_generator.generate_transaction(self.pre, gas_limit, fork)
+
+ execution_txs = self.split_transaction(benchmark_tx, gas_limit)
+ execution_block = Block(txs=execution_txs)
+
+ return [execution_block]
+
+ def generate_blockchain_test(self, fork: Fork) -> BlockchainTest:
+ """Create a BlockchainTest from this BenchmarkTest."""
+ set_props = [
+ name
+ for name, val in [
+ ("code_generator", self.code_generator),
+ ("blocks", self.blocks),
+ ("tx", self.tx),
+ ]
+ if val is not None
+ ]
+
+ if len(set_props) != 1:
+ raise ValueError(
+ f"Exactly one must be set, but got {len(set_props)}: {', '.join(set_props)}"
+ )
+
+ if self.code_generator is not None:
+ generated_blocks = self.generate_blocks_from_code_generator(fork)
+ return BlockchainTest.from_test(
+ base_test=self,
+ genesis_environment=self.env,
+ pre=self.pre,
+ post=self.post,
+ blocks=generated_blocks,
+ )
+ elif self.blocks is not None:
+ return BlockchainTest.from_test(
+ base_test=self,
+ genesis_environment=self.env,
+ pre=self.pre,
+ post=self.post,
+ blocks=self.blocks,
+ )
+ elif self.tx is not None:
+ gas_limit = fork.transaction_gas_limit_cap() or self.gas_benchmark_value
+
+ transactions = self.split_transaction(self.tx, gas_limit)
+
+ blocks = [Block(txs=transactions)]
+
+ return BlockchainTest.from_test(
+ base_test=self,
+ pre=self.pre,
+ post=self.post,
+ blocks=blocks,
+ genesis_environment=self.env,
+ )
+ else:
+ raise ValueError("Cannot create BlockchainTest without transactions or blocks")
+
+ def generate(
+ self,
+ t8n: TransitionTool,
+ fork: Fork,
+ fixture_format: FixtureFormat,
+ ) -> BaseFixture:
+ """Generate the blockchain test fixture."""
+ self.check_exception_test(exception=self.tx.error is not None if self.tx else False)
+ if fixture_format in BlockchainTest.supported_fixture_formats:
+ return self.generate_blockchain_test(fork=fork).generate(
+ t8n=t8n, fork=fork, fixture_format=fixture_format
+ )
+ else:
+ raise Exception(f"Unsupported fixture format: {fixture_format}")
+
+ def execute(
+ self,
+ *,
+ fork: Fork,
+ execute_format: ExecuteFormat,
+ ) -> BaseExecute:
+ """Execute the benchmark test by sending it to the live network."""
+ if execute_format == TransactionPost:
+ return TransactionPost(
+ blocks=[[self.tx]],
+ post=self.post,
+ )
+ raise Exception(f"Unsupported execute format: {execute_format}")
+
+
+BenchmarkTestSpec = Callable[[str], Generator[BenchmarkTest, None, None]]
+BenchmarkTestFiller = Type[BenchmarkTest]
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/blobs.py b/packages/tests/src/ethereum_test_specs/blobs.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/blobs.py
rename to packages/tests/src/ethereum_test_specs/blobs.py
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/blockchain.py b/packages/tests/src/ethereum_test_specs/blockchain.py
similarity index 84%
rename from src/ethereum_spec_tests/ethereum_test_specs/blockchain.py
rename to packages/tests/src/ethereum_test_specs/blockchain.py
index 2848a40f38..6c250a649c 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/blockchain.py
+++ b/packages/tests/src/ethereum_test_specs/blockchain.py
@@ -4,7 +4,7 @@
from typing import Any, Callable, ClassVar, Dict, Generator, List, Sequence, Tuple, Type
import pytest
-from pydantic import ConfigDict, Field, field_validator
+from pydantic import ConfigDict, Field, field_validator, model_serializer
from ethereum_clis import BlockExceptionWithMessage, Result, TransitionTool
from ethereum_test_base_types import (
@@ -130,31 +130,25 @@ class Header(CamelModel):
"""
EMPTY_FIELD: ClassVar[Removable] = Removable()
"""
- Sentinel object used to specify that a header field must be empty during verification.
+ Sentinel object used to specify that a header field must be empty during
+ verification.
- This can be used in a test to explicitly skip a field in a block's RLP encoding.
- included in the (json) output when the model is serialized. For example:
- ```
- header_modifier = Header(
- excess_blob_gas=Header.REMOVE_FIELD,
- )
- block = Block(
- timestamp=TIMESTAMP,
- rlp_modifier=header_modifier,
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
- engine_api_error_code=EngineAPIError.InvalidParams,
- )
- ```
+ This can be used in a test to explicitly skip a field in a block's RLP
+ encoding. included in the (json) output when the model is serialized. For
+ example: ``` header_modifier = Header( excess_blob_gas=Header.REMOVE_FIELD,
+ ) block = Block( timestamp=TIMESTAMP, rlp_modifier=header_modifier,
+ exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ engine_api_error_code=EngineAPIError.InvalidParams, ) ```
"""
- model_config = ConfigDict(
- arbitrary_types_allowed=True,
- # explicitly set Removable items to None so they are not included in the serialization
- # (in combination with exclude_None=True in model.dump()).
- json_encoders={
- Removable: lambda x: None,
- },
- )
+ model_config = ConfigDict(arbitrary_types_allowed=True)
+
+ @model_serializer(mode="wrap", when_used="json")
+ def _serialize_model(self, serializer, info):
+ """Exclude Removable fields from serialization."""
+ del info
+ data = serializer(self)
+ return {k: v for k, v in data.items() if not isinstance(v, Removable)}
@field_validator("withdrawals_root", mode="before")
@classmethod
@@ -165,7 +159,9 @@ def validate_withdrawals_root(cls, value):
return value
def apply(self, target: FixtureHeader) -> FixtureHeader:
- """Produce a fixture header copy with the set values from the modifier."""
+ """
+ Produce a fixture header copy with the set values from the modifier.
+ """
return target.copy(
**{
k: (v if v is not Header.REMOVE_FIELD else None)
@@ -200,9 +196,7 @@ class Block(Header):
"""Block type used to describe block properties in test specs."""
header_verify: Header | None = None
- """
- If set, the block header will be verified against the specified values.
- """
+ # If set, the block header will be verified against the specified values.
rlp_modifier: Header | None = None
"""
An RLP modifying header which values would be used to override the ones
@@ -210,46 +204,34 @@ class Block(Header):
"""
expected_block_access_list: BlockAccessListExpectation | None = None
"""
- If set, the block access list will be verified and potentially corrupted for invalid tests.
+ If set, the block access list will be verified and potentially corrupted
+ for invalid tests.
"""
exception: BLOCK_EXCEPTION_TYPE = None
- """
- If set, the block is expected to be rejected by the client.
- """
+ # If set, the block is expected to be rejected by the client.
skip_exception_verification: bool = False
"""
- Skip verifying that the exception is returned by the transition tool.
- This could be because the exception is inserted in the block after the transition tool
- evaluates it.
+ Skip verifying that the exception is returned by the transition tool. This
+ could be because the exception is inserted in the block after the
+ transition tool evaluates it.
"""
engine_api_error_code: EngineAPIError | None = None
"""
- If set, the block is expected to produce an error response from the Engine API.
+ If set, the block is expected to produce an error response from the Engine
+ API.
"""
txs: List[Transaction] = Field(default_factory=list)
- """
- List of transactions included in the block.
- """
+ """List of transactions included in the block."""
ommers: List[Header] | None = None
- """
- List of ommer headers included in the block.
- """
+ """List of ommer headers included in the block."""
withdrawals: List[Withdrawal] | None = None
- """
- List of withdrawals to perform for this block.
- """
+ """List of withdrawals to perform for this block."""
requests: List[Bytes] | None = None
- """
- Custom list of requests to embed in this block.
- """
+ """Custom list of requests to embed in this block."""
expected_post_state: Alloc | None = None
- """
- Post state for verification after block execution in BlockchainTest
- """
+ """Post state for verification after block execution in BlockchainTest"""
block_access_list: Bytes | None = Field(None)
- """
- EIP-7928: Block-level access lists (serialized).
- """
+ """EIP-7928: Block-level access lists (serialized)."""
def set_environment(self, env: Environment) -> Environment:
"""
@@ -259,8 +241,8 @@ def set_environment(self, env: Environment) -> Environment:
new_env_values: Dict[str, Any] = {}
"""
- Values that need to be set in the environment and are `None` for
- this block need to be set to their defaults.
+ Values that need to be set in the environment and are `None` for this
+ block need to be set to their defaults.
"""
new_env_values["difficulty"] = self.difficulty
new_env_values["prev_randao"] = self.prev_randao
@@ -310,10 +292,7 @@ def set_environment(self, env: Environment) -> Environment:
class BuiltBlock(CamelModel):
- """
- Model that contains all properties to build a full block or
- payload.
- """
+ """Model that contains all properties to build a full block or payload."""
header: FixtureHeader
env: Environment
@@ -414,7 +393,8 @@ def verify_block_exception(self, transition_tool_exceptions_reliable: bool):
"prev_randao": 0,
}
"""
-Default values for the genesis environment that are used to create all genesis headers.
+Default values for the genesis environment that are used to create all genesis
+headers.
"""
@@ -428,8 +408,8 @@ class BlockchainTest(BaseTest):
chain_id: int = 1
exclude_full_post_state_in_output: bool = False
"""
- Exclude the post state from the fixture output.
- In this case, the state verification is only performed based on the state root.
+ Exclude the post state from the fixture output. In this case, the state
+ verification is only performed based on the state root.
"""
supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [
@@ -458,7 +438,10 @@ def discard_fixture_format_by_marks(
fork: Fork,
markers: List[pytest.Mark],
) -> bool:
- """Discard a fixture format from filling if the appropriate marker is used."""
+ """
+ Discard a fixture format from filling if the appropriate marker is
+ used.
+ """
marker_names = [m.name for m in markers]
if fixture_format != BlockchainFixture and "blockchain_test_only" in marker_names:
return True
@@ -516,7 +499,9 @@ def generate_block_data(
previous_alloc: Alloc,
last_block: bool,
) -> BuiltBlock:
- """Generate common block data for both make_fixture and make_hive_fixture."""
+ """
+ Generate common block data for both make_fixture and make_hive_fixture.
+ """
env = block.set_environment(previous_env)
env = env.set_fork_requirements(fork)
txs = [tx.with_signature_and_sender() for tx in block.txs]
@@ -539,19 +524,30 @@ def generate_block_data(
env=env,
fork=fork,
chain_id=self.chain_id,
- reward=fork.get_reward(env.number, env.timestamp),
+ reward=fork.get_reward(block_number=env.number, timestamp=env.timestamp),
blob_schedule=fork.blob_schedule(),
),
debug_output_path=self.get_next_transition_tool_output_path(),
slow_request=self.is_tx_gas_heavy_test(),
)
- # One special case of the invalid transactions is the blob gas used, since this value
- # is not included in the transition tool result, but it is included in the block header,
- # and some clients check it before executing the block by simply counting the type-3 txs,
- # we need to set the correct value by default.
+ if transition_tool_output.result.opcode_count is not None:
+ if self._opcode_count is None:
+ self._opcode_count = transition_tool_output.result.opcode_count
+ else:
+ self._opcode_count += transition_tool_output.result.opcode_count
+
+ # One special case of the invalid transactions is the blob gas used,
+ # since this value is not included in the transition tool result, but
+ # it is included in the block header, and some clients check it before
+ # executing the block by simply counting the type-3 txs, we need to set
+ # the correct value by default.
blob_gas_used: int | None = None
- if (blob_gas_per_blob := fork.blob_gas_per_blob(env.number, env.timestamp)) > 0:
+ if (
+ blob_gas_per_blob := fork.blob_gas_per_blob(
+ block_number=env.number, timestamp=env.timestamp
+ )
+ ) > 0:
blob_gas_used = blob_gas_per_blob * count_blobs(txs)
header = FixtureHeader(
@@ -580,14 +576,16 @@ def generate_block_data(
"expected_benchmark_gas_used is not set"
)
gas_used = int(transition_tool_output.result.gas_used)
- assert gas_used == expected_benchmark_gas_used, (
- f"gas_used ({gas_used}) does not match expected_benchmark_gas_used "
- f"({expected_benchmark_gas_used})"
- f", difference: {gas_used - expected_benchmark_gas_used}"
- )
+
+ if not self.skip_gas_used_validation:
+ assert gas_used == expected_benchmark_gas_used, (
+ f"gas_used ({gas_used}) does not match expected_benchmark_gas_used "
+ f"({expected_benchmark_gas_used})"
+ f", difference: {gas_used - expected_benchmark_gas_used}"
+ )
requests_list: List[Bytes] | None = None
- if fork.header_requests_required(header.number, header.timestamp):
+ if fork.header_requests_required(block_number=header.number, timestamp=header.timestamp):
assert transition_tool_output.result.requests is not None, (
"Requests are required for this block"
)
@@ -606,7 +604,7 @@ def generate_block_data(
header.requests_hash = Hash(Requests(requests_lists=list(block.requests)))
requests_list = block.requests
- if fork.header_bal_hash_required(header.number, header.timestamp):
+ if fork.header_bal_hash_required(block_number=header.number, timestamp=header.timestamp):
assert transition_tool_output.result.block_access_list is not None, (
"Block access list is required for this block but was not provided "
"by the transition tool"
@@ -626,13 +624,17 @@ def generate_block_data(
header = block.rlp_modifier.apply(header)
header.fork = fork # Deleted during `apply` because `exclude=True`
- # Process block access list - apply transformer if present for invalid tests
- bal = transition_tool_output.result.block_access_list
- if block.expected_block_access_list is not None and bal is not None:
- # Use to_fixture_bal to validate and potentially transform the BAL
- bal = block.expected_block_access_list.to_fixture_bal(bal)
- # Don't update the header hash - leave it as the hash of the correct BAL
- # This creates a mismatch that should cause the block to be rejected
+ # Process block access list - apply transformer if present for invalid
+ # tests
+ t8n_bal = transition_tool_output.result.block_access_list
+ bal = t8n_bal
+ if block.expected_block_access_list is not None and t8n_bal is not None:
+ block.expected_block_access_list.verify_against(t8n_bal)
+
+ bal = block.expected_block_access_list.modify_if_invalid_test(t8n_bal)
+ if bal != t8n_bal:
+ # If the BAL was modified, update the header hash
+ header.block_access_list_hash = Hash(bal.rlp.keccak256())
built_block = BuiltBlock(
header=header,
@@ -663,15 +665,14 @@ def generate_block_data(
and block.expected_block_access_list._modifier is not None
)
):
- # Only verify block level exception if:
- # - No transaction exception was raised, because these are not
- # reported as block exceptions.
- # - No RLP modifier was specified, because the modifier is what
- # normally produces the block exception.
- # - No requests were specified, because modified requests are also
- # what normally produces the block exception.
- # - No BAL modifier was specified, because modified BAL also
- # produces block exceptions.
+ # Only verify block level exception if: - No transaction
+ # exception was raised, because these are not reported as block
+ # exceptions. - No RLP modifier was specified, because the
+ # modifier is what normally produces the block exception. - No
+ # requests were specified, because modified requests are also
+ # what normally produces the block exception. - No BAL modifier
+ # was specified, because modified BAL also produces block
+ # exceptions.
built_block.verify_block_exception(
transition_tool_exceptions_reliable=t8n.exception_mapper.reliable,
)
@@ -734,7 +735,8 @@ def make_fixture(
)
fixture_blocks.append(built_block.get_fixture_block())
- # BAL verification already done in to_fixture_bal() if expected_block_access_list set
+ # BAL verification already done in to_fixture_bal() if
+ # expected_block_access_list set
if block.exception is None:
# Update env, alloc and last block hash for the next block.
@@ -750,6 +752,9 @@ def make_fixture(
)
self.check_exception_test(exception=invalid_blocks > 0)
self.verify_post_state(t8n, t8n_state=alloc)
+ info = {}
+ if self._opcode_count is not None:
+ info["opcode_count"] = self._opcode_count.model_dump()
return BlockchainFixture(
fork=fork,
genesis=genesis.header,
@@ -764,6 +769,7 @@ def make_fixture(
blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()),
chain_id=self.chain_id,
),
+ info=info,
)
def make_hive_fixture(
@@ -806,7 +812,7 @@ def make_hive_fixture(
)
self.check_exception_test(exception=invalid_blocks > 0)
fcu_version = fork.engine_forkchoice_updated_version(
- built_block.header.number, built_block.header.timestamp
+ block_number=built_block.header.number, timestamp=built_block.header.timestamp
)
assert fcu_version is not None, (
"A hive fixture was requested but no forkchoice update is defined."
@@ -816,6 +822,9 @@ def make_hive_fixture(
self.verify_post_state(t8n, t8n_state=alloc)
# Create base fixture data, common to all fixture formats
+ info = {}
+ if self._opcode_count is not None:
+ info["opcode_count"] = self._opcode_count.model_dump()
fixture_data = {
"fork": fork,
"genesis": genesis.header,
@@ -829,12 +838,13 @@ def make_hive_fixture(
chain_id=self.chain_id,
blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()),
),
+ "info": info,
}
# Add format-specific fields
if fixture_format == BlockchainEngineXFixture:
- # For Engine X format, exclude pre (will be provided via shared state)
- # and prepare for state diff optimization
+ # For Engine X format, exclude pre (will be provided via shared
+ # state) and prepare for state diff optimization
fixture_data.update(
{
"post_state": alloc if not self.exclude_full_post_state_in_output else None,
@@ -847,9 +857,9 @@ def make_hive_fixture(
assert genesis.header.block_hash != head_hash, (
"Invalid payload tests negative test via sync is not supported yet."
)
- # Most clients require the header to start the sync process, so we create an empty
- # block on top of the last block of the test to send it as new payload and trigger the
- # sync process.
+ # Most clients require the header to start the sync process, so we
+ # create an empty block on top of the last block of the test to
+ # send it as new payload and trigger the sync process.
sync_built_block = self.generate_block_data(
t8n=t8n,
fork=fork,
@@ -906,9 +916,16 @@ def execute(
blocks: List[List[Transaction]] = []
for block in self.blocks:
blocks += [block.txs]
+ # Pass gas validation params for benchmark tests
+ # If not benchmark mode, skip gas used validation
+ if self._operation_mode != OpMode.BENCHMARKING:
+ self.skip_gas_used_validation = True
+
return TransactionPost(
blocks=blocks,
post=self.post,
+ expected_benchmark_gas_used=self.expected_benchmark_gas_used,
+ skip_gas_used_validation=self.skip_gas_used_validation,
)
raise Exception(f"Unsupported execute format: {execute_format}")
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/debugging.py b/packages/tests/src/ethereum_test_specs/debugging.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/debugging.py
rename to packages/tests/src/ethereum_test_specs/debugging.py
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/eof.py b/packages/tests/src/ethereum_test_specs/eof.py
similarity index 85%
rename from src/ethereum_spec_tests/ethereum_test_specs/eof.py
rename to packages/tests/src/ethereum_test_specs/eof.py
index 35f5898489..d64a98cde1 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/eof.py
+++ b/packages/tests/src/ethereum_test_specs/eof.py
@@ -53,7 +53,9 @@ def __init__(self, message):
@staticmethod
def format_code(code: Bytes, max_length=60) -> str:
- """Avoid printing long bytecode strings in the terminal upon test failure."""
+ """
+ Avoid printing long bytecode strings in the terminal upon test failure.
+ """
if len(code) > max_length:
half_length = max_length // 2 - 5 # Floor; adjust for ellipsis
return f"{code[:half_length].hex()}...{code[-half_length:].hex()}"
@@ -84,7 +86,10 @@ class ExpectedEOFExceptionError(EOFBaseExceptionError):
"""
def __init__(self, *, code: Bytes, expected: str):
- """Initialize the exception with the code and the expected exception message."""
+ """
+ Initialize the exception with the code and the expected exception
+ message.
+ """
message = (
"Expected EOF code to be invalid, but no exception was raised:\n"
f" Code: {self.format_code(code)}\n"
@@ -95,10 +100,15 @@ def __init__(self, *, code: Bytes, expected: str):
class EOFExceptionMismatchError(EOFBaseExceptionError):
- """Exception used when the actual EOF exception differs from the expected one."""
+ """
+ Exception used when the actual EOF exception differs from the expected one.
+ """
def __init__(self, code: Bytes, expected: str, got: str):
- """Initialize the exception with the code, the expected/actual exception message."""
+ """
+ Initialize the exception with the code, the expected/actual exception
+ message.
+ """
message = (
"EOF code raised a different exception than expected:\n"
f" Code: {self.format_code(code)}\n"
@@ -166,88 +176,92 @@ class EOFTest(BaseTest):
"""
Filler type that generates a test for EOF container validation.
- A state test is also automatically generated where the container is wrapped in a
- contract-creating transaction to test deployment/validation on the instantiated blockchain.
+ A state test is also automatically generated where the container is wrapped
+ in a contract-creating transaction to test deployment/validation on the
+ instantiated blockchain.
"""
container: Container
"""
EOF container that will be tested for validity.
- The only supported type at the moment is `ethereum_test_types.eof.v1.Container`.
+ The only supported type at the moment is
+ `ethereum_test_types.eof.v1.Container`.
- If an invalid container needs to be tested, and it cannot be generated using the
- Container class features, the `raw_bytes` field can be used to provide the raw
- container bytes.
+ If an invalid container needs to be tested, and it cannot be generated
+ using the Container class features, the `raw_bytes` field can be used to
+ provide the raw container bytes.
"""
expect_exception: EOFExceptionInstanceOrList | None = None
"""
- Expected exception that the container should raise when parsed by an EOF parser.
+ Expected exception that the container should raise when parsed by an EOF
+ parser.
- Can be a single exception or a list of exceptions that the container is expected to raise,
- in which case the test will pass if any of the exceptions are raised.
+ Can be a single exception or a list of exceptions that the container is
+ expected to raise, in which case the test will pass if any of the
+ exceptions are raised.
- The list of supported exceptions can be found in the `ethereum_test_exceptions.EOFException`
- class.
+ The list of supported exceptions can be found in the
+ `ethereum_test_exceptions.EOFException` class.
"""
container_kind: ContainerKind = ContainerKind.RUNTIME
"""
Container kind type that the container should be treated as.
- The container kind can be one of the following:
- - `ContainerKind.INITCODE`: The container is an initcode container.
- - `ContainerKind.RUNTIME`: The container is a runtime container.
+ The container kind can be one of the following: - `ContainerKind.INITCODE`:
+ The container is an initcode container. - `ContainerKind.RUNTIME`: The
+ container is a runtime container.
The default value is `ContainerKind.RUNTIME`.
"""
deployed_container: Container | None = None
"""
- To be used when the container is an initcode container and the expected deployed container is
- known.
-
- The value is only used when a State Test is generated from this EOF test to set the expected
- deployed container that should be found in the post state.
-
- If this field is not set, and the container is valid:
- - If the container kind is `ContainerKind.RUNTIME`, the deployed container is assumed to be
- the container itself, and an initcode container that wraps the container is generated
- automatically.
- - If the container kind is `ContainerKind.INITCODE`, `model_post_init` will attempt to infer
- the deployed container from the sections of the init-container, and the first
- container-type section will be used. An error will be raised if the deployed container
- cannot be inferred.
-
- If the value is set to `None`, it is assumed that the container is invalid and the test will
- expect that no contract is created.
-
- It is considered an error if:
- - The `deployed_container` field is set and the `container_kind` field is not set to
- `ContainerKind.INITCODE`.
- - The `deployed_container` field is set and the `expect_exception` is not `None`.
-
- The deployed container is **not** executed at any point during the EOF validation test nor
- the generated State Test. For container runtime testing use the `EOFStateTest` class.
+ To be used when the container is an initcode container and the expected
+ deployed container is known.
+
+ The value is only used when a State Test is generated from this EOF test to
+ set the expected deployed container that should be found in the post state.
+
+ If this field is not set, and the container is valid: - If the container
+ kind is `ContainerKind.RUNTIME`, the deployed container is assumed to be
+ the container itself, and an initcode container that wraps the container is
+ generated automatically. - If the container kind is
+ `ContainerKind.INITCODE`, `model_post_init` will attempt to infer the
+ deployed container from the sections of the init-container, and the first
+ container-type section will be used. An error will be raised if the
+ deployed container cannot be inferred.
+
+ If the value is set to `None`, it is assumed that the container is invalid
+ and the test will expect that no contract is created.
+
+ It is considered an error if: - The `deployed_container` field is set and
+ the `container_kind` field is not set to `ContainerKind.INITCODE`. - The
+ `deployed_container` field is set and the `expect_exception` is not `None`.
+
+ The deployed container is **not** executed at any point during the EOF
+ validation test nor the generated State Test. For container runtime testing
+ use the `EOFStateTest` class.
"""
pre: Alloc | None = None
"""
Pre alloc object that is used during State Test generation.
- This field is automatically set by the test filler when generating a State Test from this EOF
- test and should otherwise be left unset.
+ This field is automatically set by the test filler when generating a State
+ Test from this EOF test and should otherwise be left unset.
"""
post: Alloc | None = None
"""
Post alloc object that is used during State Test generation.
- This field is automatically set by the test filler when generating a State Test from this EOF
- test and is normally not set by the user.
+ This field is automatically set by the test filler when generating a State
+ Test from this EOF test and is normally not set by the user.
"""
sender: EOA | None = None
"""
Sender EOA object that is used during State Test generation.
- This field is automatically set by the `model_post_init` method and should otherwise be left
- unset.
+ This field is automatically set by the `model_post_init` method and should
+ otherwise be left unset.
"""
supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [
@@ -281,7 +295,10 @@ def discard_fixture_format_by_marks(
fork: Fork,
markers: List[pytest.Mark],
) -> bool:
- """Discard a fixture format from filling if the appropriate marker is used."""
+ """
+ Discard a fixture format from filling if the appropriate marker is
+ used.
+ """
if "eof_test_only" in [m.name for m in markers]:
return fixture_format != EOFFixture
return False
@@ -369,7 +386,9 @@ def make_eof_test_fixture(
return fixture
def verify_result(self, result: CompletedProcess, expected_result: Result, code: Bytes):
- """Check that the reported exception string matches the expected error."""
+ """
+ Check that the reported exception string matches the expected error.
+ """
evmone_exception_mapper = EvmoneExceptionMapper()
actual_exception_str = result.stdout.strip()
actual_exception: EOFExceptionWithMessage | UndefinedException | None = None
@@ -409,12 +428,13 @@ def generate_eof_contract_create_transaction(self) -> Transaction:
if self.container_kind == ContainerKind.INITCODE:
initcode = self.container
if "deployed_container" in self.model_fields_set:
- # In the case of an initcontainer where we know the deployed container,
- # we can use the initcontainer as-is.
+ # In the case of an initcontainer where we know the deployed
+ # container, we can use the initcontainer as-is.
deployed_container = self.deployed_container
elif self.expect_exception is None:
- # We have a valid init-container, but we don't know the deployed container.
- # Try to infer the deployed container from the sections of the init-container.
+ # We have a valid init-container, but we don't know the
+ # deployed container. Try to infer the deployed container from
+ # the sections of the init-container.
assert self.container.raw_bytes is None, (
"deployed_container must be set for initcode containers with raw_bytes."
)
@@ -505,34 +525,28 @@ def execute(
class EOFStateTest(EOFTest, Transaction):
"""
- Filler type that generates an EOF test for container validation, and also tests the container
- during runtime using a state test (and blockchain test).
+ Filler type that generates an EOF test for container validation, and also
+ tests the container during runtime using a state test (and blockchain
+ test).
- In the state or blockchain test, the container is first deployed to the pre-allocation and
- then a transaction is sent to the deployed container.
+ In the state or blockchain test, the container is first deployed to the
+ pre-allocation and then a transaction is sent to the deployed container.
- Container deployment/validation is **not** tested like in the `EOFTest` unless the container
- under test is an initcode container.
+ Container deployment/validation is **not** tested like in the `EOFTest`
+ unless the container under test is an initcode container.
- All fields from `ethereum_test_types.Transaction` are available for use in the test.
+ All fields from `ethereum_test_types.Transaction` are available for use in
+ the test.
"""
gas_limit: HexNumber = Field(HexNumber(10_000_000), serialization_alias="gas")
- """
- Gas limit for the transaction that deploys the container.
- """
+ """Gas limit for the transaction that deploys the container."""
tx_sender_funding_amount: int = 1_000_000_000_000_000_000_000
- """
- Amount of funds to send to the sender EOA before the transaction.
- """
+ """Amount of funds to send to the sender EOA before the transaction."""
env: Environment = Field(default_factory=Environment)
- """
- Environment object that is used during State Test generation.
- """
+ """Environment object that is used during State Test generation."""
container_post: Account = Field(default_factory=Account)
- """
- Account object used to verify the container post state.
- """
+ """Account object used to verify the container post state."""
supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [
EOFFixture
@@ -580,7 +594,8 @@ def model_post_init(self, __context):
# Run transaction model validation
Transaction.model_post_init(self, __context)
- self.post[compute_eofcreate_address(self.to, 0)] = None # Expect failure.
+ self.post[compute_eofcreate_address(self.to, 0)] = None # Expect
+ # failure.
elif self.expect_exception is not None and self.container_kind == ContainerKind.INITCODE:
# Invalid EOF initcode
self.to = self.pre.deploy_contract(
@@ -591,7 +606,8 @@ def model_post_init(self, __context):
# Run transaction model validation
Transaction.model_post_init(self, __context)
- self.post[compute_eofcreate_address(self.to, 0)] = None # Expect failure.
+ self.post[compute_eofcreate_address(self.to, 0)] = None # Expect
+ # failure.
elif self.container_kind == ContainerKind.INITCODE:
self.to = self.pre.deploy_contract(
Op.TXCREATE(tx_initcode_hash=self.container.hash) + Op.STOP
@@ -634,8 +650,8 @@ def generate(
"""Generate the BlockchainTest fixture."""
if fixture_format == EOFFixture:
if Bytes(self.container) in existing_tests:
- # Gracefully skip duplicate tests because one EOFStateTest can generate multiple
- # state fixtures with the same data.
+ # Gracefully skip duplicate tests because one EOFStateTest can
+ # generate multiple state fixtures with the same data.
pytest.skip(f"Duplicate EOF container on EOFStateTest: {self.node_id()}")
return self.make_eof_test_fixture(fork=fork)
elif fixture_format in StateTest.supported_fixture_formats:
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/helpers.py b/packages/tests/src/ethereum_test_specs/helpers.py
similarity index 94%
rename from src/ethereum_spec_tests/ethereum_test_specs/helpers.py
rename to packages/tests/src/ethereum_test_specs/helpers.py
index 1f877f21d3..27b0979310 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/helpers.py
+++ b/packages/tests/src/ethereum_test_specs/helpers.py
@@ -23,7 +23,9 @@ class ExecutionContext(StrEnum):
class UnexpectedExecutionSuccessError(Exception):
- """Exception used when the transaction expected to fail succeeded instead."""
+ """
+ Exception used when the transaction expected to fail succeeded instead.
+ """
def __init__(self, execution_context: ExecutionContext, **kwargs):
"""Initialize the unexpected success exception."""
@@ -35,7 +37,9 @@ def __init__(self, execution_context: ExecutionContext, **kwargs):
class UnexpectedExecutionFailError(Exception):
- """Exception used when a transaction/block expected to succeed failed instead."""
+ """
+ Exception used when a transaction/block expected to succeed failed instead.
+ """
def __init__(
self,
@@ -54,7 +58,10 @@ def __init__(
class UndefinedExecutionExceptionError(Exception):
- """Exception used when a client's exception message isn't present in its `ExceptionMapper`."""
+ """
+ Exception used when a client's exception message isn't present in its
+ `ExceptionMapper`.
+ """
def __init__(
self,
@@ -100,7 +107,10 @@ def __init__(
class TransactionReceiptMismatchError(Exception):
- """Exception used when the actual transaction receipt differs from the expected one."""
+ """
+ Exception used when the actual transaction receipt differs from the
+ expected one.
+ """
def __init__(
self,
@@ -259,9 +269,9 @@ def verify_transactions(
transition_tool_exceptions_reliable: bool,
) -> List[int]:
"""
- Verify accepted and rejected (if any) transactions against the expected outcome.
- Raises exception on unexpected rejections, unexpected successful txs, or successful txs with
- unexpected receipt values.
+ Verify accepted and rejected (if any) transactions against the expected
+ outcome. Raises exception on unexpected rejections, unexpected successful
+ txs, or successful txs with unexpected receipt values.
"""
rejected_txs: Dict[int, ExceptionWithMessage | UndefinedException] = {
rejected_tx.index: rejected_tx.error for rejected_tx in result.rejected_transactions
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/py.typed b/packages/tests/src/ethereum_test_specs/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/py.typed
rename to packages/tests/src/ethereum_test_specs/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/state.py b/packages/tests/src/ethereum_test_specs/state.py
similarity index 88%
rename from src/ethereum_spec_tests/ethereum_test_specs/state.py
rename to packages/tests/src/ethereum_test_specs/state.py
index f840b8db1b..b14ef89640 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/state.py
+++ b/packages/tests/src/ethereum_test_specs/state.py
@@ -35,7 +35,7 @@
Environment,
Transaction,
)
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
from .base import BaseTest, OpMode
from .blockchain import Block, BlockchainTest, Header
@@ -46,7 +46,9 @@
class StateTest(BaseTest):
- """Filler type that tests transactions over the period of a single block."""
+ """
+ Filler type that tests transactions over the period of a single block.
+ """
env: Environment = Field(default_factory=Environment)
pre: Alloc
@@ -70,7 +72,8 @@ class StateTest(BaseTest):
f"A {fixture_format.format_name} generated from a state_test",
)
for fixture_format in BlockchainTest.supported_fixture_formats
- # Exclude sync fixtures from state tests - they don't make sense for state tests
+ # Exclude sync fixtures from state tests - they don't make sense for
+ # state tests
if not (
(hasattr(fixture_format, "__name__") and "Sync" in fixture_format.__name__)
or (hasattr(fixture_format, "format") and "Sync" in fixture_format.format.__name__)
@@ -173,26 +176,33 @@ def discard_fixture_format_by_marks(
fork: Fork,
markers: List[pytest.Mark],
) -> bool:
- """Discard a fixture format from filling if the appropriate marker is used."""
+ """
+ Discard a fixture format from filling if the appropriate marker is
+ used.
+ """
if "state_test_only" in [m.name for m in markers]:
return fixture_format != StateFixture
return False
def _generate_blockchain_genesis_environment(self, *, fork: Fork) -> Environment:
- """Generate the genesis environment for the BlockchainTest formatted test."""
+ """
+ Generate the genesis environment for the BlockchainTest formatted test.
+ """
assert self.env.number >= 1, (
"genesis block number cannot be negative, set state test env.number to at least 1"
)
assert self.env.timestamp >= 1, (
"genesis timestamp cannot be negative, set state test env.timestamp to at least 1"
)
- # There's only a handful of values that we need to set in the genesis for the
- # environment values at block 1 to make sense:
+ # There's only a handful of values that we need to set in the genesis
+ # for the environment values at block 1 to make sense:
# - Number: Needs to be N minus 1
- # - Timestamp: Needs to be zero, because the subsequent block can come at any time.
+ # - Timestamp: Needs to be zero, because the subsequent
+ # block can come at any time.
# - Gas Limit: Changes from parent to child, needs to be set in genesis
# - Base Fee Per Gas: Block's base fee depends on the parent's value
- # - Excess Blob Gas: Block's excess blob gas value depends on the parent's value
+ # - Excess Blob Gas: Block's excess blob gas value depends on
+ # the parent's value
kwargs: Dict[str, Any] = {
"number": self.env.number - 1,
"timestamp": 0,
@@ -208,11 +218,13 @@ def _generate_blockchain_genesis_environment(self, *, fork: Fork) -> Environment
)
if self.env.excess_blob_gas:
- # The excess blob gas environment value means the value of the context (block header)
- # where the transaction is executed. In a blockchain test, we need to indirectly
- # set the excess blob gas by setting the excess blob gas of the genesis block
- # to the expected value plus the TARGET_BLOB_GAS_PER_BLOCK, which is the value
- # that will be subtracted from the excess blob gas when the first block is mined.
+ # The excess blob gas environment value means the value of the
+ # context (block header) where the transaction is executed. In a
+ # blockchain test, we need to indirectly set the excess blob gas by
+ # setting the excess blob gas of the genesis block to the expected
+ # value plus the TARGET_BLOB_GAS_PER_BLOCK, which is the value that
+ # will be subtracted from the excess blob gas when the first block
+ # is mined.
kwargs["excess_blob_gas"] = self.env.excess_blob_gas + (
fork.target_blobs_per_block() * fork.blob_gas_per_blob()
)
@@ -220,7 +232,10 @@ def _generate_blockchain_genesis_environment(self, *, fork: Fork) -> Environment
return Environment(**kwargs)
def _generate_blockchain_blocks(self, *, fork: Fork) -> List[Block]:
- """Generate the single block that represents this state test in a BlockchainTest format."""
+ """
+ Generate the single block that represents this state test in a
+ BlockchainTest format.
+ """
kwargs = {
"number": self.env.number,
"timestamp": self.env.timestamp,
@@ -261,8 +276,9 @@ def make_state_test_fixture(
) -> StateFixture:
"""Create a fixture from the state test definition."""
# We can't generate a state test fixture that names a transition fork,
- # so we get the fork at the block number and timestamp of the state test
- fork = fork.fork_at(self.env.number, self.env.timestamp)
+ # so we get the fork at the block number and timestamp of the state
+ # test
+ fork = fork.fork_at(block_number=self.env.number, timestamp=self.env.timestamp)
env = self.env.set_fork_requirements(fork)
tx = self.tx.with_signature_and_sender(keep_secret_key=True)
@@ -315,8 +331,9 @@ def make_state_test_fixture(
assert base_tool_output.result.traces is not None, "Traces not found."
- # First try reducing the gas limit only by one, if the validation fails, it means
- # that the traces change even with the slightest modification to the gas.
+ # First try reducing the gas limit only by one, if the validation
+ # fails, it means that the traces change even with the slightest
+ # modification to the gas.
if self.verify_modified_gas_limit(
t8n=t8n,
base_tool_output=base_tool_output,
@@ -366,15 +383,16 @@ def make_state_test_fixture(
if self._operation_mode == OpMode.BENCHMARKING:
expected_benchmark_gas_used = self.expected_benchmark_gas_used
- gas_used = int(transition_tool_output.result.gas_used)
assert expected_benchmark_gas_used is not None, (
"expected_benchmark_gas_used is not set"
)
- assert gas_used == expected_benchmark_gas_used, (
- f"gas_used ({gas_used}) does not match expected_benchmark_gas_used "
- f"({expected_benchmark_gas_used})"
- f", difference: {gas_used - expected_benchmark_gas_used}"
- )
+ gas_used = int(transition_tool_output.result.gas_used)
+ if not self.skip_gas_used_validation:
+ assert gas_used == expected_benchmark_gas_used, (
+ f"gas_used ({gas_used}) does not match expected_benchmark_gas_used "
+ f"({expected_benchmark_gas_used})"
+ f", difference: {gas_used - expected_benchmark_gas_used}"
+ )
return StateFixture(
env=FixtureEnvironment(**env.model_dump(exclude_none=True)),
@@ -426,9 +444,15 @@ def execute(
) -> BaseExecute:
"""Generate the list of test fixtures."""
if execute_format == TransactionPost:
+ # Pass gas validation params for benchmark tests
+ # If not benchmark mode, skip gas used validation
+ if self._operation_mode != OpMode.BENCHMARKING:
+ self.skip_gas_used_validation = True
return TransactionPost(
blocks=[[self.tx]],
post=self.post,
+ expected_benchmark_gas_used=self.expected_benchmark_gas_used,
+ skip_gas_used_validation=self.skip_gas_used_validation,
)
raise Exception(f"Unsupported execute format: {execute_format}")
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/__init__.py b/packages/tests/src/ethereum_test_specs/static_state/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/__init__.py
rename to packages/tests/src/ethereum_test_specs/static_state/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/account.py b/packages/tests/src/ethereum_test_specs/static_state/account.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/account.py
rename to packages/tests/src/ethereum_test_specs/static_state/account.py
index 81f16cdee1..70f4ecbdea 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/account.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/account.py
@@ -2,7 +2,7 @@
from typing import Any, Dict, List, Mapping, Set, Tuple
-from pydantic import BaseModel
+from pydantic import BaseModel, ConfigDict
from ethereum_test_base_types import Bytes, EthereumTestRootModel, HexNumber, Storage
from ethereum_test_types import Alloc
@@ -54,11 +54,7 @@ class AccountInFiller(BaseModel, TagDependentData):
nonce: ValueInFiller | None = None
storage: StorageInPre | None = None
- class Config:
- """Model Config."""
-
- extra = "forbid"
- arbitrary_types_allowed = True # For CodeInFiller
+ model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
def tag_dependencies(self) -> Mapping[str, Tag]:
"""Get tag dependencies."""
@@ -169,7 +165,8 @@ def setup(self, pre: Alloc, all_dependencies: Dict[str, Tag]) -> TagDict:
# Step 3: Get topological order
resolution_order = self._topological_sort(dep_graph)
- # Step 4: Pre-deploy all contract tags and pre-fund EOAs to get addresses
+ # Step 4: Pre-deploy all contract tags and pre-fund EOAs to get
+ # addresses
for tag_name in resolution_order:
if tag_name in tag_to_address:
tag = tag_to_address[tag_name]
@@ -181,7 +178,8 @@ def setup(self, pre: Alloc, all_dependencies: Dict[str, Tag]) -> TagDict:
)
resolved_accounts[tag_name] = deployed_address
elif isinstance(tag, SenderTag):
- # Create EOA to get address - use amount=1 to ensure account is created
+ # Create EOA to get address - use amount=1 to ensure
+ # account is created
eoa = pre.fund_eoa(amount=1, label=tag_name)
# Store the EOA object for SenderKeyTag resolution
resolved_accounts[tag_name] = eoa
@@ -247,7 +245,8 @@ def setup(self, pre: Alloc, all_dependencies: Dict[str, Tag]) -> TagDict:
if all_dependencies[extra_dependency].type != "eoa":
raise ValueError(f"Contract dependency {extra_dependency} not found in pre")
- # Create new EOA - this will have a dynamically generated key and address
+ # Create new EOA - this will have a dynamically generated key
+ # and address
eoa = pre.fund_eoa(amount=0, label=extra_dependency)
resolved_accounts[extra_dependency] = eoa
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/__init__.py b/packages/tests/src/ethereum_test_specs/static_state/common/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/__init__.py
rename to packages/tests/src/ethereum_test_specs/static_state/common/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/common.py b/packages/tests/src/ethereum_test_specs/static_state/common/common.py
similarity index 92%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/common.py
rename to packages/tests/src/ethereum_test_specs/static_state/common/common.py
index 340f08971d..d10e6f254e 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/common.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/common/common.py
@@ -69,7 +69,8 @@ def validate_from_string(cls, code: Any) -> Any:
"""Validate from string, separating label from code source."""
if isinstance(code, str):
label_marker = ":label"
- # Only look for label at the beginning of the string (possibly after whitespace)
+ # Only look for label at the beginning of the string (possibly
+ # after whitespace)
stripped_code = code.lstrip()
# Parse :label into code options
@@ -123,7 +124,8 @@ def replace_tags(raw_code, keep_prefix: bool) -> str:
substitution_address = f"{tag.resolve(tags)}"
if not keep_prefix and substitution_address.startswith("0x"):
substitution_address = substitution_address[2:]
- # Use the original string if available, otherwise construct a pattern
+ # Use the original string if available, otherwise construct a
+ # pattern
if hasattr(tag, "original_string") and tag.original_string:
raw_code = raw_code.replace(tag.original_string, substitution_address)
else:
@@ -192,9 +194,11 @@ def replace_tags(raw_code, keep_prefix: bool) -> str:
[parameter_str],
[
[
- int(t.lower(), 0) & ((1 << 256) - 1) # treat big ints as 256bits
+ # treat big ints as 256bits
+ int(t.lower(), 0) & ((1 << 256) - 1)
if parameter_types[t_index] == "uint"
- else int(t.lower(), 0) > 0 # treat positive values as True
+ # treat positive values as True
+ else int(t.lower(), 0) > 0
if parameter_types[t_index] == "bool"
else False and ValueError("unhandled parameter_types")
for t_index, t in enumerate(tokens[1:])
@@ -217,15 +221,18 @@ def replace_tags(raw_code, keep_prefix: bool) -> str:
# - using lllc
result = subprocess.run(["lllc", tmp_path], capture_output=True, text=True)
- # - using docker:
- # If the running machine does not have lllc installed, we can use docker to
- # run lllc, but we need to start a container first, and the process is generally
- # slower.
+ # - using docker: If the running machine does not have lllc
+ # installed, we can use docker to run lllc, but we need to
+ # start a container first, and the process is generally slower.
+ #
# from .docker import get_lllc_container_id
- # result = subprocess.run(
- # ["docker", "exec", get_lllc_container_id(), "lllc", tmp_path[5:]],
+ # result = subprocess.run( ["docker",
+ # "exec",
+ # get_lllc_container_id(),
+ # "lllc",
+ # tmp_path[5:]],
# capture_output=True,
- # text=True,
+ # text=True
# )
compiled_code = "".join(result.stdout.splitlines())
@@ -245,15 +252,16 @@ def tag_dependencies(self) -> Mapping[str, Tag]:
class AddressTag:
"""
Represents an address tag like:
- - .
- - .
- - .
+ - .
+ - .
+ - .
"""
def __init__(self, tag_type: str, tag_name: str, original_string: str):
"""Initialize address tag."""
self.tag_type = tag_type # "eoa", "contract", or "coinbase"
- self.tag_name = tag_name # e.g., "sender", "target", or address for 2-part tags
+ # e.g., "sender", "target", or address for 2-part tags
+ self.tag_name = tag_name
self.original_string = original_string
def __str__(self) -> str:
@@ -317,8 +325,8 @@ def parse_address_or_tag(value: Any) -> Union[Address, AddressTag]:
def parse_address_or_tag_for_access_list(value: Any) -> Union[Address, str]:
"""
- Parse either a regular address or an address tag, keeping tags as strings for later
- resolution.
+ Parse either a regular address or an address tag, keeping tags as strings
+ for later resolution.
"""
if not isinstance(value, str):
# Non-string values should be converted to Address normally
@@ -344,7 +352,9 @@ def parse_address_or_tag_for_access_list(value: Any) -> Union[Address, str]:
class AccessListInFiller(CamelModel, TagDependentData):
- """Access List for transactions in fillers that can contain address tags."""
+ """
+ Access List for transactions in fillers that can contain address tags.
+ """
address: AddressOrTagInFiller
storage_keys: List[Hash] = Field(default_factory=list)
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/compile_yul.py b/packages/tests/src/ethereum_test_specs/static_state/common/compile_yul.py
similarity index 79%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/compile_yul.py
rename to packages/tests/src/ethereum_test_specs/static_state/common/compile_yul.py
index 6e548d46b2..632d0cd31a 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/compile_yul.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/common/compile_yul.py
@@ -51,19 +51,21 @@ def safe_solc_command(
def compile_yul(source_file: str, evm_version: str | None = None, optimize: str | None = None):
"""
- Compiles a Yul source file using solc and returns the binary representation.
+ Compiles a Yul source file using solc and returns the binary
+ representation.
- Parameters_:
- source_file (str): Path to the Yul source file.
- evm_version (str, optional): The EVM version to use (e.g., 'istanbul'). Defaults to None.
- optimize (any, optional): If provided (non-None), optimization flags are not added.
- If None, additional optimization flags will be included.
+ Arguments:
+ source_file (str): Path to the Yul source file.
+ evm_version(str, optional): The EVM version to use (e.g., 'istanbul').
+ Defaults to None.
+ optimize (any, optional): If provided (non-None), optimization flags
+ are not added. If None, additional
+ optimization flags will be included.
- Returns_:
- str: The binary representation prefixed with "0x".
+ Returns: str: The binary representation prefixed with "0x".
+
+ Raises: Exception: If the solc output contains an error message.
- Raises_:
- Exception: If the solc output contains an error message.
"""
cmd = safe_solc_command(source_file, evm_version, optimize)
@@ -77,7 +79,8 @@ def compile_yul(source_file: str, evm_version: str | None = None, optimize: str
if "Error" in out:
raise Exception(f"Yul compilation error:\n{out}")
- # Search for the "Binary representation:" line and get the following line as the binary
+ # Search for the "Binary representation:" line and get the following line
+ # as the binary
lines = out.splitlines()
binary_line = ""
for i, line in enumerate(lines):
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/tags.py b/packages/tests/src/ethereum_test_specs/static_state/common/tags.py
similarity index 92%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/tags.py
rename to packages/tests/src/ethereum_test_specs/static_state/common/tags.py
index d1c75dc888..100ae06107 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/tags.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/common/tags.py
@@ -20,7 +20,8 @@ class Tag(BaseModel, Generic[T]):
name: str
type: ClassVar[str] = ""
regex_pattern: ClassVar[re.Pattern] = re.compile(r"<\w+:(\w+)(:[^>]+)?")
- original_string: str | None = None # Store the original tag string for replacement
+ # Store the original tag string for replacement
+ original_string: str | None = None
def __hash__(self) -> int:
"""Hash based on original string for use as dict key."""
@@ -64,12 +65,18 @@ class ContractTag(AddressTag):
type: ClassVar[str] = "contract"
regex_pattern: ClassVar[re.Pattern] = re.compile(r"]+)(?::(0x[a-fA-F0-9]+))?>")
- debug_address: Address | None = None # Optional hard-coded address for debugging
+ # Optional hard-coded address for debugging
+ debug_address: Address | None = None
@model_validator(mode="before")
@classmethod
def validate_from_string(cls, data: Any) -> Any:
- """Validate the contract tag from string: or ."""
+ """
+ Validate the contract tag from string:
+
+ or
+ .
+ """
if isinstance(data, str):
if m := cls.regex_pattern.match(data):
name_or_addr = m.group(1)
@@ -77,8 +84,9 @@ def validate_from_string(cls, data: Any) -> Any:
# Check if it's a 2-part format with an address
if name_or_addr.startswith("0x") and len(name_or_addr) == 42:
- # For 2-part format, use the full address as the name
- # This ensures all references to the same address get the same tag name
+ # For 2-part format, use the full address as the name This
+ # ensures all references to the same address get the same
+ # tag name
return {
"name": name_or_addr,
"debug_address": Address(name_or_addr),
@@ -146,7 +154,8 @@ class SenderTag(AddressTag):
type: ClassVar[str] = "eoa"
regex_pattern: ClassVar[re.Pattern] = re.compile(r"")
- debug_address: Address | None = None # Optional hard-coded address for debugging
+ # Optional hard-coded address for debugging
+ debug_address: Address | None = None
@model_validator(mode="before")
@classmethod
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/environment.py b/packages/tests/src/ethereum_test_specs/static_state/environment.py
similarity index 95%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/environment.py
rename to packages/tests/src/ethereum_test_specs/static_state/environment.py
index 8ad5f09905..5f4525b0f6 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/environment.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/environment.py
@@ -2,7 +2,7 @@
from typing import Any, Dict
-from pydantic import BaseModel, Field, model_validator
+from pydantic import BaseModel, ConfigDict, Field, model_validator
from ethereum_test_base_types import Address
from ethereum_test_types import Environment
@@ -26,10 +26,7 @@ class EnvironmentInStateTestFiller(BaseModel):
current_excess_blob_gas: ValueInFiller | None = Field(None, alias="currentExcessBlobGas")
- class Config:
- """Model Config."""
-
- extra = "forbid"
+ model_config = ConfigDict(extra="forbid")
@model_validator(mode="after")
def check_fields(self) -> "EnvironmentInStateTestFiller":
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/expect_section.py b/packages/tests/src/ethereum_test_specs/static_state/expect_section.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/expect_section.py
rename to packages/tests/src/ethereum_test_specs/static_state/expect_section.py
index 226b3311be..ccd7f7aa45 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/expect_section.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/expect_section.py
@@ -106,7 +106,10 @@ class AccountInExpectSection(BaseModel, TagDependentData):
@model_validator(mode="wrap")
@classmethod
def validate_should_not_exist(cls, v: Any, handler: ValidatorFunctionWrapHandler):
- """Validate the "shouldnotexist" field, which makes this validator return `None`."""
+ """
+ Validate the "shouldnotexist" field, which makes this validator return
+ `None`.
+ """
if isinstance(v, dict):
if "shouldnotexist" in v:
return None
@@ -251,8 +254,8 @@ class ResultInFiller(EthereumTestRootModel, TagDependentData):
"""
Post section in state test filler.
- A value of `None` for an address means that the account should not be in the state trie
- at the end of the test.
+ A value of `None` for an address means that the account should not be in
+ the state trie at the end of the test.
"""
root: Dict[AddressOrCreateTagInFiller, AccountInExpectSection | None]
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/general_transaction.py b/packages/tests/src/ethereum_test_specs/static_state/general_transaction.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/general_transaction.py
rename to packages/tests/src/ethereum_test_specs/static_state/general_transaction.py
index e3e44be62e..7a649fc9de 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/general_transaction.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/general_transaction.py
@@ -2,7 +2,7 @@
from typing import Any, Dict, Generator, List, Mapping
-from pydantic import BaseModel, Field, field_validator, model_validator
+from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
from ethereum_test_base_types import Address, CamelModel, EthereumTestRootModel, Hash
from ethereum_test_exceptions import TransactionExceptionInstanceOrList
@@ -86,7 +86,9 @@ def __getitem__(self, label_or_index: int | str):
raise KeyError(f"Label/index {label_or_index} not found in data indexes")
def __contains__(self, label_or_index: int | str):
- """Return True if the LabeledDataList contains the given label/index."""
+ """
+ Return True if the LabeledDataList contains the given label/index.
+ """
if isinstance(label_or_index, int):
return label_or_index < len(self.root)
if isinstance(label_or_index, str):
@@ -125,10 +127,7 @@ class GeneralTransactionInFiller(BaseModel, TagDependentData):
max_fee_per_blob_gas: ValueInFiller | None = Field(None, alias="maxFeePerBlobGas")
blob_versioned_hashes: List[Hash] | None = Field(None, alias="blobVersionedHashes")
- class Config:
- """Model Config."""
-
- extra = "forbid"
+ model_config = ConfigDict(extra="forbid")
def tag_dependencies(self) -> Mapping[str, Tag]:
"""Get tag dependencies."""
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/state_static.py b/packages/tests/src/ethereum_test_specs/static_state/state_static.py
similarity index 95%
rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/state_static.py
rename to packages/tests/src/ethereum_test_specs/static_state/state_static.py
index 7801d404b9..3f77eca94c 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/static_state/state_static.py
+++ b/packages/tests/src/ethereum_test_specs/static_state/state_static.py
@@ -4,7 +4,7 @@
import pytest
from _pytest.mark.structures import ParameterSet
-from pydantic import BaseModel, Field, model_validator
+from pydantic import BaseModel, ConfigDict, Field, model_validator
from ethereum_test_forks import Fork
from ethereum_test_types import Alloc
@@ -37,10 +37,7 @@ class StateStaticTest(BaseStaticTest):
transaction: GeneralTransactionInFiller
expect: List[ExpectSectionInStateTestFiller]
- class Config:
- """Model Config."""
-
- extra = "forbid"
+ model_config = ConfigDict(extra="forbid")
def model_post_init(self, context):
"""Initialize StateStaticTest."""
@@ -69,7 +66,9 @@ def parse_indexes(
indexes: Union[int, str, list[Union[int, str]], list[str], list[int]],
do_hint: bool = False,
) -> List[int] | int:
- """Parse indexes and replace all ranges and labels into tx indexes."""
+ """
+ Parse indexes and replace all ranges and labels into tx indexes.
+ """
result: List[int] | int = []
if do_hint:
@@ -129,8 +128,9 @@ def fill_function(self) -> Callable:
for expect in self.expect:
if expect.has_index(d.index, g, v) and expect.expect_exception is not None:
exception_test = True
- # TODO: This does not take into account exceptions that only happen on
- # specific forks, but this requires a covariant parametrize
+ # TODO: This does not take into account exceptions that
+ # only happen on specific forks, but this requires a
+ # covariant parametrize
marks = [pytest.mark.exception_test] if exception_test else []
id_label = ""
if len(self.transaction.data) > 1 or d.label is not None:
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/__init__.py b/packages/tests/src/ethereum_test_specs/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/__init__.py
rename to packages/tests/src/ethereum_test_specs/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json
rename to packages/tests/src/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/helpers.py b/packages/tests/src/ethereum_test_specs/tests/helpers.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/helpers.py
rename to packages/tests/src/ethereum_test_specs/tests/helpers.py
diff --git a/packages/tests/src/ethereum_test_specs/tests/test_benchmark.py b/packages/tests/src/ethereum_test_specs/tests/test_benchmark.py
new file mode 100644
index 0000000000..6511e427fc
--- /dev/null
+++ b/packages/tests/src/ethereum_test_specs/tests/test_benchmark.py
@@ -0,0 +1,112 @@
+"""
+Tests for the BenchmarkTest class and its
+transaction splitting functionality.
+"""
+
+import pytest
+
+from ethereum_test_base_types import HexNumber
+from ethereum_test_specs.benchmark import BenchmarkTest
+from ethereum_test_types import Alloc, Environment, Transaction
+
+
+@pytest.mark.parametrize(
+ "gas_benchmark_value_millions,expected_splits",
+ [
+ (1, 1), # 1M / 16M = 1 transaction
+ (10, 1), # 10M / 16M = 1 transaction
+ (30, 2), # 30M / 16M = 2 transactions (16M + 14M)
+ (45, 3), # 45M / 16M = 3 transactions (16M + 16M + 13M)
+ (60, 4), # 60M / 16M = 4 transactions (16M + 16M + 16M + 12M)
+ (100, 7), # 100M / 16M = 7 transactions (6x16M + 4M)
+ (150, 10), # 150M / 16M = 10 transactions (9x16M + 6M)
+ ],
+)
+def test_split_transaction(gas_benchmark_value_millions: int, expected_splits: int):
+ """
+ Test that transaction splitting works
+ correctly for Osaka fork gas cap.
+ """
+ gas_benchmark_value = gas_benchmark_value_millions * 1_000_000
+ gas_limit_cap = 16_000_000 # Osaka's transaction gas limit cap
+
+ # Create a minimal BenchmarkTest instance
+ benchmark_test = BenchmarkTest(
+ pre=Alloc(),
+ post=Alloc(),
+ tx=Transaction(sender=HexNumber(0), to=HexNumber(0), nonce=0),
+ env=Environment(),
+ gas_benchmark_value=gas_benchmark_value,
+ )
+
+ # Test the split_transaction method
+ assert benchmark_test.tx is not None, "Transaction should not be None"
+ split_txs = benchmark_test.split_transaction(benchmark_test.tx, gas_limit_cap)
+
+ # Verify the number of transactions
+ assert len(split_txs) == expected_splits, (
+ f"Expected {expected_splits} transactions for {gas_benchmark_value_millions}M gas, "
+ f"got {len(split_txs)}"
+ )
+
+ # Verify total gas equals the benchmark value
+ total_gas = sum(tx.gas_limit for tx in split_txs)
+ assert total_gas == gas_benchmark_value, (
+ f"Total gas {total_gas} doesn't match benchmark value {gas_benchmark_value}"
+ )
+
+ # Verify no transaction exceeds the cap
+ for i, tx in enumerate(split_txs):
+ assert tx.gas_limit <= gas_limit_cap, (
+ f"Transaction {i} gas limit {tx.gas_limit} exceeds cap {gas_limit_cap}"
+ )
+
+ # Verify nonces increment correctly
+ for i, tx in enumerate(split_txs):
+ assert tx.nonce == i, f"Transaction {i} has incorrect nonce {tx.nonce}"
+
+ # Verify gas distribution
+ for i, tx in enumerate(split_txs[:-1]): # All but last should be at cap
+ assert tx.gas_limit == gas_limit_cap, (
+ f"Transaction {i} should have gas limit {gas_limit_cap}, got {tx.gas_limit}"
+ )
+
+ # Last transaction should have the remainder
+ if expected_splits > 1:
+ expected_last_gas = gas_benchmark_value - (gas_limit_cap * (expected_splits - 1))
+ assert split_txs[-1].gas_limit == expected_last_gas, (
+ f"Last transaction should have {expected_last_gas} gas, got {split_txs[-1].gas_limit}"
+ )
+
+
+@pytest.mark.parametrize(
+ "gas_benchmark_value,gas_limit_cap",
+ [
+ (50_000_000, None), # No cap - should return single transaction
+ (50_000_000, 100_000_000), # Cap higher than benchmark value
+ ],
+)
+def test_split_transaction_edge_cases(gas_benchmark_value: int, gas_limit_cap: int | None):
+ """Test edge cases for transaction splitting."""
+ benchmark_test = BenchmarkTest(
+ pre=Alloc(),
+ post=Alloc(),
+ tx=Transaction(sender=HexNumber(0), to=HexNumber(0), nonce=0, gas_limit=1_000_000_000),
+ env=Environment(),
+ gas_benchmark_value=gas_benchmark_value,
+ )
+
+ assert benchmark_test.tx is not None, "Transaction should not be None"
+ split_txs = benchmark_test.split_transaction(benchmark_test.tx, gas_limit_cap)
+
+ # Should return single transaction in both cases
+ assert len(split_txs) == 1, f"Expected 1 transaction, got {len(split_txs)}"
+
+ if gas_limit_cap is None:
+ # When no cap, gas_limit should be benchmark value
+ assert split_txs[0].gas_limit == gas_benchmark_value
+ else:
+ # When cap > benchmark, gas_limit should be
+ # min of tx.gas_limit and benchmark
+ assert benchmark_test.tx is not None, "Transaction should not be None"
+ assert split_txs[0].gas_limit == min(benchmark_test.tx.gas_limit, gas_benchmark_value)
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_expect.py b/packages/tests/src/ethereum_test_specs/tests/test_expect.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_expect.py
rename to packages/tests/src/ethereum_test_specs/tests/test_expect.py
index 9f2b00acaf..0009064fc1 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_expect.py
+++ b/packages/tests/src/ethereum_test_specs/tests/test_expect.py
@@ -118,7 +118,10 @@ def state_test( # noqa: D103
indirect=["pre", "post"],
)
def test_post_storage_value_mismatch(expected_exception, state_test, default_t8n, fork):
- """Test post state `Account.storage` exceptions during state test fixture generation."""
+ """
+ Test post state `Account.storage` exceptions during state test fixture
+ generation.
+ """
with pytest.raises(Storage.KeyValueMismatchError) as e_info:
state_test.generate(t8n=default_t8n, fork=fork, fixture_format=StateFixture)
assert e_info.value == expected_exception
@@ -136,8 +139,8 @@ def test_post_storage_value_mismatch(expected_exception, state_test, default_t8n
)
def test_post_nonce_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t8n, fork):
"""
- Test post state `Account.nonce` verification and exceptions during state test
- fixture generation.
+ Test post state `Account.nonce` verification and exceptions during state
+ test fixture generation.
"""
pre_account = pre[ADDRESS_UNDER_TEST]
post_account = post[ADDRESS_UNDER_TEST]
@@ -167,8 +170,8 @@ def test_post_nonce_value_mismatch(pre: Alloc, post: Alloc, state_test, default_
)
def test_post_code_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t8n, fork):
"""
- Test post state `Account.code` verification and exceptions during state test
- fixture generation.
+ Test post state `Account.code` verification and exceptions during state
+ test fixture generation.
"""
pre_account = pre[ADDRESS_UNDER_TEST]
post_account = post[ADDRESS_UNDER_TEST]
@@ -198,8 +201,8 @@ def test_post_code_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t
)
def test_post_balance_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t8n, fork):
"""
- Test post state `Account.balance` verification and exceptions during state test
- fixture generation.
+ Test post state `Account.balance` verification and exceptions during state
+ test fixture generation.
"""
pre_account = pre[ADDRESS_UNDER_TEST]
post_account = post[ADDRESS_UNDER_TEST]
@@ -332,8 +335,8 @@ def test_transaction_expectation(
fixture_format: FixtureFormat,
):
"""
- Test a transaction that has an unexpected error, expected error, or expected a specific
- value in its receipt.
+ Test a transaction that has an unexpected error, expected error, or
+ expected a specific value in its receipt.
"""
if (
exception_type == ExecutionExceptionMismatchError
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_fixtures.py b/packages/tests/src/ethereum_test_specs/tests/test_fixtures.py
similarity index 99%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_fixtures.py
rename to packages/tests/src/ethereum_test_specs/tests/test_fixtures.py
index 665b37b067..45afb3864c 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_fixtures.py
+++ b/packages/tests/src/ethereum_test_specs/tests/test_fixtures.py
@@ -42,8 +42,8 @@ def fixture_hash(fork: Fork) -> bytes:
def test_check_helper_fixtures():
"""
Test that the framework's pydantic models serialization and deserialization
- work correctly and that they are compatible with the helper fixtures defined
- in ./fixtures/ by using the check_fixtures.py script.
+ work correctly and that they are compatible with the helper fixtures
+ defined in ./fixtures/ by using the check_fixtures.py script.
"""
runner = CliRunner()
args = [
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_transaction.py b/packages/tests/src/ethereum_test_specs/tests/test_transaction.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_transaction.py
rename to packages/tests/src/ethereum_test_specs/tests/test_transaction.py
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_types.py b/packages/tests/src/ethereum_test_specs/tests/test_types.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_types.py
rename to packages/tests/src/ethereum_test_specs/tests/test_types.py
diff --git a/src/ethereum_spec_tests/ethereum_test_specs/transaction.py b/packages/tests/src/ethereum_test_specs/transaction.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_specs/transaction.py
rename to packages/tests/src/ethereum_test_specs/transaction.py
index 0dbf927201..0511891e57 100644
--- a/src/ethereum_spec_tests/ethereum_test_specs/transaction.py
+++ b/packages/tests/src/ethereum_test_specs/transaction.py
@@ -23,7 +23,9 @@
class TransactionTest(BaseTest):
- """Filler type that tests the transaction over the period of a single block."""
+ """
+ Filler type that tests the transaction over the period of a single block.
+ """
tx: Transaction
pre: Alloc | None = None
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/__init__.py b/packages/tests/src/ethereum_test_tools/__init__.py
similarity index 91%
rename from src/ethereum_spec_tests/ethereum_test_tools/__init__.py
rename to packages/tests/src/ethereum_test_tools/__init__.py
index 18fa9543ec..9625cb2da9 100644
--- a/src/ethereum_spec_tests/ethereum_test_tools/__init__.py
+++ b/packages/tests/src/ethereum_test_tools/__init__.py
@@ -16,6 +16,11 @@
TestPrivateKey2,
)
from ethereum_test_base_types.reference_spec import ReferenceSpec, ReferenceSpecTypes
+from ethereum_test_benchmark import (
+ BenchmarkCodeGenerator,
+ ExtCallGenerator,
+ JumpLoopGenerator,
+)
from ethereum_test_exceptions import (
BlockException,
EngineAPIError,
@@ -25,6 +30,8 @@
from ethereum_test_fixtures import BaseFixture, FixtureCollector
from ethereum_test_specs import (
BaseTest,
+ BenchmarkTest,
+ BenchmarkTestFiller,
BlobsTest,
BlobsTestFiller,
BlockchainTest,
@@ -75,6 +82,7 @@
EVMCodeType,
Macro,
Macros,
+ MemoryVariable,
Opcode,
OpcodeCallArg,
Opcodes,
@@ -82,7 +90,7 @@
call_return_code,
)
-from .code import (
+from .tools_code import (
CalldataCase,
Case,
CodeGasMeasure,
@@ -112,6 +120,9 @@
"BalStorageSlot",
"BaseFixture",
"BaseTest",
+ "BenchmarkCodeGenerator",
+ "BenchmarkTest",
+ "BenchmarkTestFiller",
"Blob",
"BlockAccessList",
"BlobsTest",
@@ -128,6 +139,7 @@
"CodeGasMeasure",
"Conditional",
"ConsolidationRequest",
+ "ExtCallGenerator",
"DeploymentTestType",
"DepositRequest",
"EngineAPIError",
@@ -143,8 +155,10 @@
"Hash",
"Header",
"Initcode",
+ "JumpLoopGenerator",
"Macro",
"Macros",
+ "MemoryVariable",
"NetworkWrappedTransaction",
"Opcode",
"OpcodeCallArg",
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/py.typed b/packages/tests/src/ethereum_test_tools/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_tools/py.typed
rename to packages/tests/src/ethereum_test_tools/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/tests/__init__.py b/packages/tests/src/ethereum_test_tools/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_tools/tests/__init__.py
rename to packages/tests/src/ethereum_test_tools/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/tests/test_code.py b/packages/tests/src/ethereum_test_tools/tests/test_code.py
similarity index 98%
rename from src/ethereum_spec_tests/ethereum_test_tools/tests/test_code.py
rename to packages/tests/src/ethereum_test_tools/tests/test_code.py
index 48465367dd..37040cfbb2 100644
--- a/src/ethereum_spec_tests/ethereum_test_tools/tests/test_code.py
+++ b/packages/tests/src/ethereum_test_tools/tests/test_code.py
@@ -22,7 +22,7 @@
from ethereum_test_vm import UndefinedOpcodes
from pytest_plugins.solc.solc import SOLC_EXPECTED_MIN_VERSION
-from ..code import CalldataCase, Case, Conditional, Initcode, Switch
+from ..tools_code import CalldataCase, Case, Conditional, Initcode, Switch
@pytest.fixture(params=get_deployed_forks())
@@ -185,7 +185,9 @@ def test_initcode(initcode: Initcode, bytecode: bytes): # noqa: D103
],
)
def test_opcodes_if(conditional_bytecode: bytes, expected: bytes):
- """Test that the if opcode macro is transformed into bytecode as expected."""
+ """
+ Test that the if opcode macro is transformed into bytecode as expected.
+ """
assert bytes(conditional_bytecode) == expected
@@ -514,7 +516,9 @@ def test_opcodes_if(conditional_bytecode: bytes, expected: bytes):
def test_switch(
tx_data: bytes, switch_bytecode: bytes, expected_storage: Mapping, default_t8n: TransitionTool
):
- """Test that the switch opcode macro gets executed as using the t8n tool."""
+ """
+ Test that the switch opcode macro gets executed as using the t8n tool.
+ """
code_address = Address(0x1000)
pre = Alloc(
{
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json b/packages/tests/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json
rename to packages/tests/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/code/__init__.py b/packages/tests/src/ethereum_test_tools/tools_code/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_tools/code/__init__.py
rename to packages/tests/src/ethereum_test_tools/tools_code/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/code/generators.py b/packages/tests/src/ethereum_test_tools/tools_code/generators.py
similarity index 86%
rename from src/ethereum_spec_tests/ethereum_test_tools/code/generators.py
rename to packages/tests/src/ethereum_test_tools/tools_code/generators.py
index 7af682ab6c..350eb9b0f3 100644
--- a/src/ethereum_spec_tests/ethereum_test_tools/code/generators.py
+++ b/packages/tests/src/ethereum_test_tools/tools_code/generators.py
@@ -18,12 +18,11 @@ class Initcode(Bytecode):
The execution gas cost of the initcode is calculated, and also the
deployment gas costs for the deployed code.
- The initcode can be padded to a certain length if necessary, which
- does not affect the deployed code.
+ The initcode can be padded to a certain length if necessary, which does not
+ affect the deployed code.
- Other costs such as the CREATE2 hashing costs or the initcode_word_cost
- of EIP-3860 are *not* taken into account by any of these calculated
- costs.
+ Other costs such as the CREATE2 hashing costs or the initcode_word_cost of
+ EIP-3860 are *not* taken into account by any of these calculated costs.
"""
deploy_code: SupportsBytes | Bytes
@@ -131,8 +130,8 @@ class CodeGasMeasure(Bytecode):
"""
Helper class used to generate bytecode that measures gas usage of a
bytecode, taking into account and subtracting any extra overhead gas costs
- required to execute.
- By default, the result gas calculation is saved to storage key 0.
+ required to execute. By default, the result gas calculation is saved to
+ storage key 0.
"""
code: Bytecode
@@ -199,8 +198,8 @@ def __new__(
):
"""
Assemble the conditional bytecode by generating the necessary jump and
- jumpdest opcodes surrounding the condition and the two possible execution
- paths.
+ jumpdest opcodes surrounding the condition and the two possible
+ execution paths.
In the future, PC usage should be replaced by using RJUMP and RJUMPI
"""
@@ -213,15 +212,16 @@ def __new__(
# First we append a jumpdest to the start of the true branch
if_true = Op.JUMPDEST + if_true
- # Then we append the unconditional jump to the end of the false branch, used to skip
- # the true branch
+ # Then we append the unconditional jump to the end of the false
+ # branch, used to skip the true branch
if_false += Op.JUMP(Op.ADD(Op.PC, len(if_true) + 3))
- # Then we need to do the conditional jump by skipping the false branch
+ # Then we need to do the conditional jump by skipping the false
+ # branch
condition = Op.JUMPI(Op.ADD(Op.PC, len(if_false) + 3), condition)
- # Finally we append the condition, false and true branches, plus the jumpdest at the
- # very end
+ # Finally we append the condition, false and true branches, plus
+ # the jumpdest at the very end
bytecode = condition + if_false + if_true + Op.JUMPDEST
elif evm_code_type == EVMCodeType.EOF_V1:
@@ -284,8 +284,8 @@ def is_terminating(self) -> bool:
class CalldataCase(Case):
"""
- Small helper class to represent a single case whose condition depends
- on the value of the contract's calldata in a Switch case statement.
+ Small helper class to represent a single case whose condition depends on
+ the value of the contract's calldata in a Switch case statement.
By default the calldata is read from position zero, but this can be
overridden using `position`.
@@ -305,12 +305,14 @@ class Switch(Bytecode):
Helper class used to generate switch-case expressions in EVM bytecode.
Switch-case behavior:
- - If no condition is met in the list of BytecodeCases conditions,
- the `default_action` bytecode is executed.
- - If multiple conditions are met, the action from the first valid
- condition is the only one executed.
- - There is no fall through; it is not possible to execute multiple
- actions.
+ - If no condition is met in the list of BytecodeCases
+ conditions, the `default_action` bytecode is executed.
+
+ - If multiple conditions are met, the action from the first valid
+ condition is the only one executed.
+
+ - There is no fall through; it is not possible to execute
+ multiple actions.
"""
default_action: Bytecode | Op | None
@@ -338,55 +340,57 @@ def __new__(
evm_code_type: EVMCodeType = EVMCodeType.LEGACY,
):
"""
- Assemble the bytecode by looping over the list of cases and adding
- the necessary [R]JUMPI and JUMPDEST opcodes in order to replicate
+ Assemble the bytecode by looping over the list of cases and adding the
+ necessary [R]JUMPI and JUMPDEST opcodes in order to replicate
switch-case behavior.
"""
- # The length required to jump over subsequent actions to the final JUMPDEST at the end
- # of the switch-case block:
- # - add 6 per case for the length of the JUMPDEST and JUMP(ADD(PC, action_jump_length))
- # bytecode
- # - add 3 to the total to account for this action's JUMP; the PC within the call
- # requires a "correction" of 3.
+ # The length required to jump over subsequent actions to the final
+ # JUMPDEST at the end of the switch-case block:
+ # - add 6 per case for the length of the JUMPDEST and
+ # JUMP(ADD(PC, action_jump_length)) bytecode
+ #
+ # - add 3 to the total to account for this action's JUMP;
+ # the PC within the call requires a "correction" of 3.
bytecode = Bytecode()
- # All conditions get prepended to this bytecode; if none are met, we reach the default
+ # All conditions get prepended to this bytecode; if none are met, we
+ # reach the default
if evm_code_type == EVMCodeType.LEGACY:
action_jump_length = sum(len(case.action) + 6 for case in cases) + 3
bytecode = default_action + Op.JUMP(Op.ADD(Op.PC, action_jump_length))
- # The length required to jump over the default action and its JUMP bytecode
+ # The length required to jump over the default action and its JUMP
+ # bytecode
condition_jump_length = len(bytecode) + 3
elif evm_code_type == EVMCodeType.EOF_V1:
action_jump_length = sum(
len(case.action) + (len(Op.RJUMP[0]) if not case.is_terminating else 0)
for case in cases
- # On not terminating cases, we need to add 3 bytes for the RJUMP
+ # On not terminating cases, we need to add 3 bytes for the
+ # RJUMP
)
bytecode = default_action + Op.RJUMP[action_jump_length]
- # The length required to jump over the default action and its JUMP bytecode
+ # The length required to jump over the default action and its JUMP
+ # bytecode
condition_jump_length = len(bytecode)
- # Reversed: first case in the list has priority; it will become the outer-most onion layer.
- # We build up layers around the default_action, after 1 iteration of the loop, a simplified
- # representation of the bytecode is:
+ # Reversed: first case in the list has priority; it will become the
+ # outer-most onion layer. We build up layers around the default_action,
+ # after 1 iteration of the loop, a simplified representation of the
+ # bytecode is:
#
- # JUMPI(case[n-1].condition)
- # + default_action + JUMP()
- # + JUMPDEST + case[n-1].action + JUMP()
+ # JUMPI(case[n-1].condition)
+ # + default_action + JUMP()
+ # + JUMPDEST + case[n-1].action + JUMP()
#
# and after n=len(cases) iterations:
#
- # JUMPI(case[0].condition)
- # + JUMPI(case[1].condition)
- # ...
- # + JUMPI(case[n-1].condition)
- # + default_action + JUMP()
- # + JUMPDEST + case[n-1].action + JUMP()
- # + ...
- # + JUMPDEST + case[1].action + JUMP()
- # + JUMPDEST + case[0].action + JUMP()
- #
+ # JUMPI(case[0].condition)
+ # + JUMPI(case[1].condition)
+ # ...
+ # + JUMPI(case[n-1].condition) + default_action + JUMP() + JUMPDEST +
+ # case[n-1].action + JUMP() + ... + JUMPDEST + case[1].action + JUMP()
+ # + JUMPDEST + case[0].action + JUMP()
for case in reversed(cases):
action = case.action
if evm_code_type == EVMCodeType.LEGACY:
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/code/yul.py b/packages/tests/src/ethereum_test_tools/tools_code/yul.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_tools/code/yul.py
rename to packages/tests/src/ethereum_test_tools/tools_code/yul.py
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/__init__.py b/packages/tests/src/ethereum_test_tools/utility/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_tools/utility/__init__.py
rename to packages/tests/src/ethereum_test_tools/utility/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/generators.py b/packages/tests/src/ethereum_test_tools/utility/generators.py
similarity index 77%
rename from src/ethereum_spec_tests/ethereum_test_tools/utility/generators.py
rename to packages/tests/src/ethereum_test_tools/utility/generators.py
index 95c9094e91..f155cb3ba4 100644
--- a/src/ethereum_spec_tests/ethereum_test_tools/utility/generators.py
+++ b/packages/tests/src/ethereum_test_tools/utility/generators.py
@@ -43,7 +43,10 @@ def param(self):
class ContractAddressHasBalance(StrEnum):
- """Represents whether the target deployment test has a balance before deployment."""
+ """
+ Represents whether the target deployment test has a balance before
+ deployment.
+ """
ZERO_BALANCE = "zero_balance"
NONZERO_BALANCE = "nonzero_balance"
@@ -51,8 +54,8 @@ class ContractAddressHasBalance(StrEnum):
class SystemContractDeployTestFunction(Protocol):
"""
- Represents a function to be decorated with the `generate_system_contract_deploy_test`
- decorator.
+ Represents a function to be decorated with the
+ `generate_system_contract_deploy_test` decorator.
"""
def __call__(
@@ -64,19 +67,21 @@ def __call__(
test_type: DeploymentTestType,
) -> Generator[Block, None, None]:
"""
- Args:
- fork (Fork): The fork to test.
- pre (Alloc): The pre state of the blockchain.
- post (Alloc): The post state of the blockchain.
- test_type (DeploymentTestType): The type of deployment test currently being filled.
+ Arguments:
+ fork (Fork): The fork to test.
+ pre (Alloc): The pre state of the blockchain.
+ post (Alloc): The post state of the blockchain.
+ test_type(DeploymentTestType): The type of deployment test
+ currently being filled.
Yields:
- Block: To add after the block where the contract was deployed (e.g. can contain extra
- transactions to execute after the system contract has been deployed, and/or a header
- object to verify that the headers are correct).
+ Block: To add after the block where the contract was deployed
+ (e.g. can contain extra transactions to execute after
+ the system contract has been deployed, and/or a header
+ object to verify that the headers are correct).
"""
- ...
+ pass
def generate_system_contract_deploy_test(
@@ -92,27 +97,44 @@ def generate_system_contract_deploy_test(
Generates following test cases:
- | before/after fork | fail on | invalid block |
- | | empty block | |
- --------------------------------------|-------------------|-------------|---------------|
- `deploy_before_fork-nonzero_balance` | before | False | False |
- `deploy_before_fork-zero_balance` | before | True | False |
- `deploy_on_fork_block-nonzero_balance`| on fork block | False | False |
- `deploy_on_fork_block-zero_balance` | on fork block | True | False |
- `deploy_after_fork-nonzero_balance` | after | False | False |
- `deploy_after_fork-zero_balance` | after | True | True |
-
- The `has balance` parametrization does not have an effect on the expectation of the test.
-
- Args:
- fork (Fork): The fork to test.
- tx_json_path (Path): Path to the JSON file with the transaction to deploy the system
- contract.
- Providing a JSON file is useful to copy-paste the transaction from the EIP.
- expected_deploy_address (Address): The expected address of the deployed contract.
- fail_on_empty_code (bool): If True, the test is expected to fail on empty code.
- expected_system_contract_storage (Dict | None): The expected storage of the system
- contract.
+ | before/after fork | fail on | invalid block |
+ empty block | |
+ --------------------|-------------------|--------------|----------------|
+ `deploy_before_fork-| before | False | False |
+ nonzero_balance`
+
+ `deploy_before_fork-| before | True | False |
+ zero_balance`
+
+ `deploy_on_fork_ | on fork block | False | False |
+ block-nonzero_
+ balance`
+
+ `deploy_on_fork_ | on fork block | True | False |
+ block-zero_balance`
+
+ `deploy_after_fork | after | False | False |
+ -nonzero_balance`
+
+ `deploy_after_fork | after | True | True |
+ -zero_balance`
+
+
+ The `has balance` parametrization does not have an effect on the
+ expectation of the test.
+
+ Arguments:
+ fork (Fork): The fork to test.
+ tx_json_path (Path): Path to the JSON file with the transaction to
+ deploy the system contract. Providing a JSON
+ file is useful to copy-paste the transaction
+ from the EIP.
+ expected_deploy_address (Address): The expected address of the deployed
+ contract.
+ fail_on_empty_code (bool): If True, the test is expected to fail
+ on empty code.
+ expected_system_contract_storage (Dict | None): The expected storage of
+ the system contract.
"""
with open(tx_json_path, mode="r") as f:
@@ -213,7 +235,8 @@ def wrapper(
)
balance = 1 if has_balance == ContractAddressHasBalance.NONZERO_BALANCE else 0
pre[expected_deploy_address] = Account(
- code=b"", # Remove the code that is automatically allocated on the fork
+ code=b"", # Remove the code that is automatically allocated on
+ # the fork
nonce=0,
balance=balance,
)
@@ -227,7 +250,8 @@ def wrapper(
fork_pre_allocation = fork.pre_allocation_blockchain()
assert expected_deploy_address_int in fork_pre_allocation
expected_code = fork_pre_allocation[expected_deploy_address_int]["code"]
- # Note: balance check is omitted; it may be modified by the underlying, decorated test
+ # Note: balance check is omitted; it may be modified by the
+ # underlying, decorated test
account_kwargs = {
"code": expected_code,
"nonce": 1,
@@ -240,8 +264,8 @@ def wrapper(
nonce=1,
)
- # Extra blocks (if any) returned by the decorated function to add after the
- # contract is deployed.
+ # Extra blocks (if any) returned by the decorated function to add
+ # after the contract is deployed.
if test_type != DeploymentTestType.DEPLOY_AFTER_FORK or not fail_on_empty_code:
# Only fill more blocks if the deploy block does not fail.
blocks += list(func(fork=fork, pre=pre, post=post, test_type=test_type))
@@ -265,14 +289,15 @@ def generate_system_contract_error_test(
max_gas_limit: int,
):
"""
- Generate a test that verifies the correct behavior when a system contract fails execution.
+ Generate a test that verifies the correct behavior when a system contract
+ fails execution.
Parametrizations required:
- - system_contract (Address): The address of the system contract to deploy.
- - valid_from (Fork): The fork from which the test is valid.
+ - system_contract (Address): The address of the system contract to deploy.
+ - valid_from (Fork): The fork from which the test is valid.
- Args:
- max_gas_limit (int): The maximum gas limit for the system transaction.
+ Arguments:
+ max_gas_limit (int): The maximum gas limit for the system transaction.
"""
@@ -288,25 +313,27 @@ def wrapper(
):
modified_system_contract_code = Bytecode()
- # Depending on the test case, we need to modify the system contract code accordingly.
+ # Depending on the test case, we need to modify the system contract
+ # code accordingly.
if (
test_type == SystemContractTestType.GAS_LIMIT
or test_type == SystemContractTestType.OUT_OF_GAS_ERROR
):
# Run code so that it reaches the gas limit.
gas_costs = fork.gas_costs()
- # The code works by storing N values to storage, and N is calculated based on the
- # gas costs for the given fork.
- # This code will only work once, so if the system contract is re-executed
- # in a subsequent block, it will consume less gas.
+ # The code works by storing N values to storage, and N is
+ # calculated based on the gas costs for the given fork. This
+ # code will only work once, so if the system contract is re-
+ # executed in a subsequent block, it will consume less gas.
gas_used_per_storage = (
gas_costs.G_STORAGE_SET + gas_costs.G_COLD_SLOAD + (gas_costs.G_VERY_LOW * 2)
)
modified_system_contract_code += sum(
Op.SSTORE(i, 1) for i in range(max_gas_limit // gas_used_per_storage)
)
- # If the gas limit is not divisible by the gas used per storage, we need to add
- # some NO-OP (JUMPDEST) to the code that each consume 1 gas.
+ # If the gas limit is not divisible by the gas used per
+ # storage, we need to add some NO-OP (JUMPDEST) to the code
+ # that each consume 1 gas.
assert gas_costs.G_JUMPDEST == 1, (
f"JUMPDEST gas cost should be 1, but got {gas_costs.G_JUMPDEST}. "
"Generator `generate_system_contract_error_test` needs to be updated."
@@ -316,8 +343,9 @@ def wrapper(
)
if test_type == SystemContractTestType.OUT_OF_GAS_ERROR:
- # If the test type is OUT_OF_GAS_ERROR, we need to add a JUMPDEST to the code
- # to ensure that we go over the limit by one gas.
+ # If the test type is OUT_OF_GAS_ERROR, we need to add a
+ # JUMPDEST to the code to ensure that we go over the limit
+ # by one gas.
modified_system_contract_code += Op.JUMPDEST
modified_system_contract_code += Op.STOP
elif test_type == SystemContractTestType.REVERT_ERROR:
@@ -335,7 +363,8 @@ def wrapper(
balance=0,
)
- # Simple test transaction to verify the block failed to modify the state.
+ # Simple test transaction to verify the block failed to modify the
+ # state.
value_receiver = pre.fund_eoa(amount=0)
test_tx = Transaction(
to=value_receiver,
diff --git a/packages/tests/src/ethereum_test_tools/utility/pytest.py b/packages/tests/src/ethereum_test_tools/utility/pytest.py
new file mode 100644
index 0000000000..ca93f55e09
--- /dev/null
+++ b/packages/tests/src/ethereum_test_tools/utility/pytest.py
@@ -0,0 +1,139 @@
+"""Pytest utility functions used to write Ethereum tests."""
+
+from typing import Any, Dict, List
+
+import pytest
+from _pytest.mark.structures import ParameterSet
+
+
+class UnknownParameterInCasesError(Exception):
+ """
+ Exception raised when a test case contains parameters that are not present
+ in the defaults.
+ """
+
+ def __init__(self) -> None:
+ """Initialize the exception."""
+ super().__init__("each case must only contain parameters present in defaults")
+
+
+def extend_with_defaults(
+ defaults: Dict[str, Any], cases: List[ParameterSet], **parametrize_kwargs: Any
+) -> Dict[str, Any]:
+ """
+ Extend test cases with default parameter values.
+
+ This utility function extends test case parameters by adding default values
+ from the `defaults` dictionary to each case in the `cases` list. If a case
+ already specifies a value for a parameter, its default is ignored.
+
+ This function is particularly useful in scenarios where you want to define
+ a common set of default values but allow individual test cases to override
+ them as needed.
+
+ The function returns a dictionary that can be directly unpacked and passed
+ to the `@pytest.mark.parametrize` decorator.
+
+ Arguments:
+ defaults (Dict[str, Any]): A dictionary of default parameter names
+ and their values. These values will be added
+ to each case unless the case already defines
+ a value for each parameter.
+ cases (List[ParameterSet]): A list of `pytest.param` objects
+ representing different test cases.
+ Its first argument must be a dictionary
+ defining parameter names and values.
+ parametrize_kwargs (Any): Additional keyword arguments to be passed to
+ `@pytest.mark.parametrize`. These arguments are
+ not modified by this function and are passed
+ through unchanged.
+
+ Returns:
+ Dict[str, Any]: A dictionary with the following structure:
+ `argnames`: A list of parameter names.
+ `argvalues`: A list of test cases with modified parameter values.
+ `parametrize_kwargs`: Additional keyword arguments passed
+ through unchanged.
+
+
+ Example:
+ ```python
+ @pytest.mark.parametrize(**extend_with_defaults(
+ defaults=dict(
+ min_value=0, # default minimum value is 0
+ max_value=100, # default maximum value is 100
+ average=50, # default average value is 50
+ ),
+
+ cases=[
+ pytest.param(
+ dict(), # use default
+ values id='default_case',
+ ),
+
+ pytest.param(
+ dict(min_value=10), # override with min_value=10
+ id='min_value_10',
+ ),
+
+ pytest.param(
+ dict(max_value=200), # override with max_value=200
+ id='max_value_200',
+ ),
+
+ pytest.param(
+ dict(min_value=-10, max_value=50), # override both min_value
+ # and max_value
+ id='min_-10_max_50',
+ ),
+
+ pytest.param(
+ # all defaults are overridden
+ dict(min_value=20, max_value=80, average=50),
+ id="min_20_max_80_avg_50",
+ ),
+
+ pytest.param(
+ dict(min_value=100, max_value=0), # invalid range
+ id='invalid_range',
+ marks=pytest.mark.xfail(reason='invalid range'),
+ )
+ ],
+ ))
+ def test_range(min_value, max_value, average):
+ assert min_value <= max_value
+ assert min_value <= average <= max_value
+ ```
+
+ The above test will execute with the following sets of parameters:
+
+ ```python
+ "default_case": {"min_value": 0, "max_value": 100, "average": 50}
+ "min_value_10": {"min_value": 10, "max_value": 100, "average": 50}
+ "max_value_200": {"min_value": 0, "max_value": 200, "average": 50}
+ "min_-10_max_50": {"min_value": -10, "max_value": 50, "average": 50}
+ "min_20_max_80_avg_50": {"min_value": 20, "max_value": 80, "average": 50}
+ # expected to fail
+ "invalid_range": {"min_value": 100, "max_value": 0, "average": 50}
+ ```
+
+ Notes:
+ - Each case in `cases` must contain exactly one value, which is a
+ dictionary of parameter values.
+ - The function performs an in-place update of the `cases` list, so
+ the original `cases` list is modified.
+
+ """
+ for i, case in enumerate(cases):
+ if not (len(case.values) == 1 and isinstance(case.values[0], dict)):
+ raise ValueError(
+ "each case must contain exactly one value; a dict of parameter values"
+ )
+ if set(case.values[0].keys()) - set(defaults.keys()):
+ raise UnknownParameterInCasesError()
+ # Overwrite values in defaults if the parameter is present in the test
+ # case values
+ merged_params = {**defaults, **case.values[0]} # type: ignore
+ cases[i] = pytest.param(*merged_params.values(), id=case.id, marks=case.marks)
+
+ return {"argnames": list(defaults), "argvalues": cases, **parametrize_kwargs}
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/tests/test_pytest.py b/packages/tests/src/ethereum_test_tools/utility/tests/test_pytest.py
similarity index 96%
rename from src/ethereum_spec_tests/ethereum_test_tools/utility/tests/test_pytest.py
rename to packages/tests/src/ethereum_test_tools/utility/tests/test_pytest.py
index f8f242c92f..0db71cd0ea 100644
--- a/src/ethereum_spec_tests/ethereum_test_tools/utility/tests/test_pytest.py
+++ b/packages/tests/src/ethereum_test_tools/utility/tests/test_pytest.py
@@ -6,7 +6,8 @@
from ethereum_test_tools.utility.pytest import UnknownParameterInCasesError
-# TODO: This is from the docstring in extend_with_defaults; should be tested automatically
+# TODO: This is from the docstring in extend_with_defaults; should be tested
+# automatically
@pytest.mark.parametrize(
**extend_with_defaults(
defaults={
@@ -28,13 +29,13 @@
id="max_value_200",
),
pytest.param(
- {"min_value": -10, "max_value": 50}, # override both min_value
- # and max_value
+ # override both min_value and max_value
+ {"min_value": -10, "max_value": 50},
id="min_-10_max_50",
),
pytest.param(
- {"min_value": 20, "max_value": 80, "average": 50}, # all defaults
- # are overridden
+ # all defaults are overridden
+ {"min_value": 20, "max_value": 80, "average": 50},
id="min_20_max_80_avg_50",
),
pytest.param(
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/versioning.py b/packages/tests/src/ethereum_test_tools/utility/versioning.py
similarity index 86%
rename from src/ethereum_spec_tests/ethereum_test_tools/utility/versioning.py
rename to packages/tests/src/ethereum_test_tools/utility/versioning.py
index 1d0578fd94..58b91bcd1f 100644
--- a/src/ethereum_spec_tests/ethereum_test_tools/utility/versioning.py
+++ b/packages/tests/src/ethereum_test_tools/utility/versioning.py
@@ -9,10 +9,11 @@ def get_current_commit_hash_or_tag(repo_path=".", shorten_hash=False):
"""
Get the latest commit tag or commit hash from the repository.
- If a tag points to the current commit, return the tag name.
- If no tag exists:
- - If shorten_hash is True, return the first 8 characters of the commit hash.
- - Otherwise, return the full commit hash.
+ If a tag points to the current commit, return the tag name. If no tag
+ exists:
+ - If shorten_hash is True, return the first 8 characters of the
+ commit hash.
+ - Otherwise, return the full commit hash.
"""
try:
repo = Repo(repo_path)
diff --git a/src/ethereum_spec_tests/ethereum_test_types/__init__.py b/packages/tests/src/ethereum_test_types/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/__init__.py
rename to packages/tests/src/ethereum_test_types/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_types/account_types.py b/packages/tests/src/ethereum_test_types/account_types.py
similarity index 97%
rename from src/ethereum_spec_tests/ethereum_test_types/account_types.py
rename to packages/tests/src/ethereum_test_types/account_types.py
index 53befb4592..51a17ebe15 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/account_types.py
+++ b/packages/tests/src/ethereum_test_types/account_types.py
@@ -50,8 +50,8 @@ class State:
def set_account(state: State, address: Bytes20, account: Optional[FrontierAccount]) -> None:
"""
- Set the `Account` object at an address. Setting to `None` deletes
- the account (but not its storage, see `destroy_account()`).
+ Set the `Account` object at an address. Setting to `None` deletes the
+ account (but not its storage, see `destroy_account()`).
"""
trie_set(state._main_trie, address, account)
@@ -93,9 +93,11 @@ def get_storage_root(address: Bytes20) -> Bytes32:
class EOA(Address):
"""
- An Externally Owned Account (EOA) is an account controlled by a private key.
+ An Externally Owned Account (EOA) is an account controlled by a private
+ key.
- The EOA is defined by its address and (optionally) by its corresponding private key.
+ The EOA is defined by its address and (optionally) by its corresponding
+ private key.
"""
key: Hash | None
@@ -354,7 +356,10 @@ def fund_eoa(
delegation: Address | Literal["Self"] | None = None,
nonce: NumberConvertible | None = None,
) -> EOA:
- """Add a previously unused EOA to the pre-alloc with the balance specified by `amount`."""
+ """
+ Add a previously unused EOA to the pre-alloc with the balance specified
+ by `amount`.
+ """
raise NotImplementedError("fund_eoa is not implemented in the base class")
def fund_address(self, address: Address, amount: NumberConvertible):
@@ -370,7 +375,7 @@ def empty_account(self) -> Address:
"""
Return a previously unused account guaranteed to be empty.
- This ensures the account has zero balance, zero nonce, no code, and no storage.
- The account is not a precompile or a system contract.
+ This ensures the account has zero balance, zero nonce, no code, and no
+ storage. The account is not a precompile or a system contract.
"""
raise NotImplementedError("empty_account is not implemented in the base class")
diff --git a/src/ethereum_spec_tests/ethereum_test_types/blob_types.py b/packages/tests/src/ethereum_test_types/blob_types.py
similarity index 91%
rename from src/ethereum_spec_tests/ethereum_test_types/blob_types.py
rename to packages/tests/src/ethereum_test_types/blob_types.py
index ca7e13afc3..fa2cc59610 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/blob_types.py
+++ b/packages/tests/src/ethereum_test_types/blob_types.py
@@ -14,7 +14,7 @@
from ethereum_test_base_types.base_types import Bytes, Hash
from ethereum_test_base_types.pydantic import CamelModel
from ethereum_test_forks import Fork
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
CACHED_BLOBS_DIRECTORY: Path = (
Path(platformdirs.user_cache_dir("ethereum-execution-spec-tests")) / "cached_blobs"
@@ -50,7 +50,8 @@ class Blob(CamelModel):
data: Bytes
commitment: Bytes
proof: List[Bytes] | Bytes # Bytes < Osaka, List[Bytes] >= Osaka
- cells: List[Bytes] | None # None (in json: null) < Osaka, List[Bytes] >= Osaka
+ # None (in json: null) < Osaka, List[Bytes] >= Osaka
+ cells: List[Bytes] | None
versioned_hash: Hash
name: str
@@ -72,13 +73,18 @@ def trusted_setup(cls):
@staticmethod
def get_filename(fork: Fork, seed: int) -> str:
- """Return filename this blob would have as string (with .json extension)."""
+ """
+ Return filename this blob would have as string (with .json extension).
+ """
amount_cell_proofs: int = cast(int, fork.get_blob_constant("AMOUNT_CELL_PROOFS"))
return "blob_" + str(seed) + "_cell_proofs_" + str(amount_cell_proofs) + ".json"
@staticmethod
def get_filepath(fork: Fork, seed: int):
- """Return the Path to the blob that would be created with these parameters."""
+ """
+ Return the Path to the blob that would be created with these
+ parameters.
+ """
# determine amount of cell proofs for this fork (0 or 128)
would_be_filename: str = Blob.get_filename(fork, seed)
@@ -87,7 +93,10 @@ def get_filepath(fork: Fork, seed: int):
@staticmethod
def from_fork(fork: Fork, seed: int = 0, timestamp: int = 0) -> "Blob":
- """Construct Blob instances. Fork logic is encapsulated within nested functions."""
+ """
+ Construct Blob instances. Fork logic is encapsulated within nested
+ functions.
+ """
def generate_blob_data(rng_seed: int = 0) -> Bytes:
"""Calculate blob data deterministically via provided seed."""
@@ -139,12 +148,16 @@ def get_commitment(data: Bytes) -> Bytes:
return commitment
def get_proof(fork: Fork, data: Bytes) -> List[Bytes] | Bytes:
- # determine whether this fork is = osaka by looking at amount of cell_proofs
+ # determine whether this fork is = osaka by looking at
+ # amount of cell_proofs
amount_cell_proofs = fork.get_blob_constant("AMOUNT_CELL_PROOFS")
# cancun, prague
if amount_cell_proofs == 0:
- z = 2 # 2 is one of many possible valid field elements z (https://github.com/ethereum/consensus-specs/blob/ad884507f7a1d5962cd3dfb5f7b3e41aab728c55/tests/core/pyspec/eth2spec/test/utils/kzg_tests.py#L58-L66)
+ z = 2 # 2 is one of many possible valid field elements z
+ # https://github.com/ethereum/consensus-specs/blob/ad884507f
+ # 7a1d5962cd3dfb5f7b3e41aab728c55/tests/core/pyspec/eth2spec/
+ # test/utils/kzg_tests.py#L58-L66)
z_valid_size: bytes = z.to_bytes(
cast(int, fork.get_blob_constant("BYTES_PER_FIELD_ELEMENT")), byteorder="big"
)
@@ -164,7 +177,8 @@ def get_proof(fork: Fork, data: Bytes) -> List[Bytes] | Bytes:
)
def get_cells(fork: Fork, data: Bytes) -> List[Bytes] | None:
- # determine whether this fork is = osaka by looking at amount of cell_proofs
+ # determine whether this fork is = osaka by looking at
+ # amount of cell_proofs
amount_cell_proofs = fork.get_blob_constant("AMOUNT_CELL_PROOFS")
# cancun, prague
@@ -189,8 +203,8 @@ def get_cells(fork: Fork, data: Bytes) -> List[Bytes] | None:
parents=True, exist_ok=True
) # create all necessary dirs on the way
- # handle transition forks
- # (blob related constants are needed and only available for normal forks)
+ # handle transition forks (blob related constants are needed and only
+ # available for normal forks)
fork = fork.fork_at(timestamp=timestamp)
# if this blob already exists then load from file. use lock
@@ -224,7 +238,8 @@ def get_cells(fork: Fork, data: Bytes) -> List[Bytes] | None:
seed=seed,
timestamp=timestamp,
)
- # for most effective caching temporarily persist every blob that is created in cache
+ # for most effective caching temporarily persist every blob that is
+ # created in cache
blob.write_to_file()
return blob
@@ -234,7 +249,8 @@ def from_file(file_name: str) -> "Blob":
"""
Read a .json file and reconstruct object it represents.
- You can load a blob only via its filename (with or without .json extension).
+ You can load a blob only via its filename (with or without .json
+ extension).
"""
# ensure filename was passed
assert file_name.startswith("blob_"), (
@@ -272,11 +288,15 @@ def write_to_file(self):
if output_location.exists():
logger.debug(f"Blob {output_location} already exists. It will be overwritten.")
- with open(output_location, "w", encoding="utf-8") as f: # overwrite existing
+ # overwrite existing
+ with open(output_location, "w", encoding="utf-8") as f:
f.write(json_str)
def verify_cell_kzg_proof_batch(self, cell_indices: list) -> bool:
- """Check whether all cell proofs are valid and returns True only if that is the case."""
+ """
+ Check whether all cell proofs are valid and returns True only if that
+ is the case.
+ """
amount_cell_proofs: int = cast(int, self.fork.get_blob_constant("AMOUNT_CELL_PROOFS"))
assert amount_cell_proofs > 0, (
@@ -303,12 +323,14 @@ def delete_cells_then_recover_them(self, deletion_indices: list[int]):
"""
Simulate the cell recovery process in user-specified scenario.
- Note: Requirement for successful reconstruction is having at least N of the 2N cells.
+ Note: Requirement for successful reconstruction is having at least N of
+ the 2N cells.
- Theoretical Usage: You pass a cell list with to 128 elements to this function
- along with a list of deletion indices. These cells will be deleted and then
- the ckzg recovery mechanism is used to repair the missing cells.
- If no assertion is triggered the reconstruction was successful.
+ Theoretical Usage: You pass a cell list with to 128 elements to this
+ function along with a list of deletion indices. These cells will be
+ deleted and then the ckzg recovery mechanism is used to repair the
+ missing cells. If no assertion is triggered the reconstruction was
+ successful.
"""
amount_cell_proofs: int = cast(int, self.fork.get_blob_constant("AMOUNT_CELL_PROOFS"))
@@ -370,7 +392,8 @@ class ProofCorruptionMode(Enum):
"""
Define what the proof corruption modes do.
- For Osaka and later each Bytes object in the list is manipulated this way.
+ For Osaka and later each Bytes object in the list is manipulated this
+ way.
"""
CORRUPT_FIRST_BYTE = 1 # corrupts a single byte (index 0)
@@ -382,7 +405,9 @@ def corrupt_proof(self, mode: ProofCorruptionMode):
"""Corrupt the proof field, supports different corruption modes."""
def corrupt_byte(b: bytes) -> Bytes:
- """Bit-flip all bits of provided byte using XOR to guarantee change."""
+ """
+ Bit-flip all bits of provided byte using XOR to guarantee change.
+ """
if len(b) != 1:
raise ValueError("Input must be a single byte")
return Bytes(bytes([b[0] ^ 0xFF]))
diff --git a/packages/tests/src/ethereum_test_types/block_access_list/__init__.py b/packages/tests/src/ethereum_test_types/block_access_list/__init__.py
new file mode 100644
index 0000000000..03cad90aae
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/block_access_list/__init__.py
@@ -0,0 +1,44 @@
+"""
+Block Access List (BAL) models for EIP-7928.
+
+Following the established pattern in the codebase (AccessList,
+AuthorizationTuple), these are simple data classes that can be composed
+together.
+"""
+
+from .account_absent_values import BalAccountAbsentValues
+from .account_changes import (
+ BalAccountChange,
+ BalBalanceChange,
+ BalCodeChange,
+ BalNonceChange,
+ BalStorageChange,
+ BalStorageSlot,
+ BlockAccessListChangeLists,
+)
+from .exceptions import BlockAccessListValidationError
+from .expectations import (
+ BalAccountExpectation,
+ BlockAccessListExpectation,
+ compose,
+)
+from .t8n import BlockAccessList
+
+__all__ = [
+ # Core models
+ "BlockAccessList",
+ "BlockAccessListExpectation",
+ "BalAccountExpectation",
+ "BalAccountAbsentValues",
+ # Change types
+ "BalAccountChange",
+ "BalNonceChange",
+ "BalBalanceChange",
+ "BalCodeChange",
+ "BalStorageChange",
+ "BalStorageSlot",
+ # Utilities
+ "BlockAccessListChangeLists",
+ "BlockAccessListValidationError",
+ "compose",
+]
diff --git a/packages/tests/src/ethereum_test_types/block_access_list/account_absent_values.py b/packages/tests/src/ethereum_test_types/block_access_list/account_absent_values.py
new file mode 100644
index 0000000000..d2109477cb
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/block_access_list/account_absent_values.py
@@ -0,0 +1,215 @@
+"""
+BalAccountAbsentValues class for BAL testing.
+
+This module provides a unified class for specifying explicit absent values
+in Block Access Lists. This class uses the same change classes as
+BalAccountChanges to specify specific values that should NOT exist in the BAL.
+For checking complete absence, use BalAccountExpectation with empty lists
+instead.
+"""
+
+from typing import List
+
+from pydantic import Field, model_validator
+
+from ethereum_test_base_types import CamelModel, StorageKey
+
+from .account_changes import (
+ BalAccountChange,
+ BalBalanceChange,
+ BalCodeChange,
+ BalNonceChange,
+ BalStorageSlot,
+)
+from .exceptions import BlockAccessListValidationError
+
+EMPTY_LIST_ERROR_MSG = (
+ "Empty lists are not allowed. This would mean 'check for any change' and "
+ "is bad practice. Instead, use the `BalAccountExpectation` to define "
+ "explicit, expected changes."
+)
+
+
+class BalAccountAbsentValues(CamelModel):
+ """
+ Represents explicit absent value expectations for a specific account
+ in a block.
+
+ This class specifies specific changes that should NOT exist in the BAL
+ for a given account.
+
+ IMPORTANT: This class is for checking that specific values are absent,
+ NOT for checking that entire categories are empty. For complete
+ absence checks (e.g., "no nonce changes at all"), use
+ BalAccountExpectation with empty lists instead.
+
+ The validation works by checking that none of the specified
+ explicit changes exist in the actual BAL.
+
+ Example:
+ # Forbid specific nonce change at tx 1 with post_nonce=5, and specific
+ # storage change
+ absent_values = BalAccountAbsentValues(
+ nonce_changes=[
+ # Forbid exact nonce change at this tx
+ BalNonceChange(tx_index=1, post_nonce=5),
+ ],
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x42,
+ slot_changes=[
+ # Forbid exact storage change at this slot and tx
+ BalStorageChange(tx_index=2, post_value=0x99)
+ ],
+ )
+ ],
+ )
+
+ For checking complete absence:
+ # Use BalAccountExpectation with empty lists instead
+ expectation = BalAccountExpectation(
+ nonce_changes=[], # Expect NO nonce changes at all
+ storage_changes=[], # Expect NO storage changes at all
+ )
+
+ """
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ nonce_changes: List[BalNonceChange] = Field(
+ default_factory=list,
+ description="List of nonce changes that should NOT exist in the BAL. "
+ "Validates that none of these changes are present.",
+ )
+ balance_changes: List[BalBalanceChange] = Field(
+ default_factory=list,
+ description="List of balance changes that should NOT exist in the BAL. "
+ "Validates that none of these changes are present.",
+ )
+ code_changes: List[BalCodeChange] = Field(
+ default_factory=list,
+ description="List of code changes that should NOT exist in the BAL. "
+ "Validates that none of these changes are present.",
+ )
+ storage_changes: List[BalStorageSlot] = Field(
+ default_factory=list,
+ description="List of storage slots/changes that should NOT exist in the BAL. "
+ "Validates that none of these changes are present.",
+ )
+ storage_reads: List[StorageKey] = Field(
+ default_factory=list,
+ description="List of storage slots that should NOT be read.",
+ )
+
+ @model_validator(mode="after")
+ def validate_specific_absences_only(self) -> "BalAccountAbsentValues":
+ """Ensure absence fields contain specific values, not empty checks."""
+ # at least one field must have content
+ if not any(
+ [
+ self.nonce_changes,
+ self.balance_changes,
+ self.code_changes,
+ self.storage_changes,
+ self.storage_reads,
+ ]
+ ):
+ raise ValueError(
+ "At least one absence field must be specified. "
+ "`BalAccountAbsentValues` is for checking specific forbidden values. "
+ f"{EMPTY_LIST_ERROR_MSG}"
+ )
+
+ # check that no fields are explicitly set to empty lists
+ field_checks = [
+ ("nonce_changes", self.nonce_changes),
+ ("balance_changes", self.balance_changes),
+ ("code_changes", self.code_changes),
+ ("storage_changes", self.storage_changes),
+ ("storage_reads", self.storage_reads),
+ ]
+
+ for field_name, field_value in field_checks:
+ if field_name in self.model_fields_set and field_value == []:
+ raise ValueError(
+ f"`BalAccountAbsentValues.{field_name}` cannot be an empty list. "
+ f"{EMPTY_LIST_ERROR_MSG}"
+ )
+
+ # validate that storage_changes don't have empty slot_changes
+ for storage_slot in self.storage_changes:
+ if not storage_slot.slot_changes:
+ raise ValueError(
+ f"`BalAccountAbsentValues.storage_changes[{storage_slot.slot}].slot_changes` "
+ f"cannot be an empty list. {EMPTY_LIST_ERROR_MSG}"
+ )
+
+ return self
+
+ @staticmethod
+ def _validate_forbidden_changes(
+ actual_changes: List,
+ forbidden_changes: List,
+ match_fn,
+ error_msg_fn,
+ ) -> None:
+ for actual in actual_changes:
+ for forbidden in forbidden_changes:
+ if match_fn(actual, forbidden):
+ raise BlockAccessListValidationError(error_msg_fn(actual))
+
+ def validate_against(self, account: BalAccountChange) -> None:
+ """
+ Validate that the account does not contain the forbidden changes
+ specified in this object.
+
+ Args:
+ account: The BalAccountChange to validate against
+
+ Raises:
+ BlockAccessListValidationError: If any forbidden changes are found
+
+ """
+ self._validate_forbidden_changes(
+ account.nonce_changes,
+ self.nonce_changes,
+ lambda a, f: a.tx_index == f.tx_index and a.post_nonce == f.post_nonce,
+ lambda a: f"Unexpected nonce change found at tx {a.tx_index}",
+ )
+ self._validate_forbidden_changes(
+ account.balance_changes,
+ self.balance_changes,
+ lambda a, f: a.tx_index == f.tx_index and a.post_balance == f.post_balance,
+ lambda a: f"Unexpected balance change found at tx {a.tx_index}",
+ )
+ self._validate_forbidden_changes(
+ account.code_changes,
+ self.code_changes,
+ lambda a, f: a.tx_index == f.tx_index and a.new_code == f.new_code,
+ lambda a: f"Unexpected code change found at tx {a.tx_index}",
+ )
+
+ for forbidden_storage_slot in self.storage_changes:
+ for actual_storage_slot in account.storage_changes:
+ if actual_storage_slot.slot == forbidden_storage_slot.slot:
+ slot_id = actual_storage_slot.slot
+ self._validate_forbidden_changes(
+ actual_storage_slot.slot_changes,
+ forbidden_storage_slot.slot_changes,
+ lambda a, f: (a.tx_index == f.tx_index and a.post_value == f.post_value),
+ lambda a, slot=slot_id: (
+ f"Unexpected storage change found at slot {slot} in tx {a.tx_index}"
+ ),
+ )
+
+ for forbidden_read in self.storage_reads:
+ for actual_read in account.storage_reads:
+ if actual_read == forbidden_read:
+ raise BlockAccessListValidationError(
+ f"Unexpected storage read found at slot {actual_read}"
+ )
+
+
+__all__ = [
+ "BalAccountAbsentValues",
+]
diff --git a/packages/tests/src/ethereum_test_types/block_access_list/account_changes.py b/packages/tests/src/ethereum_test_types/block_access_list/account_changes.py
new file mode 100644
index 0000000000..b5a9632c8a
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/block_access_list/account_changes.py
@@ -0,0 +1,138 @@
+"""
+Account change classes for Block Access List.
+
+This module contains the core data structures representing changes to accounts
+in a block access list as defined in EIP-7928.
+"""
+
+from typing import ClassVar, List, Union
+
+from pydantic import Field
+
+from ethereum_test_base_types import (
+ Address,
+ Bytes,
+ CamelModel,
+ HexNumber,
+ RLPSerializable,
+ StorageKey,
+)
+
+
+class BalNonceChange(CamelModel, RLPSerializable):
+ """Represents a nonce change in the block access list."""
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ tx_index: HexNumber = Field(
+ HexNumber(1),
+ description="Transaction index where the change occurred",
+ )
+ post_nonce: HexNumber = Field(..., description="Nonce value after the transaction")
+
+ rlp_fields: ClassVar[List[str]] = ["tx_index", "post_nonce"]
+
+
+class BalBalanceChange(CamelModel, RLPSerializable):
+ """Represents a balance change in the block access list."""
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ tx_index: HexNumber = Field(
+ HexNumber(1),
+ description="Transaction index where the change occurred",
+ )
+ post_balance: HexNumber = Field(..., description="Balance after the transaction")
+
+ rlp_fields: ClassVar[List[str]] = ["tx_index", "post_balance"]
+
+
+class BalCodeChange(CamelModel, RLPSerializable):
+ """Represents a code change in the block access list."""
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ tx_index: HexNumber = Field(
+ HexNumber(1),
+ description="Transaction index where the change occurred",
+ )
+ new_code: Bytes = Field(..., description="New code bytes")
+
+ rlp_fields: ClassVar[List[str]] = ["tx_index", "new_code"]
+
+
+class BalStorageChange(CamelModel, RLPSerializable):
+ """Represents a change to a specific storage slot."""
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ tx_index: HexNumber = Field(
+ HexNumber(1),
+ description="Transaction index where the change occurred",
+ )
+ post_value: StorageKey = Field(..., description="Value after the transaction")
+
+ rlp_fields: ClassVar[List[str]] = ["tx_index", "post_value"]
+
+
+class BalStorageSlot(CamelModel, RLPSerializable):
+ """Represents all changes to a specific storage slot."""
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ slot: StorageKey = Field(..., description="Storage slot key")
+ slot_changes: List[BalStorageChange] = Field(
+ default_factory=list, description="List of changes to this slot"
+ )
+
+ rlp_fields: ClassVar[List[str]] = ["slot", "slot_changes"]
+
+
+class BalAccountChange(CamelModel, RLPSerializable):
+ """Represents all changes to a specific account in a block."""
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ address: Address = Field(..., description="Account address")
+ nonce_changes: List[BalNonceChange] = Field(
+ default_factory=list, description="List of nonce changes"
+ )
+ balance_changes: List[BalBalanceChange] = Field(
+ default_factory=list, description="List of balance changes"
+ )
+ code_changes: List[BalCodeChange] = Field(
+ default_factory=list, description="List of code changes"
+ )
+ storage_changes: List[BalStorageSlot] = Field(
+ default_factory=list, description="List of storage changes"
+ )
+ storage_reads: List[StorageKey] = Field(
+ default_factory=list, description="List of storage slots that were read"
+ )
+
+ rlp_fields: ClassVar[List[str]] = [
+ "address",
+ "storage_changes",
+ "storage_reads",
+ "balance_changes",
+ "nonce_changes",
+ "code_changes",
+ ]
+
+
+BlockAccessListChangeLists = Union[
+ List[BalNonceChange],
+ List[BalBalanceChange],
+ List[BalCodeChange],
+]
+
+
+__all__ = [
+ "BalNonceChange",
+ "BalBalanceChange",
+ "BalCodeChange",
+ "BalStorageChange",
+ "BalStorageSlot",
+ "BalAccountChange",
+ "BlockAccessListChangeLists",
+]
diff --git a/packages/tests/src/ethereum_test_types/block_access_list/exceptions.py b/packages/tests/src/ethereum_test_types/block_access_list/exceptions.py
new file mode 100644
index 0000000000..8a26cfef85
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/block_access_list/exceptions.py
@@ -0,0 +1,7 @@
+"""Exceptions related to block access list validation."""
+
+
+class BlockAccessListValidationError(Exception):
+ """Custom exception for Block Access List validation errors."""
+
+ pass
diff --git a/packages/tests/src/ethereum_test_types/block_access_list/expectations.py b/packages/tests/src/ethereum_test_types/block_access_list/expectations.py
new file mode 100644
index 0000000000..4d9ecc7fa4
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/block_access_list/expectations.py
@@ -0,0 +1,466 @@
+"""
+Block Access List expectation classes for test validation.
+
+This module contains classes for defining and validating expected
+BAL values in tests.
+"""
+
+from typing import Any, Callable, ClassVar, Dict, List, Optional
+
+from pydantic import Field, PrivateAttr
+
+from ethereum_test_base_types import Address, CamelModel, StorageKey
+
+from .account_absent_values import BalAccountAbsentValues
+from .account_changes import (
+ BalAccountChange,
+ BalBalanceChange,
+ BalCodeChange,
+ BalNonceChange,
+ BalStorageSlot,
+ BlockAccessListChangeLists,
+)
+from .exceptions import BlockAccessListValidationError
+from .t8n import BlockAccessList
+
+
+class BalAccountExpectation(CamelModel):
+ """
+ Represents expected changes to a specific account in a block.
+
+ Same as BalAccountChange but without the address field,
+ used for expectations.
+ """
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ nonce_changes: List[BalNonceChange] = Field(
+ default_factory=list, description="List of expected nonce changes"
+ )
+ balance_changes: List[BalBalanceChange] = Field(
+ default_factory=list, description="List of expected balance changes"
+ )
+ code_changes: List[BalCodeChange] = Field(
+ default_factory=list, description="List of expected code changes"
+ )
+ storage_changes: List[BalStorageSlot] = Field(
+ default_factory=list, description="List of expected storage changes"
+ )
+ storage_reads: List[StorageKey] = Field(
+ default_factory=list, description="List of expected read storage slots"
+ )
+ absent_values: Optional[BalAccountAbsentValues] = Field(
+ default=None, description="Explicit absent value expectations using BalAccountAbsentValues"
+ )
+
+ _EMPTY: ClassVar[Optional["BalAccountExpectation"]] = None
+
+ @classmethod
+ def empty(cls) -> "BalAccountExpectation":
+ """
+ Create an expectation that validates the account has NO changes.
+
+ This is distinct from `BalAccountExpectation()` with no fields set,
+ which is ambiguous and clashes with `model_fields_set` logic, and
+ will raise a clarifying error if used in expectations.
+
+ Returns:
+ A BalAccountExpectation instance with all change lists empty.
+ This uses a classvar to facilitate identity checks across
+ multiple expectation instances.
+
+ """
+ if cls._EMPTY is None:
+ cls._EMPTY = cls(
+ nonce_changes=[],
+ balance_changes=[],
+ code_changes=[],
+ storage_changes=[],
+ storage_reads=[],
+ )
+ return cls._EMPTY
+
+
+def compose(
+ *modifiers: Callable[["BlockAccessList"], "BlockAccessList"],
+) -> Callable[["BlockAccessList"], "BlockAccessList"]:
+ """Compose multiple modifiers into a single modifier."""
+
+ def composed(bal: BlockAccessList) -> BlockAccessList:
+ result = bal
+ for modifier in modifiers:
+ result = modifier(result)
+ return result
+
+ return composed
+
+
+class BlockAccessListExpectation(CamelModel):
+ """
+ Block Access List expectation model for test writing.
+
+ This model is used to define expected BAL values in tests. It supports:
+ - Partial validation (only checks explicitly set fields)
+ - Convenient test syntax with named parameters
+ - Verification against actual BAL from t8n
+ - Explicit exclusion of addresses (using None values)
+
+ Example:
+ # In test definition
+ expected_block_access_list = BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]
+ ),
+ bob: None, # Bob should NOT be in the BAL
+ }
+ )
+
+ """
+
+ model_config = CamelModel.model_config | {"extra": "forbid"}
+
+ account_expectations: Dict[Address, BalAccountExpectation | None] = Field(
+ default_factory=dict, description="Expected account changes or exclusions to verify"
+ )
+
+ _modifier: Callable[["BlockAccessList"], "BlockAccessList"] | None = PrivateAttr(default=None)
+
+ def modify(
+ self, *modifiers: Callable[["BlockAccessList"], "BlockAccessList"]
+ ) -> "BlockAccessListExpectation":
+ """
+ Create a new expectation with a modifier for invalid test cases.
+
+ Args:
+ modifiers: One or more functions that take and return
+ a BlockAccessList
+
+ Returns:
+ A new BlockAccessListExpectation instance with
+ the modifiers applied
+
+ Example:
+ from ethereum_test_types.block_access_list.
+ modifiers import remove_nonces
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={...}
+ ).modify(remove_nonces(alice))
+
+ """
+ new_instance = self.model_copy(deep=True)
+ new_instance._modifier = compose(*modifiers)
+ return new_instance
+
+ def modify_if_invalid_test(self, t8n_bal: "BlockAccessList") -> "BlockAccessList":
+ """
+ Apply the modifier to the given BAL if this is an invalid test case.
+
+ Args:
+ t8n_bal: The BlockAccessList from t8n tool
+
+ Returns:
+ The potentially transformed BlockAccessList for the fixture
+
+ """
+ if self._modifier:
+ return self._modifier(t8n_bal)
+ return t8n_bal
+
+ def verify_against(self, actual_bal: "BlockAccessList") -> None:
+ """
+ Verify that the actual BAL from the client matches this expected BAL.
+
+ Validation steps:
+ 1. Validate actual BAL conforms to EIP-7928 ordering requirements
+ 2. Verify address expectations - presence or explicit absence
+ 3. Verify expected changes within accounts match actual changes
+
+ Args:
+ actual_bal: The BlockAccessList model from the client
+
+ Raises:
+ BlockAccessListValidationError: If verification fails
+
+ """
+ # validate the actual BAL structure follows EIP-7928 ordering
+ self._validate_bal_ordering(actual_bal)
+
+ actual_accounts_by_addr = {acc.address: acc for acc in actual_bal.root}
+ for address, expectation in self.account_expectations.items():
+ if expectation is None:
+ # check explicit exclusion of address when set to `None`
+ if address in actual_accounts_by_addr:
+ raise BlockAccessListValidationError(
+ f"Address {address} should not be in BAL but was found"
+ )
+ elif not expectation.model_fields_set:
+ # Disallow ambiguous BalAccountExpectation() with no fields set
+ raise BlockAccessListValidationError(
+ f"Address {address}: BalAccountExpectation() with no fields set is "
+ f"ambiguous. Use BalAccountExpectation.empty() to validate no changes, "
+ f"or explicitly set the fields to validate "
+ f"(e.g., nonce_changes=[...])."
+ )
+ else:
+ # check address is present and validate changes
+ if address not in actual_accounts_by_addr:
+ raise BlockAccessListValidationError(
+ f"Expected address {address} not found in actual BAL"
+ )
+
+ if expectation is BalAccountExpectation.empty():
+ # explicit check for "no changes" validation w/ .empty()
+ if actual_accounts_by_addr.get(address) != BalAccountChange(address=address):
+ raise BlockAccessListValidationError(
+ f"No account changes expected for {address} but found "
+ f"changes: {actual_accounts_by_addr[address]}"
+ )
+
+ actual_account = actual_accounts_by_addr[address]
+ try:
+ self._compare_account_expectations(expectation, actual_account)
+ except AssertionError as e:
+ raise BlockAccessListValidationError(f"Account {address}: {str(e)}") from e
+
+ @staticmethod
+ def _validate_bal_ordering(bal: "BlockAccessList") -> None:
+ """
+ Validate BAL ordering follows EIP-7928 requirements.
+
+ Args:
+ bal: The BlockAccessList to validate
+
+ Raises:
+ BlockAccessListValidationError: If ordering is invalid
+
+ """
+ # Check address ordering (ascending)
+ for i in range(1, len(bal.root)):
+ if bal.root[i - 1].address >= bal.root[i].address:
+ raise BlockAccessListValidationError(
+ f"BAL addresses are not in lexicographic order: "
+ f"{bal.root[i - 1].address} >= {bal.root[i].address}"
+ )
+
+ # Check transaction index ordering and uniqueness within accounts
+ for account in bal.root:
+ changes_to_check: List[tuple[str, BlockAccessListChangeLists]] = [
+ ("nonce_changes", account.nonce_changes),
+ ("balance_changes", account.balance_changes),
+ ("code_changes", account.code_changes),
+ ]
+
+ for field_name, change_list in changes_to_check:
+ if not change_list:
+ continue
+
+ tx_indices = [c.tx_index for c in change_list]
+
+ # Check both ordering and duplicates
+ if tx_indices != sorted(tx_indices):
+ raise BlockAccessListValidationError(
+ f"Transaction indices not in ascending order in {field_name} of account "
+ f"{account.address}. Got: {tx_indices}, Expected: {sorted(tx_indices)}"
+ )
+
+ if len(tx_indices) != len(set(tx_indices)):
+ duplicates = sorted({idx for idx in tx_indices if tx_indices.count(idx) > 1})
+ raise BlockAccessListValidationError(
+ f"Duplicate transaction indices in {field_name} of account "
+ f"{account.address}. Duplicates: {duplicates}"
+ )
+
+ # Check storage slot ordering
+ for i in range(1, len(account.storage_changes)):
+ if account.storage_changes[i - 1].slot >= account.storage_changes[i].slot:
+ raise BlockAccessListValidationError(
+ f"Storage slots not in ascending order in account "
+ f"{account.address}: {account.storage_changes[i - 1].slot} >= "
+ f"{account.storage_changes[i].slot}"
+ )
+
+ # Check transaction index ordering and uniqueness within storage
+ # slots
+ for storage_slot in account.storage_changes:
+ if not storage_slot.slot_changes:
+ continue
+
+ tx_indices = [c.tx_index for c in storage_slot.slot_changes]
+
+ # Check both ordering and duplicates
+ if tx_indices != sorted(tx_indices):
+ raise BlockAccessListValidationError(
+ f"Transaction indices not in ascending order in storage slot "
+ f"{storage_slot.slot} of account {account.address}. "
+ f"Got: {tx_indices}, Expected: {sorted(tx_indices)}"
+ )
+
+ if len(tx_indices) != len(set(tx_indices)):
+ duplicates = sorted({idx for idx in tx_indices if tx_indices.count(idx) > 1})
+ raise BlockAccessListValidationError(
+ f"Duplicate transaction indices in storage slot "
+ f"{storage_slot.slot} of account {account.address}. "
+ f"Duplicates: {duplicates}"
+ )
+
+ # Check storage reads ordering
+ for i in range(1, len(account.storage_reads)):
+ if account.storage_reads[i - 1] >= account.storage_reads[i]:
+ raise BlockAccessListValidationError(
+ f"Storage reads not in ascending order in account "
+ f"{account.address}: {account.storage_reads[i - 1]} >= "
+ f"{account.storage_reads[i]}"
+ )
+
+ @staticmethod
+ def _compare_account_expectations(
+ expected: BalAccountExpectation, actual: BalAccountChange
+ ) -> None:
+ """
+ Compare expected and actual account changes using
+ subsequence validation.
+
+ Args:
+ expected: The expected account changes
+ actual: The actual account changes from the BAL
+
+ Raises:
+ AssertionError: If validation fails
+
+ """
+ # Check absence expectations first if defined
+ if expected.absent_values is not None:
+ expected.absent_values.validate_against(actual)
+
+ # Validate expected changes using subsequence validation
+ field_pairs: List[tuple[str, Any, Any]] = [
+ ("nonce_changes", expected.nonce_changes, actual.nonce_changes),
+ ("balance_changes", expected.balance_changes, actual.balance_changes),
+ ("code_changes", expected.code_changes, actual.code_changes),
+ ("storage_changes", expected.storage_changes, actual.storage_changes),
+ ("storage_reads", expected.storage_reads, actual.storage_reads),
+ ]
+
+ for field_name, expected_list, actual_list in field_pairs:
+ # Only validate fields that were explicitly set
+ if field_name not in expected.model_fields_set:
+ continue
+
+ # Check if explicitly set to empty but actual has values
+ if not expected_list and actual_list:
+ raise AssertionError(f"Expected {field_name} to be empty but found {actual_list}")
+
+ if field_name == "storage_reads":
+ # storage_reads is a simple list of StorageKey
+ actual_idx = 0
+ for expected_read in expected_list:
+ found = False
+ while actual_idx < len(actual_list):
+ if actual_list[actual_idx] == expected_read:
+ found = True
+ actual_idx += 1
+ break
+ actual_idx += 1
+
+ if not found:
+ raise AssertionError(
+ f"Storage read {expected_read} not found or not in correct order. "
+ f"Actual reads: {actual_list}"
+ )
+
+ elif field_name == "storage_changes":
+ # storage_changes is a list of BalStorageSlot
+ actual_idx = 0
+ for expected_slot in expected_list:
+ found = False
+ while actual_idx < len(actual_list):
+ if actual_list[actual_idx].slot == expected_slot.slot:
+ # Found matching slot, now validate slot_changes
+ actual_slot_changes = actual_list[actual_idx].slot_changes
+ expected_slot_changes = expected_slot.slot_changes
+
+ if not expected_slot_changes:
+ # Empty expected means any
+ # slot_changes are acceptable
+ pass
+ else:
+ # Validate slot_changes as subsequence
+ slot_actual_idx = 0
+ for expected_change in expected_slot_changes:
+ slot_found = False
+ while slot_actual_idx < len(actual_slot_changes):
+ actual_change = actual_slot_changes[slot_actual_idx]
+ if (
+ actual_change.tx_index == expected_change.tx_index
+ and actual_change.post_value
+ == expected_change.post_value
+ ):
+ slot_found = True
+ slot_actual_idx += 1
+ break
+ slot_actual_idx += 1
+
+ if not slot_found:
+ raise AssertionError(
+ f"Storage change {expected_change} not found "
+ f"or not in correct order in slot "
+ f"{expected_slot.slot}. "
+ f"Actual slot changes: {actual_slot_changes}"
+ )
+
+ found = True
+ actual_idx += 1
+ break
+ actual_idx += 1
+
+ if not found:
+ raise AssertionError(
+ f"Storage slot {expected_slot.slot} not found "
+ f"or not in correct order. Actual slots: "
+ f"{[s.slot for s in actual_list]}"
+ )
+
+ else:
+ # Handle nonce_changes, balance_changes, code_changes
+ # Create tuples for comparison (ordering already validated)
+ if field_name == "nonce_changes":
+ expected_tuples = [(c.tx_index, c.post_nonce) for c in expected_list]
+ actual_tuples = [(c.tx_index, c.post_nonce) for c in actual_list]
+ item_type = "nonce"
+ elif field_name == "balance_changes":
+ expected_tuples = [(c.tx_index, int(c.post_balance)) for c in expected_list]
+ actual_tuples = [(c.tx_index, int(c.post_balance)) for c in actual_list]
+ item_type = "balance"
+ elif field_name == "code_changes":
+ expected_tuples = [(c.tx_index, bytes(c.new_code)) for c in expected_list]
+ actual_tuples = [(c.tx_index, bytes(c.new_code)) for c in actual_list]
+ item_type = "code"
+ else:
+ # sanity check
+ raise ValueError(f"Unexpected field type: {field_name}")
+
+ # Check that expected forms a subsequence of actual
+ actual_idx = 0
+ for exp_tuple in expected_tuples:
+ found = False
+ while actual_idx < len(actual_tuples):
+ if actual_tuples[actual_idx] == exp_tuple:
+ found = True
+ actual_idx += 1
+ break
+ actual_idx += 1
+
+ if not found:
+ raise AssertionError(
+ f"{item_type.capitalize()} change {exp_tuple} not found "
+ f"or not in correct order. Actual changes: {actual_tuples}"
+ )
+
+
+__all__ = [
+ "BalAccountExpectation",
+ "BlockAccessListExpectation",
+ "compose",
+]
diff --git a/src/ethereum_spec_tests/ethereum_test_types/block_access_list/modifiers.py b/packages/tests/src/ethereum_test_types/block_access_list/modifiers.py
similarity index 54%
rename from src/ethereum_spec_tests/ethereum_test_types/block_access_list/modifiers.py
rename to packages/tests/src/ethereum_test_types/block_access_list/modifiers.py
index 718ed50814..d873de9e7d 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/block_access_list/modifiers.py
+++ b/packages/tests/src/ethereum_test_types/block_access_list/modifiers.py
@@ -1,14 +1,14 @@
"""
BAL modifier functions for invalid test cases.
-This module provides modifier functions that can be used to modify Block Access Lists
-in various ways for testing invalid block scenarios. They are composable and can be
-combined to create complex modifications.
+This module provides modifier functions that can be used to modify Block Access
+Lists in various ways for testing invalid block scenarios. They are composable
+and can be combined to create complex modifications.
"""
-from typing import Callable, List
+from typing import Any, Callable, List, Optional
-from ethereum_test_base_types import Address, Number
+from ethereum_test_base_types import Address, HexNumber
from .. import BalCodeChange
from . import (
@@ -20,222 +20,186 @@
)
-def remove_accounts(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
- """Remove entire account entries from the BAL."""
-
- def transform(bal: BlockAccessList) -> BlockAccessList:
- new_root = []
- for account_change in bal.root:
- if account_change.address not in addresses:
- new_root.append(account_change)
- return BlockAccessList(root=new_root)
-
- return transform
-
-
-def remove_nonces(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
- """Remove nonce changes from specified accounts."""
+def _remove_field_from_accounts(
+ addresses: tuple[Address, ...], field_name: str
+) -> Callable[[BlockAccessList], BlockAccessList]:
+ """Abstracted helper to remove a field from specified accounts."""
+ len_addresses = len(addresses)
+ found_addresses = set()
def transform(bal: BlockAccessList) -> BlockAccessList:
+ nonlocal found_addresses
new_root = []
for account_change in bal.root:
if account_change.address in addresses:
- # Create a copy without nonce changes
+ found_addresses.add(account_change.address)
new_account = account_change.model_copy(deep=True)
- new_account.nonce_changes = []
+ # clear the specified field
+ setattr(new_account, field_name, [])
new_root.append(new_account)
else:
new_root.append(account_change)
+
+ if len(found_addresses) != len_addresses:
+ # sanity check that we found all addresses specified
+ missing = set(addresses) - found_addresses
+ raise ValueError(f"Some specified addresses were not found in the BAL: {missing}")
+
return BlockAccessList(root=new_root)
return transform
-def remove_balances(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
- """Remove balance changes from specified accounts."""
+def _modify_field_value(
+ address: Address,
+ tx_index: int,
+ field_name: str,
+ change_class: type,
+ new_value: Any,
+ value_field: str = "post_value",
+ nested: bool = False,
+ slot: Optional[int] = None,
+) -> Callable[[BlockAccessList], BlockAccessList]:
+ """
+ Abstracted helper to modify a field value for a specific account and
+ transaction.
+ """
+ found_address = False
def transform(bal: BlockAccessList) -> BlockAccessList:
+ nonlocal found_address
new_root = []
for account_change in bal.root:
- if account_change.address in addresses:
- # Create a copy without balance changes
+ if account_change.address == address:
+ found_address = True
new_account = account_change.model_copy(deep=True)
- new_account.balance_changes = []
+ changes = getattr(new_account, field_name)
+
+ if changes:
+ if nested and slot is not None:
+ # nested structure (storage)
+ for storage_slot in changes:
+ if storage_slot.slot == slot:
+ for j, change in enumerate(storage_slot.slot_changes):
+ if change.tx_index == tx_index:
+ kwargs = {"tx_index": tx_index, value_field: new_value}
+ storage_slot.slot_changes[j] = change_class(**kwargs)
+ break
+ break
+ else:
+ # flat structure (nonce, balance, code)
+ for i, change in enumerate(changes):
+ if change.tx_index == tx_index:
+ kwargs = {"tx_index": tx_index, value_field: new_value}
+ changes[i] = change_class(**kwargs)
+ break
+
new_root.append(new_account)
else:
new_root.append(account_change)
+
+ if not found_address:
+ # sanity check that we actually found the address
+ raise ValueError(f"Address {address} not found in BAL to modify {field_name}")
+
return BlockAccessList(root=new_root)
return transform
-def remove_storage(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
- """Remove storage changes from specified accounts."""
+def remove_accounts(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
+ """Remove entire account entries from the BAL."""
def transform(bal: BlockAccessList) -> BlockAccessList:
new_root = []
for account_change in bal.root:
- if account_change.address in addresses:
- # Create a copy without storage changes
- new_account = account_change.model_copy(deep=True)
- new_account.storage_changes = []
- new_root.append(new_account)
- else:
+ if account_change.address not in addresses:
new_root.append(account_change)
return BlockAccessList(root=new_root)
return transform
-def remove_storage_reads(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
- """Remove storage reads from specified accounts."""
+def remove_nonces(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
+ """Remove nonce changes from specified accounts."""
+ return _remove_field_from_accounts(addresses, "nonce_changes")
- def transform(bal: BlockAccessList) -> BlockAccessList:
- new_root = []
- for account_change in bal.root:
- if account_change.address in addresses:
- # Create a copy without storage reads
- new_account = account_change.model_copy(deep=True)
- new_account.storage_reads = []
- new_root.append(new_account)
- else:
- new_root.append(account_change)
- return BlockAccessList(root=new_root)
- return transform
+def remove_balances(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
+ """Remove balance changes from specified accounts."""
+ return _remove_field_from_accounts(addresses, "balance_changes")
-def remove_code(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
- """Remove code changes from specified accounts."""
+def remove_storage(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
+ """Remove storage changes from specified accounts."""
+ return _remove_field_from_accounts(addresses, "storage_changes")
- def transform(bal: BlockAccessList) -> BlockAccessList:
- new_root = []
- for account_change in bal.root:
- if account_change.address in addresses:
- # Create a copy without code changes
- new_account = account_change.model_copy(deep=True)
- new_account.code_changes = []
- new_root.append(new_account)
- else:
- new_root.append(account_change)
- return BlockAccessList(root=new_root)
- return transform
+def remove_storage_reads(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
+ """Remove storage reads from specified accounts."""
+ return _remove_field_from_accounts(addresses, "storage_reads")
+
+
+def remove_code(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
+ """Remove code changes from specified accounts."""
+ return _remove_field_from_accounts(addresses, "code_changes")
def modify_nonce(
address: Address, tx_index: int, nonce: int
) -> Callable[[BlockAccessList], BlockAccessList]:
"""Set an incorrect nonce value for a specific account and transaction."""
-
- def transform(bal: BlockAccessList) -> BlockAccessList:
- new_root = []
- for account_change in bal.root:
- if account_change.address == address:
- new_account = account_change.model_copy(deep=True)
- # Find and modify the specific nonce change
- for i, nonce_change in enumerate(new_account.nonce_changes or []):
- if nonce_change.tx_index == tx_index:
- new_account.nonce_changes[i] = BalNonceChange(
- tx_index=tx_index, post_nonce=nonce
- )
- break
- new_root.append(new_account)
- else:
- new_root.append(account_change)
- return BlockAccessList(root=new_root)
-
- return transform
+ return _modify_field_value(
+ address, tx_index, "nonce_changes", BalNonceChange, nonce, "post_nonce"
+ )
def modify_balance(
address: Address, tx_index: int, balance: int
) -> Callable[[BlockAccessList], BlockAccessList]:
- """Set an incorrect balance value for a specific account and transaction."""
-
- def transform(bal: BlockAccessList) -> BlockAccessList:
- new_root = []
- for account_change in bal.root:
- if account_change.address == address:
- new_account = account_change.model_copy(deep=True)
- # Find and modify the specific balance change
- if new_account.balance_changes:
- for i, balance_change in enumerate(new_account.balance_changes):
- if balance_change.tx_index == tx_index:
- # Create new balance change with wrong value
- new_account.balance_changes[i] = BalBalanceChange(
- tx_index=tx_index, post_balance=balance
- )
- break
- new_root.append(new_account)
- else:
- new_root.append(account_change)
- return BlockAccessList(root=new_root)
-
- return transform
+ """
+ Set an incorrect balance value for a specific account and transaction.
+ """
+ return _modify_field_value(
+ address, tx_index, "balance_changes", BalBalanceChange, balance, "post_balance"
+ )
def modify_storage(
address: Address, tx_index: int, slot: int, value: int
) -> Callable[[BlockAccessList], BlockAccessList]:
- """Set an incorrect storage value for a specific account, transaction, and slot."""
-
- def transform(bal: BlockAccessList) -> BlockAccessList:
- new_root = []
- for account_change in bal.root:
- if account_change.address == address:
- new_account = account_change.model_copy(deep=True)
- # Find and modify the specific storage change (nested structure)
- if new_account.storage_changes:
- for storage_slot in new_account.storage_changes:
- if storage_slot.slot == slot:
- for j, change in enumerate(storage_slot.slot_changes):
- if change.tx_index == tx_index:
- # Create new storage change with wrong value
- storage_slot.slot_changes[j] = BalStorageChange(
- tx_index=tx_index, post_value=value
- )
- break
- break
- new_root.append(new_account)
- else:
- new_root.append(account_change)
- return BlockAccessList(root=new_root)
-
- return transform
+ """
+ Set an incorrect storage value for a specific account, transaction, and
+ slot.
+ """
+ return _modify_field_value(
+ address,
+ tx_index,
+ "storage_changes",
+ BalStorageChange,
+ value,
+ "post_value",
+ nested=True,
+ slot=slot,
+ )
def modify_code(
address: Address, tx_index: int, code: bytes
) -> Callable[[BlockAccessList], BlockAccessList]:
"""Set an incorrect code value for a specific account and transaction."""
-
- def transform(bal: BlockAccessList) -> BlockAccessList:
- new_root = []
- for account_change in bal.root:
- if account_change.address == address:
- new_account = account_change.model_copy(deep=True)
- # Find and modify the specific code change
- if new_account.code_changes:
- for i, code_change in enumerate(new_account.code_changes):
- if code_change.tx_index == tx_index:
- # Create new code change with wrong value
- new_account.code_changes[i] = BalCodeChange(
- tx_index=tx_index, post_code=code
- )
- break
- new_root.append(new_account)
- else:
- new_root.append(account_change)
- return BlockAccessList(root=new_root)
-
- return transform
+ return _modify_field_value(address, tx_index, "code_changes", BalCodeChange, code, "post_code")
def swap_tx_indices(tx1: int, tx2: int) -> Callable[[BlockAccessList], BlockAccessList]:
"""Swap transaction indices throughout the BAL, modifying tx ordering."""
+ nonce_indices = {tx1: False, tx2: False}
+ balance_indices = nonce_indices.copy()
+ storage_indices = nonce_indices.copy()
+ code_indices = nonce_indices.copy()
def transform(bal: BlockAccessList) -> BlockAccessList:
+ nonlocal nonce_indices, balance_indices, storage_indices, code_indices
new_root = []
for account_change in bal.root:
new_account = account_change.model_copy(deep=True)
@@ -244,36 +208,45 @@ def transform(bal: BlockAccessList) -> BlockAccessList:
if new_account.nonce_changes:
for nonce_change in new_account.nonce_changes:
if nonce_change.tx_index == tx1:
- nonce_change.tx_index = Number(tx2)
+ nonce_indices[tx1] = True
+ nonce_change.tx_index = HexNumber(tx2)
elif nonce_change.tx_index == tx2:
- nonce_change.tx_index = Number(tx1)
+ nonce_indices[tx2] = True
+ nonce_change.tx_index = HexNumber(tx1)
# Swap in balance changes
if new_account.balance_changes:
for balance_change in new_account.balance_changes:
if balance_change.tx_index == tx1:
- balance_change.tx_index = Number(tx2)
+ balance_indices[tx1] = True
+ balance_change.tx_index = HexNumber(tx2)
elif balance_change.tx_index == tx2:
- balance_change.tx_index = Number(tx1)
+ balance_indices[tx2] = True
+ balance_change.tx_index = HexNumber(tx1)
# Swap in storage changes (nested structure)
if new_account.storage_changes:
for storage_slot in new_account.storage_changes:
for storage_change in storage_slot.slot_changes:
if storage_change.tx_index == tx1:
- storage_change.tx_index = Number(tx2)
+ balance_indices[tx1] = True
+ storage_change.tx_index = HexNumber(tx2)
elif storage_change.tx_index == tx2:
- storage_change.tx_index = Number(tx1)
+ balance_indices[tx2] = True
+ storage_change.tx_index = HexNumber(tx1)
- # Note: storage_reads is just a list of StorageKey, no tx_index to swap
+ # Note: storage_reads is just a list of StorageKey, no tx_index to
+ # swap
# Swap in code changes
if new_account.code_changes:
for code_change in new_account.code_changes:
if code_change.tx_index == tx1:
- code_change.tx_index = Number(tx2)
+ code_indices[tx1] = True
+ code_change.tx_index = HexNumber(tx2)
elif code_change.tx_index == tx2:
- code_change.tx_index = Number(tx1)
+ code_indices[tx2] = True
+ code_change.tx_index = HexNumber(tx1)
new_root.append(new_account)
@@ -297,14 +270,22 @@ def transform(bal: BlockAccessList) -> BlockAccessList:
def duplicate_account(address: Address) -> Callable[[BlockAccessList], BlockAccessList]:
"""Duplicate an account entry in the BAL."""
+ address_present = False
def transform(bal: BlockAccessList) -> BlockAccessList:
+ nonlocal address_present
new_root = []
for account_change in bal.root:
new_root.append(account_change)
if account_change.address == address:
# Add duplicate immediately after
new_root.append(account_change.model_copy(deep=True))
+ address_present = True
+
+ if not address_present:
+ # sanity check that we actually duplicate
+ raise ValueError(f"Address {address} not found in BAL to duplicate")
+
return BlockAccessList(root=new_root)
return transform
@@ -345,6 +326,7 @@ def clear_all() -> Callable[[BlockAccessList], BlockAccessList]:
"""Return an empty BAL."""
def transform(bal: BlockAccessList) -> BlockAccessList:
+ del bal
return BlockAccessList(root=[])
return transform
@@ -352,12 +334,18 @@ def transform(bal: BlockAccessList) -> BlockAccessList:
def keep_only(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]:
"""Keep only the specified accounts, removing all others."""
+ len_addresses = len(addresses)
def transform(bal: BlockAccessList) -> BlockAccessList:
new_root = []
for account_change in bal.root:
if account_change.address in addresses:
new_root.append(account_change)
+
+ if len(new_root) != len_addresses:
+ # sanity check that we found all specified addresses
+ raise ValueError("Some specified addresses were not found in the BAL")
+
return BlockAccessList(root=new_root)
return transform
diff --git a/packages/tests/src/ethereum_test_types/block_access_list/t8n.py b/packages/tests/src/ethereum_test_types/block_access_list/t8n.py
new file mode 100644
index 0000000000..848b8d796a
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/block_access_list/t8n.py
@@ -0,0 +1,49 @@
+"""Block Access List (BAL) for t8n tool communication and fixtures."""
+
+from functools import cached_property
+from typing import Any, List
+
+import ethereum_rlp as eth_rlp
+from pydantic import Field
+
+from ethereum_test_base_types import Bytes, EthereumTestRootModel
+from ethereum_test_base_types.serialization import to_serializable_element
+
+from .account_changes import BalAccountChange
+
+
+class BlockAccessList(EthereumTestRootModel[List[BalAccountChange]]):
+ """
+ Block Access List for t8n tool communication and fixtures.
+
+ This model represents the BAL exactly as defined in EIP-7928
+ - it is itself a list of account changes (root model), not a container.
+
+ Used for:
+ - Communication with t8n tools
+ - Fixture generation
+ - RLP encoding for hash verification
+
+ Example:
+ bal = BlockAccessList([
+ BalAccountChange(address=alice, nonce_changes=[...]),
+ BalAccountChange(address=bob, balance_changes=[...])
+ ])
+
+ """
+
+ root: List[BalAccountChange] = Field(default_factory=list)
+
+ def to_list(self) -> List[Any]:
+ """Return the list for RLP encoding per EIP-7928."""
+ return to_serializable_element(self.root)
+
+ @cached_property
+ def rlp(self) -> Bytes:
+ """Return the RLP encoded block access list for hash verification."""
+ return Bytes(eth_rlp.encode(self.to_list()))
+
+ @cached_property
+ def rlp_hash(self) -> Bytes:
+ """Return the hash of the RLP encoded block access list."""
+ return self.rlp.keccak256()
diff --git a/src/ethereum_spec_tests/ethereum_test_types/block_types.py b/packages/tests/src/ethereum_test_types/block_types.py
similarity index 87%
rename from src/ethereum_spec_tests/ethereum_test_types/block_types.py
rename to packages/tests/src/ethereum_test_types/block_types.py
index 268296f49a..6df95e52d6 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/block_types.py
+++ b/packages/tests/src/ethereum_test_types/block_types.py
@@ -38,7 +38,10 @@ class EnvironmentDefaults:
class WithdrawalGeneric(CamelModel, Generic[NumberBoundTypeVar]):
- """Withdrawal generic type, used as a parent class for `Withdrawal` and `FixtureWithdrawal`."""
+ """
+ Withdrawal generic type, used as a parent class for `Withdrawal` and
+ `FixtureWithdrawal`.
+ """
index: NumberBoundTypeVar
validator_index: NumberBoundTypeVar
@@ -47,8 +50,8 @@ class WithdrawalGeneric(CamelModel, Generic[NumberBoundTypeVar]):
def to_serializable_list(self) -> List[Any]:
"""
- Return list of the withdrawal's attributes in the order they should
- be serialized.
+ Return list of the withdrawal's attributes in the order they should be
+ serialized.
"""
return [
Uint(self.index),
@@ -98,8 +101,8 @@ class EnvironmentGeneric(CamelModel, Generic[NumberBoundTypeVar]):
class Environment(EnvironmentGeneric[ZeroPaddedHexNumber]):
"""
- Structure used to keep track of the context in which a block
- must be executed.
+ Structure used to keep track of the context in which a block must be
+ executed.
"""
blob_gas_used: ZeroPaddedHexNumber | None = Field(None, alias="currentBlobGasUsed")
@@ -137,40 +140,46 @@ def set_fork_requirements(self, fork: Fork) -> "Environment":
updated_values: Dict[str, Any] = {}
- if fork.header_prev_randao_required(number, timestamp) and self.prev_randao is None:
+ if (
+ fork.header_prev_randao_required(block_number=number, timestamp=timestamp)
+ and self.prev_randao is None
+ ):
updated_values["prev_randao"] = 0
- if fork.header_withdrawals_required(number, timestamp) and self.withdrawals is None:
+ if (
+ fork.header_withdrawals_required(block_number=number, timestamp=timestamp)
+ and self.withdrawals is None
+ ):
updated_values["withdrawals"] = []
if (
- fork.header_base_fee_required(number, timestamp)
+ fork.header_base_fee_required(block_number=number, timestamp=timestamp)
and self.base_fee_per_gas is None
and self.parent_base_fee_per_gas is None
):
updated_values["base_fee_per_gas"] = DEFAULT_BASE_FEE
- if fork.header_zero_difficulty_required(number, timestamp):
+ if fork.header_zero_difficulty_required(block_number=number, timestamp=timestamp):
updated_values["difficulty"] = 0
elif self.difficulty is None and self.parent_difficulty is None:
updated_values["difficulty"] = 0x20000
if (
- fork.header_excess_blob_gas_required(number, timestamp)
+ fork.header_excess_blob_gas_required(block_number=number, timestamp=timestamp)
and self.excess_blob_gas is None
and self.parent_excess_blob_gas is None
):
updated_values["excess_blob_gas"] = 0
if (
- fork.header_blob_gas_used_required(number, timestamp)
+ fork.header_blob_gas_used_required(block_number=number, timestamp=timestamp)
and self.blob_gas_used is None
and self.parent_blob_gas_used is None
):
updated_values["blob_gas_used"] = 0
if (
- fork.header_beacon_root_required(number, timestamp)
+ fork.header_beacon_root_required(block_number=number, timestamp=timestamp)
and self.parent_beacon_block_root is None
):
updated_values["parent_beacon_block_root"] = 0
diff --git a/src/ethereum_spec_tests/ethereum_test_types/chain_config_types.py b/packages/tests/src/ethereum_test_types/chain_config_types.py
similarity index 93%
rename from src/ethereum_spec_tests/ethereum_test_types/chain_config_types.py
rename to packages/tests/src/ethereum_test_types/chain_config_types.py
index a8c7b2e484..d9ece600f1 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/chain_config_types.py
+++ b/packages/tests/src/ethereum_test_types/chain_config_types.py
@@ -9,7 +9,8 @@ class ChainConfigDefaults:
"""
Default values for the chain configuration.
- Can be modified by modules that import this module and want to override the default values.
+ Can be modified by modules that import this module and want to override the
+ default values.
"""
chain_id: int = 1
diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/__init__.py b/packages/tests/src/ethereum_test_types/eof/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/eof/__init__.py
rename to packages/tests/src/ethereum_test_types/eof/__init__.py
diff --git a/packages/tests/src/ethereum_test_types/eof/constants.py b/packages/tests/src/ethereum_test_types/eof/constants.py
new file mode 100644
index 0000000000..c047002fa2
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/eof/constants.py
@@ -0,0 +1,20 @@
+"""EVM Object Format generic constants. Applicable to all EOF versions."""
+
+EOF_MAGIC = b"\xef\x00"
+"""
+The second byte found on every EOF formatted contract, which was chosen to
+avoid clashes with three contracts which were deployed on Mainnet.
+"""
+EOF_HEADER_TERMINATOR = b"\x00"
+"""Byte that terminates the header of the EOF format."""
+LATEST_EOF_VERSION = 1
+"""Latest existing EOF version."""
+VERSION_BYTE_LENGTH = 1
+"""Length of the version byte."""
+
+MAX_RUNTIME_STACK_HEIGHT = 1024
+"""
+Maximum height of the EVM runtime operand stack. Exceeding this value during
+execution will result in the stack overflow exception. This value applies to
+both legacy EVM and EOF.
+"""
diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/v1/__init__.py b/packages/tests/src/ethereum_test_types/eof/v1/__init__.py
similarity index 86%
rename from src/ethereum_spec_tests/ethereum_test_types/eof/v1/__init__.py
rename to packages/tests/src/ethereum_test_types/eof/v1/__init__.py
index 0a7385cad9..1dddb0f71c 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/eof/v1/__init__.py
+++ b/packages/tests/src/ethereum_test_types/eof/v1/__init__.py
@@ -1,4 +1,6 @@
-"""EVM Object Format Version 1 Library to generate bytecode for testing purposes."""
+"""
+EVM Object Format Version 1 Library to generate bytecode for testing purposes.
+"""
from dataclasses import dataclass
from enum import Enum, IntEnum, auto
@@ -56,7 +58,10 @@ class ContainerKind(Enum):
def __get_pydantic_core_schema__(
source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
- """Call class constructor without info and appends the serialization schema."""
+ """
+ Call class constructor without info and appends the serialization
+ schema.
+ """
return no_info_plain_validator_function(
source_type.from_str,
serialization=to_string_ser_schema(),
@@ -105,19 +110,18 @@ class Section(CopyValidateModel):
data: Bytes = Bytes(b"")
"""
- Data to be contained by this section.
- Can be SupportsBytes, another EOF container or any other abstract data.
+ Data to be contained by this section. Can be SupportsBytes, another EOF
+ container or any other abstract data.
"""
custom_size: int = 0
"""
- Custom size value to be used in the header.
- If unset, the header is built with length of the data.
+ Custom size value to be used in the header. If unset, the header is built
+ with length of the data.
"""
kind: SectionKind | int
"""
- Kind of section that is represented by this object.
- Can be any `int` outside of the values defined by `SectionKind`
- for testing purposes.
+ Kind of section that is represented by this object. Can be any `int`
+ outside of the values defined by `SectionKind` for testing purposes.
"""
force_type_listing: bool = False
"""
@@ -125,22 +129,16 @@ class Section(CopyValidateModel):
container.
"""
code_inputs: int = 0
- """
- Data stack items consumed by this code section (function)
- """
+ """Data stack items consumed by this code section (function)"""
code_outputs: int = NON_RETURNING_SECTION
"""
Data stack items produced by or expected at the end of this code section
(function)
"""
max_stack_increase: int | None = None
- """
- Maximum operand stack height increase above the code section inputs.
- """
+ """Maximum operand stack height increase above the code section inputs."""
max_stack_height: int | None = None
- """
- Maximum height data stack reaches during execution of code section.
- """
+ """Maximum height data stack reaches during execution of code section."""
auto_max_stack_height: bool = False
"""
Whether to automatically compute the best suggestion for the
@@ -152,20 +150,17 @@ class Section(CopyValidateModel):
code_outputs values for this code section.
"""
skip_header_listing: bool = False
- """
- Skip section from listing in the header
- """
+ """Skip section from listing in the header"""
skip_body_listing: bool = False
- """
- Skip section from listing in the body
- """
+ """Skip section from listing in the body"""
skip_types_body_listing: bool = False
"""
Skip section from listing in the types body (input, output, stack) bytes
"""
skip_types_header_listing: bool = False
"""
- Skip section from listing in the types header (not calculating input, output, stack size)
+ Skip section from listing in the types header (not calculating input,
+ output, stack size)
"""
@cached_property
@@ -219,27 +214,27 @@ def type_definition(self) -> bytes:
def with_max_stack_height(self, max_stack_height) -> "Section":
"""
- Create copy of the section with `max_stack_height` set to the
- specified value.
+ Create copy of the section with `max_stack_height` set to the specified
+ value.
"""
return self.copy(max_stack_height=max_stack_height)
def with_auto_max_stack_height(self) -> "Section":
- """Create copy of the section with `auto_max_stack_height` set to True."""
+ """
+ Create copy of the section with `auto_max_stack_height` set to True.
+ """
return self.copy(auto_max_stack_height=True)
def with_auto_code_inputs_outputs(self) -> "Section":
"""
- Create copy of the section with `auto_code_inputs_outputs` set to
- True.
+ Create copy of the section with `auto_code_inputs_outputs` set to True.
"""
return self.copy(auto_code_inputs_outputs=True)
@staticmethod
def list_header(sections: List["Section"]) -> bytes:
"""
- Create single code header for all code sections contained in
- the list.
+ Create single code header for all code sections contained in the list.
"""
# Allow 'types section' to use skip_header_listing flag
if sections[0].skip_header_listing:
@@ -250,7 +245,8 @@ def list_header(sections: List["Section"]) -> bytes:
h = sections[0].kind.to_bytes(HEADER_SECTION_KIND_BYTE_LENGTH, "big")
- # Count only those sections that are not marked to be skipped for header calculation
+ # Count only those sections that are not marked to be skipped for
+ # header calculation
header_registered_sections = 0
for cs in sections:
if not cs.skip_header_listing:
@@ -258,7 +254,8 @@ def list_header(sections: List["Section"]) -> bytes:
h += header_registered_sections.to_bytes(HEADER_SECTION_COUNT_BYTE_LENGTH, "big")
for cs in sections:
- # If section is marked to skip the header calculation, don't make header for it
+ # If section is marked to skip the header calculation, don't make
+ # header for it
if cs.skip_header_listing:
continue
size = cs.custom_size if "custom_size" in cs.model_fields_set else len(cs.data)
@@ -307,13 +304,9 @@ class Container(CopyValidateModel):
"""Class that represents an EOF V1 container."""
name: Optional[str] = None
- """
- Name of the container
- """
+ """Name of the container"""
sections: List[Section] = Field(default_factory=list)
- """
- List of sections in the container
- """
+ """List of sections in the container"""
magic: Bytes = Bytes(EOF_MAGIC)
"""
Custom magic value used to override the mandatory EOF value for testing
@@ -321,59 +314,46 @@ class Container(CopyValidateModel):
"""
version: Bytes = Bytes(VERSION_NUMBER_BYTES)
"""
- Custom version value used to override the mandatory EOF V1 value
- for testing purposes.
+ Custom version value used to override the mandatory EOF V1 value for
+ testing purposes.
"""
header_terminator: Bytes = Bytes(EOF_HEADER_TERMINATOR)
- """
- Bytes used to terminate the header.
- """
+ """Bytes used to terminate the header."""
extra: Bytes = Bytes(b"")
"""
- Extra data to be appended at the end of the container, which will
- not be considered part of any of the sections, for testing purposes.
+ Extra data to be appended at the end of the container, which will not be
+ considered part of any of the sections, for testing purposes.
"""
auto_type_section: AutoSection = AutoSection.AUTO
"""
- Automatically generate a `TYPE` section based on the
- included `CODE` kind sections.
+ Automatically generate a `TYPE` section based on the included `CODE` kind
+ sections.
"""
auto_data_section: bool = True
- """
- Automatically generate a `DATA` section.
- """
+ """Automatically generate a `DATA` section."""
auto_sort_sections: AutoSection = AutoSection.AUTO
"""
- Automatically sort sections for the header and body:
- Headers: type section first, all code sections, container sections, last
- data section(s)
- Body: type section first, all code sections, data section(s), last
- container sections
+ Automatically sort sections for the header and body: Headers: type section
+ first, all code sections, container sections, last data section(s) Body:
+ type section first, all code sections, data section(s), last container
+ sections
"""
skip_join_concurrent_sections_in_header: bool = False
- """
- Skip joining concurrent sections in the header (code and container)
- """
+ """Skip joining concurrent sections in the header (code and container)"""
validity_error: EOFExceptionInstanceOrList | str | None = None
- """
- Optional error expected for the container.
-
- TODO: Remove str
- """
+ """Optional error expected for the container. TODO: Remove str"""
kind: ContainerKind = ContainerKind.RUNTIME
- """
- Kind type of the container.
- """
+ """Kind type of the container."""
raw_bytes: Optional[Bytes] = None
"""
- Optional raw bytes that represent the container.
- Used to have a cohesive type among all test cases, even those that do not
- resemble a valid EOF V1 container.
+ Optional raw bytes that represent the container. Used to have a cohesive
+ type among all test cases, even those that do not resemble a valid EOF V1
+ container.
"""
expected_bytecode: Optional[Bytes] = None
"""
- Optional raw bytes of the expected constructed bytecode.
- This allows confirming that raw EOF and Container() representations are identical.
+ Optional raw bytes of the expected constructed bytecode. This allows
+ confirming that raw EOF and Container() representations are identical.
"""
@cached_property
@@ -419,7 +399,8 @@ def bytecode(self) -> bytes:
# Add headers
if header_sections:
- # Join headers of the same kind in a list of lists, only if they are next to each other
+ # Join headers of the same kind in a list of lists, only if they
+ # are next to each other
concurrent_sections: List[List[Section]] = [[header_sections[0]]]
for s in header_sections[1:]:
if (
@@ -469,7 +450,9 @@ def Init( # noqa: N802
deploy_container: "Container",
initcode_prefix: Optional[Bytecode] = None,
) -> "Container":
- """Create simple init container that deploys the specified container."""
+ """
+ Create simple init container that deploys the specified container.
+ """
if initcode_prefix is None:
initcode_prefix = Bytecode()
return cls(
@@ -498,8 +481,8 @@ def __len__(self) -> int:
def __str__(self) -> str:
"""
- Return name of the container if available, otherwise the bytecode of the container
- as a string.
+ Return name of the container if available, otherwise the bytecode of
+ the container as a string.
"""
if self.name:
return self.name
@@ -514,13 +497,9 @@ class Initcode(Bytecode):
"""
name: str = "EOF V1 Initcode"
- """
- Name used to identify the initcode.
- """
+ """Name used to identify the initcode."""
deploy_container: Container
- """
- Container to be deployed.
- """
+ """Container to be deployed."""
@cached_property
def init_container(self) -> Container:
@@ -539,7 +518,9 @@ def init_container(self) -> Container:
@cached_property
def bytecode(self) -> bytes:
- """Generate an EOF container performs `EOFCREATE` with the specified code."""
+ """
+ Generate an EOF container performs `EOFCREATE` with the specified code.
+ """
initcode = Container(
sections=[
Section.Code(
diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/v1/constants.py b/packages/tests/src/ethereum_test_types/eof/v1/constants.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/eof/v1/constants.py
rename to packages/tests/src/ethereum_test_types/eof/v1/constants.py
diff --git a/src/ethereum_spec_tests/ethereum_test_types/helpers.py b/packages/tests/src/ethereum_test_types/helpers.py
similarity index 91%
rename from src/ethereum_spec_tests/ethereum_test_types/helpers.py
rename to packages/tests/src/ethereum_test_types/helpers.py
index 802adfced2..4378dc292b 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/helpers.py
+++ b/packages/tests/src/ethereum_test_types/helpers.py
@@ -19,8 +19,8 @@
def ceiling_division(a: int, b: int) -> int:
"""
- Calculate ceil without using floating point.
- Used by many of the EVM's formulas.
+ Calculate ceil without using floating point. Used by many of the EVM's
+ formulas.
"""
return -(a // -b)
@@ -34,8 +34,8 @@ def compute_create_address(
opcode: Op = Op.CREATE,
) -> Address:
"""
- Compute address of the resulting contract created using a transaction
- or the `CREATE` opcode.
+ Compute address of the resulting contract created using a transaction or
+ the `CREATE` opcode.
"""
if opcode == Op.CREATE:
if isinstance(address, EOA):
@@ -68,7 +68,10 @@ def compute_create2_address(
def compute_eofcreate_address(
address: FixedSizeBytesConvertible, salt: FixedSizeBytesConvertible
) -> Address:
- """Compute address of the resulting contract created using the `EOFCREATE` opcode."""
+ """
+ Compute address of the resulting contract created using the `EOFCREATE`
+ opcode.
+ """
hash_bytes = Bytes(b"\xff" + b"\x00" * 12 + Address(address) + Hash(salt)).keccak256()
return Address(hash_bytes[-20:])
@@ -106,13 +109,14 @@ class TestParameterGroup(BaseModel):
def __repr__(self):
"""
- Generate repr string, intended to be used as a test id, based on the class
- name and the values of the non-default optional fields.
+ Generate repr string, intended to be used as a test id, based on the
+ class name and the values of the non-default optional fields.
"""
class_name = self.__class__.__name__
field_strings = [
f"{field}_{value}"
- # Include the field only if it is not optional or not set to its default value
+ # Include the field only if it is not optional or not set to its
+ # default value
for field, value in self.model_dump(exclude_defaults=True, exclude_unset=True).items()
]
diff --git a/src/ethereum_spec_tests/ethereum_test_types/kzg_trusted_setup.txt b/packages/tests/src/ethereum_test_types/kzg_trusted_setup.txt
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/kzg_trusted_setup.txt
rename to packages/tests/src/ethereum_test_types/kzg_trusted_setup.txt
diff --git a/src/ethereum_spec_tests/ethereum_test_types/py.typed b/packages/tests/src/ethereum_test_types/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/py.typed
rename to packages/tests/src/ethereum_test_types/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_test_types/receipt_types.py b/packages/tests/src/ethereum_test_types/receipt_types.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/receipt_types.py
rename to packages/tests/src/ethereum_test_types/receipt_types.py
diff --git a/src/ethereum_spec_tests/ethereum_test_types/request_types.py b/packages/tests/src/ethereum_test_types/request_types.py
similarity index 89%
rename from src/ethereum_spec_tests/ethereum_test_types/request_types.py
rename to packages/tests/src/ethereum_test_types/request_types.py
index e56ed23148..d38fd62b5e 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/request_types.py
+++ b/packages/tests/src/ethereum_test_types/request_types.py
@@ -30,26 +30,18 @@ class DepositRequest(RequestBase, CamelModel):
"""Deposit Request type."""
pubkey: BLSPublicKey
- """
- The public key of the beacon chain validator.
- """
+ """The public key of the beacon chain validator."""
withdrawal_credentials: Hash
- """
- The withdrawal credentials of the beacon chain validator.
- """
+ """The withdrawal credentials of the beacon chain validator."""
amount: HexNumber
- """
- The amount in gwei of the deposit.
- """
+ """The amount in gwei of the deposit."""
signature: BLSSignature
"""
- The signature of the deposit using the validator's private key that matches the
- `pubkey`.
+ The signature of the deposit using the validator's private key that matches
+ the `pubkey`.
"""
index: HexNumber
- """
- The index of the deposit.
- """
+ """The index of the deposit."""
type: ClassVar[int] = 0
@@ -69,16 +61,16 @@ class WithdrawalRequest(RequestBase, CamelModel):
source_address: Address = Address(0)
"""
- The address of the execution layer account that made the withdrawal request.
+ The address of the execution layer account that made the withdrawal
+ request.
"""
validator_pubkey: BLSPublicKey
"""
- The current public key of the validator as it currently is in the beacon state.
+ The current public key of the validator as it currently is in the beacon
+ state.
"""
amount: HexNumber
- """
- The amount in gwei to be withdrawn on the beacon chain.
- """
+ """The amount in gwei to be withdrawn on the beacon chain."""
type: ClassVar[int] = 1
@@ -96,15 +88,18 @@ class ConsolidationRequest(RequestBase, CamelModel):
source_address: Address = Address(0)
"""
- The address of the execution layer account that made the consolidation request.
+ The address of the execution layer account that made the consolidation
+ request.
"""
source_pubkey: BLSPublicKey
"""
- The public key of the source validator as it currently is in the beacon state.
+ The public key of the source validator as it currently is in the beacon
+ state.
"""
target_pubkey: BLSPublicKey
"""
- The public key of the target validator as it currently is in the beacon state.
+ The public key of the target validator as it currently is in the beacon
+ state.
"""
type: ClassVar[int] = 2
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/__init__.py b/packages/tests/src/ethereum_test_types/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/tests/__init__.py
rename to packages/tests/src/ethereum_test_types/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_blob_types.py b/packages/tests/src/ethereum_test_types/tests/test_blob_types.py
similarity index 88%
rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_blob_types.py
rename to packages/tests/src/ethereum_test_types/tests/test_blob_types.py
index 4aefc61a91..88cf1501f5 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/tests/test_blob_types.py
+++ b/packages/tests/src/ethereum_test_types/tests/test_blob_types.py
@@ -24,14 +24,14 @@ def increment_counter(timeout: float = 10):
"""
Increment counter in file, creating if doesn't exist.
- This is needed because we require the unit test 'test_transition_fork_blobs' to run
- at the end without having to include another dependency for ordering tests.
- That test has to run at the end because it assumes that no json blobs not created
- by itself are created while it is running.
-
- The hardcoded counter value in the test above has to be updated if any new blob_related
- unit tests that create json blobs are added in the future.
-
+ This is needed because we require the unit test
+ 'test_transition_fork_blobs' to run at the end without having to include
+ another dependency for ordering tests. That test has to run at the end
+ because it assumes that no json blobs not created by itself are created
+ while it is running.
+
+ The hardcoded counter value in the test above has to be updated if any new
+ blob_related unit tests that create json blobs are added in the future.
"""
file_path = CACHED_BLOBS_DIRECTORY / "blob_unit_test_counter.txt"
lock_file = file_path.with_suffix(".lock")
@@ -62,7 +62,6 @@ def wait_until_counter_reached(target: int, poll_interval: float = 0.1):
try:
current_value = int(file_path.read_text().strip())
if current_value == target:
- # file_path.unlink() # get rid to effectively reset counter to 0
return current_value
elif current_value > target:
pytest.fail(
@@ -86,8 +85,8 @@ def test_blob_creation_and_writing_and_reading(
fork,
): # noqa: F811
"""
- Generates blobs for different forks and ensures writing to file
- and reading from file works as expected.
+ Generates blobs for different forks and ensures writing to file and reading
+ from file works as expected.
"""
timestamp = 100
b = Blob.from_fork(fork=fork, seed=seed, timestamp=timestamp)
@@ -145,15 +144,20 @@ def test_transition_fork_blobs(
fork,
timestamp,
):
- """Generates blobs for transition forks (time 14999 is old fork, time 15000 is new fork)."""
- # line below guarantees that this test runs only after the other blob unit tests are done
+ """
+ Generates blobs for transition forks (time 14999 is old fork, time 15000 is
+ new fork).
+ """
+ # line below guarantees that this test runs only after the other blob unit
+ # tests are done
wait_until_counter_reached(21)
clear_blob_cache(CACHED_BLOBS_DIRECTORY)
print(f"Original fork: {fork}, Timestamp: {timestamp}")
pre_transition_fork = fork.transitions_from()
- post_transition_fork_at_15k = fork.transitions_to() # only reached if timestamp >= 15000
+ # only reached if timestamp >= 15000
+ post_transition_fork_at_15k = fork.transitions_to()
if not pre_transition_fork.supports_blobs() and timestamp < 15000:
print(
@@ -178,6 +182,7 @@ def test_transition_fork_blobs(
f"transitioned to {post_transition_fork_at_15k.name()} but is still at {b.fork.name()}"
)
- # delete counter at last iteration (otherwise re-running all unit tests will fail)
+ # delete counter at last iteration (otherwise re-running all unit tests
+ # will fail)
if timestamp == 15_000 and pre_transition_fork == Prague:
(CACHED_BLOBS_DIRECTORY / "blob_unit_test_counter.txt").unlink()
diff --git a/packages/tests/src/ethereum_test_types/tests/test_block_access_lists.py b/packages/tests/src/ethereum_test_types/tests/test_block_access_lists.py
new file mode 100644
index 0000000000..cd78a1cfe9
--- /dev/null
+++ b/packages/tests/src/ethereum_test_types/tests/test_block_access_lists.py
@@ -0,0 +1,1132 @@
+"""Unit tests for BlockAccessListExpectation validation."""
+
+import pytest
+
+from ethereum_test_base_types import Address, StorageKey
+from ethereum_test_types.block_access_list import (
+ BalAccountAbsentValues,
+ BalAccountChange,
+ BalAccountExpectation,
+ BalBalanceChange,
+ BalCodeChange,
+ BalNonceChange,
+ BalStorageChange,
+ BalStorageSlot,
+ BlockAccessList,
+ BlockAccessListExpectation,
+ BlockAccessListValidationError,
+)
+
+
+def test_address_exclusion_validation_passes():
+ """Test that address exclusion works when address is not in BAL."""
+ alice = Address(0xA)
+ bob = Address(0xB)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]),
+ bob: None, # expect Bob is not in BAL (correctly)
+ }
+ )
+
+ expectation.verify_against(actual_bal)
+
+
+def test_address_exclusion_validation_raises_when_address_is_present():
+ """Test that validation fails when excluded address is in BAL."""
+ alice = Address(0xA)
+ bob = Address(0xB)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ BalAccountChange(
+ address=bob,
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ # explicitly expect Bob to NOT be in BAL (wrongly)
+ account_expectations={bob: None},
+ )
+
+ with pytest.raises(BlockAccessListValidationError, match="should not be in BAL but was found"):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "empty_changes_definition,exception_message",
+ [
+ [BalAccountExpectation(), "ambiguous. Use BalAccountExpectation.empty()"],
+ [BalAccountExpectation.empty(), "No account changes expected for "],
+ ],
+ ids=["BalAccountExpectation()", "BalAccountExpectation.empty()"],
+)
+def test_empty_account_changes_definitions(
+ empty_changes_definition,
+ exception_message,
+):
+ """
+ Test that validation fails when expected empty changes but actual
+ has changes.
+ """
+ alice = Address(0xA)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={alice: empty_changes_definition}
+ )
+
+ with pytest.raises(BlockAccessListValidationError, match=exception_message):
+ expectation.verify_against(actual_bal)
+
+
+def test_empty_list_validation():
+ """Test that empty list validates correctly."""
+ alice = Address(0xA)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=[],
+ balance_changes=[],
+ code_changes=[],
+ storage_changes=[],
+ storage_reads=[],
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[],
+ balance_changes=[],
+ code_changes=[],
+ storage_changes=[],
+ storage_reads=[],
+ ),
+ }
+ )
+
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "field,value",
+ [
+ ["nonce_changes", BalNonceChange(tx_index=1, post_nonce=1)],
+ ["balance_changes", BalBalanceChange(tx_index=1, post_balance=100)],
+ ["code_changes", BalCodeChange(tx_index=1, new_code=b"code")],
+ [
+ "storage_changes",
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
+ ),
+ ],
+ ["storage_reads", 0x01],
+ ],
+)
+def test_empty_list_validation_fails(field: str, value) -> None:
+ """Test that validation fails when expecting empty but field has values."""
+ alice = Address(0xA)
+
+ alice_acct_change = BalAccountChange(
+ address=alice,
+ storage_reads=[0x02],
+ )
+
+ if field == "storage_reads":
+ alice_acct_change.storage_reads = [value]
+ # set another field to non-empty to avoid all-empty account change
+ alice_acct_change.nonce_changes = [BalNonceChange(tx_index=1, post_nonce=1)]
+
+ else:
+ setattr(alice_acct_change, field, [value])
+ actual_bal = BlockAccessList([alice_acct_change])
+
+ alice_acct_expectation = BalAccountExpectation(
+ storage_reads=[0x02],
+ )
+ if field == "storage_reads":
+ alice_acct_expectation.storage_reads = []
+ # match the filled field in actual to avoid all-empty
+ # account expectation
+ alice_acct_expectation.nonce_changes = [BalNonceChange(tx_index=1, post_nonce=1)]
+ else:
+ setattr(alice_acct_expectation, field, [])
+
+ expectation = BlockAccessListExpectation(account_expectations={alice: alice_acct_expectation})
+
+ with pytest.raises(
+ BlockAccessListValidationError,
+ match=f"Expected {field} to be empty",
+ ):
+ expectation.verify_against(actual_bal)
+
+
+def test_partial_validation():
+ """Test that unset fields are not validated."""
+ alice = Address(0xA)
+
+ # Actual BAL has multiple types of changes
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
+ storage_reads=[0x01, 0x02],
+ ),
+ ]
+ )
+
+ # Only validate nonce changes, ignore balance and storage
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ # balance_changes and storage_reads not set and won't be
+ # validated
+ ),
+ }
+ )
+
+ expectation.verify_against(actual_bal)
+
+
+def test_storage_changes_validation():
+ """Test storage changes validation."""
+ contract = Address(0xC)
+
+ # Actual BAL with storage changes
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=contract,
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
+ )
+ ],
+ ),
+ ]
+ )
+
+ # Expect the same storage changes
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ contract: BalAccountExpectation(
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
+ )
+ ],
+ ),
+ }
+ )
+
+ expectation.verify_against(actual_bal)
+
+
+def test_missing_expected_address():
+ """Test that validation fails when expected address is missing."""
+ alice = Address(0xA)
+ bob = Address(0xB)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ # wrongly expect Bob to be present
+ bob: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ }
+ )
+
+ with pytest.raises(
+ BlockAccessListValidationError, match="Expected address .* not found in actual BAL"
+ ):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "addresses,error_message",
+ [
+ (
+ [
+ Address(0xB),
+ Address(0xA), # should come first
+ ],
+ "BAL addresses are not in lexicographic order",
+ ),
+ (
+ [
+ Address(0x1),
+ Address(0x3),
+ Address(0x2),
+ ],
+ "BAL addresses are not in lexicographic order",
+ ),
+ ],
+)
+def test_actual_bal_address_ordering_validation(addresses, error_message):
+ """Test that actual BAL must have addresses in lexicographic order."""
+ # Create BAL with addresses in the given order
+ actual_bal = BlockAccessList(
+ [BalAccountChange(address=addr, nonce_changes=[]) for addr in addresses]
+ )
+
+ expectation = BlockAccessListExpectation(account_expectations={})
+
+ with pytest.raises(BlockAccessListValidationError, match=error_message):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "storage_slots,error_message",
+ [
+ (
+ [StorageKey(0x02), StorageKey(0x01)], # 0x02 before 0x01
+ "Storage slots not in ascending order",
+ ),
+ (
+ [StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)],
+ "Storage slots not in ascending order",
+ ),
+ ],
+)
+def test_actual_bal_storage_slot_ordering(storage_slots, error_message):
+ """Test that actual BAL must have storage slots in lexicographic order."""
+ addr = Address(0xA)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr,
+ storage_changes=[
+ BalStorageSlot(slot=slot, slot_changes=[]) for slot in storage_slots
+ ],
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(account_expectations={})
+
+ with pytest.raises(BlockAccessListValidationError, match=error_message):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "storage_reads,error_message",
+ [
+ ([StorageKey(0x02), StorageKey(0x01)], "Storage reads not in ascending order"),
+ (
+ [StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)],
+ "Storage reads not in ascending order",
+ ),
+ ],
+)
+def test_actual_bal_storage_reads_ordering(storage_reads, error_message):
+ """Test that actual BAL must have storage reads in lexicographic order."""
+ addr = Address(0xA)
+
+ actual_bal = BlockAccessList([BalAccountChange(address=addr, storage_reads=storage_reads)])
+
+ expectation = BlockAccessListExpectation(account_expectations={})
+
+ with pytest.raises(BlockAccessListValidationError, match=error_message):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "field_name",
+ ["nonce_changes", "balance_changes", "code_changes"],
+)
+def test_actual_bal_tx_indices_ordering(field_name):
+ """Test that actual BAL must have tx indices in ascending order."""
+ addr = Address(0xA)
+
+ tx_indices = [2, 3, 1] # out of order
+
+ changes = []
+ if field_name == "nonce_changes":
+ changes = [BalNonceChange(tx_index=idx, post_nonce=1) for idx in tx_indices]
+ elif field_name == "balance_changes":
+ changes = [BalBalanceChange(tx_index=idx, post_balance=100) for idx in tx_indices]
+ elif field_name == "code_changes":
+ changes = [BalCodeChange(tx_index=idx, new_code=b"code") for idx in tx_indices]
+
+ actual_bal = BlockAccessList([BalAccountChange(address=addr, **{field_name: changes})])
+
+ expectation = BlockAccessListExpectation(account_expectations={})
+
+ with pytest.raises(
+ BlockAccessListValidationError,
+ match="Transaction indices not in ascending order",
+ ):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "field_name",
+ ["nonce_changes", "balance_changes", "code_changes"],
+)
+def test_actual_bal_duplicate_tx_indices(field_name):
+ """
+ Test that actual BAL must not have duplicate tx indices in change lists.
+ """
+ addr = Address(0xA)
+
+ # Duplicate tx_index=1
+ changes = []
+ if field_name == "nonce_changes":
+ changes = [
+ BalNonceChange(tx_index=1, post_nonce=1),
+ BalNonceChange(tx_index=1, post_nonce=2), # duplicate tx_index
+ BalNonceChange(tx_index=2, post_nonce=3),
+ ]
+ elif field_name == "balance_changes":
+ changes = [
+ BalBalanceChange(tx_index=1, post_balance=100),
+ BalBalanceChange(tx_index=1, post_balance=200), # duplicate tx_index
+ BalBalanceChange(tx_index=2, post_balance=300),
+ ]
+ elif field_name == "code_changes":
+ changes = [
+ BalCodeChange(tx_index=1, new_code=b"code1"),
+ BalCodeChange(tx_index=1, new_code=b""), # duplicate tx_index
+ BalCodeChange(tx_index=2, new_code=b"code2"),
+ ]
+
+ actual_bal = BlockAccessList([BalAccountChange(address=addr, **{field_name: changes})])
+
+ expectation = BlockAccessListExpectation(account_expectations={})
+
+ with pytest.raises(
+ BlockAccessListValidationError,
+ match=f"Duplicate transaction indices in {field_name}.*Duplicates: \\[1\\]",
+ ):
+ expectation.verify_against(actual_bal)
+
+
+def test_actual_bal_storage_duplicate_tx_indices():
+ """
+ Test that storage changes must not have duplicate tx indices within same
+ slot.
+ """
+ addr = Address(0xA)
+
+ # Create storage changes with duplicate tx_index within the same slot
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr,
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[
+ BalStorageChange(tx_index=1, post_value=0x100),
+ BalStorageChange(tx_index=1, post_value=0x200), # duplicate tx_index
+ BalStorageChange(tx_index=2, post_value=0x300),
+ ],
+ )
+ ],
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(account_expectations={})
+
+ with pytest.raises(
+ BlockAccessListValidationError,
+ match="Duplicate transaction indices in storage slot.*Duplicates: \\[1\\]",
+ ):
+ expectation.verify_against(actual_bal)
+
+
+def test_expected_addresses_auto_sorted():
+ """
+ Test that expected addresses are automatically sorted before comparison.
+
+ The BAL *Expectation address order should not matter for the dict. We DO,
+ however, validate that the actual BAL (from t8n) is sorted correctly.
+ """
+ alice = Address(0xA)
+ bob = Address(0xB)
+ charlie = Address(0xC)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(address=alice, nonce_changes=[]),
+ BalAccountChange(address=bob, nonce_changes=[]),
+ BalAccountChange(address=charlie, nonce_changes=[]),
+ ]
+ )
+
+ # expectation order should not matter for the dict though we DO validate
+ # that the _actual_ BAL (from t8n) is sorted correctly
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ charlie: BalAccountExpectation(nonce_changes=[]),
+ alice: BalAccountExpectation(nonce_changes=[]),
+ bob: BalAccountExpectation(nonce_changes=[]),
+ }
+ )
+
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "expected_slots,should_pass",
+ [
+ # Correct order - should pass
+ ([StorageKey(0x01), StorageKey(0x02), StorageKey(0x03)], True),
+ # Partial subset in correct order - should pass
+ ([StorageKey(0x01), StorageKey(0x03)], True),
+ # Out of order - should fail
+ ([StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], False),
+ # Wrong order from start - should fail
+ ([StorageKey(0x02), StorageKey(0x01)], False),
+ ],
+)
+def test_expected_storage_slots_ordering(expected_slots, should_pass):
+ """Test that expected storage slots must be defined in correct order."""
+ addr = Address(0xA)
+
+ # Actual BAL with storage slots in correct order
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr,
+ storage_changes=[
+ BalStorageSlot(slot=StorageKey(0x01), slot_changes=[]),
+ BalStorageSlot(slot=StorageKey(0x02), slot_changes=[]),
+ BalStorageSlot(slot=StorageKey(0x03), slot_changes=[]),
+ ],
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(
+ storage_changes=[
+ BalStorageSlot(slot=slot, slot_changes=[]) for slot in expected_slots
+ ],
+ ),
+ }
+ )
+
+ if should_pass:
+ expectation.verify_against(actual_bal)
+ else:
+ with pytest.raises(
+ BlockAccessListValidationError,
+ match="not found or not in correct order",
+ ):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "expected_reads,should_pass",
+ [
+ # Correct order - should pass
+ ([StorageKey(0x01), StorageKey(0x02), StorageKey(0x03)], True),
+ # Partial subset in correct order - should pass
+ ([StorageKey(0x02), StorageKey(0x03)], True),
+ # Out of order - should fail
+ ([StorageKey(0x03), StorageKey(0x02)], False),
+ # Wrong order with all elements - should fail
+ ([StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], False),
+ ],
+)
+def test_expected_storage_reads_ordering(expected_reads, should_pass):
+ """Test that expected storage reads must be defined in correct order."""
+ addr = Address(0xA)
+
+ # Actual BAL with storage reads in correct order
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr,
+ storage_reads=[StorageKey(0x01), StorageKey(0x02), StorageKey(0x03)],
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(storage_reads=expected_reads),
+ }
+ )
+
+ if should_pass:
+ expectation.verify_against(actual_bal)
+ else:
+ with pytest.raises(
+ BlockAccessListValidationError,
+ match="not found or not in correct order",
+ ):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "expected_tx_indices,should_pass",
+ [
+ # Correct order - should pass
+ ([1, 2, 3], True),
+ # Partial subset in correct order - should pass
+ ([1, 3], True),
+ # Single element - should pass
+ ([2], True),
+ # Out of order - should fail
+ ([2, 1], False),
+ # Wrong order with all elements - should fail
+ ([1, 3, 2], False),
+ ],
+)
+def test_expected_tx_indices_ordering(expected_tx_indices, should_pass):
+ """Test that expected tx indices must be defined in correct order."""
+ addr = Address(0xA)
+
+ # actual BAL with tx indices in correct order
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr,
+ nonce_changes=[
+ BalNonceChange(tx_index=1, post_nonce=1),
+ BalNonceChange(tx_index=2, post_nonce=2),
+ BalNonceChange(tx_index=3, post_nonce=3),
+ ],
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(
+ nonce_changes=[
+ BalNonceChange(tx_index=idx, post_nonce=idx) for idx in expected_tx_indices
+ ],
+ ),
+ }
+ )
+
+ if should_pass:
+ expectation.verify_against(actual_bal)
+ else:
+ with pytest.raises(
+ BlockAccessListValidationError,
+ match="not found or not in correct order",
+ ):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize("has_change_should_raise", [True, False])
+def test_absent_values_nonce_changes(has_change_should_raise):
+ """Test nonce_changes_at_tx validator with present/absent changes."""
+ alice = Address(0xA)
+
+ nonce_changes = [BalNonceChange(tx_index=1, post_nonce=1)]
+ if has_change_should_raise:
+ # add nonce change at tx 2 which should trigger failure
+ nonce_changes.append(BalNonceChange(tx_index=2, post_nonce=2))
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=nonce_changes,
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ # no nonce changes at tx 2
+ alice: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ nonce_changes=[BalNonceChange(tx_index=2, post_nonce=2)]
+ )
+ )
+ }
+ )
+
+ if has_change_should_raise:
+ with pytest.raises(Exception, match="Unexpected nonce change found at tx 0x2"):
+ expectation.verify_against(actual_bal)
+ else:
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize("has_change_should_raise", [True, False])
+def test_absent_values_balance_changes(has_change_should_raise):
+ """Test balance_changes_at_tx validator with present/absent changes."""
+ alice = Address(0xA)
+
+ balance_changes = [BalBalanceChange(tx_index=1, post_balance=100)]
+ if has_change_should_raise:
+ # add balance change at tx 2 which should trigger failure
+ balance_changes.append(BalBalanceChange(tx_index=2, post_balance=200))
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ balance_changes=balance_changes,
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ balance_changes=[BalBalanceChange(tx_index=2, post_balance=200)]
+ )
+ ),
+ }
+ )
+
+ if has_change_should_raise:
+ with pytest.raises(
+ Exception,
+ match="Unexpected balance change found at tx 0x2",
+ ):
+ expectation.verify_against(actual_bal)
+ else:
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize("has_change_should_raise", [True, False])
+def test_absent_values_storage_changes(has_change_should_raise):
+ """Test storage_changes_at_slots validator with present/absent changes."""
+ contract = Address(0xC)
+
+ storage_changes = [
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x99)],
+ )
+ ]
+ if has_change_should_raise:
+ storage_changes.append(
+ BalStorageSlot(
+ slot=0x42,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0xBEEF)],
+ )
+ )
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=contract,
+ storage_changes=storage_changes,
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ # no storage changes at slot 0x42
+ contract: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x42,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0xBEEF)],
+ )
+ ]
+ )
+ ),
+ }
+ )
+
+ if has_change_should_raise:
+ with pytest.raises(Exception, match="Unexpected storage change found at slot"):
+ expectation.verify_against(actual_bal)
+ else:
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize("has_read_should_raise", [True, False])
+def test_absent_values_storage_reads(has_read_should_raise):
+ """Test storage_reads_at_slots validator with present/absent reads."""
+ contract = Address(0xC)
+
+ # Create actual BAL with or without storage read at slot 0x42
+ storage_reads = [StorageKey(0x01)]
+ if has_read_should_raise:
+ storage_reads.append(StorageKey(0x42))
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=contract,
+ storage_reads=storage_reads,
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ # no storage reads at slot 0x42
+ contract: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(storage_reads=[StorageKey(0x42)])
+ ),
+ }
+ )
+
+ if has_read_should_raise:
+ with pytest.raises(Exception, match="Unexpected storage read found at slot"):
+ expectation.verify_against(actual_bal)
+ else:
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize("has_change_should_raise", [True, False])
+def test_absent_values_code_changes(has_change_should_raise):
+ """Test code_changes_at_tx validator with present/absent changes."""
+ alice = Address(0xA)
+
+ code_changes = [BalCodeChange(tx_index=1, new_code=b"\x00")]
+ if has_change_should_raise:
+ # add code change at tx 2 which should trigger failure
+ code_changes.append(BalCodeChange(tx_index=2, new_code=b"\x60\x00"))
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ code_changes=code_changes,
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ # no code changes at tx 2
+ alice: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ code_changes=[BalCodeChange(tx_index=2, new_code=b"\x60\x00")]
+ )
+ ),
+ }
+ )
+
+ if has_change_should_raise:
+ with pytest.raises(Exception, match="Unexpected code change found at tx 0x2"):
+ expectation.verify_against(actual_bal)
+ else:
+ expectation.verify_against(actual_bal)
+
+
+def test_multiple_absent_valuess():
+ """Test multiple absence validators working together."""
+ contract = Address(0xC)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=contract,
+ nonce_changes=[],
+ balance_changes=[],
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x99)],
+ )
+ ],
+ storage_reads=[StorageKey(0x01)],
+ code_changes=[],
+ ),
+ ]
+ )
+
+ # Test that multiple validators all pass
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ contract: BalAccountExpectation(
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x99)],
+ )
+ ],
+ absent_values=BalAccountAbsentValues(
+ nonce_changes=[
+ BalNonceChange(tx_index=1, post_nonce=0),
+ BalNonceChange(tx_index=2, post_nonce=0),
+ ],
+ balance_changes=[
+ BalBalanceChange(tx_index=1, post_balance=0),
+ BalBalanceChange(tx_index=2, post_balance=0),
+ ],
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x42, slot_changes=[BalStorageChange(tx_index=1, post_value=0)]
+ ),
+ BalStorageSlot(
+ slot=0x43, slot_changes=[BalStorageChange(tx_index=1, post_value=0)]
+ ),
+ ],
+ storage_reads=[StorageKey(0x42), StorageKey(0x43)],
+ code_changes=[
+ BalCodeChange(tx_index=1, new_code=b""),
+ BalCodeChange(tx_index=2, new_code=b""),
+ ],
+ ),
+ ),
+ }
+ )
+
+ expectation.verify_against(actual_bal)
+
+
+def test_absent_values_with_multiple_tx_indices():
+ """Test absence validators with multiple transaction indices."""
+ alice = Address(0xA)
+
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=alice,
+ nonce_changes=[
+ # nonce changes at tx 1 and 3
+ BalNonceChange(tx_index=1, post_nonce=1),
+ BalNonceChange(tx_index=3, post_nonce=2),
+ ],
+ ),
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[
+ BalNonceChange(tx_index=1, post_nonce=1),
+ BalNonceChange(tx_index=3, post_nonce=2),
+ ],
+ absent_values=BalAccountAbsentValues(
+ nonce_changes=[
+ BalNonceChange(tx_index=2, post_nonce=0),
+ BalNonceChange(tx_index=4, post_nonce=0),
+ ]
+ ),
+ ),
+ }
+ )
+
+ expectation.verify_against(actual_bal)
+
+ expectation_fail = BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ nonce_changes=[
+ # wrongly forbid change at txs 1 and 2
+ # (1 exists, so should fail)
+ BalNonceChange(tx_index=1, post_nonce=1),
+ BalNonceChange(tx_index=2, post_nonce=0),
+ ]
+ ),
+ ),
+ }
+ )
+
+ with pytest.raises(Exception, match="Unexpected nonce change found at tx 0x1"):
+ expectation_fail.verify_against(actual_bal)
+
+
+def test_bal_account_absent_values_comprehensive():
+ """Test comprehensive BalAccountAbsentValues usage."""
+ addr = Address(0xA)
+
+ # Test forbidding nonce changes
+ actual_bal = BlockAccessList(
+ [BalAccountChange(address=addr, nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)])]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]
+ )
+ ),
+ }
+ )
+
+ with pytest.raises(
+ BlockAccessListValidationError, match="Unexpected nonce change found at tx"
+ ):
+ expectation.verify_against(actual_bal)
+
+ # Test forbidding balance changes
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr, balance_changes=[BalBalanceChange(tx_index=2, post_balance=100)]
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ balance_changes=[BalBalanceChange(tx_index=2, post_balance=100)]
+ )
+ ),
+ }
+ )
+
+ with pytest.raises(
+ BlockAccessListValidationError, match="Unexpected balance change found at tx"
+ ):
+ expectation.verify_against(actual_bal)
+
+ # Test forbidding code changes
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr, code_changes=[BalCodeChange(tx_index=3, new_code=b"\x60\x00")]
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ code_changes=[BalCodeChange(tx_index=3, new_code=b"\x60\x00")]
+ )
+ ),
+ }
+ )
+
+ with pytest.raises(BlockAccessListValidationError, match="Unexpected code change found at tx"):
+ expectation.verify_against(actual_bal)
+
+ # Test forbidding storage reads
+ actual_bal = BlockAccessList(
+ [BalAccountChange(address=addr, storage_reads=[StorageKey(0x42)])]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(storage_reads=[StorageKey(0x42)])
+ ),
+ }
+ )
+
+ with pytest.raises(
+ BlockAccessListValidationError, match="Unexpected storage read found at slot"
+ ):
+ expectation.verify_against(actual_bal)
+
+ # Test forbidding storage changes
+ actual_bal = BlockAccessList(
+ [
+ BalAccountChange(
+ address=addr,
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01, slot_changes=[BalStorageChange(tx_index=1, post_value=99)]
+ )
+ ],
+ )
+ ]
+ )
+
+ expectation = BlockAccessListExpectation(
+ account_expectations={
+ addr: BalAccountExpectation(
+ absent_values=BalAccountAbsentValues(
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01, slot_changes=[BalStorageChange(tx_index=1, post_value=99)]
+ )
+ ]
+ )
+ ),
+ }
+ )
+
+ with pytest.raises(
+ BlockAccessListValidationError, match="Unexpected storage change found at slot"
+ ):
+ expectation.verify_against(actual_bal)
+
+
+@pytest.mark.parametrize(
+ "field_name,field_value",
+ [
+ ("nonce_changes", []),
+ ("balance_changes", []),
+ ("code_changes", []),
+ ("storage_changes", []),
+ ("storage_reads", []),
+ ],
+)
+def test_bal_account_absent_values_empty_list_validation_raises(field_name, field_value):
+ """
+ Test that empty lists in BalAccountAbsentValues fields
+ raise appropriate errors.
+ """
+ with pytest.raises(ValueError, match="Empty lists are not allowed"):
+ BalAccountAbsentValues(**{field_name: field_value})
+
+
+def test_bal_account_absent_values_empty_slot_changes_raises():
+ """
+ Test that empty slot_changes in storage_changes
+ raises appropriate error.
+ """
+ with pytest.raises(ValueError, match="Empty lists are not allowed"):
+ BalAccountAbsentValues(
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x42,
+ slot_changes=[], # Empty list should raise error
+ )
+ ]
+ )
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_eof_v1.py b/packages/tests/src/ethereum_test_types/tests/test_eof_v1.py
similarity index 99%
rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_eof_v1.py
rename to packages/tests/src/ethereum_test_types/tests/test_eof_v1.py
index 21c1b8b196..1c454ab870 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/tests/test_eof_v1.py
+++ b/packages/tests/src/ethereum_test_types/tests/test_eof_v1.py
@@ -867,7 +867,8 @@ def remove_comments_from_string(input_string):
# Find the index of the first '#' character
comment_start = line.find("#")
- # If a '#' is found, slice up to that point; otherwise, take the whole line
+ # If a '#' is found, slice up to that point; otherwise, take the whole
+ # line
if comment_start != -1:
cleaned_line = line[:comment_start].rstrip()
else:
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_helpers.py b/packages/tests/src/ethereum_test_types/tests/test_helpers.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_helpers.py
rename to packages/tests/src/ethereum_test_types/tests/test_helpers.py
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_post_alloc.py b/packages/tests/src/ethereum_test_types/tests/test_post_alloc.py
similarity index 94%
rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_post_alloc.py
rename to packages/tests/src/ethereum_test_types/tests/test_post_alloc.py
index c9639b7e54..45111760fc 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/tests/test_post_alloc.py
+++ b/packages/tests/src/ethereum_test_types/tests/test_post_alloc.py
@@ -10,13 +10,17 @@
@pytest.fixture()
def post(request: pytest.FixtureRequest) -> Alloc:
- """Post state: Set from the test's indirectly parametrized `post` parameter."""
+ """
+ Post state: Set from the test's indirectly parametrized `post` parameter.
+ """
return Alloc.model_validate(request.param)
@pytest.fixture()
def alloc(request: pytest.FixtureRequest) -> Alloc:
- """Alloc state: Set from the test's indirectly parametrized `alloc` parameter."""
+ """
+ Alloc state: Set from the test's indirectly parametrized `alloc` parameter.
+ """
return Alloc.model_validate(request.param)
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_transactions.py b/packages/tests/src/ethereum_test_types/tests/test_transactions.py
similarity index 99%
rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_transactions.py
rename to packages/tests/src/ethereum_test_types/tests/test_transactions.py
index 5f2313ce2f..b780dce2cb 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/tests/test_transactions.py
+++ b/packages/tests/src/ethereum_test_types/tests/test_transactions.py
@@ -249,7 +249,6 @@
],
)
def test_transaction_signing(
- request,
tx: Transaction,
expected_signature: Tuple[int, int, int],
expected_sender: str,
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_types.py b/packages/tests/src/ethereum_test_types/tests/test_types.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_types.py
rename to packages/tests/src/ethereum_test_types/tests/test_types.py
diff --git a/src/ethereum_spec_tests/ethereum_test_types/transaction_types.py b/packages/tests/src/ethereum_test_types/transaction_types.py
similarity index 93%
rename from src/ethereum_spec_tests/ethereum_test_types/transaction_types.py
rename to packages/tests/src/ethereum_test_types/transaction_types.py
index 9b3c0966d2..ce1117635e 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/transaction_types.py
+++ b/packages/tests/src/ethereum_test_types/transaction_types.py
@@ -33,7 +33,7 @@
TestPrivateKey,
)
from ethereum_test_exceptions import TransactionException
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
from .account_types import EOA
from .blob_types import Blob
@@ -81,7 +81,8 @@ class AuthorizationTupleGeneric(CamelModel, Generic[NumberBoundTypeVar], Signabl
def get_rlp_signing_prefix(self) -> bytes:
"""
- Return a prefix that has to be appended to the serialized signing object.
+ Return a prefix that has to be appended to the serialized signing
+ object.
By default, an empty string is returned.
"""
@@ -107,7 +108,10 @@ class AuthorizationTuple(AuthorizationTupleGeneric[HexNumber]):
secret_key: Hash | None = None
def model_post_init(self, __context: Any) -> None:
- """Automatically signs the authorization tuple if a secret key or sender are provided."""
+ """
+ Automatically signs the authorization tuple if a secret key or sender
+ are provided.
+ """
super().model_post_init(__context)
self.sign()
@@ -198,7 +202,9 @@ class TransactionValidateToAsEmptyString(CamelModel):
@model_validator(mode="before")
@classmethod
def validate_to_as_empty_string(cls, data: Any) -> Any:
- """If the `to` field is an empty string, set the model value to None."""
+ """
+ If the `to` field is an empty string, set the model value to None.
+ """
if (
isinstance(data, dict)
and "to" in data
@@ -210,11 +216,16 @@ def validate_to_as_empty_string(cls, data: Any) -> Any:
class TransactionFixtureConverter(TransactionValidateToAsEmptyString):
- """Handler for serializing and validating the `to` field as an empty string."""
+ """
+ Handler for serializing and validating the `to` field as an empty string.
+ """
@model_serializer(mode="wrap", when_used="json-unless-none")
def serialize_to_as_empty_string(self, serializer):
- """Serialize the `to` field as the empty string if the model value is None."""
+ """
+ Serialize the `to` field as the empty string if the model value is
+ None.
+ """
default = serializer(self)
if default is not None and "to" not in default:
default["to"] = ""
@@ -222,16 +233,18 @@ def serialize_to_as_empty_string(self, serializer):
class TransactionTransitionToolConverter(TransactionValidateToAsEmptyString):
- """Handler for serializing and validating the `to` field as an empty string."""
+ """
+ Handler for serializing and validating the `to` field as an empty string.
+ """
@model_serializer(mode="wrap", when_used="json-unless-none")
def serialize_to_as_none(self, serializer):
"""
Serialize the `to` field as `None` if the model value is None.
- This is required as we use `exclude_none=True` when serializing, but the
- t8n tool explicitly requires a value of `None` (respectively null), for
- if the `to` field should be unset (contract creation).
+ This is required as we use `exclude_none=True` when serializing, but
+ the t8n tool explicitly requires a value of `None` (respectively null),
+ for if the `to` field should be unset (contract creation).
"""
default = serializer(self)
if default is not None and "to" not in default:
@@ -250,8 +263,8 @@ class TransactionTestMetadata(CamelModel):
def to_json(self) -> str:
"""
- Convert the transaction metadata into json string for it to be embedded in the
- request id.
+ Convert the transaction metadata into json string for it to be embedded
+ in the request id.
"""
return self.model_dump_json(exclude_none=True, by_alias=True)
@@ -291,8 +304,8 @@ def __str__(self):
class InvalidSignaturePrivateKeyError(Exception):
"""
- Transaction describes both the signature and private key of
- source account.
+ Transaction describes both the signature and private key of source
+ account.
"""
def __str__(self):
@@ -522,8 +535,8 @@ def with_signature_and_sender(self, *, keep_secret_key: bool = False) -> "Transa
def get_rlp_signing_fields(self) -> List[str]:
"""
- Return the list of values included in the envelope used for signing depending on
- the transaction type.
+ Return the list of values included in the envelope used for signing
+ depending on the transaction type.
"""
field_list: List[str]
if self.ty == 6:
@@ -611,8 +624,8 @@ def get_rlp_signing_fields(self) -> List[str]:
def get_rlp_fields(self) -> List[str]:
"""
- Return the list of values included in the list used for rlp encoding depending on
- the transaction type.
+ Return the list of values included in the list used for rlp encoding
+ depending on the transaction type.
"""
fields = self.get_rlp_signing_fields()
if self.ty == 0 and self.protected:
@@ -621,8 +634,8 @@ def get_rlp_fields(self) -> List[str]:
def get_rlp_prefix(self) -> bytes:
"""
- Return the transaction type as bytes to be appended at the beginning of the
- serialized transaction if type is not 0.
+ Return the transaction type as bytes to be appended at the beginning of
+ the serialized transaction if type is not 0.
"""
if self.ty > 0:
return bytes([self.ty])
@@ -630,8 +643,8 @@ def get_rlp_prefix(self) -> bytes:
def get_rlp_signing_prefix(self) -> bytes:
"""
- Return the transaction type as bytes to be appended at the beginning of the
- serialized transaction signing envelope if type is not 0.
+ Return the transaction type as bytes to be appended at the beginning of
+ the serialized transaction signing envelope if type is not 0.
"""
if self.ty > 0:
return bytes([self.ty])
@@ -650,7 +663,10 @@ def hash(self) -> Hash:
@cached_property
def serializable_list(self) -> Any:
- """Return list of values included in the transaction as a serializable object."""
+ """
+ Return list of values included in the transaction as a serializable
+ object.
+ """
return self.rlp() if self.ty > 0 else self.to_list(signing=False)
@staticmethod
@@ -663,7 +679,9 @@ def list_root(input_txs: List["Transaction"]) -> Hash:
@staticmethod
def list_blob_versioned_hashes(input_txs: List["Transaction"]) -> List[Hash]:
- """Get list of ordered blob versioned hashes from a list of transactions."""
+ """
+ Get list of ordered blob versioned hashes from a list of transactions.
+ """
return [
blob_versioned_hash
for tx in input_txs
@@ -687,11 +705,10 @@ class NetworkWrappedTransaction(CamelModel, RLPSerializable):
Network wrapped transaction as defined in
[EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#networking).
- < Osaka:
- rlp([tx_payload_body, blobs, commitments, proofs])
+ < Osaka: rlp([tx_payload_body, blobs, commitments, proofs])
- >= Osaka:
- rlp([tx_payload_body, wrapper_version, blobs, commitments, cell_proofs])
+ >= Osaka: rlp([tx_payload_body, wrapper_version, blobs, commitments,
+ cell_proofs])
"""
tx: Transaction
@@ -740,15 +757,18 @@ def cell_proofs(self) -> Sequence[Bytes] | None:
def get_rlp_fields(self) -> List[str]:
"""
- Return an ordered list of field names to be included in RLP serialization.
+ Return an ordered list of field names to be included in RLP
+ serialization.
Function can be overridden to customize the logic to return the fields.
By default, rlp_fields class variable is used.
- The list can be nested list up to one extra level to represent nested fields.
+ The list can be nested list up to one extra level to represent nested
+ fields.
"""
- # only put a wrapper_version field for >=osaka (value 1), otherwise omit field
+ # only put a wrapper_version field for >=osaka (value 1), otherwise
+ # omit field
wrapper = []
if self.wrapper_version is not None:
wrapper = ["wrapper_version"]
@@ -761,11 +781,11 @@ def get_rlp_fields(self) -> List[str]:
if self.cell_proofs is not None:
rlp_cell_proofs = ["cell_proofs"]
- rlp_fields: List[
- str
- ] = [ # structure explained in https://eips.ethereum.org/EIPS/eip-7594#Networking
+ rlp_fields: List[str] = [ # structure explained in
+ # https://eips.ethereum.org/EIPS/eip-7594#Networking
"tx", # tx_payload_body
- *wrapper, # wrapper_version, which is always 1 for osaka (was non-existing before)
+ *wrapper, # wrapper_version, which is always 1 for osaka (was non-
+ # existing before)
"blobs", # Blob.data
"commitments",
*rlp_proofs,
@@ -782,8 +802,8 @@ def get_rlp_fields(self) -> List[str]:
def get_rlp_prefix(self) -> bytes:
"""
- Return the transaction type as bytes to be appended at the beginning of the
- serialized transaction if type is not 0.
+ Return the transaction type as bytes to be appended at the beginning of
+ the serialized transaction if type is not 0.
"""
if self.tx.ty > 0:
return bytes([self.tx.ty])
diff --git a/src/ethereum_spec_tests/ethereum_test_types/trie.py b/packages/tests/src/ethereum_test_types/trie.py
similarity index 93%
rename from src/ethereum_spec_tests/ethereum_test_types/trie.py
rename to packages/tests/src/ethereum_test_types/trie.py
index 8c97e51956..4d0c7ba312 100644
--- a/src/ethereum_spec_tests/ethereum_test_types/trie.py
+++ b/packages/tests/src/ethereum_test_types/trie.py
@@ -1,4 +1,6 @@
-"""The state trie is the structure responsible for storing."""
+"""
+The state trie is the structure responsible for storing.
+"""
import copy
from dataclasses import dataclass, field
@@ -58,17 +60,11 @@ def encode_account(raw_account_data: FrontierAccount, storage_root: Bytes) -> By
# note: an empty trie (regardless of whether it is secured) has root:
-#
-# keccak256(RLP(b''))
-# ==
-# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10
-#
+# keccak256(RLP(b'')) ==
+# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
# also:
-#
-# keccak256(RLP(()))
-# ==
-# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10
-#
+# keccak256(RLP(())) ==
+# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
# which is the sha3Uncles hash in block header with no uncles
EMPTY_TRIE_ROOT = Bytes32(
bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
@@ -137,9 +133,10 @@ class BranchNode:
def encode_internal_node(node: Optional[InternalNode]) -> Extended:
"""
- Encode a Merkle Trie node into its RLP form. The RLP will then be
- serialized into a `Bytes` and hashed unless it is less that 32 bytes
- when serialized.
+ Encode a Merkle Trie node into its RLP form.
+
+ The RLP will then be serialized into a `Bytes` and hashed unless it is less
+ that 32 bytes when serialized.
This function also accepts `None`, representing the absence of a node,
which is encoded to `b""`.
@@ -211,7 +208,6 @@ def trie_set(trie: Trie[K, V], key: K, value: V) -> None:
This method deletes the key if `value == trie.default`, because the Merkle
Trie represents the default value by omitting it from the trie.
-
"""
if value == trie.default:
if key in trie._data:
@@ -225,7 +221,6 @@ def trie_get(trie: Trie[K, V], key: K) -> V:
Get an item from the Merkle Trie.
This method returns `trie.default` if the key is missing.
-
"""
return trie._data.get(key, trie.default)
@@ -248,11 +243,10 @@ def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes:
Highest nibble::
- +---+---+----------+--------+
- | _ | _ | is_leaf | parity |
- +---+---+----------+--------+
- 3 2 1 0
-
+ +---+---+----------+--------+
+ | _ | _ | is_leaf | parity |
+ +---+---+----------+--------+
+ 3 2 1 0
The lowest bit of the nibble encodes the parity of the length of the
remaining nibbles -- `0` when even and `1` when odd. The second lowest bit
@@ -274,7 +268,9 @@ def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes:
def bytes_to_nibble_list(bytes_: Bytes) -> Bytes:
- """Convert a `Bytes` into to a sequence of nibbles (bytes with value < 16)."""
+ """
+ Convert a `Bytes` into to a sequence of nibbles (bytes with value < 16).
+ """
nibble_list = bytearray(2 * len(bytes_))
for byte_index, byte in enumerate(bytes_):
nibble_list[byte_index * 2] = (byte & 0xF0) >> 4
diff --git a/src/ethereum_spec_tests/ethereum_test_types/utils.py b/packages/tests/src/ethereum_test_types/utils.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_types/utils.py
rename to packages/tests/src/ethereum_test_types/utils.py
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/__init__.py b/packages/tests/src/ethereum_test_vm/__init__.py
similarity index 65%
rename from src/ethereum_spec_tests/ethereum_test_vm/__init__.py
rename to packages/tests/src/ethereum_test_vm/__init__.py
index 34972a73a4..0b35318fee 100644
--- a/src/ethereum_spec_tests/ethereum_test_vm/__init__.py
+++ b/packages/tests/src/ethereum_test_vm/__init__.py
@@ -2,14 +2,15 @@
from .bytecode import Bytecode
from .evm_types import EVMCodeType
-from .helpers import call_return_code
-from .opcode import Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes
+from .helpers import MemoryVariable, call_return_code
+from .opcodes import Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes
__all__ = (
"Bytecode",
"EVMCodeType",
"Macro",
"Macros",
+ "MemoryVariable",
"Opcode",
"OpcodeCallArg",
"Opcodes",
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/bytecode.py b/packages/tests/src/ethereum_test_vm/bytecode.py
similarity index 79%
rename from src/ethereum_spec_tests/ethereum_test_vm/bytecode.py
rename to packages/tests/src/ethereum_test_vm/bytecode.py
index e07ab2cad0..298f80c6e2 100644
--- a/src/ethereum_spec_tests/ethereum_test_vm/bytecode.py
+++ b/packages/tests/src/ethereum_test_vm/bytecode.py
@@ -1,6 +1,13 @@
"""Ethereum Virtual Machine bytecode primitives and utilities."""
-from typing import SupportsBytes
+from typing import Any, SupportsBytes
+
+from pydantic import GetCoreSchemaHandler
+from pydantic_core.core_schema import (
+ PlainValidatorFunctionSchema,
+ no_info_plain_validator_function,
+ plain_serializer_function_ser_schema,
+)
from ethereum_test_base_types import Bytes, Hash
@@ -9,9 +16,9 @@ class Bytecode:
"""
Base class to represent EVM bytecode.
- Stack calculations are automatically done after an addition operation between two bytecode
- objects. The stack height is not guaranteed to be correct, so the user must take this into
- consideration.
+ Stack calculations are automatically done after an addition operation
+ between two bytecode objects. The stack height is not guaranteed to be
+ correct, so the user must take this into consideration.
Parameters
----------
@@ -56,8 +63,8 @@ def __new__(
return instance
if isinstance(bytes_or_byte_code_base, Bytecode):
- # Required because Enum class calls the base class with the instantiated object as
- # parameter.
+ # Required because Enum class calls the base class with the
+ # instantiated object as parameter.
obj = super().__new__(cls)
obj._bytes_ = bytes_or_byte_code_base._bytes_
obj.popped_stack_items = bytes_or_byte_code_base.popped_stack_items
@@ -106,8 +113,8 @@ def __eq__(self, other):
Allow comparison between Bytecode instances and bytes objects.
Raises:
- - NotImplementedError: if the comparison is not between an Bytecode
- or a bytes object.
+ - NotImplementedError: if the comparison is not between an
+ Bytecode or a bytes object.
"""
if isinstance(other, Bytecode):
@@ -135,7 +142,9 @@ def __hash__(self):
)
def __add__(self, other: "Bytecode | bytes | int | None") -> "Bytecode":
- """Concatenate the bytecode representation with another bytecode object."""
+ """
+ Concatenate the bytecode representation with another bytecode object.
+ """
if other is None or (isinstance(other, int) and other == 0):
# Edge case for sum() function
return self
@@ -153,33 +162,40 @@ def __add__(self, other: "Bytecode | bytes | int | None") -> "Bytecode":
b_pop, b_push = other.popped_stack_items, other.pushed_stack_items
b_min, b_max = other.min_stack_height, other.max_stack_height
- # NOTE: "_pop" is understood as the number of elements required by an instruction or
- # bytecode to be popped off the stack before it starts returning (pushing).
+ # NOTE: "_pop" is understood as the number of elements required by an
+ # instruction or bytecode to be popped off the stack before it starts
+ # returning (pushing).
- # Auxiliary variables representing "stages" of the execution of `c = a + b` bytecode:
- # Assume starting point 0 as reference:
+ # Auxiliary variables representing "stages" of the execution of
+ # `c = a + b` bytecode: Assume starting point 0 as reference:
a_start = 0
- # A (potentially) pops some elements and reaches its "bottom", might be negative:
+ # A (potentially) pops some elements and reaches its "bottom", might be
+ # negative:
a_bottom = a_start - a_pop
- # After this A pushes some elements, then B pops and reaches its "bottom":
+ # After this A pushes some elements, then B pops and reaches its
+ # "bottom":
b_bottom = a_bottom + a_push - b_pop
# C's bottom is either at the bottom of A or B:
c_bottom = min(a_bottom, b_bottom)
if c_bottom == a_bottom:
- # C pops the same as A to reach its bottom, then the rest of A and B are C's "push"
+ # C pops the same as A to reach its bottom, then the rest of A and
+ # B are C's "push"
c_pop = a_pop
c_push = a_push - b_pop + b_push
else:
- # A and B are C's "pop" to reach its bottom, then pushes the same as B
+ # A and B are C's "pop" to reach its bottom, then pushes the same
+ # as B
c_pop = a_pop - a_push + b_pop
c_push = b_push
- # C's minimum required stack is either A's or B's shifted by the net stack balance of A
+ # C's minimum required stack is either A's or B's shifted by the net
+ # stack balance of A
c_min = max(a_min, b_min + a_pop - a_push)
- # C starts from c_min, then reaches max either in the spot where A reached a_max or in the
- # spot where B reached b_max, after A had completed.
+ # C starts from c_min, then reaches max either in the spot where A
+ # reached a_max or in the spot where B reached b_max, after A had
+ # completed.
c_max = max(c_min + a_max - a_min, c_min - a_pop + a_push + b_max - b_min)
return Bytecode(
@@ -192,7 +208,9 @@ def __add__(self, other: "Bytecode | bytes | int | None") -> "Bytecode":
)
def __radd__(self, other: "Bytecode | int | None") -> "Bytecode":
- """Concatenate the opcode byte representation with another bytes object."""
+ """
+ Concatenate the opcode byte representation with another bytes object.
+ """
if other is None or (isinstance(other, int) and other == 0):
# Edge case for sum() function
return self
@@ -200,7 +218,9 @@ def __radd__(self, other: "Bytecode | int | None") -> "Bytecode":
return other.__add__(self)
def __mul__(self, other: int) -> "Bytecode":
- """Concatenate another bytes object with the opcode byte representation."""
+ """
+ Concatenate another bytes object with the opcode byte representation.
+ """
if other < 0:
raise ValueError("Cannot multiply by a negative number")
if other == 0:
@@ -211,9 +231,28 @@ def __mul__(self, other: int) -> "Bytecode":
return output
def hex(self) -> str:
- """Return the hexadecimal representation of the opcode byte representation."""
+ """
+ Return the hexadecimal representation of the opcode byte
+ representation.
+ """
return bytes(self).hex()
def keccak256(self) -> Hash:
"""Return the keccak256 hash of the opcode byte representation."""
return Bytes(self._bytes_).keccak256()
+
+ @classmethod
+ def __get_pydantic_core_schema__(
+ cls, source_type: Any, handler: GetCoreSchemaHandler
+ ) -> PlainValidatorFunctionSchema:
+ """
+ Provide Pydantic core schema for Bytecode
+ serialization and validation.
+ """
+ return no_info_plain_validator_function(
+ cls,
+ serialization=plain_serializer_function_ser_schema(
+ lambda bytecode: "0x" + bytecode.hex(),
+ info_arg=False,
+ ),
+ )
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/evm_types.py b/packages/tests/src/ethereum_test_vm/evm_types.py
similarity index 71%
rename from src/ethereum_spec_tests/ethereum_test_vm/evm_types.py
rename to packages/tests/src/ethereum_test_vm/evm_types.py
index bb7fe296dc..992f580e89 100644
--- a/src/ethereum_spec_tests/ethereum_test_vm/evm_types.py
+++ b/packages/tests/src/ethereum_test_vm/evm_types.py
@@ -4,7 +4,9 @@
class EVMCodeType(str, Enum):
- """Enum representing the type of EVM code that is supported in a given fork."""
+ """
+ Enum representing the type of EVM code that is supported in a given fork.
+ """
LEGACY = "legacy"
EOF_V1 = "eof_v1"
diff --git a/packages/tests/src/ethereum_test_vm/helpers.py b/packages/tests/src/ethereum_test_vm/helpers.py
new file mode 100644
index 0000000000..05c10be45a
--- /dev/null
+++ b/packages/tests/src/ethereum_test_vm/helpers.py
@@ -0,0 +1,100 @@
+"""Helper functions for the EVM."""
+
+from .bytecode import Bytecode
+from .opcodes import Opcodes as Op
+
+
+class MemoryVariable(Bytecode):
+ """
+ Variable abstraction to help keep track values that are stored in memory.
+
+ To use, simply declare a variable with an unique offset that is not used
+ by any other variable.
+
+ The variable then can be used in-place to read the value from memory:
+
+ ```python
+ v = MemoryVariable(128)
+
+ bytecode = Op.ADD(v, Op.CALLDATASIZE())
+ ```
+
+ The previous example is equivalent to:
+
+ ```python
+ bytecode = Op.ADD(Op.MLOAD(offset=128), Op.CALLDATASIZE())
+ ```
+
+ The variable also contains methods to add and subtract values from the
+ memory offset.
+
+ ```python
+ v = MemoryVariable(128)
+
+ bytecode = (
+ v.set(0xff)
+ + v.add(1)
+ + v.return_value()
+ )
+ ```
+
+ The previous example is equivalent to:
+
+ ```python
+ bytecode = (
+ Op.MSTORE(offset=128, value=0xff)
+ + Op.MSTORE(offset=128, value=Op.ADD(Op.MLOAD(offset=128), 1))
+ + Op.RETURN(offset=128, size=32)
+ )
+ ```
+
+ """
+
+ offset: int
+
+ def __new__(cls, offset: int):
+ """
+ Instantiate a new EVM memory variable.
+
+ When used with normal bytecode, this class simply returns the MLOAD
+ with the provided offset.
+ """
+ instance = super().__new__(cls, Op.MLOAD(offset=offset))
+ instance.offset = offset
+ return instance
+
+ def set(self, value: int | Bytecode) -> Bytecode:
+ """Set the given value at the memory location of this variable."""
+ return Op.MSTORE(offset=self.offset, value=value)
+
+ def add(self, value: int | Bytecode) -> Bytecode:
+ """In-place add the given value to the one currently in memory."""
+ return Op.MSTORE(offset=self.offset, value=Op.ADD(Op.MLOAD(offset=self.offset), value))
+
+ def sub(self, value: int | Bytecode) -> Bytecode:
+ """
+ In-place subtract the given value from the one currently
+ in memory.
+ """
+ return Op.MSTORE(offset=self.offset, value=Op.SUB(Op.MLOAD(offset=self.offset), value))
+
+ def store_value(self, key: int | Bytecode) -> Bytecode:
+ """Op.SSTORE the value that is currently in memory."""
+ return Op.SSTORE(key, Op.MLOAD(offset=self.offset))
+
+ def return_value(self) -> Bytecode:
+ """Op.RETURN the value that is currently in memory."""
+ return Op.RETURN(offset=self.offset, size=32)
+
+
+def call_return_code(opcode: Op, success: bool, *, revert: bool = False) -> int:
+ """Return return code for a CALL operation."""
+ if opcode in [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]:
+ return int(success)
+ elif opcode in [Op.EXTCALL, Op.EXTDELEGATECALL, Op.EXTSTATICCALL]:
+ if success:
+ return 0
+ if revert:
+ return 1
+ return 2
+ raise ValueError(f"Not a call opcode: {opcode}")
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/opcode.py b/packages/tests/src/ethereum_test_vm/opcodes.py
similarity index 90%
rename from src/ethereum_spec_tests/ethereum_test_vm/opcode.py
rename to packages/tests/src/ethereum_test_vm/opcodes.py
index 5f2aef894b..85b79c65e5 100644
--- a/src/ethereum_spec_tests/ethereum_test_vm/opcode.py
+++ b/packages/tests/src/ethereum_test_vm/opcodes.py
@@ -1,9 +1,10 @@
"""
Ethereum Virtual Machine opcode definitions.
-Acknowledgments: The individual opcode documentation below is due to the work by
-[smlXL](https://github.com/smlxl) on [evm.codes](https://www.evm.codes/), available as open
-source [github.com/smlxl/evm.codes](https://github.com/smlxl/evm.codes) - thank you! And thanks
+Acknowledgments: The individual opcode documentation below is due to the work
+by [smlXL](https://github.com/smlxl) on [evm.codes](https://www.evm.codes/),
+available as open source [github.com/smlxl/
+evm.codes](https://github.com/smlxl/evm.codes) - thank you! And thanks
to @ThreeHrSleep for integrating it in the docstrings.
"""
@@ -18,7 +19,8 @@
def _get_int_size(n: int) -> int:
"""Return size of an integer in bytes."""
if n < 0:
- # Negative numbers in the EVM are represented as two's complement of 32 bytes
+ # Negative numbers in the EVM are represented as two's complement
+ # of 32 bytes
return 32
byte_count = 0
while n:
@@ -45,7 +47,8 @@ def _stack_argument_to_bytecode(
if data_size > 32:
raise ValueError("Opcode stack data must be less than 32 bytes")
elif data_size == 0:
- # Pushing 0 is done with the PUSH1 opcode for compatibility reasons.
+ # Pushing 0 is done with the PUSH1 opcode
+ # for compatibility reasons.
data_size = 1
arg = arg.to_bytes(
length=data_size,
@@ -55,7 +58,8 @@ def _stack_argument_to_bytecode(
else:
arg = to_bytes(arg).lstrip(b"\0") # type: ignore
if arg == b"":
- # Pushing 0 is done with the PUSH1 opcode for compatibility reasons.
+ # Pushing 0 is done with the PUSH1 opcode for
+ # compatibility reasons.
arg = b"\x00"
data_size = len(arg)
@@ -67,20 +71,23 @@ def _stack_argument_to_bytecode(
class Opcode(Bytecode):
"""
- Represents a single Opcode instruction in the EVM, with extra metadata useful to parametrize
- tests.
+ Represents a single Opcode instruction in the EVM, with extra
+ metadata useful to parametrize tests.
Parameters
----------
- data_portion_length: number of bytes after the opcode in the bytecode
that represent data
- - data_portion_formatter: function to format the data portion of the opcode, if any
- - stack_properties_modifier: function to modify the stack properties of the opcode after the
- data portion has been processed
- - kwargs: list of keyword arguments that can be passed to the opcode, in the order they are
- meant to be placed in the stack
- - kwargs_defaults: default values for the keyword arguments if any, otherwise 0
- - unchecked_stack: whether the bytecode should ignore stack checks when being called
+ - data_portion_formatter: function to format the data portion of the
+ opcode, if any
+ - stack_properties_modifier: function to modify the stack properties of
+ the opcode after the data portion has been processed
+ - kwargs: list of keyword arguments that can be passed to the opcode,
+ in the order they are meant to be placed in the stack
+ - kwargs_defaults: default values for the keyword arguments if any,
+ otherwise 0
+ - unchecked_stack: whether the bytecode should ignore stack checks
+ when being called
"""
@@ -111,8 +118,8 @@ def __new__(
if kwargs_defaults is None:
kwargs_defaults = {}
if type(opcode_or_byte) is Opcode:
- # Required because Enum class calls the base class with the instantiated object as
- # parameter.
+ # Required because Enum class calls the base class
+ # with the instantiated object as parameter.
return opcode_or_byte
elif isinstance(opcode_or_byte, int) or isinstance(opcode_or_byte, bytes):
obj_bytes = (
@@ -147,8 +154,8 @@ def __new__(
def __getitem__(self, *args: "int | bytes | str | Iterable[int]") -> "Opcode":
"""
- Initialize a new instance of the opcode with the data portion set, and also clear
- the data portion variables to avoid reusing them.
+ Initialize a new instance of the opcode with the data portion set,
+ and also clear the data portion variables to avoid reusing them.
"""
if self.data_portion_formatter is None and self.data_portion_length == 0:
raise ValueError("Opcode does not have a data portion or has already been set")
@@ -160,8 +167,8 @@ def __getitem__(self, *args: "int | bytes | str | Iterable[int]") -> "Opcode":
else:
data_portion = self.data_portion_formatter(*args)
elif self.data_portion_length > 0:
- # For opcodes with a data portion, the first argument is the data and the rest of the
- # arguments form the stack.
+ # For opcodes with a data portion, the first argument is the
+ # data and the rest of the arguments form the stack.
assert len(args) == 1, "Opcode with data portion requires exactly one argument"
data = args[0]
if isinstance(data, bytes) or isinstance(data, SupportsBytes) or isinstance(data, str):
@@ -222,26 +229,31 @@ def __call__(
**kwargs: "int | bytes | str | Opcode | Bytecode",
) -> Bytecode:
"""
- Make all opcode instances callable to return formatted bytecode, which constitutes a data
- portion, that is located after the opcode byte, and pre-opcode bytecode, which is normally
- used to set up the stack.
+ Make all opcode instances callable to return formatted bytecode, which
+ constitutes a data portion, that is located after the opcode byte,
+ and pre-opcode bytecode, which is normally used to set up the stack.
- This useful to automatically format, e.g., call opcodes and their stack arguments as
+ This useful to automatically format, e.g., call opcodes and their
+ stack arguments as
`Opcodes.CALL(Opcodes.GAS, 0x1234, 0x0, 0x0, 0x0, 0x0, 0x0)`.
- Data sign is automatically detected but for this reason the range of the input must be:
- `[-2^(data_portion_bits-1), 2^(data_portion_bits)]` where: `data_portion_bits ==
- data_portion_length * 8`
+ Data sign is automatically detected but for this reason the range
+ of the input must be:
+ `[-2^(data_portion_bits-1), 2^(data_portion_bits)]`
+ where:
+ `data_portion_bits == data_portion_length * 8`
- For the stack, the arguments are set up in the opposite order they are given, so the first
- argument is the last item pushed to the stack.
+ For the stack, the arguments are set up in the opposite order they
+ are given, so the first argument is the last item pushed to the stack.
- The resulting stack arrangement does not take into account opcode stack element
- consumption, so the stack height is not guaranteed to be correct and the user must take
- this into consideration.
+ The resulting stack arrangement does not take into account
+ opcode stack element consumption, so the stack height is not
+ guaranteed to be correct and the user must take this into
+ consideration.
- Integers can also be used as stack elements, in which case they are automatically converted
- to PUSH operations, and negative numbers always use a PUSH32 operation.
+ Integers can also be used as stack elements, in which case they
+ are automatically converted to PUSH operations, and negative numbers
+ always use a PUSH32 operation.
Hex-strings will be automatically converted to bytes.
"""
@@ -317,8 +329,8 @@ def __new__(
if macro_or_bytes is None:
macro_or_bytes = Bytecode()
if isinstance(macro_or_bytes, Macro):
- # Required because Enum class calls the base class with the instantiated object as
- # parameter.
+ # Required because Enum class calls the base class
+ # with the instantiated object as parameter.
return macro_or_bytes
else:
instance = super().__new__(cls, macro_or_bytes)
@@ -342,8 +354,9 @@ def __call__(self, *args_t: OpcodeCallArg, **kwargs) -> Bytecode:
RJUMPV_BRANCH_OFFSET_BYTE_LENGTH = 2
-# TODO: Allowing Iterable here is a hacky way to support `range`, because Python 3.11+ will allow
-# `Op.RJUMPV[*range(5)]`. This is a temporary solution until Python 3.11+ is the minimum required
+# TODO: Allowing Iterable here is a hacky way to support `range`,
+# because Python 3.11+ will allow `Op.RJUMPV[*range(5)]`.
+# This is a temporary solution until Python 3.11+ is the minimum required
# version.
@@ -419,8 +432,9 @@ class Opcodes(Opcode, Enum):
Contains deprecated and not yet implemented opcodes.
- This enum is !! NOT !! meant to be iterated over by the tests. Instead, create a list with
- cherry-picked opcodes from this Enum within the test if iteration is needed.
+ This enum is !! NOT !! meant to be iterated over by the tests.
+ Instead, create a list with cherry-picked opcodes from this Enum
+ within the test if iteration is needed.
Do !! NOT !! remove or modify existing opcodes from this list.
"""
@@ -585,7 +599,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - c: signed integer result of the division. If the denominator is 0, the result will be 0
+ - c: signed integer result of the division. If the denominator is 0,
+ the result will be 0
----
Fork
@@ -615,7 +630,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - a % b: integer result of the integer modulo. If the denominator is 0, the result will be 0
+ - a % b: integer result of the integer modulo. If the denominator is 0,
+ the result will be 0
Fork
----
@@ -644,8 +660,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - a % b: integer result of the signed integer modulo. If the denominator is 0, the result will
- be 0
+ - a % b: integer result of the signed integer modulo. If the denominator
+ is 0, the result will be 0
Fork
----
@@ -675,8 +691,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - (a + b) % N: integer result of the addition followed by a modulo. If the denominator is 0,
- the result will be 0
+ - (a + b) % N: integer result of the addition followed by a modulo.
+ If the denominator is 0, the result will be 0
Fork
----
@@ -706,8 +722,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - (a * b) % N: integer result of the multiplication followed by a modulo. If the denominator
- is 0, the result will be 0
+ - (a * b) % N: integer result of the multiplication followed by a modulo.
+ If the denominator is 0, the result will be 0
Fork
----
@@ -1083,8 +1099,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - y: the indicated byte at the least significant position. If the byte offset is out of range,
- the result is 0
+ - y: the indicated byte at the least significant position.
+ If the byte offset is out of range, the result is 0
Fork
----
@@ -1286,7 +1302,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - balance: balance of the given account in wei. Returns 0 if the account doesn't exist
+ - balance: balance of the given account in wei. Returns 0 if the
+ account doesn't exist
Fork
----
@@ -1315,8 +1332,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - address: the 20-byte address of the sender of the transaction. It can only be an account
- without code
+ - address: the 20-byte address of the sender of the transaction.
+ It can only be an account without code
Fork
----
@@ -1344,8 +1361,9 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - address: the 20-byte address of the caller account. This is the account that did the last
- call (except delegate call)
+ - address: the 20-byte address of the caller account.
+ This is the account that did the last
+ call (except delegate call)
Fork
----
@@ -1365,7 +1383,8 @@ class Opcodes(Opcode, Enum):
Description
----
- Get deposited value by the instruction/transaction responsible for this execution
+ Get deposited value by the instruction/transaction responsible
+ for this execution
Inputs
----
@@ -1401,8 +1420,9 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - data[offset]: 32-byte value starting from the given offset of the calldata. All bytes after
- the end of the calldata are set to 0
+ - data[offset]: 32-byte value starting from the given offset of
+ the calldata. All bytes after the end of the calldata
+ are set to 0
Fork
----
@@ -1614,7 +1634,8 @@ class Opcodes(Opcode, Enum):
----
- minimum_word_size = (size + 31) / 32
- static_gas = 0
- - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost
+ - dynamic_gas = 3 * minimum_word_size +
+ memory_expansion_cost + address_access_cost
Source: [evm.codes/#3C](https://www.evm.codes/#3C)
"""
@@ -1655,7 +1676,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- dest_offset: byte offset in the memory where the result will be copied
- - offset: byte offset in the return data from the last executed sub context to copy
+ - offset: byte offset in the return data from the last
+ executed sub context to copy
- size: byte size to copy
Fork
@@ -1686,8 +1708,9 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - hash: hash of the chosen account's code, the empty hash (0xc5d24601...) if the account has no
- code, or 0 if the account does not exist or has been destroyed
+ - hash: hash of the chosen account's code, the empty hash (0xc5d24601...)
+ if the account has no code, or 0 if the account does not exist or
+ has been destroyed
Fork
----
@@ -1712,12 +1735,14 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - blockNumber: block number to get the hash from. Valid range is the last 256 blocks (not
- including the current one). Current block number can be queried with NUMBER
+ - blockNumber: block number to get the hash from. Valid range is the
+ last 256 blocks (not including the current one). Current
+ block number can be queried with NUMBER
Outputs
----
- - hash: hash of the chosen block, or 0 if the block number is not in the valid range
+ - hash: hash of the chosen block, or 0 if the block number is not
+ in the valid range
Fork
----
@@ -1957,7 +1982,8 @@ class Opcodes(Opcode, Enum):
Description
----
- Returns the versioned hash of a single blob contained in the type-3 transaction
+ Returns the versioned hash of a single blob contained in
+ the type-3 transaction
Inputs
----
@@ -1975,7 +2001,8 @@ class Opcodes(Opcode, Enum):
----
3
- Source: [eips.ethereum.org/EIPS/eip-4844](https://eips.ethereum.org/EIPS/eip-4844)
+ Source: [eips.ethereum.org/EIPS/
+ eip-4844](https://eips.ethereum.org/EIPS/eip-4844)
"""
BLOBBASEFEE = Opcode(0x4A, popped_stack_items=0, pushed_stack_items=1)
@@ -2003,7 +2030,8 @@ class Opcodes(Opcode, Enum):
----
2
- Source: [eips.ethereum.org/EIPS/eip-7516](https://eips.ethereum.org/EIPS/eip-7516)
+ Source: [eips.ethereum.org/EIPS/eip-7516](https://eips.ethereum.org/
+ EIPS/eip-7516)
"""
POP = Opcode(0x50, popped_stack_items=1)
@@ -2049,8 +2077,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: the 32 bytes in memory starting at that offset. If it goes beyond its current size
- (see MSIZE), writes 0s
+ - value: the 32 bytes in memory starting at that offset.
+ If it goes beyond its current size (see MSIZE), writes 0s
Fork
----
@@ -2106,8 +2134,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- offset: offset in the memory in bytes
- - value: 1-byte value to write in the memory (the least significant byte of the 32-byte stack
- value)
+ - value: 1-byte value to write in the memory (the least significant
+ byte of the 32-byte stack value)
Fork
----
@@ -2136,7 +2164,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: 32-byte value corresponding to that key. 0 if that key was never written before
+ - value: 32-byte value corresponding to that key. 0 if that
+ key was never written before
Fork
----
@@ -2208,8 +2237,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - pc: byte offset in the deployed code where execution will continue from. Must be a
- JUMPDEST instruction
+ - pc: byte offset in the deployed code where execution will continue from.
+ Must be a JUMPDEST instruction
Outputs
----
@@ -2237,11 +2266,12 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - pc: byte offset in the deployed code where execution will continue from. Must be a
- JUMPDEST instruction
- - condition: the program counter will be altered with the new value only if this value is
- different from 0. Otherwise, the program counter is simply incremented and the next
- instruction will be executed
+ - pc: byte offset in the deployed code where execution will continue from.
+ Must be a JUMPDEST instruction
+ - condition: the program counter will be altered with the new value only
+ if this value is different from 0. Otherwise, the program
+ counter is simply incremented and the next instruction
+ will be executed
Fork
----
@@ -2261,7 +2291,8 @@ class Opcodes(Opcode, Enum):
Description
----
- Get the value of the program counter prior to the increment corresponding to this instruction
+ Get the value of the program counter prior to the increment corresponding
+ to this instruction
Inputs
----
@@ -2313,8 +2344,8 @@ class Opcodes(Opcode, Enum):
Description
----
- Get the amount of available gas, including the corresponding reduction for the cost of this
- instruction
+ Get the amount of available gas, including the corresponding reduction
+ for the cost of this instruction
Inputs
----
@@ -2406,7 +2437,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: 32-byte value corresponding to that key. 0 if that key was never written
+ - value: 32-byte value corresponding to that key. 0 if that key
+ was never written
Fork
----
@@ -2441,7 +2473,8 @@ class Opcodes(Opcode, Enum):
----
100
- Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/eip-1153)
+ Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/
+ eip-1153)
"""
MCOPY = Opcode(0x5E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"])
@@ -2473,7 +2506,8 @@ class Opcodes(Opcode, Enum):
- static_gas = 3
- dynamic_gas = 3 * minimum_word_size + memory_expansion_cost
- Source: [eips.ethereum.org/EIPS/eip-5656](https://eips.ethereum.org/EIPS/eip-5656)
+ Source: [eips.ethereum.org/EIPS/eip-5656](https://eips.ethereum.org/EIPS/
+ eip-5656)
"""
PUSH0 = Opcode(0x5F, pushed_stack_items=1)
@@ -2519,7 +2553,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the
+ lowest significant bytes)
Fork
----
@@ -2547,7 +2582,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the lowest
+ significant bytes)
Fork
----
@@ -2575,7 +2611,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the
+ lowest significant bytes)
Fork
----
@@ -2603,7 +2640,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the lowest
+ significant bytes)
Fork
----
@@ -2631,7 +2669,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the lowest
+ significant bytes)
Fork
----
@@ -2659,7 +2698,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the
+ lowest significant bytes)
Fork
----
@@ -2687,7 +2727,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the
+ lowest significant bytes)
Fork
----
@@ -2715,7 +2756,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the
+ lowest significant bytes)
Fork
----
@@ -2743,7 +2785,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the
+ lowest significant bytes)
Fork
----
@@ -2771,7 +2814,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -2799,7 +2843,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -2827,7 +2872,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in the
+ lowest significant bytes)
Fork
----
@@ -2855,7 +2901,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -2883,7 +2930,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -2912,7 +2960,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -2940,7 +2989,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -2968,7 +3018,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -2996,7 +3047,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3024,7 +3076,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3052,7 +3105,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3080,7 +3134,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3108,7 +3163,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3136,7 +3192,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3164,7 +3221,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3192,7 +3250,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3220,7 +3279,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3248,7 +3308,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3276,7 +3337,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3304,7 +3366,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3332,7 +3395,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3360,7 +3424,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -3388,7 +3453,8 @@ class Opcodes(Opcode, Enum):
Outputs
----
- - value: pushed value, aligned to the right (put in the lowest significant bytes)
+ - value: pushed value, aligned to the right (put in
+ the lowest significant bytes)
Fork
----
@@ -4725,7 +4791,8 @@ class Opcodes(Opcode, Enum):
Gas
----
- Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200)
+ Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/
+ eip-4200)
"""
DATALOAD = Opcode(0xD0, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"])
@@ -4755,7 +4822,8 @@ class Opcodes(Opcode, Enum):
----
4
- Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480)
+ Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/
+ eip-7480)
"""
DATALOADN = Opcode(0xD1, pushed_stack_items=1, data_portion_length=2)
@@ -4789,7 +4857,8 @@ class Opcodes(Opcode, Enum):
----
3
- Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480)
+ Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/
+ eip-7480)
"""
DATASIZE = Opcode(0xD2, pushed_stack_items=1)
@@ -4818,7 +4887,8 @@ class Opcodes(Opcode, Enum):
----
2
- Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480)
+ Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/
+ eip-7480)
"""
DATACOPY = Opcode(0xD3, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"])
@@ -4852,7 +4922,8 @@ class Opcodes(Opcode, Enum):
- static_gas = 3
- dynamic_gas = 3 * minimum_word_size + memory_expansion_cost
- Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480)
+ Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/
+ eip-7480)
"""
RJUMPI = Opcode(0xE1, popped_stack_items=1, data_portion_length=2)
@@ -4878,7 +4949,8 @@ class Opcodes(Opcode, Enum):
Gas
----
- Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200)
+ Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/
+ eip-4200)
"""
RJUMPV = Opcode(
@@ -4896,11 +4968,13 @@ class Opcodes(Opcode, Enum):
----
Relative jump with variable offset.
- When calling this opcode to generate bytecode, the first argument is used to format the data
- portion of the opcode, and it can be either of two types:
- - A bytes type, and in this instance the bytes are used verbatim as the data portion.
- - An integer iterable, list or tuple or any other iterable, where each element is a
- jump offset.
+ When calling this opcode to generate bytecode, the first argument is
+ used to format the data portion of the opcode, and it can be either
+ of two types:
+ - A bytes type, and in this instance the bytes are used verbatim
+ as the data portion.
+ - An integer iterable, list or tuple or any other iterable, where
+ each element is a jump offset.
Inputs
----
@@ -4915,7 +4989,8 @@ class Opcodes(Opcode, Enum):
Gas
----
- Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200)
+ Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/
+ eip-4200)
"""
CALLF = Opcode(0xE3, data_portion_length=2, unchecked_stack=True)
@@ -4930,21 +5005,21 @@ class Opcodes(Opcode, Enum):
- deduct 5 gas
- read uint16 operand idx
- - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in
- an exceptional halt
+ - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs,
+ execution results in an exceptional halt
- if 1024 <= len(return_stack), execution results in an exceptional halt
- push new element to return_stack (current_code_idx, pc+3)
- update current_code_idx to idx and set pc to 0
Inputs
----
- Any: The inputs are not checked because we cannot know how many inputs the callee
- function/section requires
+ Any: The inputs are not checked because we cannot know how many inputs
+ the callee function/section requires
Outputs
----
- Any: The outputs are variable because we cannot know how many outputs the callee
- function/section produces
+ Any: The outputs are variable because we cannot know how many outputs the
+ callee function/section produces
Fork
----
@@ -4955,7 +5030,8 @@ class Opcodes(Opcode, Enum):
5
Source:
- [ipsilon/eof/blob/main/spec/eof.md](https://github.com/ipsilon/eof/blob/main/spec/eof.md)
+ [ipsilon/eof/blob/main/spec/eof.md](https://github.com/ipsilon/eof/blob/
+ main/spec/eof.md)
"""
RETF = Opcode(0xE4, terminating=True)
@@ -4995,8 +5071,8 @@ class Opcodes(Opcode, Enum):
- deduct 5 gas
- read uint16 operand idx
- - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in
- an exceptional halt
+ - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs,
+ execution results in an exceptional halt
- set current_code_idx to idx
- set pc = 0
@@ -5102,7 +5178,8 @@ class Opcodes(Opcode, Enum):
Description
----
- Exchanges two stack positions. Two nybbles, n is high 4 bits + 1, then m is 4 low bits + 1.
+ Exchanges two stack positions. Two nybbles, n is high 4 bits + 1,
+ then m is 4 low bits + 1.
Exchanges the n+1'th item with the n + m + 1 item.
Inputs x and y when the opcode is used as `EXCHANGE[x, y]`, are equal to:
@@ -5231,7 +5308,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- value: value in wei to send to the new account
- - offset: byte offset in the memory in bytes, the initialization code for the new account
+ - offset: byte offset in the memory in bytes, the initialization code
+ for the new account
- size: byte size to copy (size of the initialization code)
Outputs
@@ -5250,8 +5328,9 @@ class Opcodes(Opcode, Enum):
code_deposit_cost = 200 * deployed_code_size
static_gas = 32000
- dynamic_gas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost
- + code_deposit_cost
+ dynamic_gas = init_code_cost + memory_expansion_cost +
+ deployment_code_execution_cost +
+ code_deposit_cost
```
Source: [evm.codes/#F0](https://www.evm.codes/#F0)
@@ -5265,7 +5344,8 @@ class Opcodes(Opcode, Enum):
kwargs_defaults={"gas": GAS},
)
"""
- CALL(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success
+ CALL(gas, address, value, args_offset, args_size, ret_offset, ret_size)
+ = success
----
Description
@@ -5274,14 +5354,15 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub
- context is returned to this one
+ - gas: amount of gas to send to the sub context to execute. The gas that
+ is not used by the sub context is returned to this one
- address: the account which context to execute
- value: value in wei to send to the account
- - args_offset: byte offset in the memory in bytes, the calldata of the sub context
+ - args_offset: byte offset in the memory in bytes, the calldata of
+ the sub context
- args_size: byte size to copy (size of the calldata)
- - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub
- context
+ - ret_offset: byte offset in the memory in bytes, where to store the
+ return data of the sub context
- ret_size: byte size to copy (size of the return data)
Outputs
@@ -5296,8 +5377,9 @@ class Opcodes(Opcode, Enum):
----
```
static_gas = 0
- dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost
- + positive_value_cost + value_to_empty_account_cost
+ dynamic_gas = memory_expansion_cost + code_execution_cost +
+ address_access_cost + positive_value_cost +
+ value_to_empty_account_cost
```
Source: [evm.codes/#F1](https://www.evm.codes/#F1)
@@ -5311,24 +5393,26 @@ class Opcodes(Opcode, Enum):
kwargs_defaults={"gas": GAS},
)
"""
- CALLCODE(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success
+ CALLCODE(gas, address, value, args_offset, args_size, ret_offset, ret_size)
+ = success
----
Description
----
- Message-call into this account with an alternative account's code. Executes code starting at
- the address to which the call is made.
+ Message-call into this account with an alternative account's code.
+ Executes code starting at the address to which the call is made.
Inputs
----
- - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub
- context is returned to this one
+ - gas: amount of gas to send to the sub context to execute. The gas that
+ is not used by the sub context is returned to this one
- address: the account which code to execute
- value: value in wei to send to the account
- - args_offset: byte offset in the memory in bytes, the calldata of the sub context
+ - args_offset: byte offset in the memory in bytes, the calldata of
+ the sub context
- args_size: byte size to copy (size of the calldata)
- - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub
- context
+ - ret_offset: byte offset in the memory in bytes, where to store the
+ return data of the sub context
- ret_size: byte size to copy (size of the return data)
Outputs
@@ -5343,8 +5427,8 @@ class Opcodes(Opcode, Enum):
----
```
static_gas = 0
- dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost
- + positive_value_cost
+ dynamic_gas = memory_expansion_cost + code_execution_cost +
+ address_access_cost + positive_value_cost
```
Source: [evm.codes/#F2](https://www.evm.codes/#F2)
@@ -5361,8 +5445,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - offset: byte offset in the memory in bytes, to copy what will be the return data of this
- context
+ - offset: byte offset in the memory in bytes, to copy what will be
+ the return data of this context
- size: byte size to copy (size of the return data)
Outputs
@@ -5389,23 +5473,25 @@ class Opcodes(Opcode, Enum):
kwargs_defaults={"gas": GAS},
)
"""
- DELEGATECALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success
+ DELEGATECALL(gas, address, args_offset, args_size, ret_offset, ret_size)
+ = success
----
Description
----
- Message-call into this account with an alternative account's code, but persisting the current
- values for sender and value
+ Message-call into this account with an alternative account's code, but
+ persisting the current values for sender and value
Inputs
----
- - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub
- context is returned to this one
+ - gas: amount of gas to send to the sub context to execute. The gas that
+ is not used by the sub context is returned to this one
- address: the account which code to execute
- - args_offset: byte offset in the memory in bytes, the calldata of the sub context
+ - args_offset: byte offset in the memory in bytes, the calldata of
+ the sub context
- args_size: byte size to copy (size of the calldata)
- - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub
- context
+ - ret_offset: byte offset in the memory in bytes, where to store
+ the return data of the sub context
- ret_size: byte size to copy (size of the return data)
Outputs
@@ -5419,7 +5505,8 @@ class Opcodes(Opcode, Enum):
Gas
----
- static_gas = 0
- - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost
+ - dynamic_gas = memory_expansion_cost + code_execution_cost +
+ address_access_cost
Source: [evm.codes/#F4](https://www.evm.codes/#F4)
"""
@@ -5441,9 +5528,11 @@ class Opcodes(Opcode, Enum):
Inputs
----
- value: value in wei to send to the new account
- - offset: byte offset in the memory in bytes, the initialization code of the new account
+ - offset: byte offset in the memory in bytes, the initialization code
+ of the new account
- size: byte size to copy (size of the initialization code)
- - salt: 32-byte value used to create the new account at a deterministic address
+ - salt: 32-byte value used to create the new account at a
+ deterministic address
Outputs
----
@@ -5486,7 +5575,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- address: the account which context to execute
- - args_offset: byte offset in the memory in bytes, the calldata of the sub context
+ - args_offset: byte offset in the memory in bytes, the calldata of
+ the sub context
- args_size: byte size to copy (size of the calldata)
- value: value in wei to send to the account
@@ -5494,7 +5584,8 @@ class Opcodes(Opcode, Enum):
----
- success:
- `0` if the call was successful.
- - `1` if the call has reverted (also can be pushed earlier in a light failure scenario).
+ - `1` if the call has reverted (also can be pushed earlier in a
+ light failure scenario).
- `2` if the call has failed.
Fork
@@ -5505,8 +5596,9 @@ class Opcodes(Opcode, Enum):
----
```
static_gas = 0
- dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost
- + positive_value_cost + value_to_empty_account_cost
+ dynamic_gas = memory_expansion_cost + code_execution_cost +
+ address_access_cost + positive_value_cost +
+ value_to_empty_account_cost
```
Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069)
@@ -5524,20 +5616,22 @@ class Opcodes(Opcode, Enum):
Description
----
- Message-call into this account with an alternative account's code, but persisting the current
- values for sender and value
+ Message-call into this account with an alternative account's code,
+ but persisting the current values for sender and value
Inputs
----
- address: the account which context to execute
- - args_offset: byte offset in the memory in bytes, the calldata of the sub context
+ - args_offset: byte offset in the memory in bytes, the calldata of
+ the sub context
- args_size: byte size to copy (size of the calldata)
Outputs
----
- success:
- `0` if the call was successful.
- - `1` if the call has reverted (also can be pushed earlier in a light failure scenario).
+ - `1` if the call has reverted (also can be pushed earlier in a
+ light failure scenario).
- `2` if the call has failed.
Fork
@@ -5547,7 +5641,8 @@ class Opcodes(Opcode, Enum):
Gas
----
- static_gas = 0
- - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost
+ - dynamic_gas = memory_expansion_cost + code_execution_cost +
+ address_access_cost
Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069)
"""
@@ -5560,7 +5655,8 @@ class Opcodes(Opcode, Enum):
kwargs_defaults={"gas": GAS},
)
"""
- STATICCALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success
+ STATICCALL(gas, address, args_offset, args_size, ret_offset, ret_size)
+ = success
----
Description
@@ -5569,13 +5665,14 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub
- context is returned to this one
+ - gas: amount of gas to send to the sub context to execute. The gas
+ that is not used by the sub context is returned to this one
- address: the account which context to execute
- - args_offset: byte offset in the memory in bytes, the calldata of the sub context
+ - args_offset: byte offset in the memory in bytes, the calldata of the
+ sub context
- args_size: byte size to copy (size of the calldata)
- - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub
- context
+ - ret_offset: byte offset in the memory in bytes, where to store the
+ return data of the sub context
- ret_size: byte size to copy (size of the return data)
Outputs
@@ -5589,7 +5686,8 @@ class Opcodes(Opcode, Enum):
Gas
----
- static_gas = 0
- - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost
+ - dynamic_gas = memory_expansion_cost + code_execution_cost +
+ address_access_cost
Source: [evm.codes/#FA](https://www.evm.codes/#FA)
"""
@@ -5611,14 +5709,16 @@ class Opcodes(Opcode, Enum):
Inputs
----
- address: the account which context to execute
- - args_offset: byte offset in the memory in bytes, the calldata of the sub context
+ - args_offset: byte offset in the memory in bytes, the calldata
+ of the sub context
- args_size: byte size to copy (size of the calldata)
Outputs
----
- success:
- `0` if the call was successful.
- - `1` if the call has reverted (also can be pushed earlier in a light failure scenario).
+ - `1` if the call has reverted (also can be pushed earlier in a
+ light failure scenario).
- `2` if the call has failed.
Fork
@@ -5628,7 +5728,8 @@ class Opcodes(Opcode, Enum):
Gas
----
- static_gas = 0
- - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost
+ - dynamic_gas = memory_expansion_cost + code_execution_cost +
+ address_access_cost
Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069)
"""
@@ -5644,7 +5745,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - offset: byte offset in the return data from the last executed sub context to copy
+ - offset: byte offset in the return data from the last executed
+ sub context to copy
Fork
----
@@ -5666,7 +5768,8 @@ class Opcodes(Opcode, Enum):
Inputs
----
- - offset: byte offset in the memory in bytes. The return data of the calling context
+ - offset: byte offset in the memory in bytes. The return data of
+ the calling context
- size: byte size to copy (size of the return data)
Fork
@@ -5771,7 +5874,10 @@ class Opcodes(Opcode, Enum):
def _mstore_operation(data: OpcodeCallArg = b"", offset: OpcodeCallArg = 0) -> Bytecode:
- """Generate the bytecode that stores an arbitrary amount of data in memory."""
+ """
+ Generate the bytecode that stores an arbitrary
+ amount of data in memory.
+ """
assert isinstance(offset, int)
if isinstance(data, int):
data = data.to_bytes(32, "big")
@@ -5782,10 +5888,11 @@ def _mstore_operation(data: OpcodeCallArg = b"", offset: OpcodeCallArg = 0) -> B
if len(chunk) == 32:
bytecode += Opcodes.MSTORE(offset, chunk)
else:
- # We need to MLOAD the existing data at the offset and then do a bitwise OR with the
- # new data to store it in memory.
+ # We need to MLOAD the existing data at the offset and then
+ # do a bitwise OR with the new data to store it in memory.
bytecode += Opcodes.MLOAD(offset)
- # Create a mask to zero out the leftmost bytes of the existing data.
+ # Create a mask to zero out the leftmost bytes of
+ # the existing data.
mask_size = 32 - len(chunk)
bytecode += _push_opcodes_byte_list[mask_size - 1][-1]
bytecode += Opcodes.AND
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/py.typed b/packages/tests/src/ethereum_test_vm/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_vm/py.typed
rename to packages/tests/src/ethereum_test_vm/py.typed
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/tests/__init__.py b/packages/tests/src/ethereum_test_vm/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/ethereum_test_vm/tests/__init__.py
rename to packages/tests/src/ethereum_test_vm/tests/__init__.py
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/tests/test_vm.py b/packages/tests/src/ethereum_test_vm/tests/test_vm.py
similarity index 99%
rename from src/ethereum_spec_tests/ethereum_test_vm/tests/test_vm.py
rename to packages/tests/src/ethereum_test_vm/tests/test_vm.py
index f9da93d84e..be9d7edd5d 100644
--- a/src/ethereum_spec_tests/ethereum_test_vm/tests/test_vm.py
+++ b/packages/tests/src/ethereum_test_vm/tests/test_vm.py
@@ -4,9 +4,9 @@
from ethereum_test_base_types import Address
-from ..opcode import Bytecode
-from ..opcode import Macros as Om
-from ..opcode import Opcodes as Op
+from ..opcodes import Bytecode
+from ..opcodes import Macros as Om
+from ..opcodes import Opcodes as Op
@pytest.mark.parametrize(
diff --git a/src/ethereum_spec_tests/pytest_plugins/__init__.py b/packages/tests/src/pytest_plugins/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/__init__.py
rename to packages/tests/src/pytest_plugins/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/concurrency.py b/packages/tests/src/pytest_plugins/concurrency.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/concurrency.py
rename to packages/tests/src/pytest_plugins/concurrency.py
index 10dadcca9c..0601824c33 100644
--- a/src/ethereum_spec_tests/pytest_plugins/concurrency.py
+++ b/packages/tests/src/pytest_plugins/concurrency.py
@@ -1,6 +1,6 @@
"""
-Pytest plugin to create a temporary folder for the session where
-multi-process tests can store data that is shared between processes.
+Pytest plugin to create a temporary folder for the session where multi-process
+tests can store data that is shared between processes.
The provided `session_temp_folder` fixture is used, for example, by `consume`
when running hive simulators to ensure that only one `test_suite` is created
@@ -24,8 +24,8 @@ def session_temp_folder_name(testrun_uid: str) -> str:
Define the name of the temporary folder that will be shared among all the
xdist workers to coordinate the tests.
- "testrun_uid" is a fixture provided by the xdist plugin, and is unique for each test run,
- so it is used to create the unique folder name.
+ "testrun_uid" is a fixture provided by the xdist plugin, and is unique for
+ each test run, so it is used to create the unique folder name.
"""
return f"pytest-{testrun_uid}"
@@ -35,11 +35,11 @@ def session_temp_folder(
session_temp_folder_name: str,
) -> Generator[Path, None, None]:
"""
- Create a global temporary folder that will be shared among all the
- xdist workers to coordinate the tests.
+ Create a global temporary folder that will be shared among all the xdist
+ workers to coordinate the tests.
- We also create a file to keep track of how many workers are still using the folder, so we can
- delete it when the last worker is done.
+ We also create a file to keep track of how many workers are still using the
+ folder, so we can delete it when the last worker is done.
"""
session_temp_folder = Path(get_temp_dir()) / session_temp_folder_name
session_temp_folder.mkdir(exist_ok=True)
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/__init__.py b/packages/tests/src/pytest_plugins/consume/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/__init__.py
rename to packages/tests/src/pytest_plugins/consume/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/consume.py b/packages/tests/src/pytest_plugins/consume/consume.py
similarity index 93%
rename from src/ethereum_spec_tests/pytest_plugins/consume/consume.py
rename to packages/tests/src/pytest_plugins/consume/consume.py
index e678cf7524..4313615b19 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/consume.py
+++ b/packages/tests/src/pytest_plugins/consume/consume.py
@@ -1,4 +1,6 @@
-"""A pytest plugin providing common functionality for consuming test fixtures."""
+"""
+A pytest plugin providing common functionality for consuming test fixtures.
+"""
import re
import sys
@@ -53,7 +55,10 @@ def __init__(self, url: str, destination_folder: Path): # noqa: D107
self.archive_name = self.strip_archive_extension(Path(self.parsed_url.path).name)
def download_and_extract(self) -> Tuple[bool, Path]:
- """Download the URL and extract it locally if it hasn't already been downloaded."""
+ """
+ Download the URL and extract it locally if it hasn't already been
+ downloaded.
+ """
if self.destination_folder.exists():
return True, self.detect_extracted_directory()
@@ -94,8 +99,8 @@ def fetch_and_extract(self) -> Path:
def detect_extracted_directory(self) -> Path:
"""
- Detect a single top-level dir within the extracted archive, otherwise return
- destination_folder.
+ Detect a single top-level dir within the extracted archive, otherwise
+ return destination_folder.
""" # noqa: D200
extracted_dirs = [
d for d in self.destination_folder.iterdir() if d.is_dir() and d.name != ".meta"
@@ -196,7 +201,9 @@ def from_url(
def from_release_spec(
cls, spec: str, cache_folder: Optional[Path] = None, extract_to: Optional[Path] = None
) -> "FixturesSource":
- """Create a fixture source from a release spec (e.g., develop@latest)."""
+ """
+ Create a fixture source from a release spec (e.g., develop@latest).
+ """
if cache_folder is None:
cache_folder = CACHED_DOWNLOADS_DIRECTORY
url = get_release_url(spec)
@@ -224,7 +231,9 @@ def from_release_spec(
@staticmethod
def validate_local_path(path: Path) -> "FixturesSource":
- """Validate that a local fixture path exists and contains JSON files."""
+ """
+ Validate that a local fixture path exists and contains JSON files.
+ """
if not path.exists():
pytest.exit(f"Specified fixture directory '{path}' does not exist.")
if not any(path.glob("**/*.json")):
@@ -242,24 +251,29 @@ def __init__(self, pattern: str, collectonly: bool = False): # noqa: D107
@staticmethod
def _escape_id(pattern: str) -> str:
"""
- Escape regex char in the pattern; prepend and append '.*' (for `fill` IDs).
+ Escape regex char in the pattern; prepend and append '.*' (for `fill`
+ IDs).
- The `pattern` is prefixed and suffixed with a wildcard match to allow `fill`
- test case IDs to be specified, otherwise the full `consume` test ID must be
- specified.
+ The `pattern` is prefixed and suffixed with a wildcard match to allow
+ `fill` test case IDs to be specified, otherwise the full `consume` test
+ ID must be specified.
"""
return f".*{re.escape(pattern)}.*"
@classmethod
def from_string(cls, pattern: str) -> "SimLimitBehavior":
"""
- Parse the `--sim.limit` argument and return a `SimLimitBehavior` instance.
+ Parse the `--sim.limit` argument and return a `SimLimitBehavior`
+ instance.
If `pattern`:
- - Is "collectonly", enable collection mode without filtering.
- - Starts with "collectonly:", enable collection mode and use the rest as a regex pattern.
- - Starts with "id:", treat the rest as a literal test ID and escape special regex chars.
- - Starts with "collectonly:id:", enable collection mode with a literal test ID.
+ - Is "collectonly", enable collection mode without filtering.
+ - Starts with "collectonly:", enable collection mode and use the
+ rest as a regex pattern.
+ - Starts with "id:", treat the rest as a literal test ID and escape
+ special regex chars.
+ - Starts with "collectonly:id:", enable collection mode with a
+ literal test ID.
"""
if pattern == "collectonly":
return cls(pattern=".*", collectonly=True)
@@ -357,22 +371,23 @@ def pytest_configure(config): # noqa: D103
test collection begins.
`@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is
- called before the pytest-html plugin's pytest_configure to ensure that
- it uses the modified `htmlpath` option.
+ called before the pytest-html plugin's pytest_configure to ensure that it
+ uses the modified `htmlpath` option.
"""
# Validate --extract-to usage
if config.option.extract_to_folder is not None and "cache" not in sys.argv:
pytest.exit("The --extract-to flag is only valid with the 'cache' command.")
if config.option.fixtures_source is None:
- # NOTE: Setting the default value here is necessary for correct stdin/piping behavior.
+ # NOTE: Setting the default value here is necessary for correct
+ # stdin/piping behavior.
config.fixtures_source = FixturesSource(
input_option=default_input(), path=Path(default_input())
)
else:
- # NOTE: Setting `type=FixturesSource.from_input` in pytest_addoption() causes the option to
- # be evaluated twice which breaks the result of `was_cached`; the work-around is to call it
- # manually here.
+ # NOTE: Setting `type=FixturesSource.from_input` in pytest_addoption()
+ # causes the option to be evaluated twice which breaks the result of
+ # `was_cached`; the work-around is to call it manually here.
config.fixtures_source = FixturesSource.from_input(
config.option.fixtures_source,
Path(config.option.fixture_cache_folder),
@@ -413,7 +428,6 @@ def pytest_configure(config): # noqa: D103
config.fixtures_source.path,
quiet_mode=False,
force_flag=False,
- disable_infer_format=False,
)
index = IndexFile.model_validate_json(index_file.read_text())
@@ -429,7 +443,8 @@ def pytest_configure(config): # noqa: D103
all_forks = { # type: ignore
fork for fork in set(get_forks()) | get_transition_forks() if not fork.ignore()
}
- # Append all forks within the index file (compatibility with `ethereum/tests`)
+ # Append all forks within the index file (compatibility with
+ # `ethereum/tests`)
all_forks.update(getattr(index, "forks", []))
for fork in all_forks:
config.addinivalue_line("markers", f"{fork}: Tests for the {fork} fork")
@@ -484,7 +499,8 @@ def fixtures_source(request) -> FixturesSource: # noqa: D103
def pytest_generate_tests(metafunc):
"""
Generate test cases for every test fixture in all the JSON fixture files
- within the specified fixtures directory, or read from stdin if the directory is 'stdin'.
+ within the specified fixtures directory, or read from stdin if the
+ directory is 'stdin'.
"""
if "cache" in sys.argv:
return
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/direct/__init__.py b/packages/tests/src/pytest_plugins/consume/direct/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/direct/__init__.py
rename to packages/tests/src/pytest_plugins/consume/direct/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/direct/conftest.py b/packages/tests/src/pytest_plugins/consume/direct/conftest.py
similarity index 98%
rename from src/ethereum_spec_tests/pytest_plugins/consume/direct/conftest.py
rename to packages/tests/src/pytest_plugins/consume/direct/conftest.py
index e584e01347..db9208a910 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/direct/conftest.py
+++ b/packages/tests/src/pytest_plugins/consume/direct/conftest.py
@@ -1,6 +1,6 @@
"""
-A pytest plugin that configures the consume command to act as a test runner
-for "direct" client fixture consumer interfaces.
+A pytest plugin that configures the consume command to act as a test runner for
+"direct" client fixture consumer interfaces.
For example, via go-ethereum's `evm blocktest` or `evm statetest` commands.
"""
@@ -120,7 +120,8 @@ def fixture_path(test_case: TestCaseIndexFile | TestCaseStream, fixtures_source:
"""
Path to the current JSON fixture file.
- If the fixture source is stdin, the fixture is written to a temporary json file.
+ If the fixture source is stdin, the fixture is written to a temporary json
+ file.
"""
if fixtures_source.is_stdin:
assert isinstance(test_case, TestCaseStream)
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/direct/test_via_direct.py b/packages/tests/src/pytest_plugins/consume/direct/test_via_direct.py
similarity index 81%
rename from src/ethereum_spec_tests/pytest_plugins/consume/direct/test_via_direct.py
rename to packages/tests/src/pytest_plugins/consume/direct/test_via_direct.py
index f1f9508144..e1f014d019 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/direct/test_via_direct.py
+++ b/packages/tests/src/pytest_plugins/consume/direct/test_via_direct.py
@@ -1,6 +1,6 @@
"""
-Executes a JSON test fixture directly against a client using a dedicated
-client interface similar to geth's EVM 'blocktest' command.
+Executes a JSON test fixture directly against a client using a dedicated client
+interface similar to geth's EVM 'blocktest' command.
"""
from pathlib import Path
@@ -16,8 +16,8 @@ def test_fixture(
test_dump_dir: Path | None,
):
"""
- Generic test function used to call the fixture consumer with a given fixture file path and
- a fixture name (for a single test run).
+ Generic test function used to call the fixture consumer with a given
+ fixture file path and a fixture name (for a single test run).
"""
fixture_consumer.consume_fixture(
test_case.format,
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/hive_engine_test/__init__.py b/packages/tests/src/pytest_plugins/consume/hive_engine_test/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/hive_engine_test/__init__.py
rename to packages/tests/src/pytest_plugins/consume/hive_engine_test/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/hive_simulators_reorg/__init__.py b/packages/tests/src/pytest_plugins/consume/hive_simulators_reorg/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/hive_simulators_reorg/__init__.py
rename to packages/tests/src/pytest_plugins/consume/hive_simulators_reorg/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/releases.py b/packages/tests/src/pytest_plugins/consume/releases.py
similarity index 92%
rename from src/ethereum_spec_tests/pytest_plugins/consume/releases.py
rename to packages/tests/src/pytest_plugins/consume/releases.py
index 2e694a7eec..26ecc67b17 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/releases.py
+++ b/packages/tests/src/pytest_plugins/consume/releases.py
@@ -48,7 +48,8 @@ def from_string(cls, release_string: str) -> "ReleaseTag":
"""
Create a release descriptor from a string.
- The release source can be in the format `tag_name@version` or just `tag_name`.
+ The release source can be in the format `tag_name@version` or just
+ `tag_name`.
"""
version: str | None
if "@" in release_string:
@@ -69,7 +70,8 @@ def __eq__(self, value) -> bool:
"""
Check if the release descriptor matches the string value.
- Returns True if the value is the same as the tag name or the tag name and version.
+ Returns True if the value is the same as the tag name or the tag name
+ and version.
"""
assert isinstance(value, str), f"Expected a string, but got: {value}"
if self.version is not None:
@@ -141,7 +143,9 @@ class Releases(RootModel[List[ReleaseInformation]]):
def is_docker_or_ci() -> bool:
- """Check if the code is running inside a Docker container or a CI environment."""
+ """
+ Check if the code is running inside a Docker container or a CI environment.
+ """
return "GITHUB_ACTIONS" in os.environ or Path("/.dockerenv").exists()
@@ -221,14 +225,16 @@ def get_release_page_url(release_string: str) -> str:
Return the GitHub Release page URL for a specific release descriptor.
This function can handle:
- - A standard release string (e.g., "eip7692@latest") - from execution-spec-tests only.
+ - A standard release string (e.g., "eip7692@latest") from
+ execution-spec-tests only.
- A direct asset download link (e.g.,
- "https://github.com/ethereum/execution-spec-tests/releases/download/v4.0.0/fixtures_eip7692.tar.gz").
+ "https://github.com/ethereum/execution-spec-tests/releases/
+ download/v4.0.0/fixtures_eip7692.tar.gz").
"""
release_information = get_release_information()
- # Case 1: If it's a direct GitHub Releases download link,
- # find which release in `release_information` has an asset with this exact URL.
+ # Case 1: If it's a direct GitHub Releases download link, find which
+ # release in `release_information` has an asset with this exact URL.
repo_pattern = "|".join(re.escape(repo) for repo in SUPPORTED_REPOS)
regex_pattern = rf"https://github\.com/({repo_pattern})/releases/download/"
if re.match(regex_pattern, release_string):
@@ -238,7 +244,8 @@ def get_release_page_url(release_string: str) -> str:
return release.url # The HTML page for this release
raise NoSuchReleaseError(f"No release found for asset URL: {release_string}")
- # Case 2: Otherwise, treat it as a release descriptor (e.g., "eip7692@latest")
+ # Case 2: Otherwise, treat it as a release descriptor (e.g.,
+ # "eip7692@latest")
release_descriptor = ReleaseTag.from_string(release_string)
for release in release_information:
if release_descriptor in release:
@@ -252,9 +259,10 @@ def get_release_information() -> List[ReleaseInformation]:
"""
Get the release information.
- First check if the cached release information file exists. If it does, but it is older than 4
- hours, delete the file, unless running inside a CI environment or a Docker container.
- Then download the release information from the Github API and save it to the cache file.
+ First check if the cached release information file exists. If it does, but
+ it is older than 4 hours, delete the file, unless running inside a CI
+ environment or a Docker container. Then download the release information
+ from the Github API and save it to the cache file.
"""
if CACHED_RELEASE_INFORMATION_FILE.exists():
last_modified = CACHED_RELEASE_INFORMATION_FILE.stat().st_mtime
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/__init__.py
rename to packages/tests/src/pytest_plugins/consume/simulators/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/base.py b/packages/tests/src/pytest_plugins/consume/simulators/base.py
similarity index 87%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/base.py
rename to packages/tests/src/pytest_plugins/consume/simulators/base.py
index 0b62ebb587..22736c97eb 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/base.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/base.py
@@ -45,7 +45,9 @@ def __init__(self) -> None:
self._fixtures: Dict[Path, Fixtures] = {}
def __getitem__(self, key: Path) -> Fixtures:
- """Return the fixtures from the index file, if not found, load from disk."""
+ """
+ Return the fixtures from the index file, if not found, load from disk.
+ """
assert key.is_file(), f"Expected a file path, got '{key}'"
if key not in self._fixtures:
self._fixtures[key] = Fixtures.model_validate_json(key.read_text())
@@ -54,7 +56,10 @@ def __getitem__(self, key: Path) -> Fixtures:
@pytest.fixture(scope="session")
def fixture_file_loader() -> Dict[Path, Fixtures]:
- """Return a singleton dictionary that caches loaded fixture files used in all tests."""
+ """
+ Return a singleton dictionary that caches loaded fixture files used in all
+ tests.
+ """
return FixturesDict()
@@ -65,12 +70,12 @@ def fixture(
test_case: TestCaseIndexFile | TestCaseStream,
) -> BaseFixture:
"""
- Load the fixture from a file or from stream in any of the supported
- fixture formats.
+ Load the fixture from a file or from stream in any of the supported fixture
+ formats.
- The fixture is either already available within the test case (if consume
- is taking input on stdin) or loaded from the fixture json file if taking
- input from disk (fixture directory with index file).
+ The fixture is either already available within the test case (if consume is
+ taking input on stdin) or loaded from the fixture json file if taking input
+ from disk (fixture directory with index file).
"""
fixture: BaseFixture
if fixtures_source.is_stdin:
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/engine/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/__init__.py
rename to packages/tests/src/pytest_plugins/consume/simulators/engine/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/conftest.py b/packages/tests/src/pytest_plugins/consume/simulators/engine/conftest.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/conftest.py
rename to packages/tests/src/pytest_plugins/consume/simulators/engine/conftest.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/exceptions.py b/packages/tests/src/pytest_plugins/consume/simulators/exceptions.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/exceptions.py
rename to packages/tests/src/pytest_plugins/consume/simulators/exceptions.py
index 0e8d4d63a7..8db60438e0 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/exceptions.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/exceptions.py
@@ -54,7 +54,10 @@ def client_exception_mapper(
@pytest.fixture(scope="session")
def disable_strict_exception_matching(request: pytest.FixtureRequest) -> List[str]:
- """Return the list of clients or forks that should NOT use strict exception matching."""
+ """
+ Return the list of clients or forks that should NOT use strict exception
+ matching.
+ """
config_string = request.config.getoption("disable_strict_exception_matching")
return config_string.split(",") if config_string else []
@@ -76,7 +79,8 @@ def fork_strict_exception_matching(
disable_strict_exception_matching: List[str],
) -> bool:
"""Return True if the fork should use strict exception matching."""
- # NOTE: `in` makes it easier for transition forks ("Prague" in "CancunToPragueAtTime15k")
+ # NOTE: `in` makes it easier for transition forks ("Prague" in
+ # "CancunToPragueAtTime15k")
return not any(
s.lower() in str(fixture.fork).lower() for s in disable_strict_exception_matching
)
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/__init__.py
rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/exceptions.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/exceptions.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/exceptions.py
rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/exceptions.py
index 6307fb095b..f6a7e7e2bc 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/exceptions.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/helpers/exceptions.py
@@ -16,10 +16,16 @@
class GenesisBlockMismatchExceptionError(Exception):
- """Definers a mismatch exception between the client and fixture genesis blockhash."""
+ """
+ Definers a mismatch exception between the client and fixture genesis
+ blockhash.
+ """
def __init__(self, *, expected_header: FixtureHeader, got_genesis_block: Dict[str, str]):
- """Initialize the exception with the expected and received genesis block headers."""
+ """
+ Initialize the exception with the expected and received genesis block
+ headers.
+ """
message = (
"Genesis block hash mismatch.\n\n"
f"Expected: {expected_header.block_hash}\n"
@@ -47,7 +53,9 @@ def __init__(self, *, expected_header: FixtureHeader, got_genesis_block: Dict[st
@staticmethod
def compare_models(expected: FixtureHeader, got: FixtureHeader) -> Tuple[Dict, List]:
- """Compare two FixtureHeader model instances and return their differences."""
+ """
+ Compare two FixtureHeader model instances and return their differences.
+ """
differences = {}
unexpected_fields = []
for (exp_name, exp_value), (got_name, got_value) in zip(expected, got, strict=False):
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/ruleset.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/ruleset.py
similarity index 98%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/ruleset.py
rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/ruleset.py
index c1b7195b29..2098dc6c93 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/ruleset.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/helpers/ruleset.py
@@ -43,10 +43,12 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]:
"""
Generate blob schedule entries for each fork (and respective parent forks).
- Adds the following entries to the ruleset for the given fork (and parent forks):
- HIVE_{FORK}_BLOB_TARGET: target_blobs_per_block()
- HIVE_{FORK}_BLOB_MAX: max_blobs_per_block()
- HIVE_{FORK}_BLOB_BASE_FEE_UPDATE_FRACTION: blob_base_fee_update_fraction()
+ Adds the following entries to the ruleset for the given fork (and parent
+ forks):
+ HIVE_{FORK}_BLOB_TARGET: target_blobs_per_block()
+ HIVE_{FORK}_BLOB_MAX: max_blobs_per_block()
+ HIVE_{FORK}_BLOB_BASE_FEE_UPDATE_FRACTION: blob_base_fee_update_
+ fraction()
"""
entries: Dict = {}
forks_with_blobs: List[Fork] = []
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/timing.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/timing.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/timing.py
rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/timing.py
index eddfe3f780..e5cadee957 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/timing.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/helpers/timing.py
@@ -5,7 +5,9 @@
class TimingData:
- """The times taken to perform the various steps of a test case (seconds)."""
+ """
+ The times taken to perform the various steps of a test case (seconds).
+ """
name: str
start_time: float | None
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/rlp/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/__init__.py
rename to packages/tests/src/pytest_plugins/consume/simulators/rlp/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/conftest.py b/packages/tests/src/pytest_plugins/consume/simulators/rlp/conftest.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/conftest.py
rename to packages/tests/src/pytest_plugins/consume/simulators/rlp/conftest.py
index f2d8f93a34..66ad7dd62a 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/conftest.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/rlp/conftest.py
@@ -46,7 +46,10 @@ def blocks_rlp(fixture: BlockchainFixture) -> List[Bytes]:
@pytest.fixture(scope="function")
def buffered_blocks_rlp(blocks_rlp: List[bytes]) -> List[io.BufferedReader]:
- """Convert the RLP-encoded blocks of the current test fixture to buffered readers."""
+ """
+ Convert the RLP-encoded blocks of the current test fixture to buffered
+ readers.
+ """
block_rlp_files = []
for _, block_rlp in enumerate(blocks_rlp):
block_rlp_stream = io.BytesIO(block_rlp)
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/__init__.py
rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py
similarity index 91%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py
rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py
index 26e95719c5..1ef5a774de 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py
@@ -1,8 +1,10 @@
"""
-A hive based simulator that executes blocks against clients using the `engine_newPayloadVX` method
-from the Engine API. The simulator uses the `BlockchainEngineFixtures` to test against clients.
+A hive based simulator that executes blocks against clients using the
+`engine_newPayloadVX` method from the Engine API. The simulator uses the
+`BlockchainEngineFixtures` to test against clients.
-Each `engine_newPayloadVX` is verified against the appropriate VALID/INVALID responses.
+Each `engine_newPayloadVX` is verified against the appropriate VALID/INVALID
+responses.
"""
import time
@@ -10,14 +12,17 @@
from ethereum_test_exceptions import UndefinedException
from ethereum_test_fixtures import BlockchainEngineFixture
from ethereum_test_rpc import EngineRPC, EthRPC
-from ethereum_test_rpc.types import ForkchoiceState, JSONRPCError, PayloadStatusEnum
+from ethereum_test_rpc.rpc_types import ForkchoiceState, JSONRPCError, PayloadStatusEnum
-from ....logging import get_logger
+from ....custom_logging import get_logger
from ..helpers.exceptions import GenesisBlockMismatchExceptionError
from ..helpers.timing import TimingData
logger = get_logger(__name__)
+MAX_RETRIES = 30
+DELAY_BETWEEN_RETRIES_IN_SEC = 1
+
class LoggedError(Exception):
"""Exception that uses the logger to log the failure."""
@@ -36,16 +41,17 @@ def test_blockchain_via_engine(
strict_exception_matching: bool,
):
"""
- 1. Check the client genesis block hash matches `fixture.genesis.block_hash`.
- 2. Execute the test case fixture blocks against the client under test using the
- `engine_newPayloadVX` method from the Engine API.
- 3. For valid payloads a forkchoice update is performed to finalize the chain.
+ 1. Check the client genesis block hash matches
+ `fixture.genesis.block_hash`.
+ 2. Execute the test case fixture blocks against the client under test using
+ the `engine_newPayloadVX` method from the Engine API.
+ 3. For valid payloads a forkchoice update is performed to finalize the
+ chain.
"""
# Send a initial forkchoice update
with timing_data.time("Initial forkchoice update"):
logger.info("Sending initial forkchoice update to genesis block...")
- delay = 0.5
- for attempt in range(3):
+ for attempt in range(1, MAX_RETRIES + 1):
forkchoice_response = engine_rpc.forkchoice_updated(
forkchoice_state=ForkchoiceState(
head_block_hash=fixture.genesis.block_hash,
@@ -54,16 +60,16 @@ def test_blockchain_via_engine(
version=fixture.payloads[0].forkchoice_updated_version,
)
status = forkchoice_response.payload_status.status
- logger.info(f"Initial forkchoice update response attempt {attempt + 1}: {status}")
+ logger.info(f"Initial forkchoice update response attempt {attempt}: {status}")
if status != PayloadStatusEnum.SYNCING:
break
- if attempt < 2:
- time.sleep(delay)
- delay *= 2
+
+ if attempt < MAX_RETRIES:
+ time.sleep(DELAY_BETWEEN_RETRIES_IN_SEC)
if forkchoice_response.payload_status.status != PayloadStatusEnum.VALID:
logger.error(
- f"Client failed to initialize properly after 3 attempts, "
+ f"Client failed to initialize properly after {MAX_RETRIES} attempts, "
f"final status: {forkchoice_response.payload_status.status}"
)
raise LoggedError(
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py
similarity index 90%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py
rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py
index f2a7363700..e894947a30 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py
@@ -1,8 +1,9 @@
"""
-A hive based simulator that executes RLP-encoded blocks against clients. The simulator uses the
-`BlockchainFixtures` to test this against clients.
+A hive based simulator that executes RLP-encoded blocks against clients. The
+simulator uses the `BlockchainFixtures` to test this against clients.
-Clients consume the genesis and RLP-encoded blocks from input files upon start-up.
+Clients consume the genesis and RLP-encoded blocks from input files upon
+start-up.
"""
import logging
@@ -23,7 +24,8 @@ def test_via_rlp(
fixture: BlockchainFixture,
):
"""
- 1. Check the client genesis block hash matches `fixture.genesis.block_hash`.
+ 1. Check the client genesis block hash matches
+ `fixture.genesis.block_hash`.
2. Check the client last block hash matches `fixture.last_block_hash`.
"""
with timing_data.time("Get genesis block"):
@@ -63,10 +65,10 @@ def test_via_rlp(
)
raise AssertionError(
"blockHash mismatch in last block - field mismatches:"
- f"\n{'\n'.join(mismatches)}"
+ "\n" + "\n".join(mismatches)
)
- except Exception as e:
+ except Exception:
raise AssertionError(
f"blockHash mismatch in last block: got `{block['hash']}`, "
f"expected `{fixture.last_block_hash}`"
- ) from e
+ ) from None
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py
similarity index 81%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py
rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py
index adbbbb0f8a..d9f2dc3197 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py
@@ -1,10 +1,12 @@
"""
-A hive based simulator that executes blocks against clients using the `engine_newPayloadV*` method
-from the Engine API with sync testing. The simulator uses the `BlockchainEngineSyncFixtures` to
-test against clients with client synchronization.
+A hive based simulator that executes blocks against clients using the
+`engine_newPayloadV*` method from the Engine API with sync testing. The
+simulator uses the `BlockchainEngineSyncFixtures` to test against clients with
+client synchronization.
This simulator:
-1. Spins up two clients: one as the client under test and another as the sync client
+1. Spins up two clients: one as the client under test and another as the sync
+ client
2. Executes payloads on the client under test
3. Has the sync client synchronize from the client under test
4. Verifies that the sync was successful
@@ -14,17 +16,16 @@
import pytest
-from ethereum_test_base_types import Hash
from ethereum_test_exceptions import UndefinedException
from ethereum_test_fixtures import BlockchainEngineSyncFixture
from ethereum_test_rpc import AdminRPC, EngineRPC, EthRPC, NetRPC
-from ethereum_test_rpc.types import (
+from ethereum_test_rpc.rpc_types import (
ForkchoiceState,
JSONRPCError,
PayloadStatusEnum,
)
-from ....logging import get_logger
+from ....custom_logging import get_logger
from ..helpers.exceptions import GenesisBlockMismatchExceptionError
from ..helpers.timing import TimingData
@@ -40,72 +41,11 @@ def __init__(self, *args: object) -> None:
logger.fail(str(self))
-def wait_for_sync(
- sync_eth_rpc: EthRPC,
- sync_engine_rpc: EngineRPC,
- expected_block_hash: str | Hash,
- timeout: int = 10,
- poll_interval: float = 1.0,
-) -> bool:
- """Wait for the sync client to reach the expected block hash."""
- start_time = time.time()
- last_block_number = 0
- no_progress_count = 0
-
- while time.time() - start_time < timeout:
- try:
- # First check if we have the expected block
- block = sync_eth_rpc.get_block_by_hash(Hash(expected_block_hash))
- if block is not None:
- logger.info(f"Sync complete! Client has block {expected_block_hash}")
- return True
-
- # Check current sync progress
- current_block = sync_eth_rpc.get_block_by_number("latest")
- if current_block:
- current_number = int(current_block.get("number", "0x0"), 16)
- current_hash = current_block.get("hash", "unknown")
- if current_number > last_block_number:
- logger.info(f"Sync progress: block {current_number} (hash: {current_hash})")
- last_block_number = current_number
- no_progress_count = 0
- else:
- no_progress_count += 1
- if no_progress_count == 1:
- logger.info(
- f"Sync client is at block {current_number} (hash: {current_hash})"
- )
- elif no_progress_count % 10 == 0:
- logger.debug(
- f"No sync progress for {no_progress_count} polls, "
- f"still at block {current_number}"
- )
-
- except Exception as e:
- logger.debug(f"Error checking sync status: {e}")
-
- time.sleep(poll_interval)
-
- # Log final state
- try:
- final_block = sync_eth_rpc.get_block_by_number("latest")
- if final_block:
- logger.warning(
- f"Sync timeout! Final block: {final_block.get('number', 'unknown')} "
- f"(hash: {final_block.get('hash', 'unknown')})"
- )
- except Exception:
- pass
-
- return False
-
-
def test_blockchain_via_sync(
timing_data: TimingData,
eth_rpc: EthRPC,
engine_rpc: EngineRPC,
net_rpc: NetRPC,
- admin_rpc: AdminRPC,
sync_eth_rpc: EthRPC,
sync_engine_rpc: EngineRPC,
sync_net_rpc: NetRPC,
@@ -330,8 +270,8 @@ def test_blockchain_via_sync(
f"{forkchoice_response}"
)
- # Add peer using admin_addPeer
- # This seems to be required... TODO: we can maybe improve flow here if not required
+ # Add peer using admin_addPeer This seems to be required... TODO: we can
+ # maybe improve flow here if not required
logger.info(f"Adding peer: {client_enode_url}")
assert sync_admin_rpc is not None, "sync_admin_rpc is required"
try:
@@ -340,7 +280,8 @@ def test_blockchain_via_sync(
except Exception as e:
raise LoggedError(f"admin_addPeer failed: {e}") from e
- time.sleep(1) # quick sleep to allow for connection - TODO: is this necessary?
+ # quick sleep to allow for connection - TODO: is this necessary?
+ time.sleep(1)
try:
sync_peer_count = sync_net_rpc.peer_count()
@@ -354,7 +295,8 @@ def test_blockchain_via_sync(
except Exception as e:
logger.warning(f"Could not verify peer connection: {e}")
- # Trigger sync by sending the target block via newPayload followed by forkchoice update
+ # Trigger sync by sending the target block via newPayload followed by
+ # forkchoice update
logger.info(f"Triggering sync to block {last_valid_block_hash}")
# Find the last valid payload to send to sync client
@@ -376,7 +318,8 @@ def test_blockchain_via_sync(
)
try:
- version = last_valid_payload.new_payload_version # log version used for debugging
+ # log version used for debugging
+ version = last_valid_payload.new_payload_version
logger.info(f"Sending target payload via engine_newPayloadV{version}")
# send the payload to sync client
@@ -405,9 +348,9 @@ def test_blockchain_via_sync(
# Give a moment for P2P connections to establish after sync starts
time.sleep(1)
- # Check peer count after triggering sync
- # Note: Reth does not actually raise the peer count but doesn't seem
- # to need this to sync.
+ # Check peer count after triggering sync Note: Reth does not
+ # actually raise the peer count but doesn't seem to need this to
+ # sync.
try:
assert sync_net_rpc is not None, "sync_net_rpc is required"
client_peer_count = net_rpc.peer_count()
@@ -442,11 +385,12 @@ def test_blockchain_via_sync(
last_forkchoice_time = time.time()
forkchoice_interval = 2.0 # Send forkchoice updates every 2 seconds
- while time.time() - sync_start_time < 10: # 10 second timeout
+ while time.time() - sync_start_time < 15: # 15 second timeout
# Send periodic forkchoice updates to keep sync alive
if time.time() - last_forkchoice_time >= forkchoice_interval:
try:
- # Send forkchoice update to sync client to trigger/maintain sync
+ # Send forkchoice update to sync client to trigger/maintain
+ # sync
assert sync_engine_rpc is not None, "sync_engine_rpc is required"
sync_fc_response = sync_engine_rpc.forkchoice_updated(
forkchoice_state=last_valid_block_forkchoice_state,
@@ -469,35 +413,42 @@ def test_blockchain_via_sync(
f"within timeout"
)
- # Final verification
+ logger.info("Sync verification successful!")
+
+ # Verify the final state but give a few tries
+ assert eth_rpc is not None, "eth_rpc is required"
assert sync_eth_rpc is not None, "sync_eth_rpc is required"
- assert sync_engine_rpc is not None, "sync_engine_rpc is required"
- if wait_for_sync(sync_eth_rpc, sync_engine_rpc, last_valid_block_hash, timeout=5):
- logger.info("Sync verification successful!")
-
- # Verify the final state
- sync_block = sync_eth_rpc.get_block_by_hash(last_valid_block_hash)
- client_block = eth_rpc.get_block_by_hash(last_valid_block_hash)
-
- if sync_block["stateRoot"] != client_block["stateRoot"]:
- raise LoggedError(
- f"State root mismatch after sync. "
- f"Sync client: {sync_block['stateRoot']}, "
- f"Client under test: {client_block['stateRoot']}"
- )
- # Verify post state if available
- if fixture.post_state_hash:
- if sync_block["stateRoot"] != str(fixture.post_state_hash):
+ for attempt in range(5):
+ try:
+ sync_block = sync_eth_rpc.get_block_by_hash(last_valid_block_hash)
+ client_block = eth_rpc.get_block_by_hash(last_valid_block_hash)
+
+ if sync_block is None or client_block is None:
raise LoggedError(
- f"Final state root mismatch. "
- f"Expected: {fixture.post_state_hash}, "
- f"Got: {sync_block['stateRoot']}"
+ f"Failed to retrieve block {last_valid_block_hash} "
+ f"on attempt {attempt + 1}"
)
- else:
- raise LoggedError(
- f"Sync client failed to synchronize to block {last_valid_block_hash} "
- f"within timeout"
- )
+
+ if sync_block["stateRoot"] != client_block["stateRoot"]:
+ raise LoggedError(
+ f"State root mismatch after sync. "
+ f"Sync client: {sync_block['stateRoot']}, "
+ f"Client under test: {client_block['stateRoot']}"
+ )
+
+ if fixture.post_state_hash:
+ if sync_block["stateRoot"] != str(fixture.post_state_hash):
+ raise LoggedError(
+ f"Final state root mismatch. "
+ f"Expected: {fixture.post_state_hash}, "
+ f"Got: {sync_block['stateRoot']}"
+ )
+ break
+ except Exception as e:
+ if attempt < 4:
+ time.sleep(1)
+ continue
+ raise e
logger.info("Sync test completed successfully!")
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/single_test_client.py b/packages/tests/src/pytest_plugins/consume/simulators/single_test_client.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/single_test_client.py
rename to packages/tests/src/pytest_plugins/consume/simulators/single_test_client.py
index b6db7674c9..0ea5da90ac 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/single_test_client.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/single_test_client.py
@@ -1,4 +1,6 @@
-"""Common pytest fixtures for simulators with single-test client architecture."""
+"""
+Common pytest fixtures for simulators with single-test client architecture.
+"""
import io
import json
@@ -23,7 +25,10 @@
@pytest.fixture(scope="function")
def client_genesis(fixture: BlockchainFixtureCommon) -> dict:
- """Convert the fixture genesis block header and pre-state to a client genesis state."""
+ """
+ Convert the fixture genesis block header and pre-state to a client genesis
+ state.
+ """
genesis = to_json(fixture.genesis)
alloc = to_json(fixture.pre)
# NOTE: nethermind requires account keys without '0x' prefix
@@ -51,7 +56,10 @@ def environment(
@pytest.fixture(scope="function")
def buffered_genesis(client_genesis: dict) -> io.BufferedReader:
- """Create a buffered reader for the genesis block header of the current test fixture."""
+ """
+ Create a buffered reader for the genesis block header of the current test
+ fixture.
+ """
genesis_json = json.dumps(client_genesis)
genesis_bytes = genesis_json.encode("utf-8")
return io.BufferedReader(cast(io.RawIOBase, io.BytesIO(genesis_bytes)))
@@ -71,7 +79,9 @@ def client(
client_type: ClientType,
total_timing_data: TimingData,
) -> Generator[Client, None, None]:
- """Initialize the client with the appropriate files and environment variables."""
+ """
+ Initialize the client with the appropriate files and environment variables.
+ """
logger.info(f"Starting client ({client_type.name})...")
logger.debug(f"Main client Network ID: {environment.get('HIVE_NETWORK_ID', 'NOT SET!')}")
logger.debug(f"Main client Chain ID: {environment.get('HIVE_CHAIN_ID', 'NOT SET!')}")
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/sync/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/__init__.py
rename to packages/tests/src/pytest_plugins/consume/simulators/sync/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/conftest.py b/packages/tests/src/pytest_plugins/consume/simulators/sync/conftest.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/conftest.py
rename to packages/tests/src/pytest_plugins/consume/simulators/sync/conftest.py
index 10af1907c2..dcc884d3d6 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/conftest.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/sync/conftest.py
@@ -44,7 +44,13 @@ def pytest_generate_tests(metafunc):
@pytest.hookimpl(trylast=True)
def pytest_collection_modifyitems(session, config, items):
"""Modify test IDs to show both client and sync client clearly."""
+ del session, config
+
for item in items:
+ # Auto-mark all verify_sync tests as flaky with 3 reruns
+ if item.get_closest_marker("blockchain_test_sync"):
+ item.add_marker(pytest.mark.flaky(reruns=3))
+
# Check if this test has both client_type and sync_client_type
if (
hasattr(item, "callspec")
@@ -58,7 +64,8 @@ def pytest_collection_modifyitems(session, config, items):
# Format: ``-{client}_sync_{sync_client}``
new_suffix = f"-{client_name}::sync_{sync_client_name}"
- # client_param-tests/path/to/test.py::test_name[test_params]-sync_client_param
+ # client_param-
+ # tests/path/to/test.py::test_name[test_params]-sync_client_param
# 1. Remove the client prefix from the beginning
# 2. Replace the -client_param part at the end with our new format
nodeid = item.nodeid
@@ -117,7 +124,10 @@ def admin_rpc(client: Client) -> AdminRPC:
@pytest.fixture(scope="function")
def sync_genesis(fixture: BlockchainEngineSyncFixture) -> dict:
- """Convert the fixture genesis block header and pre-state to a sync client genesis state."""
+ """
+ Convert the fixture genesis block header and pre-state to a sync client
+ genesis state.
+ """
genesis = to_json(fixture.genesis)
alloc = to_json(fixture.pre)
# NOTE: nethermind requires account keys without '0x' prefix
@@ -127,7 +137,9 @@ def sync_genesis(fixture: BlockchainEngineSyncFixture) -> dict:
@pytest.fixture(scope="function")
def sync_buffered_genesis(sync_genesis: dict) -> io.BufferedReader:
- """Create a buffered reader for the genesis block header of the sync client."""
+ """
+ Create a buffered reader for the genesis block header of the sync client.
+ """
genesis_json = json.dumps(sync_genesis)
genesis_bytes = genesis_json.encode("utf-8")
return io.BufferedReader(cast(io.RawIOBase, io.BytesIO(genesis_bytes)))
@@ -160,7 +172,6 @@ def client_enode_url(client: Client) -> str:
@pytest.fixture(scope="function")
def sync_client(
hive_test: HiveTest,
- client: Client, # The main client under test
sync_client_files: dict,
environment: dict,
sync_client_type: ClientType, # Separate parametrization for sync client
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/test_case_description.py b/packages/tests/src/pytest_plugins/consume/simulators/test_case_description.py
similarity index 91%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/test_case_description.py
rename to packages/tests/src/pytest_plugins/consume/simulators/test_case_description.py
index 3a97c63f19..8989bd05c2 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/test_case_description.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/test_case_description.py
@@ -1,4 +1,7 @@
-"""Pytest fixtures that help create the test case "Description" displayed in the Hive UI."""
+"""
+Pytest fixtures that help create the test case "Description" displayed in the
+Hive UI.
+"""
import logging
import textwrap
@@ -30,7 +33,10 @@ def hive_clients_yaml_generator_command(
hive_clients_yaml_target_filename: str,
hive_info: HiveInfo,
) -> str:
- """Generate a shell command that creates a clients YAML file for the current client."""
+ """
+ Generate a shell command that creates a clients YAML file for the current
+ client.
+ """
try:
if not client_file:
raise ValueError("No client information available - try updating hive")
@@ -65,10 +71,13 @@ def filtered_hive_options(hive_info: HiveInfo) -> List[str]:
logger.info("Hive info: %s", hive_info.command)
unwanted_options = [
- "--client", # gets overwritten: we specify a single client; the one from the test case
+ "--client", # gets overwritten: we specify a single client; the one
+ # from the test case
"--client-file", # gets overwritten: we'll write our own client file
- "--results-root", # use default value instead (or you have to pass it to ./hiveview)
- "--sim.limit", # gets overwritten: we only run the current test case id
+ "--results-root", # use default value instead (or you have to pass it
+ # to ./hiveview)
+ "--sim.limit", # gets overwritten: we only run the current test case
+ # id
"--sim.parallelism", # skip; we'll only be running a single test
]
@@ -118,7 +127,10 @@ def hive_dev_command(
client_type: ClientType,
hive_client_config_file_parameter: str,
) -> str:
- """Return the command used to instantiate hive alongside the `consume` command."""
+ """
+ Return the command used to instantiate hive alongside the `consume`
+ command.
+ """
return f"./hive --dev {hive_client_config_file_parameter} --client {client_type.name}"
@@ -151,7 +163,8 @@ def test_case_description(
if "description" not in fixture.info or fixture.info["description"] is None:
test_docstring = "No documentation available."
else:
- # this prefix was included in the fixture description field for fixtures <= v4.3.0
+ # this prefix was included in the fixture description field for
+ # fixtures <= v4.3.0
test_docstring = fixture.info["description"].replace("Test function documentation:\n", "") # type: ignore
description = textwrap.dedent(f"""
@@ -162,15 +175,18 @@ def test_case_description(
{test_docstring}
Run This Test Locally:
- To run this test in hive:
+ To run this test in
+ hive
+ :
{hive_clients_yaml_generator_command}
{hive_consume_command}
- Advanced: Run the test against a hive developer backend using EEST's consume
command
+ Advanced: Run the test against a hive developer backend using
+ EEST's consume
command
Create the client YAML file, as above, then:
1. Start hive in dev mode: {hive_dev_command}
2. In the EEST repository root: {eest_consume_command}
- """) # noqa: E501
+ """)
description = description.strip()
description = description.replace("\n", "
")
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/timing_data.py b/packages/tests/src/pytest_plugins/consume/simulators/timing_data.py
similarity index 98%
rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/timing_data.py
rename to packages/tests/src/pytest_plugins/consume/simulators/timing_data.py
index e63fedfad0..76468e04a6 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/timing_data.py
+++ b/packages/tests/src/pytest_plugins/consume/simulators/timing_data.py
@@ -39,5 +39,7 @@ def timing_data(
total_timing_data: TimingData, client: Client
) -> Generator[TimingData, None, None]:
"""Record timing data for the main execution of the test case."""
+ del client
+
with total_timing_data.time("Test case execution") as timing_data:
yield timing_data
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/__init__.py b/packages/tests/src/pytest_plugins/consume/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/__init__.py
rename to packages/tests/src/pytest_plugins/consume/tests/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/release_information.json b/packages/tests/src/pytest_plugins/consume/tests/release_information.json
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/release_information.json
rename to packages/tests/src/pytest_plugins/consume/tests/release_information.json
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_consume_args.py b/packages/tests/src/pytest_plugins/consume/tests/test_consume_args.py
similarity index 93%
rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/test_consume_args.py
rename to packages/tests/src/pytest_plugins/consume/tests/test_consume_args.py
index 553232e7ef..5864687926 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_consume_args.py
+++ b/packages/tests/src/pytest_plugins/consume/tests/test_consume_args.py
@@ -22,7 +22,10 @@ def test_function(state_test, pre):
@pytest.fixture
def minimal_test_path(pytester: pytest.Pytester) -> Path:
- """Minimal test file that's written to a file using pytester and ready to fill."""
+ """
+ Minimal test file that's written to a file using pytester and ready to
+ fill.
+ """
tests_dir = pytester.mkdir("tests")
test_file = tests_dir / MINIMAL_TEST_FILE_NAME
test_file.write_text(MINIMAL_TEST_CONTENTS)
@@ -72,11 +75,12 @@ def fill_tests(
"""
Run fill to generate test fixtures for use with testing consume.
- We only need to do this once so ideally the scope of this fixture should be "module",
- however the `pytester` fixture's scope is function and cannot be accessed from a higher
- scope fixture.
+ We only need to do this once so ideally the scope of this fixture should be
+ "module", however the `pytester` fixture's scope is function and cannot be
+ accessed from a higher scope fixture.
- Instead we use a file lock and only write the fixtures once to the directory.
+ Instead we use a file lock and only write the fixtures once to the
+ directory.
"""
with FileLock(fixtures_dir.with_suffix(".lock")):
meta_folder = fixtures_dir / ".meta"
@@ -100,10 +104,14 @@ def fill_tests(
@pytest.fixture(autouse=True, scope="function")
def test_fixtures(pytester: Pytester, fixtures_dir: Path, fill_tests: None) -> List[Path]:
"""
- Copy test fixtures from the regular temp path to the pytester temporary dir.
+ Copy test fixtures from the regular temp path to the pytester temporary
+ dir.
- We intentionally copy the `.meta/index.json` file to test its compatibility with consume.
+ We intentionally copy the `.meta/index.json` file to test its compatibility
+ with consume.
"""
+ del fill_tests
+
test_fixtures = []
for json_file in fixtures_dir.rglob("*.json"):
target_dir = Path(pytester.path) / json_file.parent
@@ -129,7 +137,11 @@ def copy_consume_test_paths(pytester: Pytester):
shutil.move("conftest.py", target_dir / "conftest.py")
-single_test_id = f"src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/{MINIMAL_TEST_FILE_NAME}::test_function[fork_Shanghai-state_test]]" # noqa: E501
+single_test_id = (
+ "src/pytest_plugins/consume/direct/"
+ "test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/"
+ f"{MINIMAL_TEST_FILE_NAME}::test_function[fork_Shanghai-state_test]]"
+)
@pytest.mark.parametrize(
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_fixtures_source_input_types.py b/packages/tests/src/pytest_plugins/consume/tests/test_fixtures_source_input_types.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/test_fixtures_source_input_types.py
rename to packages/tests/src/pytest_plugins/consume/tests/test_fixtures_source_input_types.py
index 9eb205c73f..e18cc2b731 100644
--- a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_fixtures_source_input_types.py
+++ b/packages/tests/src/pytest_plugins/consume/tests/test_fixtures_source_input_types.py
@@ -10,7 +10,9 @@ class TestSimplifiedConsumeBehavior:
"""Test suite for the simplified consume behavior."""
def test_fixtures_source_from_release_url_no_api_calls(self):
- """Test that direct release URLs do not make API calls for release page."""
+ """
+ Test that direct release URLs do not make API calls for release page.
+ """
test_url = "https://github.com/ethereum/execution-spec-tests/releases/download/v3.0.0/fixtures_develop.tar.gz"
with patch("pytest_plugins.consume.consume.FixtureDownloader") as mock_downloader:
@@ -26,7 +28,9 @@ def test_fixtures_source_from_release_url_no_api_calls(self):
assert source.input_option == test_url
def test_fixtures_source_from_release_spec_makes_api_calls(self):
- """Test that release specs still make API calls and get release page."""
+ """
+ Test that release specs still make API calls and get release page.
+ """
test_spec = "stable@latest"
with patch("pytest_plugins.consume.consume.get_release_url") as mock_get_url:
@@ -68,7 +72,9 @@ def test_fixtures_source_from_regular_url_no_release_page(self):
assert source.url == test_url
def test_output_formatting_without_release_page_for_direct_urls(self):
- """Test output formatting when release page is empty for direct URLs."""
+ """
+ Test output formatting when release page is empty for direct URLs.
+ """
from unittest.mock import MagicMock
from pytest import Config
@@ -97,7 +103,9 @@ def test_output_formatting_without_release_page_for_direct_urls(self):
assert "Input:" in reason
def test_output_formatting_with_release_page_for_specs(self):
- """Test output formatting when release page is present for release specs."""
+ """
+ Test output formatting when release page is present for release specs.
+ """
from unittest.mock import MagicMock
from pytest import Config
diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_releases.py b/packages/tests/src/pytest_plugins/consume/tests/test_releases.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/test_releases.py
rename to packages/tests/src/pytest_plugins/consume/tests/test_releases.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/__init__.py b/packages/tests/src/pytest_plugins/custom_logging/__init__.py
similarity index 72%
rename from src/ethereum_spec_tests/pytest_plugins/logging/__init__.py
rename to packages/tests/src/pytest_plugins/custom_logging/__init__.py
index 7c2d7fe3e6..9e71d615ba 100644
--- a/src/ethereum_spec_tests/pytest_plugins/logging/__init__.py
+++ b/packages/tests/src/pytest_plugins/custom_logging/__init__.py
@@ -1,6 +1,9 @@
-"""Import the logging module content to make it available from pytest_plugins.logging."""
+"""
+Import the logging module content to make it available from
+pytest_plugins.logging.
+"""
-from .logging import (
+from .plugin_logging import (
FAIL_LEVEL,
VERBOSE_LEVEL,
ColorFormatter,
diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/logging.py b/packages/tests/src/pytest_plugins/custom_logging/plugin_logging.py
similarity index 87%
rename from src/ethereum_spec_tests/pytest_plugins/logging/logging.py
rename to packages/tests/src/pytest_plugins/custom_logging/plugin_logging.py
index 66d7e58b38..3387992c8a 100644
--- a/src/ethereum_spec_tests/pytest_plugins/logging/logging.py
+++ b/packages/tests/src/pytest_plugins/custom_logging/plugin_logging.py
@@ -1,15 +1,17 @@
"""
A Pytest plugin to configure logging for pytest sessions.
-Note: While pytest's builtin logging is generally amazing, it does not write timestamps
-when log output is written to pytest's caplog (the captured output for a test). And having
-timestamps in this output is the main use case for adding logging to our plugins.
-This output gets shown in the `FAILURES` summary section, which is shown as the
-"simulator log" in hive simulations. For this use case, timestamps are essential to verify
-timing issues against the clients log.
+Note: While pytest's builtin logging is generally amazing, it does not write
+timestamps when log output is written to pytest's caplog (the captured output
+for a test). And having timestamps in this output is the main use case for
+adding logging to our plugins. This output gets shown in the `FAILURES` summary
+section, which is shown as the "simulator log" in hive simulations. For this
+use case, timestamps are essential to verify timing issues against the clients
+log.
This module provides both:
-1. A standalone logging configuration system that can be used in any Python project
+1. A standalone logging configuration system that can be used in any
+ Python project
2. A pytest plugin that automatically configures logging for pytest sessions
"""
@@ -71,8 +73,8 @@ def fail(
"""
Log a message with FAIL level severity (35).
- This level is between WARNING (30) and ERROR (40), intended for test failures
- and similar issues.
+ This level is between WARNING (30) and ERROR (40), intended for test
+ failures and similar issues.
"""
if stacklevel is None:
stacklevel = 1
@@ -94,15 +96,22 @@ def get_logger(name: str) -> EESTLogger:
class UTCFormatter(logging.Formatter):
- """Log formatter that formats UTC timestamps with milliseconds and +00:00 suffix."""
+ """
+ Log formatter that formats UTC timestamps with milliseconds and +00:00
+ suffix.
+ """
- def formatTime(self, record, datefmt=None): # noqa: D102,N802 # camelcase required
+ def formatTime(self, record, datefmt=None): # noqa: D102,N802
+ # camelcase required
dt = datetime.fromtimestamp(record.created, tz=timezone.utc)
return dt.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] + "+00:00"
class ColorFormatter(UTCFormatter):
- """Formatter that adds ANSI color codes to log level names for terminal output."""
+ """
+ Formatter that adds ANSI color codes to log level names for terminal
+ output.
+ """
running_in_docker: ClassVar[bool] = Path("/.dockerenv").exists()
@@ -150,9 +159,9 @@ def from_cli(cls, value: str) -> int:
raise ValueError(f"Invalid log level '{value}'. Expected one of: {valid} or a number.")
-# ==============================================================================
+# =========================================================================
# Standalone logging configuration (usable without pytest)
-# ==============================================================================
+# =========================================================================
def configure_logging(
@@ -169,14 +178,13 @@ def configure_logging(
same settings as the pytest plugin.
Args:
- log_level: The logging level to use (name or numeric value)
- log_file: Path to the log file (if None, no file logging is set up)
- log_to_stdout: Whether to log to stdout
- log_format: The log format string
- use_color: Whether to use colors in stdout output (auto-detected if None)
+ log_level: The logging level to use (name or numeric value)
+ log_file: Path to the log file (if None, no file logging is set up)
+ log_to_stdout: Whether to log to stdout
+ log_format: The log format string
+ use_color: Whether to use colors in stdout output (auto-detected if None)
- Returns:
- The file handler if log_file is provided, otherwise None
+ Returns: The file handler if log_file is provided, otherwise None
"""
# Initialize root logger
@@ -222,9 +230,9 @@ def configure_logging(
return file_handler_instance
-# ==============================================================================
+# ==========================================================================
# Pytest plugin integration
-# ==============================================================================
+# ==========================================================================
def pytest_addoption(parser): # noqa: D103
@@ -232,7 +240,8 @@ def pytest_addoption(parser): # noqa: D103
"logging", "Arguments related to logging from test fixtures and tests."
)
logging_group.addoption(
- "--eest-log-level", # --log-level is defined by pytest's built-in logging
+ "--eest-log-level", # --log-level is defined by pytest's built-in
+ # logging
"--eestloglevel",
action="store",
default="INFO",
@@ -274,9 +283,9 @@ def pytest_configure(config: pytest.Config) -> None:
"""
Initialize logging for pytest sessions.
- This goes to a lot of effort to ensure that a log file is created per worker
- if xdist is used and that the timestamp used in the filename is the same across
- main and all workers.
+ This goes to a lot of effort to ensure that a log file is created per
+ worker if xdist is used and that the timestamp used in the filename is the
+ same across main and all workers.
"""
global file_handler
@@ -312,15 +321,18 @@ def pytest_report_header(config: pytest.Config) -> list[str]:
return []
-def pytest_terminal_summary(terminalreporter: TerminalReporter, exitstatus: int) -> None:
- """Display the log file path in the terminal summary like the HTML report does."""
+def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None:
+ """
+ Display the log file path in the terminal summary like the HTML report
+ does.
+ """
if terminalreporter.config.option.collectonly:
return
if eest_log_file_path := terminalreporter.config.option.eest_log_file_path:
terminalreporter.write_sep("-", f"Log file: {eest_log_file_path.resolve()}", yellow=True)
-def log_only_to_file(level: int, msg: str, *args, **kwargs) -> None:
+def log_only_to_file(level: int, msg: str, *args) -> None:
"""Log a message only to the file handler, bypassing stdout."""
if not file_handler:
return
@@ -344,6 +356,8 @@ def log_only_to_file(level: int, msg: str, *args, **kwargs) -> None:
def pytest_runtest_logstart(nodeid: str, location: tuple[str, int, str]) -> None:
"""Log test start to file."""
+ del location
+
log_only_to_file(logging.INFO, f"ℹ️ - START TEST: {nodeid}")
@@ -383,4 +397,6 @@ def pytest_runtest_logreport(report: pytest.TestReport) -> None:
def pytest_runtest_logfinish(nodeid: str, location: tuple[str, int, str]) -> None:
"""Log end of test to file."""
+ del location
+
log_only_to_file(logging.INFO, f"ℹ️ - END TEST: {nodeid}")
diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/tests/__init__.py b/packages/tests/src/pytest_plugins/custom_logging/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/logging/tests/__init__.py
rename to packages/tests/src/pytest_plugins/custom_logging/tests/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/tests/test_logging.py b/packages/tests/src/pytest_plugins/custom_logging/tests/test_logging.py
similarity index 98%
rename from src/ethereum_spec_tests/pytest_plugins/logging/tests/test_logging.py
rename to packages/tests/src/pytest_plugins/custom_logging/tests/test_logging.py
index dad7b82b9d..9437f2e6cb 100644
--- a/src/ethereum_spec_tests/pytest_plugins/logging/tests/test_logging.py
+++ b/packages/tests/src/pytest_plugins/custom_logging/tests/test_logging.py
@@ -12,7 +12,7 @@
from pathlib import Path
from unittest.mock import MagicMock, patch
-from ..logging import (
+from ..plugin_logging import (
FAIL_LEVEL,
VERBOSE_LEVEL,
ColorFormatter,
@@ -194,7 +194,7 @@ class TestPytestIntegration:
def test_pytest_configure(self, monkeypatch, tmpdir):
"""Test that pytest_configure sets up logging correctly."""
- from pytest_plugins.logging.logging import pytest_configure
+ from pytest_plugins.custom_logging.plugin_logging import pytest_configure
# Create logs directory if it doesn't exist
log_dir = Path("logs")
diff --git a/packages/tests/src/pytest_plugins/execute/__init__.py b/packages/tests/src/pytest_plugins/execute/__init__.py
new file mode 100644
index 0000000000..71d37fb87e
--- /dev/null
+++ b/packages/tests/src/pytest_plugins/execute/__init__.py
@@ -0,0 +1,4 @@
+"""
+A pytest plugin that provides fixtures that execute tests in live
+devnets/testnets.
+"""
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/__init__.py b/packages/tests/src/pytest_plugins/execute/eth_config/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/__init__.py
rename to packages/tests/src/pytest_plugins/execute/eth_config/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/eth_config.py b/packages/tests/src/pytest_plugins/execute/eth_config/eth_config.py
similarity index 94%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/eth_config.py
rename to packages/tests/src/pytest_plugins/execute/eth_config/eth_config.py
index 1e7da09cb3..c373083eb9 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/eth_config.py
+++ b/packages/tests/src/pytest_plugins/execute/eth_config/eth_config.py
@@ -10,9 +10,9 @@
import requests
from ethereum_test_rpc import EthRPC
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
-from .types import Genesis, NetworkConfigFile
+from .execute_types import Genesis, NetworkConfigFile
CURRENT_FILE = Path(realpath(__file__))
CURRENT_FOLDER = CURRENT_FILE.parent
@@ -95,8 +95,8 @@ def pytest_addoption(parser):
def pytest_configure(config: pytest.Config) -> None:
"""
- Load the network configuration file and load the specific network to be used for
- the test.
+ Load the network configuration file and load the specific network to be
+ used for the test.
"""
genesis_config_file = config.getoption("genesis_config_file")
genesis_config_url = config.getoption("genesis_config_url")
@@ -183,14 +183,20 @@ def pytest_configure(config: pytest.Config) -> None:
@pytest.fixture(autouse=True, scope="session")
def rpc_endpoint(request) -> str:
- """Return remote RPC endpoint to be used to make requests to the execution client."""
+ """
+ Return remote RPC endpoint to be used to make requests to the execution
+ client.
+ """
return request.config.getoption("rpc_endpoint")
def all_rpc_endpoints(config) -> Dict[str, List[EthRPC]]:
- """Derive a mapping of exec clients to the RPC URLs they are reachable at."""
+ """
+ Derive a mapping of exec clients to the RPC URLs they are reachable at.
+ """
rpc_endpoint = config.getoption("rpc_endpoint")
- el_clients: List[str] = config.getoption("majority_clients") # besu, erigon, ..
+ # besu, erigon, ..
+ el_clients: List[str] = config.getoption("majority_clients")
if len(el_clients) == 0:
endpoint_name = rpc_endpoint
try:
@@ -215,23 +221,23 @@ def all_rpc_endpoints(config) -> Dict[str, List[EthRPC]]:
for exec_client in el_clients
}
# url_dict looks like this:
- # {
- # 'besu': [, , ..], # noqa: E501
- # 'erigon': ...
- # ...
- # }
+ # { 'besu': [,
+ # , ..],
+ # 'erigon': ... ... }
return url_dict
def pytest_generate_tests(metafunc: pytest.Metafunc):
"""Generate tests for all clients under test."""
# all_rpc_endpoints is a dictionary with the name of the exec client as key
- # and the possible URLs to contact it (different cl combinations) as value list
+ # and the possible URLs to contact it (different cl combinations) as value
+ # list
all_rpc_endpoints_dict = all_rpc_endpoints(metafunc.config)
if metafunc.definition.name == "test_eth_config_majority":
if len(all_rpc_endpoints_dict) < 2:
- # The test function is not run because we only have a single client, so no majority comparison # noqa: E501
+ # The test function is not run because we only have a single
+ # client, so no majority comparison
logger.info(
"Skipping eth_config majority because less than 2 exec clients were passed"
)
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/execute_eth_config.py b/packages/tests/src/pytest_plugins/execute/eth_config/execute_eth_config.py
similarity index 90%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/execute_eth_config.py
rename to packages/tests/src/pytest_plugins/execute/eth_config/execute_eth_config.py
index 194bce8f75..efdc3122f9 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/execute_eth_config.py
+++ b/packages/tests/src/pytest_plugins/execute/eth_config/execute_eth_config.py
@@ -1,4 +1,6 @@
-"""Pytest test to verify a client's configuration using `eth_config` RPC endpoint."""
+"""
+Pytest test to verify a client's configuration using `eth_config` RPC endpoint.
+"""
import json
import time
@@ -8,16 +10,18 @@
import pytest
from ethereum_test_rpc import EthConfigResponse, EthRPC
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
-from .types import NetworkConfig
+from .execute_types import NetworkConfig
logger = get_logger(__name__)
@pytest.fixture(scope="function")
def eth_config_response(eth_rpc: List[EthRPC]) -> EthConfigResponse | None:
- """Get the `eth_config` response from the client to be verified by all tests."""
+ """
+ Get the `eth_config` response from the client to be verified by all tests.
+ """
for rpc in eth_rpc:
try:
response = rpc.config()
@@ -37,13 +41,17 @@ def network(request) -> NetworkConfig:
@pytest.fixture(scope="function")
def current_time() -> int:
- """Get the `eth_config` response from the client to be verified by all tests."""
+ """
+ Get the `eth_config` response from the client to be verified by all tests.
+ """
return int(time.time())
@pytest.fixture(scope="function")
def expected_eth_config(network: NetworkConfig, current_time: int) -> EthConfigResponse:
- """Calculate the current fork value to verify against the client's response."""
+ """
+ Calculate the current fork value to verify against the client's response.
+ """
return network.get_eth_config(current_time)
@@ -190,12 +198,15 @@ def test_eth_config_last_fork_id(
def test_eth_config_majority(
all_rpc_endpoints: Dict[str, List[EthRPC]],
) -> None:
- """Queries devnet exec clients for their eth_config and fails if not all have the same response.""" # noqa: E501
+ """
+ Queries devnet exec clients for their eth_config and fails if not all have
+ the same response.
+ """
responses = dict() # Dict[exec_client_name : response] # noqa: C408
client_to_url_used_dict = dict() # noqa: C408
for exec_client in all_rpc_endpoints.keys():
- # try only as many consensus+exec client combinations until you receive a response
- # if all combinations for a given exec client fail we panic
+ # try only as many consensus+exec client combinations until you receive
+ # a response if all combinations for a given exec client fail we panic
for eth_rpc_target in all_rpc_endpoints[exec_client]:
try:
response = eth_rpc_target.config(timeout=5)
@@ -212,7 +223,7 @@ def test_eth_config_majority(
responses[exec_client] = response_str
client_to_url_used_dict[exec_client] = (
eth_rpc_target.url
- ) # remember which cl+el combination was used # noqa: E501
+ ) # remember which cl+el combination was used
logger.info(f"Response of {exec_client}: {response_str}\n\n")
break # no need to gather more responses for this client
@@ -226,14 +237,15 @@ def test_eth_config_majority(
"this execution client"
)
# determine hashes of client responses
- client_to_hash_dict = dict() # Dict[exec_client : response hash] # noqa: C408
+ client_to_hash_dict = {} # Dict[exec_client : response hash] # noqa: C408
for client in responses.keys():
response_bytes = responses[client].encode("utf-8")
response_hash = sha256(response_bytes).digest().hex()
logger.info(f"Response hash of client {client}: {response_hash}")
client_to_hash_dict[client] = response_hash
- # if not all responses have the same hash there is a critical consensus issue
+ # if not all responses have the same hash there is a critical consensus
+ # issue
expected_hash = ""
for h in client_to_hash_dict.keys():
if expected_hash == "":
@@ -241,15 +253,17 @@ def test_eth_config_majority(
continue
assert client_to_hash_dict[h] == expected_hash, (
- "Critical consensus issue: Not all eth_config responses are the same!\n"
+ "Critical consensus issue: Not all eth_config responses are the "
+ " same!\n"
"Here is an overview of client response hashes:\n"
+ "\n\t".join(f"{k}: {v}" for k, v in client_to_hash_dict.items())
- + "\n\n" # noqa: E501
+ + "\n\n"
"Here is an overview of which URLs were contacted:\n\t"
+ "\n\t".join(f"{k}: @{v.split('@')[1]}" for k, v in client_to_url_used_dict.items())
- + "\n\n" # log which cl+el combinations were used without leaking full url # noqa: E501
+ + "\n\n"
+ # log which cl+el combinations were used without leaking full url
"Here is a dump of all client responses:\n"
- + "\n\n".join(f"{k}: {v}" for k, v in responses.items()) # noqa: E501
+ + "\n\n".join(f"{k}: {v}" for k, v in responses.items())
)
assert expected_hash != ""
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/types.py b/packages/tests/src/pytest_plugins/execute/eth_config/execute_types.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/types.py
rename to packages/tests/src/pytest_plugins/execute/eth_config/execute_types.py
index efe32bb430..393d5c251c 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/types.py
+++ b/packages/tests/src/pytest_plugins/execute/eth_config/execute_types.py
@@ -33,8 +33,8 @@
class AddressOverrideDict(EthereumTestRootModel):
"""
Dictionary with overrides to the default addresses specified for each fork.
- Required for testnets or devnets which have a different location of precompiles or system
- contracts.
+ Required for testnets or devnets which have a different location of
+ precompiles or system contracts.
"""
root: Dict[Address, Address]
@@ -73,8 +73,8 @@ def system_contracts(self) -> Dict[str, Address]:
def get_config(self, fork_id: ForkHash) -> ForkConfig:
"""
- Get the current and next fork configurations given the current time and the network
- configuration.
+ Get the current and next fork configurations given the current time and
+ the network configuration.
"""
return ForkConfig(
activation_time=self.activation_time,
@@ -87,7 +87,10 @@ def get_config(self, fork_id: ForkHash) -> ForkConfig:
def calculate_fork_id(genesis_hash: Hash, activation_times: Set[int]) -> ForkHash:
- """Calculate the fork Id given the genesis hash and each fork activation times."""
+ """
+ Calculate the fork Id given the genesis hash and each fork activation
+ times.
+ """
buffer = bytes(genesis_hash)
for activation_time in sorted(activation_times):
if activation_time == 0:
@@ -275,9 +278,11 @@ def fork(self) -> Fork:
@classmethod
def preprocess_fork_times_blocks(cls, data: Any):
"""
- Pre-process the dictionary to put fork block numbers and times in the correct format.
+ Pre-process the dictionary to put fork block numbers and times in the
+ correct format.
- Fork times and block numbers have the following format in the root of the object:
+ Fork times and block numbers have the following format in the root of
+ the object:
```
"berlinBlock": 0,
@@ -287,8 +292,8 @@ def preprocess_fork_times_blocks(cls, data: Any):
"osakaTime": 1753379304,
```
- This function strips the "*Block" and "*Time" part and moves the values.
-
+ This function strips the "*Block" and "*Time" part and moves the
+ values.
"""
if isinstance(data, dict):
fork_activation_times: Dict[str, int] = {}
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/networks.yml b/packages/tests/src/pytest_plugins/execute/eth_config/networks.yml
similarity index 64%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/networks.yml
rename to packages/tests/src/pytest_plugins/execute/eth_config/networks.yml
index a04898e07f..56d54f84ee 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/networks.yml
+++ b/packages/tests/src/pytest_plugins/execute/eth_config/networks.yml
@@ -27,6 +27,18 @@ Mainnet:
target: 6
max: 9
baseFeeUpdateFraction: 5007716
+ Osaka:
+ target: 6
+ max: 9
+ baseFeeUpdateFraction: 5007716
+ BPO1:
+ target: 10
+ max: 15
+ baseFeeUpdateFraction: 8346193
+ BPO2:
+ target: 14
+ max: 21
+ baseFeeUpdateFraction: 11684671
Sepolia:
chainId: 0xaa36a7
@@ -37,6 +49,9 @@ Sepolia:
Shanghai: 1677557088
Cancun: 1706655072
Prague: 1741159776
+ Osaka: 1760427360
+ BPO1: 1761017184
+ BPO2: 1761607008
blobSchedule:
Cancun:
target: 3
@@ -46,6 +61,18 @@ Sepolia:
target: 6
max: 9
baseFeeUpdateFraction: 5007716
+ Osaka:
+ target: 6
+ max: 9
+ baseFeeUpdateFraction: 5007716
+ BPO1:
+ target: 10
+ max: 15
+ baseFeeUpdateFraction: 8346193
+ BPO2:
+ target: 14
+ max: 21
+ baseFeeUpdateFraction: 11684671
addressOverrides:
0x00000000219ab540356cbb839cbe05303d7705fa: 0x7f02c3e3c98b133055b8b348b2ac625669ed295d
@@ -55,6 +82,9 @@ Hoodi:
forkActivationTimes:
Cancun: 0
Prague: 1742999832
+ Osaka: 1761677592
+ BPO1: 1762365720
+ BPO2: 1762955544
blobSchedule:
Cancun:
target: 3
@@ -64,6 +94,18 @@ Hoodi:
target: 6
max: 9
baseFeeUpdateFraction: 5007716
+ Osaka:
+ target: 6
+ max: 9
+ baseFeeUpdateFraction: 5007716
+ BPO1:
+ target: 10
+ max: 15
+ baseFeeUpdateFraction: 8346193
+ BPO2:
+ target: 14
+ max: 21
+ baseFeeUpdateFraction: 11684671
Holesky:
chainId: 0x4268
@@ -73,6 +115,9 @@ Holesky:
Shanghai: 1696000704
Cancun: 1707305664
Prague: 1740434112
+ Osaka: 1759308480
+ BPO1: 1759800000
+ BPO2: 1760389824
addressOverrides:
0x00000000219ab540356cbb839cbe05303d7705fa: 0x4242424242424242424242424242424242424242
blobSchedule:
@@ -83,4 +128,16 @@ Holesky:
Prague:
target: 6
max: 9
- baseFeeUpdateFraction: 5007716
\ No newline at end of file
+ baseFeeUpdateFraction: 5007716
+ Osaka:
+ target: 6
+ max: 9
+ baseFeeUpdateFraction: 5007716
+ BPO1:
+ target: 10
+ max: 15
+ baseFeeUpdateFraction: 8346193
+ BPO2:
+ target: 14
+ max: 21
+ baseFeeUpdateFraction: 11684671
\ No newline at end of file
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/__init__.py b/packages/tests/src/pytest_plugins/execute/eth_config/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/__init__.py
rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/genesis_example.json b/packages/tests/src/pytest_plugins/execute/eth_config/tests/genesis_example.json
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/genesis_example.json
rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/genesis_example.json
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py b/packages/tests/src/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py
similarity index 99%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py
rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py
index 8feebb8371..7a7bd7df0c 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py
+++ b/packages/tests/src/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py
@@ -10,7 +10,7 @@
from ethereum_test_base_types import ForkHash
from ethereum_test_rpc import EthConfigResponse
-from ..types import NetworkConfig, NetworkConfigFile
+from ..execute_types import NetworkConfig, NetworkConfigFile
EXPECTED_CANCUN = json.loads("""
{
@@ -414,7 +414,7 @@
target: 15
max: 20
baseFeeUpdateFraction: 5007716
-"""
+""" # W505
@pytest.fixture(scope="session")
@@ -435,7 +435,9 @@ def network(request: pytest.FixtureRequest, network_configs: NetworkConfigFile)
@pytest.fixture
def eth_config(network: NetworkConfig, current_time: int) -> EthConfigResponse:
- """Get the `eth_config` response from the client to be verified by all tests."""
+ """
+ Get the `eth_config` response from the client to be verified by all tests.
+ """
return network.get_eth_config(current_time)
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_genesis.py b/packages/tests/src/pytest_plugins/execute/eth_config/tests/test_genesis.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_genesis.py
rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/test_genesis.py
index 46fbadba5c..dcf02ecc65 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_genesis.py
+++ b/packages/tests/src/pytest_plugins/execute/eth_config/tests/test_genesis.py
@@ -28,7 +28,7 @@
ForkConfigBlobSchedule,
)
-from ..types import ForkActivationTimes, Genesis, NetworkConfig
+from ..execute_types import ForkActivationTimes, Genesis, NetworkConfig
CURRENT_FILE = Path(realpath(__file__))
CURRENT_FOLDER = CURRENT_FILE.parent
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/execute.py b/packages/tests/src/pytest_plugins/execute/execute.py
similarity index 91%
rename from src/ethereum_spec_tests/pytest_plugins/execute/execute.py
rename to packages/tests/src/pytest_plugins/execute/execute.py
index 842c759a11..62d5aa1cc6 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/execute.py
+++ b/packages/tests/src/pytest_plugins/execute/execute.py
@@ -1,4 +1,6 @@
-"""Test execution plugin for pytest, to run Ethereum tests using in live networks."""
+"""
+Test execution plugin for pytest, to run Ethereum tests using in live networks.
+"""
import os
from dataclasses import dataclass, field
@@ -122,12 +124,12 @@ def pytest_configure(config):
Couple of notes:
1. Register the plugin's custom markers and process command-line options.
- Custom marker registration:
- https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers
+ Custom marker registration:
+ https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers
2. `@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is
- called before the pytest-html plugin's pytest_configure to ensure that
- it uses the modified `htmlpath` option.
+ called before the pytest-html plugin's pytest_configure to ensure that
+ it uses the modified `htmlpath` option.
"""
# Modify the block gas limit if specified.
if config.getoption("transaction_gas_limit"):
@@ -256,7 +258,9 @@ def default_max_priority_fee_per_gas(request) -> int:
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."""
+ """
+ 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
@@ -264,7 +268,10 @@ def modify_transaction_defaults(
@dataclass(kw_only=True)
class Collector:
- """A class that collects transactions and post-allocations for every test case."""
+ """
+ A class that collects transactions and post-allocations for every test
+ case.
+ """
eth_rpc: EthRPC
collected_tests: Dict[str, BaseExecute] = field(default_factory=dict)
@@ -280,9 +287,11 @@ def collector(
eth_rpc: EthRPC,
) -> Generator[Collector, None, None]:
"""
- Return configured fixture collector instance used for all tests
- in one test module.
+ Return configured fixture collector instance used for all tests in one test
+ module.
"""
+ del request
+
collector = Collector(eth_rpc=eth_rpc)
yield collector
@@ -291,8 +300,8 @@ def base_test_parametrizer(cls: Type[BaseTest]):
"""
Generate pytest.fixture for a given BaseTest subclass.
- Implementation detail: All spec fixtures must be scoped on test function level to avoid
- leakage between tests.
+ Implementation detail: All spec fixtures must be scoped on test function
+ level to avoid leakage between tests.
"""
cls_fixture_parameters = [p for p in ALL_FIXTURE_PARAMETERS if p in cls.model_fields]
@@ -309,14 +318,15 @@ def base_test_parametrizer_func(
collector: Collector,
):
"""
- Fixture used to instantiate an auto-fillable BaseTest object from within
- a test function.
+ Fixture used to instantiate an auto-fillable BaseTest object from
+ within a test function.
- Every test that defines a test filler must explicitly specify its parameter name
- (see `pytest_parameter_name` in each implementation of BaseTest) in its function
- arguments.
+ Every test that defines a test filler must explicitly specify its
+ parameter name (see `pytest_parameter_name` in each implementation of
+ BaseTest) in its function arguments.
- When parametrize, indirect must be used along with the fixture format as value.
+ When parametrize, indirect must be used along with the fixture format
+ as value.
"""
execute_format = request.param
assert execute_format in BaseExecute.formats.values()
@@ -332,6 +342,11 @@ def __init__(self, *args, **kwargs):
kwargs["pre"] = pre
elif kwargs["pre"] != pre:
raise ValueError("The pre-alloc object was modified by the test.")
+ # Set default for expected_benchmark_gas_used
+ if "expected_benchmark_gas_used" not in kwargs:
+ kwargs["expected_benchmark_gas_used"] = request.getfixturevalue(
+ "gas_benchmark_value"
+ )
kwargs |= {
p: request.getfixturevalue(p)
for p in cls_fixture_parameters
@@ -375,8 +390,8 @@ def __init__(self, *args, **kwargs):
def pytest_generate_tests(metafunc: pytest.Metafunc):
"""
- Pytest hook used to dynamically generate test cases for each fixture format a given
- test spec supports.
+ Pytest hook used to dynamically generate test cases for each fixture format
+ a given test spec supports.
"""
engine_rpc_supported = metafunc.config.engine_rpc_supported # type: ignore
for test_type in BaseTest.spec_types.values():
@@ -395,8 +410,11 @@ def pytest_generate_tests(metafunc: pytest.Metafunc):
)
-def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]):
- """Remove transition tests and add the appropriate execute markers to the test."""
+def pytest_collection_modifyitems(items: List[pytest.Item]):
+ """
+ Remove transition tests and add the appropriate execute markers to the
+ test.
+ """
items_for_removal = []
for i, item in enumerate(items):
if isinstance(item, EIPSpecTestItem):
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/execute_recover.py b/packages/tests/src/pytest_plugins/execute/execute_recover.py
similarity index 98%
rename from src/ethereum_spec_tests/pytest_plugins/execute/execute_recover.py
rename to packages/tests/src/pytest_plugins/execute/execute_recover.py
index d23038a501..3e25fd7509 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/execute_recover.py
+++ b/packages/tests/src/pytest_plugins/execute/execute_recover.py
@@ -21,6 +21,8 @@ def test_recover_funds(
eth_rpc: EthRPC,
) -> None:
"""Recover funds from a failed remote execution."""
+ del index
+
remaining_balance = eth_rpc.get_balance(eoa)
refund_gas_limit = 21_000
tx_cost = refund_gas_limit * gas_price
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/pre_alloc.py b/packages/tests/src/pytest_plugins/execute/pre_alloc.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/execute/pre_alloc.py
rename to packages/tests/src/pytest_plugins/execute/pre_alloc.py
index 8ee83b3f0a..434d4a7a4a 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/pre_alloc.py
+++ b/packages/tests/src/pytest_plugins/execute/pre_alloc.py
@@ -23,7 +23,7 @@
)
from ethereum_test_forks import Fork
from ethereum_test_rpc import EthRPC
-from ethereum_test_rpc.types import TransactionByHashResponse
+from ethereum_test_rpc.rpc_types import TransactionByHashResponse
from ethereum_test_tools import (
EOA,
Account,
@@ -48,8 +48,9 @@ class AddressStubs(EthereumTestRootModel[Dict[str, Address]]):
"""
Address stubs class.
- The key represents the label that is used in the test to tag the contract, and the value
- is the address where the contract is already located at in the current network.
+ The key represents the label that is used in the test to tag the contract,
+ and the value is the address where the contract is already located at in
+ the current network.
"""
root: Dict[str, Address]
@@ -65,8 +66,8 @@ def __getitem__(self, item: str) -> Address:
@classmethod
def model_validate_json_or_file(cls, json_data_or_path: str) -> Self:
"""
- Try to load from file if the value resembles a path that ends with .json/.yml and the
- file exists.
+ Try to load from file if the value resembles a path that ends with
+ .json/.yml and the file exists.
"""
lower_json_data_or_path = json_data_or_path.lower()
if (
@@ -259,6 +260,7 @@ def deploy_contract(
storage={},
),
)
+ return contract_address
initcode_prefix = Bytecode()
@@ -291,7 +293,7 @@ def deploy_contract(
f"initcode too large {len(initcode)} > {MAX_INITCODE_SIZE}"
)
- calldata_gas_calculator = self._fork.calldata_gas_calculator()
+ calldata_gas_calculator = self._fork.calldata_gas_calculator(block_number=0, timestamp=0)
deploy_gas_limit += calldata_gas_calculator(data=initcode)
# Limit the gas limit
@@ -341,7 +343,10 @@ def fund_eoa(
delegation: Address | Literal["Self"] | None = None,
nonce: NumberConvertible | None = None,
) -> EOA:
- """Add a previously unused EOA to the pre-alloc with the balance specified by `amount`."""
+ """
+ Add a previously unused EOA to the pre-alloc with the balance specified
+ by `amount`.
+ """
assert nonce is None, "nonce parameter is not supported for execute"
eoa = next(self._eoa_iterator)
eoa.label = label
@@ -384,7 +389,8 @@ def fund_eoa(
if delegation is not None:
if not isinstance(delegation, Address) and delegation == "Self":
delegation = eoa
- # TODO: This tx has side-effects on the EOA state because of the delegation
+ # TODO: This tx has side-effects on the EOA state because of
+ # the delegation
fund_tx = Transaction(
sender=self._sender,
to=eoa,
@@ -408,7 +414,8 @@ def fund_eoa(
authorization_list=[
AuthorizationTuple(
chain_id=self._chain_id,
- address=0, # Reset delegation to an address without code
+ # Reset delegation to an address without code
+ address=0,
nonce=eoa.nonce,
signer=eoa,
),
@@ -477,7 +484,8 @@ def fund_address(self, address: Address, amount: NumberConvertible):
def empty_account(self) -> Address:
"""
- Add a previously unused account guaranteed to be empty to the pre-alloc.
+ Add a previously unused account guaranteed to be empty to the
+ pre-alloc.
This ensures the account has:
- Zero balance
@@ -485,8 +493,9 @@ def empty_account(self) -> Address:
- No code
- No storage
- This is different from precompiles or system contracts. The function does not
- send any transactions, ensuring that the account remains "empty."
+ This is different from precompiles or system contracts. The function
+ does not send any transactions, ensuring that the account remains
+ "empty."
Returns:
Address: The address of the created empty account.
@@ -539,6 +548,12 @@ def pre(
request: pytest.FixtureRequest,
) -> Generator[Alloc, None, None]:
"""Return default pre allocation for all tests (Empty alloc)."""
+ # FIXME: Static tests don't have a fork so we need to get it from the node.
+ actual_fork = fork
+ if actual_fork is None:
+ assert hasattr(request.node, "fork")
+ actual_fork = request.node.fork
+
# Record the starting balance of the sender
sender_test_starting_balance = eth_rpc.get_balance(sender_key)
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/recover.py b/packages/tests/src/pytest_plugins/execute/recover.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/recover.py
rename to packages/tests/src/pytest_plugins/execute/recover.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/__init__.py b/packages/tests/src/pytest_plugins/execute/rpc/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/__init__.py
rename to packages/tests/src/pytest_plugins/execute/rpc/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py b/packages/tests/src/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py
similarity index 92%
rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py
rename to packages/tests/src/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py
index ac78b29968..fb5d4f89cf 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py
+++ b/packages/tests/src/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py
@@ -1,4 +1,7 @@
-"""Chain builder Ethereum RPC that can drive the chain when new transactions are submitted."""
+"""
+Chain builder Ethereum RPC that can drive the chain when new transactions are
+submitted.
+"""
import time
from pathlib import Path
@@ -11,7 +14,7 @@
from ethereum_test_forks import Fork
from ethereum_test_rpc import EngineRPC
from ethereum_test_rpc import EthRPC as BaseEthRPC
-from ethereum_test_rpc.types import (
+from ethereum_test_rpc.rpc_types import (
ForkchoiceState,
PayloadAttributes,
PayloadStatusEnum,
@@ -87,10 +90,11 @@ def __iter__(self):
class PendingTxHashes:
"""
- A class to manage the pending transaction hashes in a multi-process environment.
+ A class to manage the pending transaction hashes in a multi-process
+ environment.
- It uses a lock file to ensure that only one process can access the pending hashes file at a
- time.
+ It uses a lock file to ensure that only one process can access the pending
+ hashes file at a time.
"""
pending_hashes_file: Path
@@ -166,9 +170,9 @@ def __iter__(self):
class ChainBuilderEthRPC(BaseEthRPC, namespace="eth"):
"""
- Special type of Ethereum RPC client that also has access to the Engine API and automatically
- coordinates block generation based on the number of pending transactions or a block generation
- interval.
+ Special type of Ethereum RPC client that also has access to the Engine API
+ and automatically coordinates block generation based on the number of
+ pending transactions or a block generation interval.
"""
fork: Fork
@@ -243,7 +247,9 @@ def generate_block(self: "ChainBuilderEthRPC"):
forkchoice_state = ForkchoiceState(
head_block_hash=head_block["hash"],
)
- parent_beacon_block_root = Hash(0) if self.fork.header_beacon_root_required(0, 0) else None
+ parent_beacon_block_root = (
+ Hash(0) if self.fork.header_beacon_root_required(block_number=0, timestamp=0) else None
+ )
payload_attributes = PayloadAttributes(
timestamp=HexNumber(head_block["timestamp"]) + 1,
prev_randao=Hash(0),
@@ -251,13 +257,17 @@ def generate_block(self: "ChainBuilderEthRPC"):
withdrawals=[] if self.fork.header_withdrawals_required() else None,
parent_beacon_block_root=parent_beacon_block_root,
target_blobs_per_block=(
- self.fork.target_blobs_per_block(0, 0)
- if self.fork.engine_payload_attribute_target_blobs_per_block(0, 0)
+ self.fork.target_blobs_per_block(block_number=0, timestamp=0)
+ if self.fork.engine_payload_attribute_target_blobs_per_block(
+ block_number=0, timestamp=0
+ )
else None
),
max_blobs_per_block=(
- self.fork.max_blobs_per_block(0, 0)
- if self.fork.engine_payload_attribute_max_blobs_per_block(0, 0)
+ self.fork.max_blobs_per_block(block_number=0, timestamp=0)
+ if self.fork.engine_payload_attribute_max_blobs_per_block(
+ block_number=0, timestamp=0
+ )
else None
),
)
@@ -336,11 +346,12 @@ def wait_for_transactions(
self, transactions: List[Transaction]
) -> List[TransactionByHashResponse]:
"""
- Wait for all transactions in the provided list to be included in a block.
+ Wait for all transactions in the provided list to be included in a
+ block.
- Waits for all transactions in the provided list to be included in a block
- by polling `eth_getTransactionByHash` until they are confirmed or a
- timeout occurs.
+ Waits for all transactions in the provided list to be included in a
+ block by polling `eth_getTransactionByHash` until they are confirmed or
+ a timeout occurs.
Args:
transactions: A list of transactions to track.
@@ -398,8 +409,8 @@ def wait_for_transactions(
class PendingTransactionHandler:
"""
- Manages block generation based on the number of pending transactions or a block generation
- interval.
+ Manages block generation based on the number of pending transactions or a
+ block generation interval.
Attributes:
block_generation_interval: The number of iterations after which a block
@@ -423,11 +434,12 @@ def handle(self):
"""
Handle pending transactions and generate blocks if necessary.
- If the number of pending transactions reaches the limit, a block is generated.
+ If the number of pending transactions reaches the limit, a block is
+ generated.
- If no new transactions have been added to the pending list and the block
- generation interval has been reached, a block is generated to avoid potential
- deadlock.
+ If no new transactions have been added to the pending list and the
+ block generation interval has been reached, a block is generated to
+ avoid potential deadlock.
"""
with self.chain_builder_eth_rpc.pending_tx_hashes:
if (
@@ -442,8 +454,8 @@ def handle(self):
== self.last_pending_tx_hashes_count
and self.i % self.block_generation_interval == 0
):
- # If no new transactions have been added to the pending list,
- # generate a block to avoid potential deadlock.
+ # If no new transactions have been added to the pending
+ # list, generate a block to avoid potential deadlock.
self.chain_builder_eth_rpc.generate_block()
self.last_pending_tx_hashes_count = len(self.chain_builder_eth_rpc.pending_tx_hashes)
self.i += 1
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/hive.py b/packages/tests/src/pytest_plugins/execute/rpc/hive.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/hive.py
rename to packages/tests/src/pytest_plugins/execute/rpc/hive.py
index 0ae0f02e09..c36349c5fa 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/hive.py
+++ b/packages/tests/src/pytest_plugins/execute/rpc/hive.py
@@ -147,7 +147,10 @@ def base_pre_genesis(
@pytest.fixture(scope="session")
def client_genesis(base_pre_genesis: Tuple[Alloc, FixtureHeader]) -> dict:
- """Convert the fixture's genesis block header and pre-state to a client genesis state."""
+ """
+ Convert the fixture's genesis block header and pre-state to a client
+ genesis state.
+ """
genesis = to_json(base_pre_genesis[1]) # NOTE: to_json() excludes None values
alloc = to_json(base_pre_genesis[0])
# NOTE: nethermind requires account keys without '0x' prefix
@@ -211,7 +214,9 @@ def test_suite_description() -> str:
def base_hive_test(
request: pytest.FixtureRequest, test_suite: HiveTestSuite, session_temp_folder: Path
) -> Generator[HiveTest, None, None]:
- """Test (base) used to deploy the main client to be used throughout all tests."""
+ """
+ Test (base) used to deploy the main client to be used throughout all tests.
+ """
base_name = "base_hive_test"
base_file = session_temp_folder / base_name
base_lock_file = session_temp_folder / f"{base_name}.lock"
@@ -276,7 +281,9 @@ def client(
client_type: ClientType,
session_temp_folder: Path,
) -> Generator[Client, None, None]:
- """Initialize the client with the appropriate files and environment variables."""
+ """
+ Initialize the client with the appropriate files and environment variables.
+ """
base_name = "hive_client"
base_file = session_temp_folder / base_name
base_error_file = session_temp_folder / f"{base_name}.err"
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote.py b/packages/tests/src/pytest_plugins/execute/rpc/remote.py
similarity index 96%
rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote.py
rename to packages/tests/src/pytest_plugins/execute/rpc/remote.py
index d5168af951..4f87766235 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote.py
+++ b/packages/tests/src/pytest_plugins/execute/rpc/remote.py
@@ -87,7 +87,8 @@ def pytest_configure(config: pytest.Config):
"""Check if a chain ID configuration is provided."""
if config.getoption("rpc_chain_id") is None and config.getoption("chain_id") is None:
pytest.exit("No chain ID configuration found. Please use --chain-id.")
- # Verify the chain ID configuration is consistent with the remote RPC endpoint
+ # Verify the chain ID configuration is consistent with the remote RPC
+ # endpoint
rpc_endpoint = config.getoption("rpc_endpoint")
eth_rpc = EthRPC(rpc_endpoint)
remote_chain_id = eth_rpc.chain_id()
@@ -127,8 +128,9 @@ def pytest_configure(config: pytest.Config):
f"JWT secret must be a bytes object, got {type(jwt_secret)}"
)
engine_rpc = EngineRPC(engine_endpoint, jwt_secret=jwt_secret)
- # TODO: Perform a request to the engine endpoint to verify that the JWT secret is valid.
- # Potentially could be `engine_getClientVersionV1` but need to implement this in rpc.py.
+ # TODO: Perform a request to the engine endpoint to verify that the JWT
+ # secret is valid. Potentially could be `engine_getClientVersionV1` but
+ # need to implement this in rpc.py.
config.engine_rpc = engine_rpc # type: ignore
@@ -140,7 +142,10 @@ def engine_rpc(request) -> EngineRPC | None:
@pytest.fixture(autouse=True, scope="session")
def rpc_endpoint(request) -> str:
- """Return remote RPC endpoint to be used to make requests to the execution client."""
+ """
+ Return remote RPC endpoint to be used to make requests to the execution
+ client.
+ """
return request.config.getoption("rpc_endpoint")
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote_seed_sender.py b/packages/tests/src/pytest_plugins/execute/rpc/remote_seed_sender.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote_seed_sender.py
rename to packages/tests/src/pytest_plugins/execute/rpc/remote_seed_sender.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/sender.py b/packages/tests/src/pytest_plugins/execute/sender.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/execute/sender.py
rename to packages/tests/src/pytest_plugins/execute/sender.py
index 016fd4862f..a93a4081d2 100644
--- a/src/ethereum_spec_tests/pytest_plugins/execute/sender.py
+++ b/packages/tests/src/pytest_plugins/execute/sender.py
@@ -85,15 +85,17 @@ def sender_key_initial_balance(
"""
Calculate the initial balance of each sender key.
- The way to do this is to fetch the seed sender balance and divide it by the number of
- workers. This way we can ensure that each sender key has the same initial balance.
+ The way to do this is to fetch the seed sender balance and divide it by the
+ number of workers. This way we can ensure that each sender key has the same
+ initial balance.
- We also only do this once per session, because if we try to fetch the balance again, it
- could be that another worker has already sent a transaction and the balance is different.
+ We also only do this once per session, because if we try to fetch the
+ balance again, it could be that another worker has already sent a
+ transaction and the balance is different.
- It's not really possible to calculate the transaction costs of each test that each worker
- is going to run, so we can't really calculate the initial balance of each sender key
- based on that.
+ It's not really possible to calculate the transaction costs of each test
+ that each worker is going to run, so we can't really calculate the initial
+ balance of each sender key based on that.
"""
base_name = "sender_key_initial_balance"
base_file = session_temp_folder / base_name
@@ -108,7 +110,8 @@ def sender_key_initial_balance(
seed_account_sweep_amount = eth_rpc.get_balance(seed_sender)
seed_sender_balance_per_worker = seed_account_sweep_amount // worker_count
assert seed_sender_balance_per_worker > 100, "Seed sender balance too low"
- # Subtract the cost of the transaction that is going to be sent to the seed sender
+ # Subtract the cost of the transaction that is going to be sent to
+ # the seed sender
sender_key_initial_balance = seed_sender_balance_per_worker - (
sender_fund_refund_gas_limit * sender_funding_transactions_gas_price
)
@@ -132,11 +135,12 @@ def sender_key(
"""
Get the sender keys for all tests.
- The seed sender is going to be shared among different processes, so we need to lock it
- before we produce each funding transaction.
+ The seed sender is going to be shared among different processes, so we need
+ to lock it before we produce each funding transaction.
"""
- # For the seed sender we do need to keep track of the nonce because it is shared among
- # different processes, and there might not be a new block produced between the transactions.
+ # For the seed sender we do need to keep track of the nonce because it is
+ # shared among different processes, and there might not be a new block
+ # produced between the transactions.
seed_sender_nonce_file_name = "seed_sender_nonce"
seed_sender_lock_file_name = f"{seed_sender_nonce_file_name}.lock"
seed_sender_nonce_file = session_temp_folder / seed_sender_nonce_file_name
@@ -172,15 +176,16 @@ def sender_key(
)
refund_gas_limit = sender_fund_refund_gas_limit
- # double the gas price to ensure the transaction is included and overwrites any other
- # transaction that might have been sent by the sender.
+ # double the gas price to ensure the transaction is included and overwrites
+ # any other transaction that might have been sent by the sender.
refund_gas_price = sender_funding_transactions_gas_price * 2
tx_cost = refund_gas_limit * refund_gas_price
if (remaining_balance - 1) < tx_cost:
return
- # Update the nonce of the sender in case one of the pre-alloc transactions failed
+ # Update the nonce of the sender in case one of the pre-alloc transactions
+ # failed
sender.nonce = Number(eth_rpc.get_transaction_count(sender))
refund_tx = Transaction(
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/tests/__init__.py b/packages/tests/src/pytest_plugins/execute/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/tests/__init__.py
rename to packages/tests/src/pytest_plugins/execute/tests/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/tests/test_pre_alloc.py b/packages/tests/src/pytest_plugins/execute/tests/test_pre_alloc.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/execute/tests/test_pre_alloc.py
rename to packages/tests/src/pytest_plugins/execute/tests/test_pre_alloc.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/__init__.py b/packages/tests/src/pytest_plugins/filler/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/filler/__init__.py
rename to packages/tests/src/pytest_plugins/filler/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/eip_checklist.py b/packages/tests/src/pytest_plugins/filler/eip_checklist.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/filler/eip_checklist.py
rename to packages/tests/src/pytest_plugins/filler/eip_checklist.py
index 4405347d34..855c903bb5 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/eip_checklist.py
+++ b/packages/tests/src/pytest_plugins/filler/eip_checklist.py
@@ -1,8 +1,8 @@
"""
Pytest plugin for generating EIP test completion checklists.
-This plugin collects checklist markers from tests and generates a filled checklist
-for each EIP based on the template at
+This plugin collects checklist markers from tests and generates a filled
+checklist for each EIP based on the template at
docs/writing_tests/checklist_templates/eip_testing_checklist_template.md
"""
@@ -118,7 +118,7 @@ def __str__(self) -> str:
status = "❓"
else:
status = "✅"
- tests = ", ".join(sorted(map(resolve_test_link, self.tests)))
+ tests = ", ".join(sorted(self.tests))
elif self.not_applicable:
status = "N/A"
tests = self.not_applicable_reason
@@ -160,17 +160,6 @@ def resolve_id(item_id: str) -> Set[str]:
return covered_ids
-def resolve_test_link(test_id: str) -> str:
- """Resolve a test ID to a test link."""
- # test_id example: tests/fork/eip1234_some_eip/test_file.py::test_function[test_param1-...]
- # Relative path: ../../../../tests/fork/eip1234_some_eip/test_file/test_function/
- pattern = r"(.*)\.py::(\w+)"
- match = re.match(pattern, test_id)
- if not match:
- return test_id
- return f"[{test_id}](../../../../{match.group(1)}/{match.group(2)}/)"
-
-
ALL_CHECKLIST_WARNINGS: Dict[str, Type["ChecklistWarning"]] = {}
@@ -206,7 +195,9 @@ class ConflictingChecklistItemsWarning(ChecklistWarning):
@classmethod
def from_items(cls, all_items: Dict[str, EIPItem]) -> ChecklistWarning | None:
- """Generate a conflicting checklist items warning from a list of items."""
+ """
+ Generate a conflicting checklist items warning from a list of items.
+ """
conflicting_items = [
item for item in all_items.values() if item.not_applicable and item.covered
]
@@ -222,8 +213,7 @@ def from_items(cls, all_items: Dict[str, EIPItem]) -> ChecklistWarning | None:
for item in conflicting_items:
details.append(
f"| {item.id} | {item.description} | "
- + f"{item.not_applicable_reason} | "
- + f"{', '.join(sorted(map(resolve_test_link, item.tests)))} |"
+ + f"{item.not_applicable_reason} | {', '.join(sorted(item.tests))} |"
)
return cls(details=details)
@@ -245,6 +235,7 @@ def add_covered_test(self, checklist_id: str, node_id: str) -> None:
def covered_items(self) -> int:
"""Return the number of covered items."""
return sum(1 for item in self.items.values() if item.covered and not item.not_applicable)
+ return sum(1 for item in self.items.values() if item.covered and not item.not_applicable)
@property
def total_items(self) -> int:
@@ -346,8 +337,8 @@ def generate_filled_checklist_lines(self) -> List[str]:
# Replace the title line with the EIP number
lines[lines.index(TITLE_LINE)] = f"# EIP-{self.number} Test Checklist"
- # Last, add the warnings if there are any, this must be the last thing we do
- # to avoid shifting the lines below the percentage line
+ # Last, add the warnings if there are any, this must be the last thing
+ # we do to avoid shifting the lines below the percentage line
if self.warnings:
warnings_line_idx = lines.index(WARNINGS_LINE)
warnings_lines = ["", "## ⚠️ Checklist Warnings ⚠️", ""]
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/filler.py b/packages/tests/src/pytest_plugins/filler/filler.py
similarity index 93%
rename from src/ethereum_spec_tests/pytest_plugins/filler/filler.py
rename to packages/tests/src/pytest_plugins/filler/filler.py
index aef7fa7503..edb3293c87 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/filler.py
+++ b/packages/tests/src/pytest_plugins/filler/filler.py
@@ -2,8 +2,8 @@
Top-level pytest configuration file providing:
- Command-line options,
- Test-fixtures that can be used by all test cases,
-and that modifies pytest hooks in order to fill test specs for all tests and
-writes the generated fixtures to file.
+and that modifies pytest hooks in order to fill test specs for all tests
+and writes the generated fixtures to file.
"""
import configparser
@@ -60,12 +60,16 @@ class PhaseManager:
"""
Manages the execution phase for fixture generation.
- The filler plugin supports two-phase execution for pre-allocation group generation:
- - Phase 1: Generate pre-allocation groups (pytest run with --generate-pre-alloc-groups).
- - Phase 2: Fill fixtures using pre-allocation groups (pytest run with --use-pre-alloc-groups).
+ The filler plugin supports two-phase execution for pre-allocation group
+ generation:
+ - Phase 1: Generate pre-allocation groups (pytest run with
+ --generate-pre-alloc-groups).
- Note: These are separate pytest runs orchestrated by the CLI wrapper.
- Each run gets a fresh PhaseManager instance (no persistence between phases).
+ - Phase 2: Fill fixtures using pre-allocation
+ groups (pytest run with --use-pre-alloc-groups).
+
+ Note: These are separate pytest runs orchestrated by the CLI wrapper. Each
+ run gets a fresh PhaseManager instance (no persistence between phases).
"""
current_phase: FixtureFillingPhase
@@ -77,13 +81,15 @@ def from_config(cls, config: pytest.Config) -> "Self":
Create a PhaseManager from pytest configuration.
Flag logic:
- - use_pre_alloc_groups: We're in phase 2 (FILL) after phase 1 (PRE_ALLOC_GENERATION).
- - generate_pre_alloc_groups or generate_all_formats: We're in phase 1
- (PRE_ALLOC_GENERATION).
- - Otherwise: Normal single-phase filling (FILL).
-
- Note: generate_all_formats triggers PRE_ALLOC_GENERATION because the CLI
- passes it to phase 1 to ensure all formats are considered for grouping.
+ - use_pre_alloc_groups: We're in phase 2 (FILL) after phase
+ 1 (PRE_ALLOC_GENERATION).
+ - generate_pre_alloc_groups or generate_all_formats:
+ We're in phase 1 (PRE_ALLOC_GENERATION). -
+ Otherwise: Normal single-phase filling (FILL).
+
+ Note: generate_all_formats triggers PRE_ALLOC_GENERATION because the
+ CLI passes it to phase 1 to ensure all formats are considered for
+ grouping.
"""
generate_pre_alloc = config.getoption("generate_pre_alloc_groups", False)
use_pre_alloc = config.getoption("use_pre_alloc_groups", False)
@@ -127,10 +133,11 @@ def is_single_phase_fill(self) -> bool:
@dataclass(kw_only=True)
class FormatSelector:
"""
- Handles fixture format selection based on the current phase and format capabilities.
+ Handles fixture format selection based on the current phase and format
+ capabilities.
- This class encapsulates the complex logic for determining which fixture formats
- should be generated in each phase of the two-phase execution model.
+ This class encapsulates the complex logic for determining which fixture
+ formats should be generated in each phase of the two-phase execution model.
"""
phase_manager: PhaseManager
@@ -141,10 +148,11 @@ def should_generate(self, fixture_format: Type[BaseFixture] | LabeledFixtureForm
Determine if a fixture format should be generated in the current phase.
Args:
- fixture_format: The fixture format to check (may be wrapped in LabeledFixtureFormat)
+ fixture_format: The fixture format to check (may be wrapped in
+ LabeledFixtureFormat).
Returns:
- True if the format should be generated in the current phase
+ True if the format should be generated in the current phase.
"""
format_phases = fixture_format.format_phases
@@ -155,7 +163,10 @@ def should_generate(self, fixture_format: Type[BaseFixture] | LabeledFixtureForm
return self._should_generate_fill(format_phases)
def _should_generate_pre_alloc(self, format_phases: Set[FixtureFillingPhase]) -> bool:
- """Determine if format should be generated during pre-alloc generation phase."""
+ """
+ Determine if format should be generated during pre-alloc generation
+ phase.
+ """
# Only generate formats that need pre-allocation groups
return FixtureFillingPhase.PRE_ALLOC_GENERATION in format_phases
@@ -164,7 +175,8 @@ def _should_generate_fill(self, format_phases: Set[FixtureFillingPhase]) -> bool
if FixtureFillingPhase.PRE_ALLOC_GENERATION in self.phase_manager.previous_phases:
# Phase 2: After pre-alloc generation
if self.generate_all_formats:
- # Generate all formats, including those that don't need pre-alloc
+ # Generate all formats, including those that don't need pre-
+ # alloc
return True
else:
# Only generate formats that needed pre-alloc groups
@@ -179,12 +191,13 @@ class FillingSession:
"""
Manages all state for a single pytest fill session.
- This class serves as the single source of truth for all filler state management,
- including phase management, format selection, and pre-allocation groups.
+ This class serves as the single source of truth for all filler state
+ management, including phase management, format selection, and
+ pre-allocation groups.
- Important: Each pytest run gets a fresh FillingSession instance. There is no
- persistence between phase 1 (generate pre-alloc) and phase 2 (use pre-alloc)
- except through file I/O.
+ Important: Each pytest run gets a fresh FillingSession instance. There is
+ no persistence between phase 1 (generate pre-alloc) and phase 2 (use
+ pre-alloc) except through file I/O.
"""
fixture_output: FixtureOutput
@@ -240,7 +253,8 @@ def should_generate_format(
self, fixture_format: Type[BaseFixture] | LabeledFixtureFormat
) -> bool:
"""
- Determine if a fixture format should be generated in the current session.
+ Determine if a fixture format should be generated in the current
+ session.
Args:
fixture_format: The fixture format to check.
@@ -335,9 +349,9 @@ def calculate_post_state_diff(post_state: Alloc, genesis_state: Alloc) -> Alloc:
"""
Calculate the state difference between post_state and genesis_state.
- This function enables significant space savings in Engine X fixtures by storing
- only the accounts that changed during test execution, rather than the full
- post-state which may contain thousands of unchanged accounts.
+ This function enables significant space savings in Engine X fixtures by
+ storing only the accounts that changed during test execution, rather than
+ the full post-state which may contain thousands of unchanged accounts.
Returns an Alloc containing only the accounts that:
- Changed between genesis and post state (balance, nonce, storage, code)
@@ -624,12 +638,12 @@ def pytest_configure(config):
Couple of notes:
1. Register the plugin's custom markers and process command-line options.
- Custom marker registration:
- https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers
+ Custom marker registration:
+ https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers
2. `@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is
- called before the pytest-html plugin's pytest_configure to ensure that
- it uses the modified `htmlpath` option.
+ called before the pytest-html plugin's pytest_configure to ensure that
+ it uses the modified `htmlpath` option.
"""
# Register custom markers
# Modify the block gas limit if specified.
@@ -646,7 +660,8 @@ def pytest_configure(config):
return
try:
- # Check whether the directory exists and is not empty; if --clean is set, it will delete it
+ # Check whether the directory exists and is not empty; if --clean is
+ # set, it will delete it
config.fixture_output.create_directories(is_master=not hasattr(config, "workerinput"))
except ValueError as e:
pytest.exit(str(e), returncode=pytest.ExitCode.USAGE_ERROR)
@@ -670,8 +685,9 @@ def pytest_configure(config):
"optimize_gas", False
)
- # Instantiate the transition tool here to check that the binary path/trace option is valid.
- # This ensures we only raise an error once, if appropriate, instead of for every test.
+ # Instantiate the transition tool here to check that the binary path/trace
+ # option is valid. This ensures we only raise an error once, if
+ # appropriate, instead of for every test.
evm_bin = config.getoption("evm_bin")
trace = config.getoption("evm_collect_traces")
t8n_server_url = config.getoption("t8n_server_url")
@@ -730,8 +746,8 @@ def pytest_report_teststatus(report, config: pytest.Config):
We use this:
1. To disable test session progress report if we're writing the JSON
- fixtures to stdout to be read by a consume command on stdin. I.e.,
- don't write this type of output to the console:
+ fixtures to stdout to be read by a consume command on stdin. I.e., don't
+ write this type of output to the console:
```text
...x...
```
@@ -750,6 +766,8 @@ def pytest_terminal_summary(
Emphasize that fixtures have only been filled; they must now be executed to
actually run the tests.
"""
+ del exitstatus
+
yield
if config.fixture_output.is_stdout or hasattr(config, "workerinput"): # type: ignore[attr-defined]
return
@@ -870,7 +888,8 @@ def pytest_runtest_makereport(item, call):
]:
report.user_properties.append(("evm_dump_dir", item.config.evm_dump_dir))
else:
- report.user_properties.append(("evm_dump_dir", "N/A")) # not yet for EOF
+ # not yet for EOF
+ report.user_properties.append(("evm_dump_dir", "N/A"))
def pytest_html_report_title(report):
@@ -887,8 +906,7 @@ def evm_bin(request: pytest.FixtureRequest) -> Path | None:
@pytest.fixture(autouse=True, scope="session")
def verify_fixtures_bin(request: pytest.FixtureRequest) -> Path | None:
"""
- Return configured evm tool binary path used to run statetest or
- blocktest.
+ Return configured evm tool binary path used to run statetest or blocktest.
"""
return request.config.getoption("verify_fixtures_bin")
@@ -933,8 +951,8 @@ def evm_fixture_verification(
verify_fixtures_bin: Path | None,
) -> Generator[FixtureConsumer | None, None, None]:
"""
- Return configured evm binary for executing statetest and blocktest
- commands used to verify generated JSON fixtures.
+ Return configured evm binary for executing statetest and blocktest commands
+ used to verify generated JSON fixtures.
"""
if not do_fixture_verification:
yield None
@@ -1047,8 +1065,9 @@ def dump_dir_parameter_level(
Directory to dump evm transition tool debug output on a test parameter
level.
- Example with --evm-dump-dir=/tmp/evm:
- -> /tmp/evm/shanghai__eip3855_push0__test_push0__test_push0_key_sstore/fork_shanghai/
+ Example with --evm-dump-dir=/tmp/evm: ->
+ /tmp/evm/shanghai__eip3855_push0__test_push0__test_push0_key_sstore/fork_shangh
+ ai/
"""
evm_dump_dir = node_to_test_info(request.node).get_dump_dir_path(
base_dump_dir,
@@ -1069,6 +1088,8 @@ def get_fixture_collection_scope(fixture_name, config):
See: https://docs.pytest.org/en/stable/how-to/fixtures.html#dynamic-scope
"""
+ del fixture_name
+
if config.fixture_output.is_stdout:
return "session"
if config.fixture_output.single_fixture_per_file:
@@ -1098,8 +1119,8 @@ def fixture_collector(
fixture_output: FixtureOutput,
) -> Generator[FixtureCollector, None, None]:
"""
- Return configured fixture collector instance used for all tests
- in one test module.
+ Return configured fixture collector instance used for all tests in one test
+ module.
"""
# Dynamically load the 'static_filler' and 'solc' plugins if needed
if request.config.getoption("fill_static_tests_enabled"):
@@ -1159,8 +1180,9 @@ def fixture_source_url(
)
test_module_relative_path = os.path.relpath(request.module.__file__)
if module_relative_path != test_module_relative_path:
- # This can be the case when the test function's body only contains pass and the entire
- # test logic is implemented as a test generator from the framework.
+ # This can be the case when the test function's body only contains pass
+ # and the entire test logic is implemented as a test generator from the
+ # framework.
test_module_github_url = generate_github_url(
test_module_relative_path,
branch_or_commit_or_tag=commit_hash_or_tag,
@@ -1173,8 +1195,8 @@ def base_test_parametrizer(cls: Type[BaseTest]):
"""
Generate pytest.fixture for a given BaseTest subclass.
- Implementation detail: All spec fixtures must be scoped on test function level to avoid
- leakage between tests.
+ Implementation detail: All spec fixtures must be scoped on test function
+ level to avoid leakage between tests.
"""
cls_fixture_parameters = [p for p in ALL_FIXTURE_PARAMETERS if p in cls.model_fields]
@@ -1197,14 +1219,15 @@ def base_test_parametrizer_func(
witness_generator,
):
"""
- Fixture used to instantiate an auto-fillable BaseTest object from within
- a test function.
+ Fixture used to instantiate an auto-fillable BaseTest object from
+ within a test function.
- Every test that defines a test filler must explicitly specify its parameter name
- (see `pytest_parameter_name` in each implementation of BaseTest) in its function
- arguments.
+ Every test that defines a test filler must explicitly specify its
+ parameter name (see `pytest_parameter_name` in each implementation of
+ BaseTest) in its function arguments.
- When parametrize, indirect must be used along with the fixture format as value.
+ When parametrize, indirect must be used along with the fixture format
+ as value.
"""
if hasattr(request.node, "fixture_format"):
fixture_format = request.node.fixture_format
@@ -1244,13 +1267,15 @@ def __init__(self, *args, **kwargs):
# Phase 1: Generate pre-allocation groups
if session.phase_manager.is_pre_alloc_generation:
- # Use the original update_pre_alloc_groups method which returns the groups
+ # Use the original update_pre_alloc_groups method which
+ # returns the groups
self.update_pre_alloc_groups(
session.pre_alloc_groups, fork, request.node.nodeid
)
return # Skip fixture generation in phase 1
- # Phase 2: Use pre-allocation groups (only for BlockchainEngineXFixture)
+ # Phase 2: Use pre-allocation groups (only for
+ # BlockchainEngineXFixture)
pre_alloc_hash = None
if FixtureFillingPhase.PRE_ALLOC_GENERATION in fixture_format.format_phases:
pre_alloc_hash = self.compute_pre_alloc_group_hash(fork=fork)
@@ -1269,11 +1294,13 @@ def __init__(self, *args, **kwargs):
):
gas_optimized_tests = request.config.gas_optimized_tests
assert gas_optimized_tests is not None
- # Force adding something to the list, even if it's None,
- # to keep track of failed tests in the output file.
+ # Force adding something to the list, even if it's
+ # None, to keep track of failed tests in the output
+ # file.
gas_optimized_tests[request.node.nodeid] = self._gas_optimization
- # Post-process for Engine X format (add pre_hash and state diff)
+ # Post-process for Engine X format (add pre_hash and state
+ # diff)
if (
FixtureFillingPhase.PRE_ALLOC_GENERATION in fixture_format.format_phases
and pre_alloc_hash is not None
@@ -1295,7 +1322,8 @@ def __init__(self, *args, **kwargs):
_info_metadata=t8n._info_metadata,
)
- # Generate witness data if witness functionality is enabled via the witness plugin
+ # Generate witness data if witness functionality is enabled via
+ # the witness plugin
if witness_generator is not None:
witness_generator(fixture)
@@ -1324,11 +1352,11 @@ def __init__(self, *args, **kwargs):
def pytest_generate_tests(metafunc: pytest.Metafunc):
"""
- Pytest hook used to dynamically generate test cases for each fixture format a given
- test spec supports.
+ Pytest hook used to dynamically generate test cases for each fixture format
+ a given test spec supports.
- NOTE: The static test filler does NOT use this hook. See FillerFile.collect() in
- ./static_filler.py for more details.
+ NOTE: The static test filler does NOT use this hook. See
+ FillerFile.collect() in ./static_filler.py for more details.
"""
session: FillingSession = metafunc.config.filling_session # type: ignore[attr-defined]
for test_type in BaseTest.spec_types.values():
@@ -1356,11 +1384,14 @@ def pytest_collection_modifyitems(
Remove pre-Paris tests parametrized to generate hive type fixtures; these
can't be used in the Hive Pyspec Simulator.
- Replaces the test ID for state tests that use a transition fork with the base fork.
+ Replaces the test ID for state tests that use a transition fork with the
+ base fork.
These can't be handled in this plugins pytest_generate_tests() as the fork
parametrization occurs in the forks plugin.
"""
+ del config
+
items_for_removal = []
for i, item in enumerate(items):
item.name = item.name.strip().replace(" ", "-")
@@ -1384,7 +1415,8 @@ def pytest_collection_modifyitems(
markers = list(item.iter_markers())
- # Automatically apply pre_alloc_group marker to slow tests that are not benchmark tests
+ # Automatically apply pre_alloc_group marker to slow tests that are not
+ # benchmark tests
has_slow_marker = any(marker.name == "slow" for marker in markers)
has_benchmark_marker = any(marker.name == "benchmark" for marker in markers)
has_pre_alloc_group_marker = any(marker.name == "pre_alloc_group" for marker in markers)
@@ -1402,8 +1434,8 @@ def pytest_collection_modifyitems(
# Re-collect markers after adding the new one
markers = list(item.iter_markers())
- # Both the fixture format itself and the spec filling it have a chance to veto the
- # filling of a specific format.
+ # Both the fixture format itself and the spec filling it have a chance
+ # to veto the filling of a specific format.
if fixture_format.discard_fixture_format_by_marks(fork, markers):
items_for_removal.append(i)
continue
@@ -1443,6 +1475,8 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int):
- Generate index file for all produced fixtures.
- Create tarball of the output directory if the output is a tarball.
"""
+ del exitstatus
+
# Save pre-allocation groups after phase 1
fixture_output: FixtureOutput = session.config.fixture_output # type: ignore[attr-defined]
session_instance: FillingSession = session.config.filling_session # type: ignore[attr-defined]
@@ -1475,9 +1509,7 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int):
session.config.getoption("generate_index")
and not session_instance.phase_manager.is_pre_alloc_generation
):
- generate_fixtures_index(
- fixture_output.directory, quiet_mode=True, force_flag=False, disable_infer_format=False
- )
+ generate_fixtures_index(fixture_output.directory, quiet_mode=True, force_flag=False)
# Create tarball of the output directory if the output is a tarball.
fixture_output.create_tarball()
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/fixture_output.py b/packages/tests/src/pytest_plugins/filler/fixture_output.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/filler/fixture_output.py
rename to packages/tests/src/pytest_plugins/filler/fixture_output.py
index 3238c7d6ec..c9f421f6ed 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/fixture_output.py
+++ b/packages/tests/src/pytest_plugins/filler/fixture_output.py
@@ -69,7 +69,9 @@ def pre_alloc_groups_folder_path(self) -> Path:
@property
def should_auto_enable_all_formats(self) -> bool:
- """Check if all formats should be auto-enabled due to tarball output."""
+ """
+ Check if all formats should be auto-enabled due to tarball output.
+ """
return self.is_tarball
@staticmethod
@@ -95,7 +97,8 @@ def is_directory_usable_for_phase(self) -> bool:
# Phase 1: Directory must be completely empty
return self.is_directory_empty()
elif self.use_pre_alloc_groups:
- # Phase 2: Only pre-allocation groups must exist, no other files allowed
+ # Phase 2: Only pre-allocation groups must exist, no other files
+ # allowed
if not self.pre_alloc_groups_folder_path.exists():
return False
# Check that only the pre-allocation group files exist
@@ -149,13 +152,14 @@ def create_directories(self, is_master: bool) -> None:
"""
Create output and metadata directories if needed.
- If clean flag is set, remove and recreate the directory.
- Otherwise, verify the directory is empty before proceeding.
+ If clean flag is set, remove and recreate the directory. Otherwise,
+ verify the directory is empty before proceeding.
"""
if self.is_stdout:
return
- # Only the master process should delete/create directories if using pytest-xdist
+ # Only the master process should delete/create directories if using
+ # pytest-xdist
if not is_master:
return
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/__init__.py b/packages/tests/src/pytest_plugins/filler/gen_test_doc/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/__init__.py
rename to packages/tests/src/pytest_plugins/filler/gen_test_doc/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/gen_test_doc.py b/packages/tests/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
similarity index 87%
rename from src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
rename to packages/tests/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
index 044b2a2e9a..6f1d162a68 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
+++ b/packages/tests/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
@@ -1,34 +1,34 @@
"""
A pytest plugin that generates test case documentation for use in mkdocs.
-It generates the top-level "Test Case Reference" section in EEST's mkdocs
-site.
+It generates the top-level "Test Case Reference" section in EEST's mkdocs site.
Note:
----
-- No output directory is specified for the generated output; file IO occurs
- via the `mkdocs-gen-files` plugin. `mkdocs serve` writes intermediate files
- to our local `docs/` directory and then copies it to the site directory.
- We modify `docs/navigation.md` and write all other output underneath
- `docs/tests`. If mkdocs is interrupted, these intermediate artifacts are
- left in `docs/`.
+- No output directory is specified for the generated output; file IO
+occurs via the `mkdocs-gen-files` plugin. `mkdocs serve` writes intermediate
+files to our local `docs/` directory and then copies it to the site directory.
+We modify `docs/navigation.md` and write all other output underneath
+`docs/tests`. If mkdocs is interrupted, these intermediate artifacts are left
+in `docs/`.
Usage:
------
!!! note "Ensuring a clean build"
- In case mkdocs has polluted the `docs/` directory with intermediate files, run:
+In case mkdocs has polluted the `docs/` directory with intermediate files, run:
- ```console
- git restore docs/navigation.md # Careful if you have local modifications!
- rm -rf docs/tests docs/docs site
- ```
+```console
+git restore docs/navigation.md # Careful if you have local modifications!
+rm -rf docs/tests docs/docs site
+```
To test doc generation, run the plugin without mkdocs:
```console
-uv run fill -p pytest_plugins.filler.gen_test_doc.gen_test_doc --gen-docs --fork= tests
+uv run fill -p pytest_plugins.filler.gen_test_doc.gen_test_doc --gen-docs \
+ --fork= tests
```
Or to build and view the site:
@@ -128,8 +128,8 @@ def get_test_function_import_path(item: pytest.Item) -> str:
"""
Retrieve the fully qualified import path for an item's test function.
- This is used in jinja2 templates to get the test function, respectively
- the test function's class, documentation with mkdocstrings.
+ This is used in jinja2 templates to get the test function, respectively the
+ test function's class, documentation with mkdocstrings.
"""
item = cast(pytest.Function, item) # help mypy infer type
module_name = item.module.__name__
@@ -150,7 +150,8 @@ def get_import_path(path: Path) -> str:
Get the import path for a given path.
- For modules, strip the file extension.
- - For directories (i.e., packages such as `tests.berlin`), `with_suffix()` is ignored.
+ - For directories (i.e., packages such as `tests.berlin`),
+ `with_suffix()` is ignored.
To do:
------
@@ -273,7 +274,8 @@ def pytest_collection_modifyitems(self, config: pytest.Config, items: List[pytes
self.create_module_page_props()
# add the pages to the page_props dict
self.page_props = {**self.page_props, **self.function_page_props, **self.module_page_props}
- # this adds pages for the intermediate directory structure (tests, tests/berlin)
+ # this adds pages for the intermediate directory structure (tests,
+ # tests/berlin)
self.add_directory_page_props()
# add other interesting pages
self.add_spec_page_props()
@@ -297,7 +299,8 @@ def _setup_logger(self):
Configure the mkdocs logger and adds a StreamHandler if outside mkdocs.
We use the mkdocs logger to report warnings if conditions are invalid -
- this will inform the user and fail the build with `mkdocs build --strict`.
+ this will inform the user and fail the build with `mkdocs build
+ --strict`.
"""
if not logger.hasHandlers() or logger.level == logging.NOTSET:
stream_handler = logging.StreamHandler(sys.stdout)
@@ -309,12 +312,12 @@ def get_doc_site_base_url(self) -> str:
"""
Return site's base in its URL for inclusion of local files.
- This is required in order to include docs/javascripts/site.js, for
+ This is required in order to include docs/javascripts/site.js, for
example, in the standalone html pages.
- Github pages deploys to a sub-directory "execution-spec-tests" and
- mike deploys a version of the site underneath a sub-directory named
- after the version, e.g.:
+ Github pages deploys to a sub-directory "execution-spec-tests" and mike
+ deploys a version of the site underneath a sub-directory named after
+ the version, e.g.:
- https://eest.ethereum.org/main/
- https://eest.ethereum.org/v4.1.0/
@@ -352,7 +355,8 @@ def add_global_page_props_to_env(self):
def create_function_page_props(self, test_functions: Dict["str", List[Item]]) -> None:
"""
- Traverse all test items and create a lookup of doc pages & required props.
+ Traverse all test items and create a lookup of doc pages & required
+ props.
To do: Needs refactor.
"""
@@ -361,17 +365,20 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) ->
]
for function_id, function_items in test_functions.items():
assert all(isinstance(item, pytest.Function) for item in function_items)
- items = cast(List[pytest.Function], function_items) # help mypy infer type
+ # help mypy infer type
+ items = cast(List[pytest.Function], function_items)
# extract parametrized test cases for each test function
test_cases = []
if getattr(items[0], "callspec", None):
for item in items:
param_set = item.callspec.params
- # Don't show skipped parameters as columns in the test case table
+ # Don't show skipped parameters as columns in the test case
+ # table
keys = [key for key in param_set.keys() if key not in skip_params]
values = [param_set[key] for key in keys]
- # TODO: This formatting of bytes objects should be moved elsewhere
+ # TODO: This formatting of bytes objects should be moved
+ # elsewhere
values = [
(
" ".join(
@@ -406,8 +413,8 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) ->
if not valid_from_marker:
valid_from_fork = "Frontier"
else:
- # NOTE: The EOF tests cases contain two fork names in their valid_from marker,
- # separated by a comma. Take the last.
+ # NOTE: The EOF tests cases contain two fork names in their
+ # valid_from marker, separated by a comma. Take the last.
valid_from_fork = valid_from_marker.args[0].split(",")[-1]
target_or_valid_fork = (
@@ -424,6 +431,7 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) ->
)
is_benchmark = items[0].get_closest_marker("benchmark") is not None
+ is_stateful = items[0].get_closest_marker("stateful") is not None
self.function_page_props[function_id] = FunctionPageProps(
title=get_test_function_name(items[0]),
@@ -440,6 +448,7 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) ->
html_static_page_target=f"./{get_test_function_name(items[0])}.html",
mkdocs_function_page_target=f"./{get_test_function_name(items[0])}/",
is_benchmark=is_benchmark,
+ is_stateful=is_stateful,
)
def create_module_page_props(self) -> None:
@@ -455,6 +464,7 @@ def create_module_page_props(self) -> None:
pytest_node_id=str(module_path),
package_name=get_import_path(module_path),
is_benchmark=function_page.is_benchmark,
+ is_stateful=function_page.is_stateful,
test_functions=[
TestFunction(
name=function_page.title,
@@ -468,6 +478,8 @@ def create_module_page_props(self) -> None:
existing_module_page = self.module_page_props[str(function_page.path)]
if function_page.is_benchmark:
existing_module_page.is_benchmark = True
+ if function_page.is_stateful:
+ existing_module_page.is_stateful = True
existing_module_page.test_functions.append(
TestFunction(
name=function_page.title,
@@ -481,7 +493,8 @@ def add_directory_page_props(self) -> None:
"""
Discover the intermediate directory pages and extract their properties.
- These directories may not have any test modules within them, e.g., tests/berlin/.
+ These directories may not have any test modules within them, e.g.,
+ tests/berlin/.
"""
sub_paths: Set[Path] = set()
for module_page in self.module_page_props.values():
@@ -503,7 +516,12 @@ def add_directory_page_props(self) -> None:
is_benchmark = any(
module_page.is_benchmark
for module_page in self.module_page_props.values()
- if module_page.path.parent == directory
+ if directory in module_page.path.parents or module_page.path.parent == directory
+ )
+ is_stateful = any(
+ module_page.is_stateful
+ for module_page in self.module_page_props.values()
+ if directory in module_page.path.parents or module_page.path.parent == directory
)
self.page_props[str(directory)] = DirectoryPageProps(
@@ -511,11 +529,14 @@ def add_directory_page_props(self) -> None:
path=directory,
pytest_node_id=str(directory),
source_code_url=generate_github_url(directory, branch_or_commit_or_tag=self.ref),
- # TODO: This won't work in all cases; should be from the development fork
- # Currently breaks for `tests/unscheduled/eip7692_eof_v1/index.md` # noqa: SC100
+ # TODO: This won't work in all cases; should be from the
+ # development fork Currently breaks for
+ # `tests/unscheduled/eip7692_eof_v1/index.md`
target_or_valid_fork=fork.capitalize() if fork else "Unknown",
- package_name=get_import_path(directory), # init.py will be used for docstrings
+ # init.py will be used for docstrings
+ package_name=get_import_path(directory),
is_benchmark=is_benchmark,
+ is_stateful=is_stateful,
)
def find_files_within_collection_scope(self, file_pattern: str) -> List[Path]:
@@ -538,7 +559,10 @@ def find_files_within_collection_scope(self, file_pattern: str) -> List[Path]:
return [Path(file) for file in set(files)]
def add_spec_page_props(self) -> None:
- """Add page path properties for spec files discovered in the collection scope."""
+ """
+ Add page path properties for spec files discovered in the collection
+ scope.
+ """
for spec_path in self.find_files_within_collection_scope("spec.py"):
self.page_props[str(spec_path)] = ModulePageProps(
title="Spec",
@@ -551,44 +575,58 @@ def add_spec_page_props(self) -> None:
)
def add_markdown_page_props(self) -> None:
- """Add page path properties for markdown files discovered in the collection scope."""
+ """
+ Add page path properties for markdown files discovered in the
+ collection scope.
+ """
for md_path in self.find_files_within_collection_scope("*.md"):
self.page_props[str(md_path)] = MarkdownPageProps(
title=md_path.stem,
path=md_path,
source_code_url=generate_github_url(md_path, branch_or_commit_or_tag=self.ref),
- pytest_node_id=str(md_path), # abuse: not a test, but used in source code link
+ # abuse: not a test, but used in source code link
+ pytest_node_id=str(md_path),
target_or_valid_fork="",
package_name="",
)
def update_mkdocs_nav(self) -> None:
- """Add the generated 'Test Case Reference' entries to the mkdocs navigation menu."""
+ """
+ Add the generated 'Test Case Reference' entries to the mkdocs
+ navigation menu.
+ """
fork_order = {fork.name().lower(): i for i, fork in enumerate(reversed(get_forks()))}
def sort_by_fork_deployment_and_path(x: PageProps) -> Tuple[Any, ...]:
"""
- Key function used to sort navigation menu entries for test case ref docs.
+ Key function used to sort navigation menu entries for test case ref
+ docs.
Nav entries / output files contain special cases such as:
- ("Test Case Reference",) -> tests/index.md
- ("Test Case Reference", "Berlin") -> tests/berlin/index.md
- ("Test Case Reference", "EIP-7692 EOF V1", tracker.md")
- tests/unscheduled/eip7692_eof_v1/tracker.md
+ tests/unscheduled/eip7692_eof_v1/tracker.md
- ("Test Case Reference", "Shanghai", "EIP-3855 PUSH0", "Spec") ->
- tests/shanghai/eip3855_push0/spec.py
+ tests/shanghai/eip3855_push0/spec.py
- This function provides and ordering to sort nav men entries as follows:
+ This function provides and ordering to sort nav men entries as
+ follows:
- 1. Forks are listed in the chronological order that they were deployed.
- 2. Special files listed first (before test pages): "*.md" and `Spec.py`,
- 3. The page's corresponding file path under `./tests/`.
+ 1. Forks are listed in the chronological order that they were
+ deployed.
+ 2. Special files listed first (before test pages): "*.md"
+ and `Spec.py`,
+ 3. The page's corresponding file path under
+ `./tests/`.
"""
length = len(x.path.parts)
if length > 1:
- fork = str(x.path.parts[1]).lower() # the fork folder from the relative path
- if fork not in fork_order: # unscheduled features added to the end
+ # the fork folder from the relative path
+ fork = str(x.path.parts[1]).lower()
+ # unscheduled features added to the end
+ if fork not in fork_order:
return (999, str(x.path))
if length == 1:
return (0,)
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/page_props.py b/packages/tests/src/pytest_plugins/filler/gen_test_doc/page_props.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/page_props.py
rename to packages/tests/src/pytest_plugins/filler/gen_test_doc/page_props.py
index 2c3194ee8c..cf6d8adb5a 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/page_props.py
+++ b/packages/tests/src/pytest_plugins/filler/gen_test_doc/page_props.py
@@ -1,10 +1,10 @@
"""
Classes and helpers used for templates, navigation menus and file output.
-The dataclass fields are used to define the page properties fields which
-are used in the jinja2 templates when generating site content (located in
-docs/templates). The classes also define each page's navigation menu entry
-and target output file.
+The dataclass fields are used to define the page properties fields which are
+used in the jinja2 templates when generating site content (located in
+docs/templates). The classes also define each page's navigation menu entry and
+target output file.
A few helpers are defined with EEST logic in order to sanitize strings from
file paths for use in navigation menu.
@@ -23,7 +23,8 @@
def apply_name_filters(input_string: str):
"""
- Apply a list of capitalizations/regexes to names used in titles & nav menus.
+ Apply a list of capitalizations/regexes to names used in titles & nav
+ menus.
Note: As of 2024-10-08, with 634 doc pages, this function constitutes ~2.0s
of the total runtime (~5.5s). This seems to be insignificant with the time
@@ -62,7 +63,9 @@ def apply_name_filters(input_string: str):
def snake_to_capitalize(string: str) -> str: # noqa: D103
- """Convert valid identifiers to a capitalized string, otherwise leave as-is."""
+ """
+ Convert valid identifiers to a capitalized string, otherwise leave as-is.
+ """
if string.isidentifier():
return " ".join(word.capitalize() for word in string.split("_"))
return string
@@ -74,14 +77,17 @@ def sanitize_string_title(string: str) -> str:
def nav_path_to_sanitized_str_tuple(nav_path: Path) -> tuple:
- """Convert a nav path to a tuple of sanitized strings for use in mkdocs navigation."""
+ """
+ Convert a nav path to a tuple of sanitized strings for use in mkdocs
+ navigation.
+ """
return tuple(sanitize_string_title(part) for part in nav_path.parts)
class FileOpener(Protocol):
"""
- Protocol to replace `mkdocs_gen_files` so it doesn't have to be imported/installed for
- unit tests.
+ Protocol to replace `mkdocs_gen_files` so it doesn't have to be
+ imported/installed for unit tests.
"""
def open(self, path: Path, mode: str) -> ContextManager[IO[Any]]:
@@ -94,8 +100,8 @@ class PagePropsBase:
"""
Common test reference doc page properties and definitions.
- The dataclass attributes are made directly available in the jinja2
- found in `docs/templates/*.j2`.
+ The dataclass attributes are made directly available in the jinja2 found in
+ `docs/templates/*.j2`.
"""
title: str
@@ -105,6 +111,7 @@ class PagePropsBase:
pytest_node_id: str
package_name: str
is_benchmark: bool = False
+ is_stateful: bool = False
@property
@abstractmethod
@@ -159,7 +166,10 @@ def write_page(self, file_opener: FileOpener, jinja2_env: Environment):
@dataclass
class TestCase:
- """Properties used to define a single test case in test function parameter tables."""
+ """
+ Properties used to define a single test case in test function parameter
+ tables.
+ """
full_id: str
abbreviated_id: str
@@ -200,10 +210,11 @@ def nav_entry(self, top_level_nav_entry) -> tuple:
def write_page(self, file_opener: FileOpener, jinja2_env: Environment):
"""
- Test functions also get a static HTML page with parametrized test cases.
+ Test functions also get a static HTML page with parametrized test
+ cases.
- This is intended for easier viewing (without mkdocs styling) of the data-table
- that documents the parametrized test cases.
+ This is intended for easier viewing (without mkdocs styling) of the
+ data-table that documents the parametrized test cases.
"""
super().write_page(file_opener, jinja2_env)
if not self.cases:
@@ -218,7 +229,10 @@ def write_page(self, file_opener: FileOpener, jinja2_env: Environment):
@dataclass
class TestFunction:
- """Properties used to build the test function overview table in test module pages."""
+ """
+ Properties used to build the test function overview table in test module
+ pages.
+ """
name: str
test_type: str
@@ -228,7 +242,10 @@ class TestFunction:
@dataclass
class ModulePageProps(PagePropsBase):
- """Definitions used for test modules, e.g., `tests/berlin/eip2930_access_list/test_acl.py`."""
+ """
+ Definitions used for test modules, e.g.,
+ `tests/berlin/eip2930_access_list/test_acl.py`.
+ """
test_functions: List[TestFunction] = field(default_factory=list)
@@ -247,7 +264,10 @@ def target_output_file(self) -> Path:
@dataclass
class DirectoryPageProps(PagePropsBase):
- """Definitions used for parent directories in test paths, e.g., `tests/berlin`."""
+ """
+ Definitions used for parent directories in test paths, e.g.,
+ `tests/berlin`.
+ """
@property
def template(self) -> str:
@@ -262,7 +282,9 @@ def target_output_file(self) -> Path:
@dataclass
class MarkdownPageProps(PagePropsBase):
- """Definitions used to verbatim include markdown files included in test paths."""
+ """
+ Definitions used to verbatim include markdown files included in test paths.
+ """
@property
def template(self) -> str:
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/ported_tests.py b/packages/tests/src/pytest_plugins/filler/ported_tests.py
similarity index 95%
rename from src/ethereum_spec_tests/pytest_plugins/filler/ported_tests.py
rename to packages/tests/src/pytest_plugins/filler/ported_tests.py
index 228647baf5..0d7f5475bb 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/ported_tests.py
+++ b/packages/tests/src/pytest_plugins/filler/ported_tests.py
@@ -1,20 +1,21 @@
"""
A pytest plugin that shows `ported_from` marker information.
-This plugin extracts and displays information from @pytest.mark.ported_from markers,
-showing either the static filler file paths or associated PR URLs.
+This plugin extracts and displays information from @pytest.mark.ported_from
+markers, showing either the static filler file paths or associated PR URLs.
Usage:
------
-# Show static filler file paths
-uv run fill --show-ported-from tests/
+# Show static filler file paths:
+# uv run fill --show-ported-from tests/
-# Show PR URLs instead
-uv run fill --show-ported-from=prs tests/
+# Show PR URLs instead:
+# uv run fill --show-ported-from=prs tests/
The plugin will:
1. Collect all test items with @pytest.mark.ported_from markers
-2. Extract either the file paths (first positional argument) or PR URLs (pr keyword argument)
+2. Extract either the file paths (first positional argument) or PR URLs (pr
+ keyword argument)
3. Output a deduplicated, sorted list, one per line
4. Skip test execution (collection only)
5. Exclude tests with coverage_missed_reason from output
@@ -22,7 +23,8 @@
Marker Format:
--------------
@pytest.mark.ported_from(
- ["path/to/static_filler1.json", "path/to/static_filler2.json"],
+ ["path/to/static_filler1.json",
+ "path/to/static_filler2.json"],
pr=[
"https://github.com/ethereum/execution-spec-tests/pull/1234",
"https://github.com/ethereum/execution-spec-tests/pull/5678",
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/pre_alloc.py b/packages/tests/src/pytest_plugins/filler/pre_alloc.py
similarity index 88%
rename from src/ethereum_spec_tests/pytest_plugins/filler/pre_alloc.py
rename to packages/tests/src/pytest_plugins/filler/pre_alloc.py
index 49a9a4594b..e7a5809251 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/pre_alloc.py
+++ b/packages/tests/src/pytest_plugins/filler/pre_alloc.py
@@ -96,6 +96,7 @@ class Alloc(BaseAlloc):
_contract_address_iterator: Iterator[Address] = PrivateAttr()
_eoa_iterator: Iterator[EOA] = PrivateAttr()
_evm_code_type: EVMCodeType | None = PrivateAttr(None)
+ _fork: Fork = PrivateAttr()
def __init__(
self,
@@ -103,6 +104,7 @@ def __init__(
alloc_mode: AllocMode,
contract_address_iterator: Iterator[Address],
eoa_iterator: Iterator[EOA],
+ fork: Fork,
evm_code_type: EVMCodeType | None = None,
**kwargs,
):
@@ -112,6 +114,7 @@ def __init__(
self._contract_address_iterator = contract_address_iterator
self._eoa_iterator = eoa_iterator
self._evm_code_type = evm_code_type
+ self._fork = fork
def __setitem__(self, address: Address | FixedSizeBytesConvertible, account: Account | None):
"""Set account associated with an address."""
@@ -147,8 +150,9 @@ def deploy_contract(
"""
Deploy a contract to the allocation.
- Warning: `address` parameter is a temporary solution to allow tests to hard-code the
- contract address. Do NOT use in new tests as it will be removed in the future!
+ Warning: `address` parameter is a temporary solution to allow tests to
+ hard-code the contract address. Do NOT use in new tests as it will be
+ removed in the future!
"""
if storage is None:
storage = {}
@@ -162,12 +166,19 @@ def deploy_contract(
if self._alloc_mode == AllocMode.STRICT:
assert Number(nonce) >= 1, "impossible to deploy contract with nonce lower than one"
+ code = self.code_pre_processor(code, evm_code_type=evm_code_type)
+ code_bytes = bytes(code) if not isinstance(code, (bytes, str)) else code
+ max_code_size = self._fork.max_code_size()
+ assert len(code_bytes) <= max_code_size, (
+ f"code too large: {len(code_bytes)} > {max_code_size}"
+ )
+
super().__setitem__(
contract_address,
Account(
nonce=nonce,
balance=balance,
- code=self.code_pre_processor(code, evm_code_type=evm_code_type),
+ code=code,
storage=storage,
),
)
@@ -195,10 +206,11 @@ def fund_eoa(
nonce: NumberConvertible | None = None,
) -> EOA:
"""
- Add a previously unused EOA to the pre-alloc with the balance specified by `amount`.
+ Add a previously unused EOA to the pre-alloc with the balance specified
+ by `amount`.
- If amount is 0, nothing will be added to the pre-alloc but a new and unique EOA will be
- returned.
+ If amount is 0, nothing will be added to the pre-alloc but a new and
+ unique EOA will be returned.
"""
eoa = next(self._eoa_iterator)
if amount is None:
@@ -218,13 +230,14 @@ def fund_eoa(
if nonce > 0:
eoa.nonce = nonce
else:
- # Type-4 transaction is sent to the EOA to set the storage, so the nonce must be 1
+ # Type-4 transaction is sent to the EOA to set the storage, so
+ # the nonce must be 1
if not isinstance(delegation, Address) and delegation == "Self":
delegation = eoa
- # If delegation is None but storage is not, realistically the nonce should be 2
- # because the account must have delegated to set the storage and then again to
- # reset the delegation (but can be overridden by the test for a non-realistic
- # scenario)
+ # If delegation is None but storage is not, realistically the
+ # nonce should be 2 because the account must have delegated to
+ # set the storage and then again to reset the delegation (but
+ # can be overridden by the test for a non-realistic scenario)
real_nonce = 2 if delegation is None else 1
nonce = Number(real_nonce if nonce is None else nonce)
account = Account(
@@ -257,7 +270,8 @@ def fund_address(self, address: Address, amount: NumberConvertible):
def empty_account(self) -> Address:
"""
- Add a previously unused account guaranteed to be empty to the pre-alloc.
+ Add a previously unused account guaranteed to be empty to the
+ pre-alloc.
This ensures the account has:
- Zero balance
@@ -265,8 +279,9 @@ def empty_account(self) -> Address:
- No code
- No storage
- This is different from precompiles or system contracts. The function does not
- send any transactions, ensuring that the account remains "empty."
+ This is different from precompiles or system contracts. The function
+ does not send any transactions, ensuring that the account remains
+ "empty."
Returns:
Address: The address of the created empty account.
@@ -314,8 +329,8 @@ def sha256_from_string(s: str) -> int:
if name not in ALL_FIXTURE_FORMAT_NAMES:
ALL_FIXTURE_FORMAT_NAMES.append(name)
-# Sort by length, from longest to shortest, since some fixture format names contain others
-# so we are always sure to catch the longest one first.
+# Sort by length, from longest to shortest, since some fixture format names
+# contain others so we are always sure to catch the longest one first.
ALL_FIXTURE_FORMAT_NAMES.sort(key=len, reverse=True)
@@ -324,17 +339,18 @@ def node_id_for_entropy(request: pytest.FixtureRequest, fork: Fork | None) -> st
"""
Return the node id with the fixture format name and fork name stripped.
- Used in cases where we are filling for pre-alloc groups, and we take the name of the
- test as source of entropy to get a deterministic address when generating the pre-alloc
- grouping.
+ Used in cases where we are filling for pre-alloc groups, and we take the
+ name of the test as source of entropy to get a deterministic address when
+ generating the pre-alloc grouping.
- Removing the fixture format and the fork name from the node id before hashing results in the
- contracts and senders addresses being the same across fixture types and forks for the same
- test.
+ Removing the fixture format and the fork name from the node id before
+ hashing results in the contracts and senders addresses being the same
+ across fixture types and forks for the same test.
"""
node_id: str = request.node.nodeid
if fork is None:
- # FIXME: Static tests don't have a fork, so we need to get it from the node.
+ # FIXME: Static tests don't have a fork, so we need to get it from the
+ # node.
assert hasattr(request.node, "fork")
fork = request.node.fork
for fixture_format_name in ALL_FIXTURE_FORMAT_NAMES:
@@ -358,7 +374,8 @@ def contract_address_iterator(
) -> Iterator[Address]:
"""Return iterator over contract addresses with dynamic scoping."""
if request.config.getoption(
- # TODO: Ideally, we should check the fixture format instead of checking parameters.
+ # TODO: Ideally, we should check the fixture format instead of checking
+ # parameters.
"generate_pre_alloc_groups",
default=False,
) or request.config.getoption("use_pre_alloc_groups", default=False):
@@ -383,7 +400,8 @@ def eoa_iterator(
) -> Iterator[EOA]:
"""Return iterator over EOAs copies with dynamic scoping."""
if request.config.getoption(
- # TODO: Ideally, we should check the fixture format instead of checking parameters.
+ # TODO: Ideally, we should check the fixture format instead of checking
+ # parameters.
"generate_pre_alloc_groups",
default=False,
) or request.config.getoption("use_pre_alloc_groups", default=False):
@@ -416,11 +434,20 @@ def pre(
contract_address_iterator: Iterator[Address],
eoa_iterator: Iterator[EOA],
evm_code_type: EVMCodeType,
+ fork: Fork | None,
+ request: pytest.FixtureRequest,
) -> Alloc:
"""Return default pre allocation for all tests (Empty alloc)."""
+ # FIXME: Static tests don't have a fork so we need to get it from the node.
+ actual_fork = fork
+ if actual_fork is None:
+ assert hasattr(request.node, "fork")
+ actual_fork = request.node.fork
+
return Alloc(
alloc_mode=alloc_mode,
contract_address_iterator=contract_address_iterator,
eoa_iterator=eoa_iterator,
+ fork=actual_fork,
evm_code_type=evm_code_type,
)
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/static_filler.py b/packages/tests/src/pytest_plugins/filler/static_filler.py
similarity index 96%
rename from src/ethereum_spec_tests/pytest_plugins/filler/static_filler.py
rename to packages/tests/src/pytest_plugins/filler/static_filler.py
index 33271d3172..70feff2023 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/static_filler.py
+++ b/packages/tests/src/pytest_plugins/filler/static_filler.py
@@ -1,6 +1,6 @@
"""
-Static filler pytest plugin that reads test cases from static files and fills them into test
-fixtures.
+Static filler pytest plugin that reads test cases from static files and fills
+them into test fixtures.
"""
import inspect
@@ -19,7 +19,7 @@
from ethereum_test_fixtures import BaseFixture, LabeledFixtureFormat
from ethereum_test_forks import Fork, get_closest_fork
from ethereum_test_specs import BaseStaticTest, BaseTest
-from ethereum_test_tools.code.yul import Yul
+from ethereum_test_tools.tools_code.yul import Yul
from ..forks.forks import ValidityMarker
from ..shared.helpers import labeled_format_parameter_set
@@ -111,7 +111,10 @@ def get_all_combinations_from_parametrize_marks(
def pytest_collect_file(file_path: Path, parent) -> pytest.Collector | None:
- """Pytest hook that collects test cases from static files and fills them into test fixtures."""
+ """
+ Pytest hook that collects test cases from static files and fills them into
+ test fixtures.
+ """
fill_static_tests_enabled = parent.config.getoption("fill_static_tests_enabled")
if not fill_static_tests_enabled:
return None
@@ -147,8 +150,8 @@ class NoIntResolver(yaml.SafeLoader):
class FillerFile(pytest.File):
"""
- Filler file that reads test cases from static files and fills them into test
- fixtures.
+ Filler file that reads test cases from static files and fills them into
+ test fixtures.
"""
def collect(self: "FillerFile") -> Generator["FillerTestItem", None, None]:
@@ -241,7 +244,8 @@ def collect(self: "FillerFile") -> Generator["FillerTestItem", None, None]:
get_all_combinations_from_parametrize_marks(parametrize_marks)
)
for parameter_set in parameter_set_list:
- # Copy and extend the params with the parameter set
+ # Copy and extend the params with the
+ # parameter set
case_marks = (
marks[:]
+ [
@@ -349,10 +353,10 @@ def yul(fork: Fork, request: pytest.FixtureRequest):
"""
Fixture that allows contract code to be defined with Yul code.
- This fixture defines a class that wraps the ::ethereum_test_tools.Yul
- class so that upon instantiation within the test case, it provides the
- test case's current fork parameter. The forks is then available for use
- in solc's arguments for the Yul code compilation.
+ This fixture defines a class that wraps the ::ethereum_test_tools.Yul class
+ so that upon instantiation within the test case, it provides the test
+ case's current fork parameter. The forks is then available for use in
+ solc's arguments for the Yul code compilation.
Test cases can override the default value by specifying a fixed version
with the @pytest.mark.compile_yul_with(FORK) marker.
@@ -372,7 +376,7 @@ class so that upon instantiation within the test case, it provides the
else:
pytest.fail(f"{request.node.name}: Fork {marker.args[0]} not found in forks list.")
else:
- solc_target_fork = get_closest_fork(fork, request.config.solc_version)
+ solc_target_fork = get_closest_fork(fork)
assert solc_target_fork is not None, "No fork supports provided solc version."
if solc_target_fork != fork and request.config.getoption("verbose") >= 1:
warnings.warn(
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/__init__.py b/packages/tests/src/pytest_plugins/filler/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/__init__.py
rename to packages/tests/src/pytest_plugins/filler/tests/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_benchmarking.py b/packages/tests/src/pytest_plugins/filler/tests/test_benchmarking.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_benchmarking.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_benchmarking.py
index acceecda6b..42c8f80874 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_benchmarking.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_benchmarking.py
@@ -37,12 +37,11 @@ def setup_test_directory_structure(
Set up the common test directory structure used across multiple tests.
Args:
- pytester: The pytest Pytester fixture
- test_content: The content to write to the test file
- test_filename: The name of the test file to create
+ pytester: The pytest Pytester fixture
+ test_content: The content to write to the test file
+ test_filename: The name of the test file to create
- Returns:
- The path to the created test module file
+ Returns: The path to the created test module file
"""
tests_dir = pytester.mkdir("tests")
@@ -71,7 +70,10 @@ def test_gas_benchmark_option_added(pytester: pytest.Pytester):
def test_benchmarking_mode_configured_with_option(pytester: pytest.Pytester):
- """Test that fill_mode is set to BENCHMARKING when --gas-benchmark-values is used."""
+ """
+ Test that fill_mode is set to BENCHMARKING when --gas-benchmark-values is
+ used.
+ """
setup_test_directory_structure(pytester, test_module_dummy, "test_dummy_benchmark.py")
# Test with gas benchmark values
@@ -96,7 +98,10 @@ def test_benchmarking_mode_configured_with_option(pytester: pytest.Pytester):
def test_benchmarking_mode_not_configured_without_option(pytester: pytest.Pytester):
- """Test that fill_mode is not set to BENCHMARKING when --gas-benchmark-values is not used."""
+ """
+ Test that fill_mode is not set to BENCHMARKING when --gas-benchmark-values
+ is not used.
+ """
setup_test_directory_structure(pytester, test_module_dummy, "test_dummy_benchmark.py")
# Test without gas benchmark values
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_collect_only.py b/packages/tests/src/pytest_plugins/filler/tests/test_collect_only.py
similarity index 93%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_collect_only.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_collect_only.py
index 8fee4e198f..b9b09974cb 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_collect_only.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_collect_only.py
@@ -51,6 +51,6 @@ def test_collect_only_output(pytester: pytest.Pytester):
in line
for line in result.outlines
), f"Expected test output: {result.outlines}"
- # fill generates 3 test variants: state_test, blockchain_test_from_state_test,
- # blockchain_test_engine_from_state_test
+ # fill generates 3 test variants: state_test,
+ # blockchain_test_from_state_test, blockchain_test_engine_from_state_test
assert any("3 tests collected" in line for line in result.outlines)
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_eip_checklist.py b/packages/tests/src/pytest_plugins/filler/tests/test_eip_checklist.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_eip_checklist.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_eip_checklist.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filler.py b/packages/tests/src/pytest_plugins/filler/tests/test_filler.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filler.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_filler.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filling_session.py b/packages/tests/src/pytest_plugins/filler/tests/test_filling_session.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filling_session.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_filling_session.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_format_selector.py b/packages/tests/src/pytest_plugins/filler/tests/test_format_selector.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_format_selector.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_format_selector.py
index 16c34c5939..0346bc1ce5 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_format_selector.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_format_selector.py
@@ -77,11 +77,14 @@ def test_should_generate_single_phase_pre_alloc_format(self):
},
)
- # Should not generate because it needs pre-alloc but we're in single phase
+ # Should not generate because it needs pre-alloc but we're in single
+ # phase
assert not format_selector.should_generate(format_with_pre_alloc)
def test_should_generate_phase2_with_pre_alloc_format(self):
- """Test phase 2 (after pre-alloc) with format that supports pre-alloc."""
+ """
+ Test phase 2 (after pre-alloc) with format that supports pre-alloc.
+ """
phase_manager = PhaseManager(
current_phase=FixtureFillingPhase.FILL,
previous_phases={FixtureFillingPhase.PRE_ALLOC_GENERATION},
@@ -166,8 +169,12 @@ def test_should_generate_labeled_format(self):
assert format_selector.should_generate(labeled_format)
def test_comprehensive_scenarios(self):
- """Test comprehensive scenarios covering all phase and format combinations."""
- # Test matrix: (current_phase, previous_phases, format_phases, generate_all) -> expected
+ """
+ Test comprehensive scenarios covering all phase and format
+ combinations.
+ """
+ # Test matrix: (current_phase, previous_phases, format_phases,
+ # generate_all) -> expected
test_cases: List[ # type: ignore[annotation-unchecked]
Tuple[
FixtureFillingPhase, Set[FixtureFillingPhase], Set[FixtureFillingPhase], bool, bool
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_generate_all_formats.py b/packages/tests/src/pytest_plugins/filler/tests/test_generate_all_formats.py
similarity index 87%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_generate_all_formats.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_generate_all_formats.py
index 8c39d01708..3f7a354333 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_generate_all_formats.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_generate_all_formats.py
@@ -4,7 +4,10 @@
def test_fixture_output_with_generate_all_formats():
- """Test that FixtureOutput properly handles the should_generate_all_formats parameter."""
+ """
+ Test that FixtureOutput properly handles the should_generate_all_formats
+ parameter.
+ """
# Test with should_generate_all_formats=True
fixture_output = FixtureOutput(
output_path="/tmp/test",
@@ -20,7 +23,10 @@ def test_fixture_output_with_generate_all_formats():
def test_fixture_output_from_config_includes_generate_all_formats():
- """Test that FixtureOutput.from_config includes the should_generate_all_formats option."""
+ """
+ Test that FixtureOutput.from_config includes the
+ should_generate_all_formats option.
+ """
# Mock pytest config object
class MockConfig:
@@ -43,7 +49,10 @@ def getoption(self, option):
def test_tarball_output_auto_enables_generate_all_formats():
- """Test that tarball output (.tar.gz) automatically enables should_generate_all_formats."""
+ """
+ Test that tarball output (.tar.gz) automatically enables
+ should_generate_all_formats.
+ """
# Mock pytest config object with tarball output
class MockConfig:
@@ -67,7 +76,10 @@ def getoption(self, option):
def test_regular_output_does_not_auto_enable_generate_all_formats():
- """Test that regular directory output doesn't auto-enable should_generate_all_formats."""
+ """
+ Test that regular directory output doesn't auto-enable
+ should_generate_all_formats.
+ """
# Mock pytest config object with regular output
class MockConfig:
@@ -91,7 +103,10 @@ def getoption(self, option):
def test_explicit_generate_all_formats_overrides_tarball_auto_enable():
- """Test that explicitly setting should_generate_all_formats=True works with tarball output."""
+ """
+ Test that explicitly setting should_generate_all_formats=True works with
+ tarball output.
+ """
# Mock pytest config object with tarball output and explicit flag
class MockConfig:
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_output_directory.py b/packages/tests/src/pytest_plugins/filler/tests/test_output_directory.py
similarity index 93%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_output_directory.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_output_directory.py
index 4eba64d88f..eca2cb1015 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_output_directory.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_output_directory.py
@@ -21,7 +21,10 @@ def test_function(state_test, pre):
@pytest.fixture
def minimal_test_path(pytester: pytest.Pytester) -> Path:
- """Minimal test file that's written to a file using pytester and ready to fill."""
+ """
+ Minimal test file that's written to a file using pytester and ready to
+ fill.
+ """
tests_dir = pytester.mkdir("tests")
test_file = tests_dir / MINIMAL_TEST_FILE_NAME
test_file.write_text(MINIMAL_TEST_CONTENTS)
@@ -48,7 +51,10 @@ def run_fill(
fill_fork_until: str,
default_t8n: TransitionTool,
):
- """Create a function to run the fill command with various output directory scenarios."""
+ """
+ Create a function to run the fill command with various output directory
+ scenarios.
+ """
def _run_fill(
output_dir: Path,
@@ -56,7 +62,10 @@ def _run_fill(
expect_failure: bool = False,
disable_capture_output: bool = False,
) -> pytest.RunResult:
- """Run the fill command with the specified output directory and clean flag."""
+ """
+ Run the fill command with the specified output directory and clean
+ flag.
+ """
pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini")
args = [
"-c",
@@ -141,7 +150,9 @@ def test_fill_to_nonempty_directory_with_clean(tmp_path_factory: TempPathFactory
def test_fill_to_directory_with_meta_fails(tmp_path_factory: TempPathFactory, run_fill):
- """Test filling to a directory with .meta subdirectory fails without --clean."""
+ """
+ Test filling to a directory with .meta subdirectory fails without --clean.
+ """
# Create a directory with .meta
output_dir = tmp_path_factory.mktemp("directory_with_meta")
meta_dir = output_dir / ".meta"
@@ -204,7 +215,9 @@ def test_fill_to_tarball_directory(tmp_path_factory: TempPathFactory, run_fill):
# New tests for the is_master functionality
def test_create_directories_skips_when_not_master():
- """Test that create_directories skips operations when not the master process."""
+ """
+ Test that create_directories skips operations when not the master process.
+ """
fixture_output = FixtureOutput(
output_path=Path("/fake/path"),
clean=True,
@@ -227,7 +240,10 @@ def test_create_directories_skips_when_not_master():
def test_create_directories_operates_when_master():
- """Test that create_directories performs operations when is the master process."""
+ """
+ Test that create_directories performs operations when is the master
+ process.
+ """
fixture_output = FixtureOutput(
output_path=Path("/fake/path"),
clean=True,
@@ -264,7 +280,8 @@ def test_create_directories_checks_empty_when_master():
patch.object(Path, "exists", return_value=True),
patch.object(Path, "mkdir"),
):
- # Call with is_master=True and expect an error about non-empty directory
+ # Call with is_master=True and expect an error about non-empty
+ # directory
with pytest.raises(ValueError, match="not empty"):
fixture_output.create_directories(is_master=True)
@@ -274,7 +291,10 @@ def test_create_directories_checks_empty_when_master():
def test_stdout_skips_directory_operations_regardless_of_master():
- """Test that stdout output skips directory operations regardless of is_master value."""
+ """
+ Test that stdout output skips directory operations regardless of is_master
+ value.
+ """
fixture_output = FixtureOutput(
output_path=Path("stdout"),
clean=True,
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_phase_manager.py b/packages/tests/src/pytest_plugins/filler/tests/test_phase_manager.py
similarity index 92%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_phase_manager.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_phase_manager.py
index e727b64154..6aa6e5fa7b 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_phase_manager.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_phase_manager.py
@@ -74,7 +74,7 @@ def test_from_config_use_pre_alloc(self):
assert not phase_manager.is_single_phase_fill
def test_from_config_generate_all_formats(self):
- """Test that generate_all_formats triggers PRE_ALLOC_GENERATION phase."""
+ """Generate_all_formats should trigger PRE_ALLOC_GENERATION phase."""
config = MockConfig(generate_all_formats=True)
phase_manager = PhaseManager.from_config(config)
@@ -94,7 +94,7 @@ def test_from_config_generate_all_and_pre_alloc(self):
assert phase_manager.is_pre_alloc_generation
def test_from_config_use_pre_alloc_with_generate_all(self):
- """Test phase 2 with generate_all_formats (passed by CLI to phase 2)."""
+ """Test phase 2 with generate_all_formats (passed by CLI)."""
config = MockConfig(use_pre_alloc_groups=True, generate_all_formats=True)
phase_manager = PhaseManager.from_config(config)
@@ -104,19 +104,27 @@ def test_from_config_use_pre_alloc_with_generate_all(self):
assert phase_manager.is_fill_after_pre_alloc
def test_all_flag_combinations(self):
- """Test all 8 possible flag combinations to ensure correct phase determination."""
+ """
+ Test all 8 possible flag combinations to ensure correct phase
+ determination.
+ """
test_cases = [
- # (generate_pre_alloc, use_pre_alloc, generate_all) -> (current_phase, has_previous)
- (False, False, False, FixtureFillingPhase.FILL, False), # Normal fill
+ # (generate_pre_alloc, use_pre_alloc, generate_all) ->
+ # (current_phase, has_previous)
+ # Normal fill
+ (False, False, False, FixtureFillingPhase.FILL, False),
# Generate all triggers phase 1
(False, False, True, FixtureFillingPhase.PRE_ALLOC_GENERATION, False),
(False, True, False, FixtureFillingPhase.FILL, True), # Phase 2
- (False, True, True, FixtureFillingPhase.FILL, True), # Phase 2 with generate all
+ # Phase 2 with generate all
+ (False, True, True, FixtureFillingPhase.FILL, True),
(True, False, False, FixtureFillingPhase.PRE_ALLOC_GENERATION, False), # Phase 1
# Phase 1 with generate all
(True, False, True, FixtureFillingPhase.PRE_ALLOC_GENERATION, False),
- (True, True, False, FixtureFillingPhase.FILL, True), # Invalid but use_pre_alloc wins
- (True, True, True, FixtureFillingPhase.FILL, True), # Invalid but use_pre_alloc wins
+ # Invalid but use_pre_alloc wins
+ (True, True, False, FixtureFillingPhase.FILL, True),
+ # Invalid but use_pre_alloc wins
+ (True, True, True, FixtureFillingPhase.FILL, True),
]
for gen_pre, use_pre, gen_all, expected_phase, has_previous in test_cases:
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_pre_alloc.py b/packages/tests/src/pytest_plugins/filler/tests/test_pre_alloc.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_pre_alloc.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_pre_alloc.py
index e7c09a6425..ba7b9290d4 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_pre_alloc.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_pre_alloc.py
@@ -5,6 +5,7 @@
import pytest
from ethereum_test_base_types import Address, TestPrivateKey, TestPrivateKey2
+from ethereum_test_forks import Fork, Prague
from ethereum_test_types import EOA
from ethereum_test_vm import EVMCodeType
from ethereum_test_vm import Opcodes as Op
@@ -18,7 +19,9 @@
def create_test_alloc(
- alloc_mode: AllocMode = AllocMode.PERMISSIVE, evm_code_type: EVMCodeType = EVMCodeType.LEGACY
+ alloc_mode: AllocMode = AllocMode.PERMISSIVE,
+ fork: Fork = Prague,
+ evm_code_type: EVMCodeType = EVMCodeType.LEGACY,
) -> Alloc:
"""Create a test Alloc instance with default iterators."""
contract_iter = iter(
@@ -33,6 +36,7 @@ def create_test_alloc(
alloc_mode=alloc_mode,
contract_address_iterator=contract_iter,
eoa_iterator=eoa_iter,
+ fork=fork,
evm_code_type=evm_code_type,
)
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group.py b/packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group.py
similarity index 98%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group.py
index dfceb93dcc..29e9da7c62 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group.py
@@ -232,7 +232,7 @@ class StateTest(FormattedTest): # noqa: D101
StateTestFiller,
Transaction
)
- from ethereum_test_tools.vm.opcode import Opcodes as Op
+ from ethereum_test_vm import Opcodes as Op
@pytest.mark.valid_from("Istanbul")
def test_chainid(state_test: StateTestFiller, pre: Alloc):
@@ -269,7 +269,7 @@ class BlockchainTest(FormattedTest): # noqa: D101
Environment,
Transaction
)
- from ethereum_test_tools.vm.opcode import Opcodes as Op
+ from ethereum_test_vm import Opcodes as Op
@pytest.mark.valid_from("Istanbul")
def test_chainid_blockchain(blockchain_test: BlockchainTestFiller, pre: Alloc):
@@ -412,7 +412,10 @@ def test_pre_alloc_grouping_by_test_type(
test_definitions: List[FormattedTest],
expected_different_pre_alloc_groups: int,
):
- """Test pre-alloc grouping when filling state tests, and the effect of the `state_test.env`."""
+ """
+ Test pre-alloc grouping when filling state tests, and the effect of the
+ `state_test.env`.
+ """
tests_dir = Path(pytester.mkdir("tests"))
for i, test in enumerate(test_definitions):
test_module = tests_dir / f"test_{i}.py"
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py b/packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py
similarity index 73%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py
index 508db25a68..6ffd67994a 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py
@@ -1,8 +1,8 @@
"""
Example usage of the pre_alloc_group marker.
-This file demonstrates how tests would use the marker in practice.
-Note: This is just documentation, not executable tests.
+This file demonstrates how tests would use the marker in practice. Note: This
+is just documentation, not executable tests.
"""
import pytest
@@ -13,9 +13,12 @@
"separate", reason="Deploys beacon root contract using actual hardcoded deployer address"
)
def test_beacon_root_contract_deployment():
- """Test beacon root contract deployment with the official deployer address."""
- # This test uses the actual beacon root deployer address (e.g., 0x4242...4242)
- # which could conflict with dynamically allocated addresses in other tests
+ """
+ Test beacon root contract deployment with the official deployer address.
+ """
+ # This test uses the actual beacon root deployer address (e.g.,
+ # 0x4242...4242) which could conflict with dynamically allocated addresses
+ # in other tests
pass
@@ -25,8 +28,9 @@ def test_beacon_root_contract_deployment():
)
def test_custom_consolidation_contract():
"""Test that deploys a modified consolidation contract."""
- # This test deploys a consolidation contract with custom bytecode that differs
- # from the standard implementation, requiring isolation from other consolidation tests
+ # This test deploys a consolidation contract with custom bytecode that
+ # differs from the standard implementation, requiring isolation from other
+ # consolidation tests
pass
@@ -36,8 +40,9 @@ def test_custom_consolidation_contract():
)
def test_custom_consolidation_edge_cases():
"""Test edge cases with the custom consolidation contract."""
- # This test can share the pre-allocation with test_custom_consolidation_contract
- # since they both use the same custom contract setup
+ # This test can share the pre-allocation with
+ # test_custom_consolidation_contract since they both use the same custom
+ # contract setup
pass
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py b/packages/tests/src/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py
similarity index 92%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py
index c5f3d012c1..67b0d43c5f 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py
@@ -6,7 +6,10 @@
def test_slow_marker_gets_pre_alloc_group(pytester, default_t8n: TransitionTool):
- """Test that slow tests without benchmark marker get pre_alloc_group automatically."""
+ """
+ Test that slow tests without benchmark marker get pre_alloc_group
+ automatically.
+ """
test_module = textwrap.dedent(
"""\
import pytest
@@ -49,7 +52,9 @@ def test_slow_without_benchmark(state_test: StateTestFiller, pre: Alloc):
def test_slow_with_benchmark_no_pre_alloc(pytester, default_t8n: TransitionTool):
- """Test that slow tests WITH benchmark marker do NOT get pre_alloc_group."""
+ """
+ Test that slow tests WITH benchmark marker do NOT get pre_alloc_group.
+ """
test_module = textwrap.dedent(
"""\
import pytest
@@ -92,7 +97,9 @@ def test_slow_with_benchmark(state_test: StateTestFiller, pre: Alloc):
def test_slow_with_existing_pre_alloc_unchanged(pytester, default_t8n: TransitionTool):
- """Test that slow tests with existing pre_alloc_group marker are unchanged."""
+ """
+ Test that slow tests with existing pre_alloc_group marker are unchanged.
+ """
test_module = textwrap.dedent(
"""\
import pytest
@@ -176,7 +183,9 @@ def test_normal_speed(state_test: StateTestFiller, pre: Alloc):
def test_integration_with_fill(pytester, default_t8n: TransitionTool):
- """Integration test using actual fill command to verify marker application."""
+ """
+ Integration test using actual fill command to verify marker application.
+ """
test_module = textwrap.dedent(
"""\
import pytest
@@ -221,10 +230,15 @@ def test_slow_for_integration(state_test: StateTestFiller, pre: Alloc):
"tests/cancun/slow_test_module/",
]
- # The test generates 3 formats (state_test, blockchain_test, blockchain_test_engine)
- # But it also runs on multiple forks (Cancun and Prague), so expect more tests
- # This is fine - the important thing is that they all pass
+ # The test generates 3 formats (state_test, blockchain_test,
+ # blockchain_test_engine).
+
+ # But it also runs on multiple forks (Cancun and
+ # Prague), so expect more tests.
+
+ # This is fine - the important thing is that they all pass.
result = pytester.runpytest(*args)
- # Verify that tests passed (don't care about exact count due to fork variations)
+ # Verify that tests passed (don't care about exact count due to fork
+ # variations)
assert result.ret == 0, "Fill command should succeed"
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_verify_sync_marker.py b/packages/tests/src/pytest_plugins/filler/tests/test_verify_sync_marker.py
similarity index 80%
rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_verify_sync_marker.py
rename to packages/tests/src/pytest_plugins/filler/tests/test_verify_sync_marker.py
index 2ecc167d62..83e7450dfb 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_verify_sync_marker.py
+++ b/packages/tests/src/pytest_plugins/filler/tests/test_verify_sync_marker.py
@@ -72,9 +72,12 @@ def test_verify_sync_marker(
Test blockchain sync fixture generation with verify_sync marker.
The test module has 3 test functions (4 test cases with parametrization):
- - test_verify_sync_default: generates all formats except sync (no verify_sync marker)
- - test_verify_sync_with_marker: generates all formats including sync (has verify_sync marker)
- - test_verify_sync_with_param_marks: tests parametrized marks with verify_sync (2 cases)
+ - test_verify_sync_default: generates all formats except sync
+ (no verify_sync marker)
+ - test_verify_sync_with_marker: generates all formats including sync
+ (has verify_sync marker)
+ - test_verify_sync_with_param_marks: tests parametrized marks with
+ verify_sync (2 cases)
Each test generates fixture formats:
- BlockchainFixture (always)
@@ -83,13 +86,15 @@ def test_verify_sync_marker(
Expected outcomes:
- 4 test cases total
- - Each generates BlockchainFixture (4) and BlockchainEngineFixture (4) = 8 fixtures
+ - Each generates BlockchainFixture (4) and BlockchainEngineFixture (4) =
+ 8 fixtures
+
- Sync fixtures:
- - test_verify_sync_with_marker: 1 sync fixture ✓
- - test_verify_sync_with_param_marks[no_exception]: 1 sync fixture ✓
- - Total sync fixtures: 2
- - Not generated (due to exception_test marker):
- - test_verify_sync_with_param_marks[with_exception]: sync fixture not generated
+ - test_verify_sync_with_marker: 1 sync fixture ✓
+ - test_verify_sync_with_param_marks[no_exception]: 1 sync fixture ✓
+ - Total sync fixtures: 2 - Not generated (due to exception_test marker):
+ - test_verify_sync_with_param_marks[with_exception]: sync fixture
+ not generated
Final counts:
- Passed: 8 (base fixtures) + 2 (sync fixtures) = 10 passed
diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/witness.py b/packages/tests/src/pytest_plugins/filler/witness.py
similarity index 85%
rename from src/ethereum_spec_tests/pytest_plugins/filler/witness.py
rename to packages/tests/src/pytest_plugins/filler/witness.py
index fc21e3dcee..fe88ab282c 100644
--- a/src/ethereum_spec_tests/pytest_plugins/filler/witness.py
+++ b/packages/tests/src/pytest_plugins/filler/witness.py
@@ -1,8 +1,9 @@
"""
Pytest plugin for witness functionality.
-Provides --witness command-line option that checks for the witness-filler tool in PATH
-and generates execution witness data for blockchain test fixtures when enabled.
+Provides --witness command-line option that checks for the witness-filler tool
+in PATH and generates execution witness data for blockchain test fixtures when
+enabled.
"""
import shutil
@@ -17,7 +18,9 @@
class WitnessFillerResult(EthereumTestRootModel[List[WitnessChunk]]):
- """Model that defines the expected result from the `witness-filler` command."""
+ """
+ Model that defines the expected result from the `witness-filler` command.
+ """
root: List[WitnessChunk]
@@ -26,9 +29,9 @@ class Merge(Paris):
"""
Paris fork that serializes as 'Merge' for witness-filler compatibility.
- IMPORTANT: This class MUST be named 'Merge' (not 'MergeForWitness' or similar)
- because the class name is used directly in Pydantic serialization, and
- witness-filler expects exactly 'Merge' for this fork.
+ IMPORTANT: This class MUST be named 'Merge' (not 'MergeForWitness' or
+ similar) because the class name is used directly in Pydantic serialization,
+ and witness-filler expects exactly 'Merge' for this fork.
"""
pass
@@ -54,7 +57,8 @@ def pytest_configure(config):
"""
Pytest hook called after command line options have been parsed.
- If --witness is enabled, checks that the witness-filler tool is available in PATH.
+ If --witness is enabled, checks that the witness-filler tool is available
+ in PATH.
"""
if config.getoption("witness"):
# Check if witness-filler binary is available in PATH
@@ -75,20 +79,22 @@ def witness_generator(
"""
Provide a witness generator function if --witness is enabled.
- Returns:
- None if witness functionality is disabled.
- Callable that generates witness data for a BlockchainFixture if enabled.
-
+ Returns: None if witness functionality is disabled. Callable that generates
+ witness data for a BlockchainFixture if enabled.
"""
if not request.config.getoption("witness"):
return None
def generate_witness(fixture: BlockchainFixture) -> None:
- """Generate witness data for a blockchain fixture using the witness-filler tool."""
+ """
+ Generate witness data for a blockchain fixture using the witness-filler
+ tool.
+ """
if not isinstance(fixture, BlockchainFixture):
return None
- # Hotfix: witness-filler expects "Merge" but execution-spec-tests uses "Paris"
+ # Hotfix: witness-filler expects "Merge" but execution-spec-tests uses
+ # "Paris"
original_fork = None
if fixture.fork is Paris:
original_fork = fixture.fork
diff --git a/src/ethereum_spec_tests/pytest_plugins/fix_package_test_path.py b/packages/tests/src/pytest_plugins/fix_package_test_path.py
similarity index 79%
rename from src/ethereum_spec_tests/pytest_plugins/fix_package_test_path.py
rename to packages/tests/src/pytest_plugins/fix_package_test_path.py
index a8503deeaa..c54580ee2f 100644
--- a/src/ethereum_spec_tests/pytest_plugins/fix_package_test_path.py
+++ b/packages/tests/src/pytest_plugins/fix_package_test_path.py
@@ -1,6 +1,6 @@
"""
-Pytest plugin to fix the test IDs for all pytest command that use a command-logic test
-file.
+Pytest plugin to fix the test IDs for all pytest command that use a
+command-logic test file.
"""
from typing import List
@@ -9,7 +9,10 @@
def pytest_collection_modifyitems(items: List[pytest.Item]):
- """Modify collected item names to remove the test runner function from the name."""
+ """
+ Modify collected item names to remove the test runner function from the
+ name.
+ """
for item in items:
original_name = item.originalname # type: ignore
remove = f"{original_name}["
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/__init__.py b/packages/tests/src/pytest_plugins/forks/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/forks/__init__.py
rename to packages/tests/src/pytest_plugins/forks/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/forks.py b/packages/tests/src/pytest_plugins/forks/forks.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/forks/forks.py
rename to packages/tests/src/pytest_plugins/forks/forks.py
index 6291951fec..52346f366f 100644
--- a/src/ethereum_spec_tests/pytest_plugins/forks/forks.py
+++ b/packages/tests/src/pytest_plugins/forks/forks.py
@@ -25,7 +25,7 @@
get_transition_forks,
transition_fork_to,
)
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
logger = get_logger(__name__)
@@ -87,10 +87,12 @@ def __init__(
Initialize a new fork parametrizer object for a given fork.
Args:
- fork: The fork for which the test cases will be parametrized.
- marks: A list of pytest marks to apply to all the test cases parametrized by the fork.
- fork_covariant_parameters: A list of fork covariant parameters for the test case, for
- unit testing purposes only.
+ fork: The fork for which the test cases will be parametrized.
+ marks: A list of pytest marks to apply to all the test cases
+ parametrized by the fork.
+ fork_covariant_parameters: A list of fork covariant parameters
+ for the test case, for unit testing
+ purposes only.
"""
if marks is None:
@@ -122,7 +124,8 @@ def argnames(self) -> List[str]:
def argvalues(self) -> List[ParameterSet]:
"""Return the parameter values for the test case."""
parameter_set_combinations = itertools.product(
- # Add the values for each parameter, all of them are lists of at least one element.
+ # Add the values for each parameter, all of them are lists of at
+ # least one element.
*[p.values for p in self.fork_covariant_parameters],
)
@@ -148,8 +151,8 @@ def argvalues(self) -> List[ParameterSet]:
class CovariantDescriptor:
"""
- A descriptor for a parameter that is covariant with the fork:
- the parametrized values change depending on the fork.
+ A descriptor for a parameter that is covariant with the fork: the
+ parametrized values change depending on the fork.
"""
argnames: List[str] = []
@@ -175,11 +178,13 @@ def __init__(
Initialize a new covariant descriptor.
Args:
- argnames: The names of the parameters that are covariant with the fork.
- fn: A function that takes the fork as the single parameter and returns the values for
- the parameter for each fork.
- selector: A function that filters the values for the parameter.
- marks: A list of pytest marks to apply to the test cases parametrized by the parameter.
+ argnames: The names of the parameters that are covariant with the
+ fork.
+ fn: A function that takes the fork as the single parameter and
+ returns the values for the parameter for each fork.
+ selector: A function that filters the values for the parameter.
+ marks: A list of pytest marks to apply to the test cases
+ parametrized by the parameter.
"""
self.argnames = (
@@ -226,8 +231,8 @@ def process_values(self, values: Iterable[Any]) -> List[ParameterSet]:
"""
Filter the values for the covariant parameter.
- I.e. if the marker has an argument, the argument is interpreted as a lambda function
- that filters the values.
+ I.e. if the marker has an argument, the argument is interpreted as a
+ lambda function that filters the values.
"""
processed_values: List[ParameterSet] = []
for value in values:
@@ -251,18 +256,21 @@ def add_values(self, fork_parametrizer: ForkParametrizer) -> None:
class CovariantDecorator(CovariantDescriptor):
"""
- A marker used to parametrize a function by a covariant parameter with the values
- returned by a fork method.
+ A marker used to parametrize a function by a covariant parameter with the
+ values returned by a fork method.
- The decorator must be subclassed with the appropriate class variables before initialization.
+ The decorator must be subclassed with the appropriate class variables
+ before initialization.
Attributes:
- marker_name: Name of the marker.
- description: Description of the marker.
- fork_attribute_name: Name of the method to call on the fork to get the values.
- marker_parameter_names: Names of the parameters to be parametrized in the test function.
- indirect: Whether the parameters should be passed through fixtures (indirect
- parametrization).
+ marker_name: Name of the marker.
+ description: Description of the marker.
+ fork_attribute_name: Name of the method to call on the fork to
+ get the values.
+ marker_parameter_names: Names of the parameters to be parametrized
+ in the test function.
+ indirect: Whether the parameters should be passed through fixtures
+ (indirect parametrization).
"""
@@ -276,11 +284,12 @@ def __init__(self, metafunc: Metafunc):
"""
Initialize the covariant decorator.
- The decorator must already be subclassed with the appropriate class variables before
- initialization.
+ The decorator must already be subclassed with the appropriate class
+ variables before initialization.
Args:
- metafunc: The metafunc object that pytest uses when generating tests.
+ metafunc: The metafunc object that pytest uses when generating
+ tests.
"""
self.metafunc = metafunc
@@ -408,7 +417,8 @@ def pytest_configure(config: pytest.Config):
Register the plugin's custom markers and process command-line options.
Custom marker registration:
- https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers
+ https://docs.pytest.org/en/7.1.x/how-to/
+ writing_plugins.html# registering-custom-markers
"""
config.addinivalue_line(
"markers",
@@ -533,6 +543,8 @@ def get_fork_option(config, option_name: str, parameter_name: str) -> Set[Fork]:
@pytest.hookimpl(trylast=True)
def pytest_report_header(config, start_path):
"""Pytest hook called to obtain the report header."""
+ del start_path
+
bold = "\033[1m"
warning = "\033[93m"
reset = "\033[39;49m"
@@ -563,7 +575,10 @@ def fork(request):
@pytest.fixture(scope="session")
def session_fork(request: pytest.FixtureRequest) -> Fork | None:
- """Session-wide fork object used if the plugin is configured in single-fork mode."""
+ """
+ Session-wide fork object used if the plugin is configured in single-fork
+ mode.
+ """
if hasattr(request.config, "single_fork_mode") and request.config.single_fork_mode:
return list(request.config.selected_fork_set)[0] # type: ignore
raise AssertionError(
@@ -582,12 +597,14 @@ class ValidityMarker(ABC):
Subclassing this class allows for the creation of new validity markers.
- Instantiation must be done per test function, and the `process` method must be called to
- process the fork arguments.
+ Instantiation must be done per test function, and the `process` method must
+ be called to process the fork arguments.
When subclassing, the following optional parameters can be set:
- - marker_name: Name of the marker, if not set, the class name is converted to underscore.
- - mutually_exclusive: List of other marker types incompatible with this one.
+ - marker_name: Name of the marker, if not set, the class name is
+ converted to underscore.
+ - mutually_exclusive: List of other marker types incompatible
+ with this one.
- flag: Whether the marker is a flag and should always be included.
"""
@@ -607,7 +624,8 @@ def __init_subclass__(
"""Register the validity marker subclass."""
super().__init_subclass__(**kwargs)
if marker_name is None:
- # Use the class name converted to underscore: https://stackoverflow.com/a/1176023
+ # Use the class name converted to underscore:
+ # https://stackoverflow.com/a/1176023
marker_name = MARKER_NAME_REGEX.sub("_", cls.__name__).lower()
cls.marker_name = marker_name
cls.mutually_exclusive = mutually_exclusive if mutually_exclusive else []
@@ -659,14 +677,18 @@ def get_all_validity_markers(markers: Iterator[pytest.Mark]) -> List["ValidityMa
@staticmethod
def get_test_fork_set(validity_markers: List["ValidityMarker"]) -> Set[Fork]:
- """Get the set of forks where a test is valid from the validity markers and filters."""
+ """
+ Get the set of forks where a test is valid from the validity markers
+ and filters.
+ """
if not len(
[validity_marker for validity_marker in validity_markers if not validity_marker.flag]
):
# Limit to non-transition forks if no validity markers were applied
test_fork_set = set(ALL_FORKS)
else:
- # Start with all forks and transitions if any validity markers were applied
+ # Start with all forks and transitions if any validity markers were
+ # applied
test_fork_set = set(ALL_FORKS_WITH_TRANSITIONS)
for v in validity_markers:
@@ -677,14 +699,20 @@ def get_test_fork_set(validity_markers: List["ValidityMarker"]) -> Set[Fork]:
@staticmethod
def get_test_fork_set_from_markers(markers: Iterator[pytest.Mark]) -> Set[Fork]:
- """Get the set of forks where a test is valid using the markers applied to the test."""
+ """
+ Get the set of forks where a test is valid using the markers applied to
+ the test.
+ """
return ValidityMarker.get_test_fork_set(ValidityMarker.get_all_validity_markers(markers))
@staticmethod
def get_test_fork_set_from_metafunc(
metafunc: Metafunc,
) -> Set[Fork]:
- """Get the set of forks where a test is valid using its pytest meta-function."""
+ """
+ Get the set of forks where a test is valid using its pytest
+ meta-function.
+ """
return ValidityMarker.get_test_fork_set_from_markers(metafunc.definition.iter_markers())
@staticmethod
@@ -709,16 +737,17 @@ def _process_with_marker_args(self, *args, **kwargs) -> Set[Fork]:
Method must be implemented by the subclass.
- If the validity marker is of flag type, the returned forks will be subtracted from the
- fork set, otherwise the returned forks will be intersected with the current set.
+ If the validity marker is of flag type, the returned forks will be
+ subtracted from the fork set, otherwise the returned forks will be
+ intersected with the current set.
"""
pass
class ValidFrom(ValidityMarker):
"""
- Marker used to specify the fork from which the test is valid. The test will not be filled for
- forks before the specified fork.
+ Marker used to specify the fork from which the test is valid. The test will
+ not be filled for forks before the specified fork.
```python
import pytest
@@ -733,8 +762,8 @@ def test_something_only_valid_after_london(
pass
```
- In this example, the test will only be filled for the London fork and after, e.g. London,
- Paris, Shanghai, Cancun, etc.
+ In this example, the test will only be filled for the London fork and
+ after, e.g. London, Paris, Shanghai, Cancun, etc.
"""
def _process_with_marker_args(self, *fork_args) -> Set[Fork]:
@@ -748,8 +777,8 @@ def _process_with_marker_args(self, *fork_args) -> Set[Fork]:
class ValidUntil(ValidityMarker):
"""
- Marker to specify the fork until which the test is valid. The test will not be filled for
- forks after the specified fork.
+ Marker to specify the fork until which the test is valid. The test will not
+ be filled for forks after the specified fork.
```python
import pytest
@@ -764,8 +793,8 @@ def test_something_only_valid_until_london(
pass
```
- In this example, the test will only be filled for the London fork and before, e.g. London,
- Berlin, Istanbul, etc.
+ In this example, the test will only be filled for the London fork and
+ before, e.g. London, Berlin, Istanbul, etc.
"""
def _process_with_marker_args(self, *fork_args) -> Set[Fork]:
@@ -794,7 +823,8 @@ def test_something_only_valid_at_london_and_cancun(
pass
```
- In this example, the test will only be filled for the London and Cancun forks.
+ In this example, the test will only be filled for the London and Cancun
+ forks.
"""
def _process_with_marker_args(self, *fork_args) -> Set[Fork]:
@@ -804,11 +834,12 @@ def _process_with_marker_args(self, *fork_args) -> Set[Fork]:
class ValidAtTransitionTo(ValidityMarker, mutually_exclusive=[ValidAt, ValidFrom, ValidUntil]):
"""
- Marker to specify that a test is only meant to be filled at the transition to the specified
- fork.
+ Marker to specify that a test is only meant to be filled at the transition
+ to the specified fork.
- The test usually starts at the fork prior to the specified fork at genesis and at block 5 (for
- pre-merge forks) or at timestamp 15,000 (for post-merge forks) the fork transition occurs.
+ The test usually starts at the fork prior to the specified fork at genesis
+ and at block 5 (for pre-merge forks) or at timestamp 15,000 (for post-merge
+ forks) the fork transition occurs.
```python
import pytest
@@ -823,36 +854,40 @@ def test_something_that_happens_during_the_fork_transition_to_london(
pass
```
- In this example, the test will only be filled for the fork that transitions to London at block
- number 5, `BerlinToLondonAt5`, and no other forks.
+ In this example, the test will only be filled for the fork that transitions
+ to London at block number 5, `BerlinToLondonAt5`, and no other forks.
- To see or add a new transition fork, see the `ethereum_test_forks.forks.transition` module.
+ To see or add a new transition fork, see the
+ `ethereum_test_forks.forks.transition` module.
- Note that the test uses a `BlockchainTestFiller` fixture instead of a `StateTestFiller`,
- as the transition forks are used to test changes throughout the blockchain progression, and
- not just the state change of a single transaction.
+ Note that the test uses a `BlockchainTestFiller` fixture instead of a
+ `StateTestFiller`, as the transition forks are used to test changes
+ throughout the blockchain progression, and not just the state change of a
+ single transaction.
This marker also accepts the following keyword arguments:
- - `subsequent_transitions`: Force the test to also fill for subsequent fork transitions.
- - `until`: Implies `subsequent_transitions` and puts a limit on which transition fork will the
- test filling will be limited to.
+ - `subsequent_transitions`: Force the test to also fill for subsequent fork
+ transitions.
+ - `until`: Implies `subsequent_transitions` and puts a limit
+ on which transition fork will the test filling will be limited to.
For example:
```python
@pytest.mark.valid_at_transition_to("Cancun", subsequent_transitions=True)
```
- produces tests on `ShanghaiToCancunAtTime15k` and `CancunToPragueAtTime15k`, and any transition
- fork after that.
+ produces tests on `ShanghaiToCancunAtTime15k` and
+ `CancunToPragueAtTime15k`, and any transition fork after that.
And:
```python
- @pytest.mark.valid_at_transition_to("Cancun", subsequent_transitions=True, until="Prague")
+ @pytest.mark.valid_at_transition_to("Cancun",
+ subsequent_transitions=True, until="Prague")
```
- produces tests on `ShanghaiToCancunAtTime15k` and `CancunToPragueAtTime15k`, but no forks after
- Prague.
+ produces tests on `ShanghaiToCancunAtTime15k` and
+ `CancunToPragueAtTime15k`, but no forks after Prague.
"""
def _process_with_marker_args(
@@ -982,7 +1017,10 @@ def pytest_generate_tests(metafunc: pytest.Metafunc):
def add_fork_covariant_parameters(
metafunc: Metafunc, fork_parametrizers: List[ForkParametrizer]
) -> None:
- """Iterate over the fork covariant descriptors and add their values to the test function."""
+ """
+ Iterate over the fork covariant descriptors and add their values to the
+ test function.
+ """
# Process all covariant decorators uniformly
for covariant_descriptor in fork_covariant_decorators:
if list(metafunc.definition.iter_markers(covariant_descriptor.marker_name)):
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/__init__.py b/packages/tests/src/pytest_plugins/forks/tests/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/__init__.py
rename to packages/tests/src/pytest_plugins/forks/tests/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_command_line_options.py b/packages/tests/src/pytest_plugins/forks/tests/test_bad_command_line_options.py
similarity index 88%
rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_command_line_options.py
rename to packages/tests/src/pytest_plugins/forks/tests/test_bad_command_line_options.py
index 3799dbb570..5d45dd2427 100644
--- a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_command_line_options.py
+++ b/packages/tests/src/pytest_plugins/forks/tests/test_bad_command_line_options.py
@@ -1,6 +1,5 @@
"""
-Test that the correct error is produced if bad/invalid command-line
-arguments are used.
+Test the correct error is produced with bad/invalid command-line arguments.
"""
import pytest
@@ -59,11 +58,11 @@
def test_bad_options(pytester, options, error_string):
"""
Test that a test with an invalid command-line options:
- - Creates an outcome with exactly one error.
- - Triggers the expected error string in pytest's console output.
+ - Creates an outcome with exactly one error.
+ - Triggers the expected error string in pytest's console output.
- Each invalid marker/marker combination is tested with one test in its own test
- session.
+ Each invalid marker/marker combination is tested with one test in its own
+ test session.
"""
pytester.makepyfile(
"""
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_validity_markers.py b/packages/tests/src/pytest_plugins/forks/tests/test_bad_validity_markers.py
similarity index 96%
rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_validity_markers.py
rename to packages/tests/src/pytest_plugins/forks/tests/test_bad_validity_markers.py
index 7aea95220c..1e33c30aed 100644
--- a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_validity_markers.py
+++ b/packages/tests/src/pytest_plugins/forks/tests/test_bad_validity_markers.py
@@ -1,4 +1,6 @@
-"""Test that the correct error is produced if bad/invalid validity markers are specified."""
+"""
+Test the correct error is produced with bad/invalid validity markers.
+"""
import pytest
@@ -214,11 +216,11 @@ def test_case(state_test):
def test_invalid_validity_markers(pytester, error_string, test_function):
"""
Test that a test with an invalid marker cases:
- - Creates an outcome with exactly one error.
- - Triggers the expected error string in pytest's console output.
+ - Creates an outcome with exactly one error.
+ - Triggers the expected error string in pytest's console output.
- Each invalid marker/marker combination is tested with one test in its own test
- session.
+ Each invalid marker/marker combination is tested with one test in its own
+ test session.
"""
pytester.makepyfile(test_function)
pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini")
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_covariant_markers.py b/packages/tests/src/pytest_plugins/forks/tests/test_covariant_markers.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_covariant_markers.py
rename to packages/tests/src/pytest_plugins/forks/tests/test_covariant_markers.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_fork_parametrizer_types.py b/packages/tests/src/pytest_plugins/forks/tests/test_fork_parametrizer_types.py
similarity index 98%
rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_fork_parametrizer_types.py
rename to packages/tests/src/pytest_plugins/forks/tests/test_fork_parametrizer_types.py
index e655b46605..94d6eb5eb1 100644
--- a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_fork_parametrizer_types.py
+++ b/packages/tests/src/pytest_plugins/forks/tests/test_fork_parametrizer_types.py
@@ -188,7 +188,9 @@ def test_fork_parametrizer(
expected_names: List[str],
expected_parameter_sets: List[ParameterSet],
):
- """Test that the fork parametrizer correctly parametrizes tests based on the fork name."""
+ """
+ Test the fork parametrizer correctly parametrizes using the fork name.
+ """
argnames, values = parameters_from_fork_parametrizer_list(fork_parametrizers)
assert argnames == expected_names
assert len(values) == len(expected_parameter_sets)
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_forks.py b/packages/tests/src/pytest_plugins/forks/tests/test_forks.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_forks.py
rename to packages/tests/src/pytest_plugins/forks/tests/test_forks.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_markers.py b/packages/tests/src/pytest_plugins/forks/tests/test_markers.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_markers.py
rename to packages/tests/src/pytest_plugins/forks/tests/test_markers.py
diff --git a/packages/tests/src/pytest_plugins/help/__init__.py b/packages/tests/src/pytest_plugins/help/__init__.py
new file mode 100644
index 0000000000..2e861b4d85
--- /dev/null
+++ b/packages/tests/src/pytest_plugins/help/__init__.py
@@ -0,0 +1,3 @@
+"""
+Pytest plugin that prints help defined in other execution-spec-tests plugins.
+"""
diff --git a/src/ethereum_spec_tests/pytest_plugins/help/help.py b/packages/tests/src/pytest_plugins/help/help.py
similarity index 96%
rename from src/ethereum_spec_tests/pytest_plugins/help/help.py
rename to packages/tests/src/pytest_plugins/help/help.py
index b70c0357a5..808584e314 100644
--- a/src/ethereum_spec_tests/pytest_plugins/help/help.py
+++ b/packages/tests/src/pytest_plugins/help/help.py
@@ -65,7 +65,9 @@ def pytest_addoption(parser):
@pytest.hookimpl(tryfirst=True)
def pytest_configure(config):
- """Handle specific help flags by displaying the corresponding help message."""
+ """
+ Handle specific help flags by displaying the corresponding help message.
+ """
if config.getoption("show_check_eip_versions_help"):
show_specific_help(
config,
@@ -143,7 +145,10 @@ def pytest_configure(config):
def show_specific_help(config, expected_ini, substrings):
- """Print help options filtered by specific substrings from the given configuration."""
+ """
+ Print help options filtered by specific substrings from the given
+ configuration.
+ """
pytest_ini = Path(config.inifile)
if pytest_ini.name != expected_ini:
raise ValueError(
diff --git a/src/ethereum_spec_tests/pytest_plugins/help/tests/test_help.py b/packages/tests/src/pytest_plugins/help/tests/test_help.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/help/tests/test_help.py
rename to packages/tests/src/pytest_plugins/help/tests/test_help.py
index 9b7b45ae6c..3ed648720b 100644
--- a/src/ethereum_spec_tests/pytest_plugins/help/tests/test_help.py
+++ b/packages/tests/src/pytest_plugins/help/tests/test_help.py
@@ -18,8 +18,8 @@
@pytest.mark.parametrize("help_flag", ["--fill-help"])
def test_local_arguments_present_in_fill_help(pytester, help_flag):
"""
- Test that locally defined command-line flags appear in the help if
- our custom help flag is used.
+ Test that locally defined command-line flags appear in the help if our
+ custom help flag is used.
"""
pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini")
result = pytester.runpytest("-c", "pytest-fill.ini", help_flag)
@@ -43,7 +43,10 @@ def test_local_arguments_present_in_fill_help(pytester, help_flag):
],
)
def test_local_arguments_present_in_base_consume_help(pytester, help_flag, command):
- """Test that locally defined command-line flags appear in the help for consume subcommands."""
+ """
+ Test that locally defined command-line flags appear in the help for consume
+ subcommands.
+ """
pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-consume.ini")
result = pytester.runpytest("-c", "pytest-consume.ini", command, help_flag)
for test_arg in CONSUME_TEST_ARGS:
diff --git a/src/ethereum_spec_tests/pytest_plugins/py.typed b/packages/tests/src/pytest_plugins/py.typed
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/py.typed
rename to packages/tests/src/pytest_plugins/py.typed
diff --git a/src/ethereum_spec_tests/pytest_plugins/pytest_hive/hive_info.py b/packages/tests/src/pytest_plugins/pytest_hive/hive_info.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/pytest_hive/hive_info.py
rename to packages/tests/src/pytest_plugins/pytest_hive/hive_info.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/pytest_hive/pytest_hive.py b/packages/tests/src/pytest_plugins/pytest_hive/pytest_hive.py
similarity index 89%
rename from src/ethereum_spec_tests/pytest_plugins/pytest_hive/pytest_hive.py
rename to packages/tests/src/pytest_plugins/pytest_hive/pytest_hive.py
index fb29cf3345..b1624391ef 100644
--- a/src/ethereum_spec_tests/pytest_plugins/pytest_hive/pytest_hive.py
+++ b/packages/tests/src/pytest_plugins/pytest_hive/pytest_hive.py
@@ -10,23 +10,28 @@
Log Capture Architecture:
-------------------------
-This module implements a log capture approach that ensures all logs, including those
-generated during fixture teardown, are properly captured and included in the test results.
-
-The key insight is that we need to ensure that test finalization happens *before* the
-test suite is finalized, but *after* all fixtures have been torn down so we can capture
-their logs. This is accomplished through the fixture teardown mechanism in pytest:
-
-1. Since the `hive_test` fixture depends on the `test_suite` fixture, pytest guarantees
- that the teardown of `hive_test` runs before the teardown of `test_suite`
-2. All logs are processed and the test is finalized in the teardown phase of the
- `hive_test` fixture using the pytest test report data
-3. This sequencing ensures that all logs are captured and the test is properly finalized
- before its parent test suite is finalized
-
-This approach relies on the pytest fixture dependency graph and teardown ordering to
-ensure proper sequencing, which is more reliable than using hooks which might run in
-an unpredictable order relative to fixture teardown.
+This module implements a log capture approach that ensures all logs,
+including those generated during fixture teardown, are properly
+captured and included in the test results.
+
+The key insight is that we need to ensure that test finalization happens
+*before* the test suite is finalized, but *after* all fixtures have been torn
+down so we can capture their logs. This is accomplished through the fixture
+teardown mechanism in pytest:
+
+1. Since the `hive_test` fixture depends on the `test_suite` fixture, pytest
+guarantees that the teardown of `hive_test` runs before the teardown of
+`test_suite`
+
+2. All logs are processed and the test is finalized in the
+teardown phase of the `hive_test` fixture using the pytest test report data
+
+3. This sequencing ensures that all logs are captured and the test is properly
+finalized before its parent test suite is finalized
+
+This approach relies on the pytest fixture dependency graph and teardown
+ordering to ensure proper sequencing, which is more reliable than using hooks
+which might run in an unpredictable order relative to fixture teardown.
"""
import json
@@ -41,7 +46,7 @@
from hive.simulation import Simulation
from hive.testing import HiveTest, HiveTestResult, HiveTestSuite
-from ..logging import get_logger
+from ..custom_logging import get_logger
from .hive_info import ClientFile, HiveInfo
logger = get_logger(__name__)
@@ -59,8 +64,8 @@ def pytest_configure(config): # noqa: D103
"or in fish:\n"
"set -x HIVE_SIMULATOR http://127.0.0.1:3000"
)
- # TODO: Try and get these into fixtures; this is only here due to the "dynamic" parametrization
- # of client_type with hive_execution_clients.
+ # TODO: Try and get these into fixtures; this is only here due to the
+ # "dynamic" parametrization of client_type with hive_execution_clients.
config.hive_simulator_url = hive_simulator_url
config.hive_simulator = Simulation(url=hive_simulator_url)
try:
@@ -111,6 +116,8 @@ def get_hive_info(simulator: Simulation) -> HiveInfo | None:
@pytest.hookimpl(trylast=True)
def pytest_report_header(config, start_path):
"""Add lines to pytest's console output header."""
+ del start_path
+
if config.option.collectonly:
return
header_lines = [f"hive simulator: {config.hive_simulator_url}"]
@@ -131,8 +138,8 @@ def pytest_report_header(config, start_path):
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
"""
- Make the setup, call, and teardown results available in the teardown phase of
- a test fixture (i.e., after yield has been called).
+ Make the setup, call, and teardown results available in the teardown phase
+ of a test fixture (i.e., after yield has been called).
This is used to get the test result and pass it to the hive test suite.
@@ -141,6 +148,8 @@ def pytest_runtest_makereport(item, call):
- result_call - test result
- result_teardown - teardown result
"""
+ del call
+
outcome = yield
report = outcome.get_result()
setattr(item, f"result_{report.when}", report)
@@ -172,6 +181,8 @@ def get_test_suite_scope(fixture_name, config: pytest.Config):
See: https://docs.pytest.org/en/stable/how-to/fixtures.html#dynamic-scope
"""
+ del fixture_name
+
if hasattr(config, "test_suite_scope"):
return config.test_suite_scope
return "module"
@@ -232,10 +243,11 @@ def hive_test(request, test_suite: HiveTestSuite):
"""
Propagate the pytest test case and its result to the hive server.
- This fixture handles both starting the test and ending it with all logs, including
- those generated during teardown of other fixtures. The approach of processing teardown
- logs directly in the teardown phase of this fixture ensures that the test gets properly
- finalized before the test suite is torn down.
+ This fixture handles both starting the test and ending it with all logs,
+ including those generated during teardown of other fixtures. The approach
+ of processing teardown logs directly in the teardown phase of this fixture
+ ensures that the test gets properly finalized before the test suite is torn
+ down.
"""
try:
test_case_description = request.getfixturevalue("test_case_description")
diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/benchmarking.py b/packages/tests/src/pytest_plugins/shared/benchmarking.py
similarity index 91%
rename from src/ethereum_spec_tests/pytest_plugins/shared/benchmarking.py
rename to packages/tests/src/pytest_plugins/shared/benchmarking.py
index 6f19877665..c5688476b3 100644
--- a/src/ethereum_spec_tests/pytest_plugins/shared/benchmarking.py
+++ b/packages/tests/src/pytest_plugins/shared/benchmarking.py
@@ -55,7 +55,10 @@ def gas_benchmark_value(request: pytest.FixtureRequest) -> int:
@pytest.fixture
def genesis_environment(request: pytest.FixtureRequest) -> Environment: # noqa: D103
- """Return an Environment instance with appropriate gas limit based on test type."""
+ """
+ Return an Environment instance with appropriate gas limit based on test
+ type.
+ """
if request.node.get_closest_marker("benchmark") is not None:
return Environment(gas_limit=BENCHMARKING_MAX_GAS)
return Environment()
@@ -63,7 +66,10 @@ def genesis_environment(request: pytest.FixtureRequest) -> Environment: # noqa:
@pytest.fixture
def env(request: pytest.FixtureRequest) -> Environment: # noqa: D103
- """Return an Environment instance with appropriate gas limit based on test type."""
+ """
+ Return an Environment instance with appropriate gas limit based on test
+ type.
+ """
if request.node.get_closest_marker("benchmark") is not None:
return Environment(gas_limit=BENCHMARKING_MAX_GAS)
return Environment()
diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/execute_fill.py b/packages/tests/src/pytest_plugins/shared/execute_fill.py
similarity index 90%
rename from src/ethereum_spec_tests/pytest_plugins/shared/execute_fill.py
rename to packages/tests/src/pytest_plugins/shared/execute_fill.py
index d5330f4bf8..e1f91d55a4 100644
--- a/src/ethereum_spec_tests/pytest_plugins/shared/execute_fill.py
+++ b/packages/tests/src/pytest_plugins/shared/execute_fill.py
@@ -1,4 +1,6 @@
-"""Shared pytest fixtures and hooks for EEST generation modes (fill and execute)."""
+"""
+Shared pytest fixtures and hooks for EEST generation modes (fill and execute).
+"""
from typing import List
@@ -13,15 +15,17 @@
from ..spec_version_checker.spec_version_checker import EIPSpecTestItem
ALL_FIXTURE_PARAMETERS = {
+ "gas_benchmark_value",
"genesis_environment",
"env",
}
"""
-List of test parameters that have a default fixture value which can be retrieved and used
-for the test instance if it was not explicitly specified when calling from the test
-function.
+List of test parameters that have a default fixture value which can be
+retrieved and used for the test instance if it was not explicitly specified
+when calling from the test function.
-All parameter names included in this list must define a fixture in one of the plugins.
+All parameter names included in this list must define a fixture in one of the
+plugins.
"""
@@ -34,12 +38,12 @@ def pytest_configure(config: pytest.Config):
Couple of notes:
1. Register the plugin's custom markers and process command-line options.
- Custom marker registration:
- https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers
+ Custom marker registration:
+ https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers
2. `@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is
- called before the pytest-html plugin's pytest_configure to ensure that
- it uses the modified `htmlpath` option.
+ called before the pytest-html plugin's pytest_configure to ensure that
+ it uses the modified `htmlpath` option.
"""
if config.pluginmanager.has_plugin("pytest_plugins.filler.filler"):
for fixture_format in BaseFixture.formats.values():
@@ -96,6 +100,10 @@ def pytest_configure(config: pytest.Config):
"markers",
"benchmark: Tests relevant to benchmarking EVMs.",
)
+ config.addinivalue_line(
+ "markers",
+ "stateful: Tests for stateful benchmarking scenarios.",
+ )
config.addinivalue_line(
"markers",
"exception_test: Negative tests that include an invalid block or transaction.",
@@ -153,7 +161,10 @@ def pytest_configure(config: pytest.Config):
@pytest.fixture(scope="function")
def test_case_description(request: pytest.FixtureRequest) -> str:
- """Fixture to extract and combine docstrings from the test class and the test function."""
+ """
+ Fixture to extract and combine docstrings from the test class and the test
+ function.
+ """
description_unavailable = (
"No description available - add a docstring to the python test class or function."
)
@@ -171,9 +182,10 @@ def test_case_description(request: pytest.FixtureRequest) -> str:
def pytest_make_parametrize_id(config: pytest.Config, val: str, argname: str):
"""
- Pytest hook called when generating test ids. We use this to generate
- more readable test ids for the generated tests.
+ Pytest hook called when generating test ids. We use this to generate more
+ readable test ids for the generated tests.
"""
+ del config
return f"{argname}_{val}"
diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/helpers.py b/packages/tests/src/pytest_plugins/shared/helpers.py
similarity index 96%
rename from src/ethereum_spec_tests/pytest_plugins/shared/helpers.py
rename to packages/tests/src/pytest_plugins/shared/helpers.py
index bbe720b652..3c55d59376 100644
--- a/src/ethereum_spec_tests/pytest_plugins/shared/helpers.py
+++ b/packages/tests/src/pytest_plugins/shared/helpers.py
@@ -30,11 +30,11 @@ def labeled_format_parameter_set(
| FixtureFormat,
) -> ParameterSet:
"""
- Return a parameter set from a fixture/execute format and parses a label if there's
- any.
+ Return a parameter set from a fixture/execute format and parses a label if
+ there's any.
- The label will be used in the test id and also will be added as a marker to the
- generated test case when filling/executing the test.
+ The label will be used in the test id and also will be added as a marker to
+ the generated test case when filling/executing the test.
"""
if isinstance(format_with_or_without_label, LabeledExecuteFormat) or isinstance(
format_with_or_without_label, LabeledFixtureFormat
diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/transaction_fixtures.py b/packages/tests/src/pytest_plugins/shared/transaction_fixtures.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/shared/transaction_fixtures.py
rename to packages/tests/src/pytest_plugins/shared/transaction_fixtures.py
index be3b16a6d6..cfe0cd6ef5 100644
--- a/src/ethereum_spec_tests/pytest_plugins/shared/transaction_fixtures.py
+++ b/packages/tests/src/pytest_plugins/shared/transaction_fixtures.py
@@ -125,10 +125,12 @@ def type_4_default_transaction(sender, pre):
@pytest.fixture
def typed_transaction(request, fork):
"""
- Fixture that provides a Transaction object based on the parametrized tx type.
+ Fixture that provides a Transaction object based on the parametrized tx
+ type.
- This fixture works with the @pytest.mark.with_all_typed_transactions marker,
- which parametrizes the test with all transaction types supported by the fork.
+ This fixture works with the @pytest.mark.with_all_typed_transactions
+ marker, which parametrizes the test with all transaction types supported by
+ the fork.
The actual transaction type value comes from the marker's parametrization.
"""
diff --git a/src/ethereum_spec_tests/pytest_plugins/solc/__init__.py b/packages/tests/src/pytest_plugins/solc/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/solc/__init__.py
rename to packages/tests/src/pytest_plugins/solc/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/solc/solc.py b/packages/tests/src/pytest_plugins/solc/solc.py
similarity index 97%
rename from src/ethereum_spec_tests/pytest_plugins/solc/solc.py
rename to packages/tests/src/pytest_plugins/solc/solc.py
index f134a45a7a..692c5237c9 100644
--- a/src/ethereum_spec_tests/pytest_plugins/solc/solc.py
+++ b/packages/tests/src/pytest_plugins/solc/solc.py
@@ -85,7 +85,8 @@ def pytest_configure(config: pytest.Config):
# Extract version number
try:
- # --version format is typically something like "0.8.24+commit.e11b9ed9.Linux.g++"
+ # --version format is typically something like
+ # "0.8.24+commit.e11b9ed9.Linux.g++"
version_str = version_line.split()[1].split("+")[0]
solc_version_semver = Version.parse(version_str)
except (IndexError, ValueError) as e:
@@ -128,6 +129,8 @@ def solc_bin(request: pytest.FixtureRequest):
@pytest.hookimpl(trylast=True)
def pytest_report_header(config, start_path):
"""Add lines to pytest's console output header."""
+ del start_path
+
if config.option.collectonly:
return
solc_version = config.stash[metadata_key]["Tools"]["solc"]
diff --git a/src/ethereum_spec_tests/pytest_plugins/spec_version_checker/__init__.py b/packages/tests/src/pytest_plugins/spec_version_checker/__init__.py
similarity index 100%
rename from src/ethereum_spec_tests/pytest_plugins/spec_version_checker/__init__.py
rename to packages/tests/src/pytest_plugins/spec_version_checker/__init__.py
diff --git a/src/ethereum_spec_tests/pytest_plugins/spec_version_checker/spec_version_checker.py b/packages/tests/src/pytest_plugins/spec_version_checker/spec_version_checker.py
similarity index 86%
rename from src/ethereum_spec_tests/pytest_plugins/spec_version_checker/spec_version_checker.py
rename to packages/tests/src/pytest_plugins/spec_version_checker/spec_version_checker.py
index c5344e0882..b5fb41c93d 100644
--- a/src/ethereum_spec_tests/pytest_plugins/spec_version_checker/spec_version_checker.py
+++ b/packages/tests/src/pytest_plugins/spec_version_checker/spec_version_checker.py
@@ -70,18 +70,17 @@ def get_ref_spec_from_module(
Return the reference spec object defined in a module.
Args:
- module: The module to extract reference spec from
- github_token: Optional GitHub token for API authentication
+ module: The module to extract reference spec from
+ github_token: Optional GitHub token for API authentication
Raises:
- Exception: If the module path contains "eip" and the module
- does not define a reference spec.
+ Exception: If the module path contains "eip" and the module does
+ not define a reference spec.
Returns:
- spec_obj: Return None if the module path does not contain "eip",
- i.e., the module is not required to define a reference spec,
- otherwise, return the ReferenceSpec object as defined by the
- module.
+ spec_obj: Return None if the module path does not contain "eip",
+ i.e., the module is not required to define a reference spec, otherwise,
+ return the ReferenceSpec object as defined by the module.
"""
if not is_test_for_an_eip(str(module.__file__)):
@@ -115,13 +114,12 @@ def is_test_for_an_eip(input_string: str) -> bool:
def test_eip_spec_version(module: ModuleType, github_token: Optional[str] = None):
"""
- Test that the ReferenceSpec object as defined in the test module
- is not outdated when compared to the remote hash from
- ethereum/EIPs.
+ Test that the ReferenceSpec object as defined in the test module is not
+ outdated when compared to the remote hash from ethereum/EIPs.
Args:
- module: Module to test
- github_token: Optional GitHub token for API authentication
+ module: Module to test
+ github_token: Optional GitHub token for API authentication
"""
ref_spec = get_ref_spec_from_module(module, github_token=github_token)
@@ -157,9 +155,9 @@ def __init__(self, name: str, parent: Node, **kwargs: Any):
Initialize the test item.
Args:
- name: Name of the test
- parent: Parent node
- **kwargs: Additional keyword arguments
+ name: Name of the test
+ parent: Parent node
+ **kwargs: Additional keyword arguments
"""
super().__init__(name, parent)
@@ -202,10 +200,11 @@ def reportinfo(self) -> tuple[str, int, str]:
return "spec_version_checker", 0, f"{self.name}"
-def pytest_collection_modifyitems(
- session: pytest.Session, config: pytest.Config, items: List[Item]
-):
- """Insert a new test EIPSpecTestItem for every test module with 'eip' in its path."""
+def pytest_collection_modifyitems(config: pytest.Config, items: List[Item]):
+ """
+ Insert a new test EIPSpecTestItem for every test module with 'eip' in its
+ path.
+ """
github_token = config.github_token if hasattr(config, "github_token") else None
modules: Set[Module] = {item.parent for item in items if isinstance(item.parent, Module)}
diff --git a/pyproject.toml b/pyproject.toml
index 5407127960..5c753b938c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,97 +30,9 @@ dependencies = [
[tool.setuptools.package-dir]
"" = "src"
-cli = "src/ethereum_spec_tests/cli"
-config = "src/ethereum_spec_tests/config"
-ethereum_clis = "src/ethereum_spec_tests/ethereum_clis"
-ethereum_test_base_types = "src/ethereum_spec_tests/ethereum_test_base_types"
-ethereum_test_checklists = "src/ethereum_spec_tests/ethereum_test_checklists"
-ethereum_test_exceptions = "src/ethereum_spec_tests/ethereum_test_exceptions"
-ethereum_test_execution = "src/ethereum_spec_tests/ethereum_test_execution"
-ethereum_test_fixtures = "src/ethereum_spec_tests/ethereum_test_fixtures"
-ethereum_test_forks = "src/ethereum_spec_tests/ethereum_test_forks"
-ethereum_test_rpc = "src/ethereum_spec_tests/ethereum_test_rpc"
-ethereum_test_specs = "src/ethereum_spec_tests/ethereum_test_specs"
-ethereum_test_tools = "src/ethereum_spec_tests/ethereum_test_tools"
-ethereum_test_types = "src/ethereum_spec_tests/ethereum_test_types"
-ethereum_test_vm = "src/ethereum_spec_tests/ethereum_test_vm"
-pytest_plugins = "src/ethereum_spec_tests/pytest_plugins"
[tool.setuptools]
packages = [
- "cli",
- "cli.eest",
- "cli.eest.commands",
- "cli.eest.make",
- "cli.eest.make.commands",
- "cli.gentest",
- "cli.gentest.tests",
- "cli.input",
- "cli.pytest_commands",
- "cli.tests",
- "config",
- "ethereum_clis",
- "ethereum_clis.clis",
- "ethereum_test_base_types",
- "ethereum_test_base_types.reference_spec",
- "ethereum_test_base_types.tests",
- "ethereum_test_checklists",
- "ethereum_test_checklists.tests",
- "ethereum_test_exceptions",
- "ethereum_test_exceptions.exceptions",
- "ethereum_test_exceptions.tests",
- "ethereum_test_execution",
- "ethereum_test_fixtures",
- "ethereum_test_fixtures.tests",
- "ethereum_test_forks",
- "ethereum_test_forks.forks",
- "ethereum_test_forks.tests",
- "ethereum_test_rpc",
- "ethereum_test_rpc.tests",
- "ethereum_test_specs",
- "ethereum_test_specs.static_state",
- "ethereum_test_specs.static_state.common",
- "ethereum_test_specs.tests",
- "ethereum_test_tools",
- "ethereum_test_tools.code",
- "ethereum_test_tools.tests",
- "ethereum_test_tools.utility",
- "ethereum_test_tools.vm",
- "ethereum_test_types",
- "ethereum_test_types.block_access_list",
- "ethereum_test_types.eof",
- "ethereum_test_types.eof.v1",
- "ethereum_test_types.tests",
- "ethereum_test_vm",
- "ethereum_test_vm.tests",
- "pytest_plugins",
- "pytest_plugins.consume",
- "pytest_plugins.consume.direct",
- "pytest_plugins.consume.hive_engine_test",
- "pytest_plugins.consume.hive_simulators_reorg",
- "pytest_plugins.consume.simulators",
- "pytest_plugins.consume.simulators.engine",
- "pytest_plugins.consume.simulators.helpers",
- "pytest_plugins.consume.simulators.rlp",
- "pytest_plugins.consume.simulators.simulator_logic",
- "pytest_plugins.consume.simulators.sync",
- "pytest_plugins.consume.tests",
- "pytest_plugins.execute",
- "pytest_plugins.execute.eth_config",
- "pytest_plugins.execute.eth_config.tests",
- "pytest_plugins.execute.rpc",
- "pytest_plugins.filler",
- "pytest_plugins.filler.gen_test_doc",
- "pytest_plugins.filler.tests",
- "pytest_plugins.forks",
- "pytest_plugins.forks.tests",
- "pytest_plugins.help",
- "pytest_plugins.logging",
- "pytest_plugins.logging.tests",
- "pytest_plugins.pytest_hive",
- "pytest_plugins.shared",
- "pytest_plugins.solc",
- "pytest_plugins.spec_version_checker",
"ethereum_spec_tools",
"ethereum_spec_tools.evm_tools",
"ethereum_spec_tools.evm_tools.t8n",
@@ -242,11 +154,6 @@ packages = [
"assets/blocks/block_12964999.json",
]
"ethereum_spec_tools" = ["py.typed"]
-"ethereum_test_forks" = ["forks/contracts/*.bin"]
-"pytest_plugins.execute" = ["eth_config/networks.yml"]
-"cli.eest.make" = ["templates/*.j2"]
-"cli.pytest_commands" = ["pytest_ini_files/*.ini"]
-"ethereum_test_types" = ["kzg_trusted_setup.txt"]
[project.optional-dependencies]
test = [
@@ -258,37 +165,8 @@ test = [
"requests",
"requests-cache>=1.2.1,<2",
"libcst>=1.8,<2",
+ "ethereum-execution-tests",
]
-
-fill = [
- "click>=8.1.0,<9",
- "ethereum-hive>=0.1.0a1,<1.0.0",
- "gitpython>=3.1.31,<4",
- "PyJWT>=2.3.0,<3",
- "tenacity>8.2.0,<9",
- "requests_unixsocket2>=0.4.0",
- "colorlog>=6.7.0,<7",
- "pytest-custom-report>=1.0.1,<2",
- "pytest-html>=4.1.0,<5",
- "pytest-metadata>=3,<4",
- "coincurve>=20.0.0,<21",
- "trie>=3.1.0,<4",
- "semver>=3.0.1,<4",
- "pydantic>=2.11.0,<3",
- "rich>=13.7.0,<14",
- "ethereum-types>=0.2.1,<0.3",
- "pyyaml>=6.0.2,<7",
- "types-pyyaml>=6.0.12.20240917,<7",
- "pytest-json-report>=1.5.0,<2",
- "typing-extensions>=4.12.2,<5",
- "questionary>=2.1.0,<3",
- "ethereum-rlp>=0.1.3,<0.2",
- "pytest-regex>=0.2.0,<0.3",
- "eth-abi>=5.2.0",
- "joblib>=1.4.2",
- "ckzg>=2.1.1",
-]
-
lint = [
"codespell==2.4.1",
"mypy==1.17.0",
@@ -317,25 +195,6 @@ ethereum-spec-sync = "ethereum_spec_tools.sync:main"
ethereum-spec-new-fork = "ethereum_spec_tools.new_fork.cli:main"
ethereum-spec-patch = "ethereum_spec_tools.patch_tool:main"
ethereum-spec-evm = "ethereum_spec_tools.evm_tools:main"
-check_eip_versions = "cli.pytest_commands.check_eip_versions:check_eip_versions"
-checkfixtures = "cli.check_fixtures:check_fixtures"
-checklist = "cli.pytest_commands.checklist:checklist"
-compare_fixtures = "cli.compare_fixtures:main"
-consume = "cli.pytest_commands.consume:consume"
-eest = "cli.eest.cli:eest"
-eofwrap = "cli.eofwrap:eof_wrap"
-evm_bytes = "cli.evm_bytes:evm_bytes"
-execute = "cli.pytest_commands.execute:execute"
-extract_config = "cli.extract_config:extract_config"
-fill = "cli.pytest_commands.fill:fill"
-fillerconvert = "cli.fillerconvert.fillerconvert:main"
-generate_checklist_stubs = "cli.generate_checklist_stubs:generate_checklist_stubs"
-genindex = "cli.gen_index:generate_fixtures_index_cli"
-gentest = "cli.gentest:generate"
-groupstats = "cli.show_pre_alloc_group_stats:main"
-hasher = "cli.hasher:main"
-order_fixtures = "cli.order_fixtures:order_fixtures"
-phil = "cli.pytest_commands.fill:phil"
[project.entry-points."docc.plugins"]
"ethereum_spec_tools.docc.discover" = "ethereum_spec_tools.docc:EthereumDiscover"
@@ -409,7 +268,6 @@ paths = [
excluded_paths = [
"src/ethereum_optimized",
"src/ethereum_spec_tools",
- "src/ethereum_spec_tests",
]
[tool.docc.plugins."docc.html.context"]
@@ -508,3 +366,9 @@ check-hidden = false # Don't check hidden files (starting with .)
[tool.uv]
required-version = ">=0.7.0"
+
+[tool.uv.workspace]
+members = ["packages/*"]
+
+[tool.uv.sources]
+ethereum-execution-tests = { workspace = true }
diff --git a/src/ethereum/__init__.py b/src/ethereum/__init__.py
index e46aa41100..145437d149 100644
--- a/src/ethereum/__init__.py
+++ b/src/ethereum/__init__.py
@@ -21,7 +21,7 @@
import sys
-__version__ = "2.18.0rc5.dev1"
+__version__ = "2.18.0rc5.dev2"
#
# Ensure we can reach 1024 frames of recursion
diff --git a/src/ethereum_spec_tests/cli/eest/make/commands/__init__.py b/src/ethereum_spec_tests/cli/eest/make/commands/__init__.py
deleted file mode 100644
index 706333ca04..0000000000
--- a/src/ethereum_spec_tests/cli/eest/make/commands/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""
-Holds subcommands for the make command. New subcommands must be created as
-modules and exported from this package, then registered under the make command in
-`cli.py`.
-"""
-
-from .env import create_default_env
-from .test import test
-
-__all__ = ["test", "create_default_env"]
diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/evmone.py b/src/ethereum_spec_tests/ethereum_clis/clis/evmone.py
deleted file mode 100644
index c76dfd4cf9..0000000000
--- a/src/ethereum_spec_tests/ethereum_clis/clis/evmone.py
+++ /dev/null
@@ -1,130 +0,0 @@
-"""Evmone Transition tool interface."""
-
-import re
-from pathlib import Path
-from typing import ClassVar, Dict, Optional
-
-from ethereum_test_exceptions import (
- EOFException,
- ExceptionBase,
- ExceptionMapper,
- TransactionException,
-)
-from ethereum_test_forks import Fork
-
-from ..transition_tool import TransitionTool
-
-
-class EvmOneTransitionTool(TransitionTool):
- """Evmone `evmone-t8n` Transition tool interface wrapper class."""
-
- default_binary = Path("evmone-t8n")
- detect_binary_pattern = re.compile(r"^evmone-t8n\b")
- t8n_use_stream = False
-
- binary: Path
- cached_version: Optional[str] = None
- trace: bool
-
- def __init__(
- self,
- *,
- binary: Optional[Path] = None,
- trace: bool = False,
- ):
- """Initialize the Evmone Transition tool interface."""
- super().__init__(exception_mapper=EvmoneExceptionMapper(), binary=binary, trace=trace)
-
- def is_fork_supported(self, fork: Fork) -> bool:
- """
- Return True if the fork is supported by the tool.
- Currently, evmone-t8n provides no way to determine supported forks.
- """
- return True
-
-
-class EvmoneExceptionMapper(ExceptionMapper):
- """Translate between EEST exceptions and error strings returned by Evmone."""
-
- mapping_substring: ClassVar[Dict[ExceptionBase, str]] = {
- TransactionException.SENDER_NOT_EOA: "sender not an eoa:",
- TransactionException.GAS_ALLOWANCE_EXCEEDED: "gas limit reached",
- TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS: (
- "max priority fee per gas higher than max fee per gas"
- ),
- TransactionException.NONCE_IS_MAX: "nonce has max value:",
- TransactionException.TYPE_4_TX_CONTRACT_CREATION: "set code transaction must ",
- TransactionException.TYPE_4_INVALID_AUTHORITY_SIGNATURE: "invalid authorization signature",
- TransactionException.TYPE_4_INVALID_AUTHORITY_SIGNATURE_S_TOO_HIGH: (
- "authorization signature s value too high"
- ),
- TransactionException.TYPE_4_EMPTY_AUTHORIZATION_LIST: "empty authorization list",
- TransactionException.INTRINSIC_GAS_TOO_LOW: "intrinsic gas too low",
- TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST: "intrinsic gas too low",
- TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: "blob gas limit exceeded",
- TransactionException.INITCODE_SIZE_EXCEEDED: "max initcode size exceeded",
- TransactionException.INSUFFICIENT_ACCOUNT_FUNDS: (
- "insufficient funds for gas * price + value"
- ),
- TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS: (
- "max fee per gas less than block base fee"
- ),
- TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS: (
- "max blob fee per gas less than block base fee"
- ),
- TransactionException.TYPE_4_TX_PRE_FORK: "transaction type not supported",
- TransactionException.TYPE_3_TX_PRE_FORK: "transaction type not supported",
- TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH: "invalid blob hash version",
- TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: "blob gas limit exceeded",
- TransactionException.TYPE_3_TX_ZERO_BLOBS: "empty blob hashes list",
- TransactionException.TYPE_3_TX_CONTRACT_CREATION: (
- "blob transaction must not be a create transaction"
- ),
- TransactionException.NONCE_MISMATCH_TOO_LOW: "nonce too low",
- TransactionException.NONCE_MISMATCH_TOO_HIGH: "nonce too high",
- # TODO EVMONE needs to differentiate when the section is missing in the header or body
- EOFException.MISSING_STOP_OPCODE: "err: no_terminating_instruction",
- EOFException.MISSING_CODE_HEADER: "err: code_section_missing",
- EOFException.MISSING_TYPE_HEADER: "err: type_section_missing",
- # TODO EVMONE these exceptions are too similar, this leeds to ambiguity
- EOFException.MISSING_TERMINATOR: "err: header_terminator_missing",
- EOFException.MISSING_HEADERS_TERMINATOR: "err: section_headers_not_terminated",
- EOFException.INVALID_VERSION: "err: eof_version_unknown",
- EOFException.INVALID_NON_RETURNING_FLAG: "err: invalid_non_returning_flag",
- EOFException.INVALID_MAGIC: "err: invalid_prefix",
- EOFException.INVALID_FIRST_SECTION_TYPE: "err: invalid_first_section_type",
- EOFException.INVALID_SECTION_BODIES_SIZE: "err: invalid_section_bodies_size",
- EOFException.INVALID_TYPE_SECTION_SIZE: "err: invalid_type_section_size",
- EOFException.INCOMPLETE_SECTION_SIZE: "err: incomplete_section_size",
- EOFException.INCOMPLETE_SECTION_NUMBER: "err: incomplete_section_number",
- EOFException.TOO_MANY_CODE_SECTIONS: "err: too_many_code_sections",
- EOFException.ZERO_SECTION_SIZE: "err: zero_section_size",
- EOFException.MISSING_DATA_SECTION: "err: data_section_missing",
- EOFException.UNDEFINED_INSTRUCTION: "err: undefined_instruction",
- EOFException.INPUTS_OUTPUTS_NUM_ABOVE_LIMIT: "err: inputs_outputs_num_above_limit",
- EOFException.UNREACHABLE_INSTRUCTIONS: "err: unreachable_instructions",
- EOFException.INVALID_RJUMP_DESTINATION: "err: invalid_rjump_destination",
- EOFException.UNREACHABLE_CODE_SECTIONS: "err: unreachable_code_sections",
- EOFException.STACK_UNDERFLOW: "err: stack_underflow",
- EOFException.STACK_OVERFLOW: "err: stack_overflow",
- EOFException.MAX_STACK_INCREASE_ABOVE_LIMIT: "err: max_stack_increase_above_limit",
- EOFException.STACK_HIGHER_THAN_OUTPUTS: "err: stack_higher_than_outputs_required",
- EOFException.JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS: (
- "err: jumpf_destination_incompatible_outputs"
- ),
- EOFException.INVALID_MAX_STACK_INCREASE: "err: invalid_max_stack_increase",
- EOFException.INVALID_DATALOADN_INDEX: "err: invalid_dataloadn_index",
- EOFException.TRUNCATED_INSTRUCTION: "err: truncated_instruction",
- EOFException.TOPLEVEL_CONTAINER_TRUNCATED: "err: toplevel_container_truncated",
- EOFException.ORPHAN_SUBCONTAINER: "err: unreferenced_subcontainer",
- EOFException.CONTAINER_SIZE_ABOVE_LIMIT: "err: container_size_above_limit",
- EOFException.INVALID_CONTAINER_SECTION_INDEX: "err: invalid_container_section_index",
- EOFException.INCOMPATIBLE_CONTAINER_KIND: "err: incompatible_container_kind",
- EOFException.AMBIGUOUS_CONTAINER_KIND: "err: ambiguous_container_kind",
- EOFException.STACK_HEIGHT_MISMATCH: "err: stack_height_mismatch",
- EOFException.TOO_MANY_CONTAINERS: "err: too_many_container_sections",
- EOFException.INVALID_CODE_SECTION_INDEX: "err: invalid_code_section_index",
- EOFException.CALLF_TO_NON_RETURNING: "err: callf_to_non_returning_function",
- EOFException.EOFCREATE_WITH_TRUNCATED_CONTAINER: "err: eofcreate_with_truncated_container",
- }
- mapping_regex: ClassVar[Dict[ExceptionBase, str]] = {}
diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/mixins.py b/src/ethereum_spec_tests/ethereum_test_base_types/mixins.py
deleted file mode 100644
index f44eafcaa5..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_base_types/mixins.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""Provides various mixins for Pydantic models."""
-
-from typing import Any, Literal
-
-from pydantic import BaseModel
-
-
-class ModelCustomizationsMixin:
- """
- A mixin that customizes the behavior of pydantic models. Any pydantic
- configuration override that must apply to all models
- should be placed here.
-
- This mixin is applied to both `EthereumTestBaseModel` and `EthereumTestRootModel`.
- """
-
- def serialize(
- self,
- mode: Literal["json", "python"],
- by_alias: bool,
- exclude_none: bool = True,
- ) -> dict[str, Any]:
- """
- Serialize the model to the specified format with the given parameters.
-
- :param mode: The mode of serialization.
- If mode is 'json', the output will only contain JSON serializable types.
- If mode is 'python', the output may contain non-JSON-serializable Python objects.
- :param by_alias: Whether to use aliases for field names.
- :param exclude_none: Whether to exclude fields with None values, default is True.
- :return: The serialized representation of the model.
- """
- if not hasattr(self, "model_dump"):
- raise NotImplementedError(
- f"{self.__class__.__name__} does not have 'model_dump' method."
- "Are you sure you are using a Pydantic model?"
- )
- return self.model_dump(mode=mode, by_alias=by_alias, exclude_none=exclude_none)
-
- def __repr_args__(self):
- """
- Generate a list of attribute-value pairs for the object representation.
-
- This method serializes the model, retrieves the attribute names,
- and constructs a list of tuples containing attribute names and their corresponding values.
- Only attributes with non-None values are included in the list.
-
- This method is used by the __repr__ method to generate the object representation,
- and is used by `gentest` module to generate the test cases.
-
- See:
- - https://pydantic-docs.helpmanual.io/usage/models/#custom-repr
- - https://github.com/ethereum/execution-spec-tests/pull/901#issuecomment-2443296835
-
- Returns:
- List[Tuple[str, Any]]: A list of tuples where each tuple contains an attribute name
- and its corresponding non-None value.
-
- """
- attrs_names = self.serialize(mode="python", by_alias=False).keys()
- attrs = ((s, getattr(self, s)) for s in attrs_names)
-
- # Convert field values based on their type.
- # This ensures consistency between JSON and Python object representations.
- # Should a custom `__repr__` be needed for a specific type, it can added in the
- # match statement below.
- # Otherwise, the default string representation is used.
- repr_attrs = []
- for a, v in attrs:
- match v:
- # Note: The `None` case handles an edge case with transactions
- # see: https://github.com/ethereum/execution-spec-tests/pull/901#discussion_r1828491918 # noqa: E501
- case list() | dict() | BaseModel() | None:
- repr_attrs.append((a, v))
- case _:
- repr_attrs.append((a, str(v)))
- return repr_attrs
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/eof.py b/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/eof.py
deleted file mode 100644
index 03df7faf64..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/eof.py
+++ /dev/null
@@ -1,219 +0,0 @@
-"""EOF Exceptions."""
-
-from enum import auto, unique
-
-from .base import ExceptionBase
-
-
-@unique
-class EOFException(ExceptionBase):
- """Exception raised when an EOF container is invalid."""
-
- DEFAULT_EXCEPTION = auto()
- """
- Expect some exception, not yet known.
- """
-
- UNDEFINED_EXCEPTION = auto()
- """
- Indicates that exception string is not mapped to an exception enum.
- """
-
- UNDEFINED_INSTRUCTION = auto()
- """
- EOF container has undefined instruction in it's body code.
- """
-
- UNKNOWN_VERSION = auto()
- """
- EOF container has an unknown version.
- """
- INCOMPLETE_MAGIC = auto()
- """
- EOF container has not enough bytes to read magic.
- """
- INVALID_MAGIC = auto()
- """
- EOF container has not allowed magic version byte.
- """
- INVALID_VERSION = auto()
- """
- EOF container version bytes mismatch.
- """
- INVALID_NON_RETURNING_FLAG = auto()
- """
- EOF container's section has non-returning flag set incorrectly.
- """
- INVALID_RJUMP_DESTINATION = auto()
- """
- Code has RJUMP instruction with invalid parameters.
- """
- MISSING_TYPE_HEADER = auto()
- """
- EOF container missing types section.
- """
- INVALID_TYPE_SECTION_SIZE = auto()
- """
- EOF container types section has wrong size.
- """
- INVALID_TYPE_BODY = auto()
- """
- EOF container types body section bytes are wrong.
- """
- MISSING_CODE_HEADER = auto()
- """
- EOF container missing code section.
- """
- INVALID_CODE_SECTION = auto()
- """
- EOF container code section bytes are incorrect.
- """
- INCOMPLETE_CODE_HEADER = auto()
- """
- EOF container code header missing bytes.
- """
- INCOMPLETE_DATA_HEADER = auto()
- """
- EOF container data header missing bytes.
- """
- ZERO_SECTION_SIZE = auto()
- """
- EOF container data header construction is wrong.
- """
- MISSING_DATA_SECTION = auto()
- """
- EOF container missing data section
- """
- INCOMPLETE_CONTAINER = auto()
- """
- EOF container bytes are incomplete.
- """
- INVALID_SECTION_BODIES_SIZE = auto()
- """
- Sections bodies does not match sections headers.
- """
- TRAILING_BYTES = auto()
- """
- EOF container has bytes beyond data section.
- """
- MISSING_TERMINATOR = auto()
- """
- EOF container missing terminator bytes between header and body.
- """
- MISSING_HEADERS_TERMINATOR = auto()
- """
- Some type of another exception about missing headers terminator.
- """
- INVALID_FIRST_SECTION_TYPE = auto()
- """
- EOF container header does not have types section first.
- """
- INCOMPLETE_SECTION_NUMBER = auto()
- """
- EOF container header has section that is missing declaration bytes.
- """
- INCOMPLETE_SECTION_SIZE = auto()
- """
- EOF container header has section that is defined incorrectly.
- """
- TOO_MANY_CODE_SECTIONS = auto()
- """
- EOF container header has too many code sections.
- """
- MISSING_STOP_OPCODE = auto()
- """
- EOF container's code missing STOP bytecode at it's end.
- """
- INPUTS_OUTPUTS_NUM_ABOVE_LIMIT = auto()
- """
- EOF container code section inputs/outputs number is above the limit
- """
- UNREACHABLE_INSTRUCTIONS = auto()
- """
- EOF container's code have instructions that are unreachable.
- """
- UNREACHABLE_CODE_SECTIONS = auto()
- """
- EOF container's body have code sections that are unreachable.
- """
- STACK_UNDERFLOW = auto()
- """
- EOF container's code produces an stack underflow.
- """
- STACK_OVERFLOW = auto()
- """
- EOF container's code produces an stack overflow.
- """
- STACK_HEIGHT_MISMATCH = auto()
- """
- EOF container section stack height mismatch.
- """
- MAX_STACK_INCREASE_ABOVE_LIMIT = auto()
- """
- EOF container's specified max stack increase is above the limit.
- """
- STACK_HIGHER_THAN_OUTPUTS = auto()
- """
- EOF container section stack height is higher than the outputs.
- when returning
- """
- JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS = auto()
- """
- EOF container section JUMPF's to a destination section with incompatible outputs.
- """
- INVALID_MAX_STACK_INCREASE = auto()
- """
- EOF container section's specified max stack increase does not match the actual stack height.
- """
- INVALID_DATALOADN_INDEX = auto()
- """
- A DATALOADN instruction has out-of-bounds index for the data section.
- """
- TRUNCATED_INSTRUCTION = auto()
- """
- EOF container's code section has truncated instruction.
- """
- TOPLEVEL_CONTAINER_TRUNCATED = auto()
- """
- Top-level EOF container has data section truncated
- """
- ORPHAN_SUBCONTAINER = auto()
- """
- EOF container has an unreferenced subcontainer.
- '"""
- CONTAINER_SIZE_ABOVE_LIMIT = auto()
- """
- EOF container is above size limit
- """
- INVALID_CONTAINER_SECTION_INDEX = auto()
- """
- Instruction references container section that does not exist.
- """
- INCOMPATIBLE_CONTAINER_KIND = auto()
- """
- Incompatible instruction found in a container of a specific kind.
- """
- AMBIGUOUS_CONTAINER_KIND = auto()
- """
- The kind of a sub-container cannot be uniquely deduced.
- """
- TOO_MANY_CONTAINERS = auto()
- """
- EOF container header has too many sub-containers.
- """
- INVALID_CODE_SECTION_INDEX = auto()
- """
- CALLF Operation refers to a non-existent code section
- """
- UNEXPECTED_HEADER_KIND = auto()
- """
- Header parsing encountered a section kind it wasn't expecting
- """
- CALLF_TO_NON_RETURNING = auto()
- """
- CALLF instruction targeting a non-returning code section
- """
- EOFCREATE_WITH_TRUNCATED_CONTAINER = auto()
- """
- EOFCREATE with truncated container
- """
diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/transaction.py b/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/transaction.py
deleted file mode 100644
index 4d3bbc97b8..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/transaction.py
+++ /dev/null
@@ -1,291 +0,0 @@
-"""Transaction Exceptions."""
-
-from enum import auto, unique
-
-from .base import ExceptionBase
-
-
-@unique
-class TransactionException(ExceptionBase):
- """
- Exception raised when a transaction is invalid, and thus cannot be executed.
-
- If a transaction with any of these exceptions is included in a block, the block is invalid.
- """
-
- TYPE_NOT_SUPPORTED = auto()
- """
- Transaction type is not supported on this chain configuration.
- """
- SENDER_NOT_EOA = auto()
- """
- Transaction is coming from address that is not exist anymore.
- """
- ADDRESS_TOO_SHORT = auto()
- """
- Transaction `to` is not allowed to be less than 20 bytes.
- """
- ADDRESS_TOO_LONG = auto()
- """
- Transaction `to` is not allowed to be more than 20 bytes.
- """
- NONCE_MISMATCH_TOO_HIGH = auto()
- """
- Transaction nonce > sender.nonce.
- """
- NONCE_MISMATCH_TOO_LOW = auto()
- """
- Transaction nonce < sender.nonce.
- """
- NONCE_TOO_BIG = auto()
- """
- Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably TransactionTest).
- """
- NONCE_IS_MAX = auto()
- """
- Transaction `nonce` is not allowed to be max_uint64 - 1 (this is StateTests).
- """
- NONCE_OVERFLOW = auto()
- """
- Transaction `nonce` is not allowed to be more than uint64.
- """
- GASLIMIT_OVERFLOW = auto()
- """
- Transaction gaslimit exceeds 2^64-1 maximum value.
- """
- VALUE_OVERFLOW = auto()
- """
- Transaction value exceeds 2^256-1 maximum value.
- """
- GASPRICE_OVERFLOW = auto()
- """
- Transaction gasPrice exceeds 2^256-1 maximum value.
- """
- GASLIMIT_PRICE_PRODUCT_OVERFLOW = auto()
- """
- Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value.
- """
- INVALID_SIGNATURE_VRS = auto()
- """
- Invalid transaction v, r, s values.
- """
- RLP_INVALID_SIGNATURE_R = auto()
- """
- Error reading transaction signature R value.
- """
- RLP_INVALID_SIGNATURE_S = auto()
- """
- Error reading transaction signature S value.
- """
- RLP_LEADING_ZEROS_GASLIMIT = auto()
- """
- Error reading transaction gaslimit field RLP.
- """
- RLP_LEADING_ZEROS_GASPRICE = auto()
- """
- Error reading transaction gasprice field RLP.
- """
- RLP_LEADING_ZEROS_VALUE = auto()
- """
- Error reading transaction value field RLP.
- """
- RLP_LEADING_ZEROS_NONCE = auto()
- """
- Error reading transaction nonce field RLP.
- """
- RLP_LEADING_ZEROS_R = auto()
- """
- Error reading transaction signature R field RLP.
- """
- RLP_LEADING_ZEROS_S = auto()
- """
- Error reading transaction signature S field RLP.
- """
- RLP_LEADING_ZEROS_V = auto()
- """
- Error reading transaction signature V field RLP.
- """
- RLP_LEADING_ZEROS_BASEFEE = auto()
- """
- Error reading transaction basefee field RLP.
- """
- RLP_LEADING_ZEROS_PRIORITY_FEE = auto()
- """
- Error reading transaction priority fee field RLP.
- """
- RLP_LEADING_ZEROS_DATA_SIZE = auto()
- """
- Error reading transaction data field RLP, (rlp field length has leading zeros).
- """
- RLP_LEADING_ZEROS_NONCE_SIZE = auto()
- """
- Error reading transaction nonce field RLP, (rlp field length has leading zeros).
- """
- RLP_TOO_FEW_ELEMENTS = auto()
- """
- Error reading transaction RLP, structure has too few elements than expected.
- """
- RLP_TOO_MANY_ELEMENTS = auto()
- """
- Error reading transaction RLP, structure has too many elements than expected.
- """
- RLP_ERROR_EOF = auto()
- """
- Error reading transaction RLP, rlp stream unexpectedly finished.
- """
- RLP_ERROR_SIZE = auto()
- """
- Error reading transaction RLP, rlp size is invalid.
- """
- RLP_ERROR_SIZE_LEADING_ZEROS = auto()
- """
- Error reading transaction RLP, field size has leading zeros.
- """
- INVALID_CHAINID = auto()
- """
- Transaction chain id encoding is incorrect.
- """
- RLP_INVALID_DATA = auto()
- """
- Transaction data field is invalid rlp.
- """
- RLP_INVALID_GASLIMIT = auto()
- """
- Transaction gaslimit field is invalid rlp.
- """
- RLP_INVALID_NONCE = auto()
- """
- Transaction nonce field is invalid rlp.
- """
- RLP_INVALID_TO = auto()
- """
- Transaction to field is invalid rlp.
- """
- RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_LONG = auto()
- """
- Transaction access list address is > 20 bytes.
- """
- RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_SHORT = auto()
- """
- Transaction access list address is < 20 bytes.
- """
- RLP_INVALID_ACCESS_LIST_STORAGE_TOO_LONG = auto()
- """
- Transaction access list storage hash > 32 bytes.
- """
- RLP_INVALID_ACCESS_LIST_STORAGE_TOO_SHORT = auto()
- """
- Transaction access list storage hash < 32 bytes.
- """
- RLP_INVALID_HEADER = auto()
- """
- Transaction failed to read from RLP as rlp header is invalid.
- """
- RLP_INVALID_VALUE = auto()
- """
- Transaction value field is invalid rlp/structure.
- """
- EC_RECOVERY_FAIL = auto()
- """
- Transaction has correct signature, but ec recovery failed.
- """
- INSUFFICIENT_ACCOUNT_FUNDS = auto()
- """
- Transaction's sender does not have enough funds to pay for the transaction.
- """
- INSUFFICIENT_MAX_FEE_PER_GAS = auto()
- """
- Transaction's max-fee-per-gas is lower than the block base-fee.
- """
- PRIORITY_OVERFLOW = auto()
- """
- Transaction's max-priority-fee-per-gas is exceeds 2^256-1 maximum value.
- """
- PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS = auto()
- """
- Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas.
- """
- PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS_2 = auto()
- """
- Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas (TransactionTests).
- """
- INSUFFICIENT_MAX_FEE_PER_BLOB_GAS = auto()
- """
- Transaction's max-fee-per-blob-gas is lower than the block's blob-gas price.
- """
- INTRINSIC_GAS_TOO_LOW = auto()
- """
- Transaction's gas limit is too low.
- """
- INTRINSIC_GAS_BELOW_FLOOR_GAS_COST = auto()
- """
- Transaction's gas limit is below the floor gas cost.
- """
- INITCODE_SIZE_EXCEEDED = auto()
- """
- Transaction's initcode for a contract-creating transaction is too large.
- """
- TYPE_3_TX_PRE_FORK = auto()
- """
- Transaction type 3 included before activation fork.
- """
- TYPE_3_TX_ZERO_BLOBS_PRE_FORK = auto()
- """
- Transaction type 3, with zero blobs, included before activation fork.
- """
- TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH = auto()
- """
- Transaction contains a blob versioned hash with an invalid version.
- """
- TYPE_3_TX_WITH_FULL_BLOBS = auto()
- """
- Transaction contains full blobs (network-version of the transaction).
- """
- TYPE_3_TX_BLOB_COUNT_EXCEEDED = auto()
- """
- Transaction contains too many blob versioned hashes.
- """
- TYPE_3_TX_CONTRACT_CREATION = auto()
- """
- Transaction is a type 3 transaction and has an empty `to`.
- """
- TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED = auto()
- """
- Transaction causes block to go over blob gas limit.
- """
- GAS_ALLOWANCE_EXCEEDED = auto()
- """
- Transaction causes block to go over blob gas limit.
- """
- GAS_LIMIT_EXCEEDS_MAXIMUM = auto()
- """
- Transaction gas limit exceeds the maximum allowed limit of 30 million.
- """
- TYPE_3_TX_ZERO_BLOBS = auto()
- """
- Transaction is type 3, but has no blobs.
- """
- TYPE_4_EMPTY_AUTHORIZATION_LIST = auto()
- """
- Transaction is type 4, but has an empty authorization list.
- """
- TYPE_4_INVALID_AUTHORITY_SIGNATURE = auto()
- """
- Transaction authority signature is invalid
- """
- TYPE_4_INVALID_AUTHORITY_SIGNATURE_S_TOO_HIGH = auto()
- """
- Transaction authority signature is invalid
- """
- TYPE_4_TX_CONTRACT_CREATION = auto()
- """
- Transaction is a type 4 transaction and has an empty `to`.
- """
- TYPE_4_INVALID_AUTHORIZATION_FORMAT = auto()
- """
- Transaction is type 4, but contains an authorization that has an invalid format.
- """
- TYPE_4_TX_PRE_FORK = auto()
- """
- Transaction type 4 included before activation fork.
- """
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/pytest.py b/src/ethereum_spec_tests/ethereum_test_tools/utility/pytest.py
deleted file mode 100644
index 4e01a6cd4a..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_tools/utility/pytest.py
+++ /dev/null
@@ -1,127 +0,0 @@
-"""Pytest utility functions used to write Ethereum tests."""
-
-from typing import Any, Dict, List
-
-import pytest
-from _pytest.mark.structures import ParameterSet
-
-
-class UnknownParameterInCasesError(Exception):
- """
- Exception raised when a test case contains parameters
- that are not present in the defaults.
- """
-
- def __init__(self) -> None:
- """Initialize the exception."""
- super().__init__("each case must only contain parameters present in defaults")
-
-
-def extend_with_defaults(
- defaults: Dict[str, Any], cases: List[ParameterSet], **parametrize_kwargs: Any
-) -> Dict[str, Any]:
- """
- Extend test cases with default parameter values.
-
- This utility function extends test case parameters by adding default values
- from the `defaults` dictionary to each case in the `cases` list. If a case
- already specifies a value for a parameter, its default is ignored.
-
- This function is particularly useful in scenarios where you want to define
- a common set of default values but allow individual test cases to override
- them as needed.
-
- The function returns a dictionary that can be directly unpacked and passed
- to the `@pytest.mark.parametrize` decorator.
-
- Args:
- defaults (Dict[str, Any]): A dictionary of default parameter names and
- their values. These values will be added to each case unless the case
- already defines a value for each parameter.
- cases (List[ParameterSet]): A list of `pytest.param` objects representing
- different test cases. Its first argument must be a dictionary defining
- parameter names and values.
- parametrize_kwargs (Any): Additional keyword arguments to be passed to
- `@pytest.mark.parametrize`. These arguments are not modified by this
- function and are passed through unchanged.
-
- Returns:
- Dict[str, Any]: A dictionary with the following structure:
- `argnames`: A list of parameter names.
- `argvalues`: A list of test cases with modified parameter values.
- `parametrize_kwargs`: Additional keyword arguments passed through unchanged.
-
-
- Example:
- ```python
- @pytest.mark.parametrize(**extend_with_defaults(
- defaults=dict(
- min_value=0, # default minimum value is 0
- max_value=100, # default maximum value is 100
- average=50, # default average value is 50
- ),
- cases=[
- pytest.param(
- dict(), # use default values
- id='default_case',
- ),
- pytest.param(
- dict(min_value=10), # override with min_value=10
- id='min_value_10',
- ),
- pytest.param(
- dict(max_value=200), # override with max_value=200
- id='max_value_200',
- ),
- pytest.param(
- dict(min_value=-10, max_value=50), # override both min_value
- # and max_value
- id='min_-10_max_50',
- ),
- pytest.param(
- dict(min_value=20, max_value=80, average=50), # all defaults
- # are overridden
- id="min_20_max_80_avg_50",
- ),
- pytest.param(
- dict(min_value=100, max_value=0), # invalid range
- id='invalid_range',
- marks=pytest.mark.xfail(reason='invalid range'),
- )
- ],
- ))
- def test_range(min_value, max_value, average):
- assert min_value <= max_value
- assert min_value <= average <= max_value
- ```
-
- The above test will execute with the following sets of parameters:
-
- ```python
- "default_case": {"min_value": 0, "max_value": 100, "average": 50}
- "min_value_10": {"min_value": 10, "max_value": 100, "average": 50}
- "max_value_200": {"min_value": 0, "max_value": 200, "average": 50}
- "min_-10_max_50": {"min_value": -10, "max_value": 50, "average": 50}
- "min_20_max_80_avg_50": {"min_value": 20, "max_value": 80, "average": 50}
- "invalid_range": {"min_value": 100, "max_value": 0, "average": 50} # expected to fail
- ```
-
- Notes:
- - Each case in `cases` must contain exactly one value, which is a dictionary
- of parameter values.
- - The function performs an in-place update of the `cases` list, so the
- original `cases` list is modified.
-
- """
- for i, case in enumerate(cases):
- if not (len(case.values) == 1 and isinstance(case.values[0], dict)):
- raise ValueError(
- "each case must contain exactly one value; a dict of parameter values"
- )
- if set(case.values[0].keys()) - set(defaults.keys()):
- raise UnknownParameterInCasesError()
- # Overwrite values in defaults if the parameter is present in the test case values
- merged_params = {**defaults, **case.values[0]} # type: ignore
- cases[i] = pytest.param(*merged_params.values(), id=case.id, marks=case.marks)
-
- return {"argnames": list(defaults), "argvalues": cases, **parametrize_kwargs}
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/vm/__init__.py b/src/ethereum_spec_tests/ethereum_test_tools/vm/__init__.py
deleted file mode 100644
index 6bd0c74648..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_tools/vm/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Mirror module to import `ethereum_test_vm`."""
-
-from .opcode import Bytecode, Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes
-
-__all__ = (
- "Bytecode",
- "Macro",
- "Macros",
- "Opcode",
- "OpcodeCallArg",
- "Opcodes",
- "UndefinedOpcodes",
-)
diff --git a/src/ethereum_spec_tests/ethereum_test_tools/vm/opcode.py b/src/ethereum_spec_tests/ethereum_test_tools/vm/opcode.py
deleted file mode 100644
index fc5ed0c8ef..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_tools/vm/opcode.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""Import shortcuts for the ethereum_test_vm package."""
-
-from ethereum_test_vm import (
- Bytecode,
- Macro,
- Macros,
- Opcode,
- OpcodeCallArg,
- Opcodes,
- UndefinedOpcodes,
-)
-
-__all__ = (
- "Bytecode",
- "Macro",
- "Macros",
- "Opcode",
- "OpcodeCallArg",
- "Opcodes",
- "UndefinedOpcodes",
-)
diff --git a/src/ethereum_spec_tests/ethereum_test_types/block_access_list/__init__.py b/src/ethereum_spec_tests/ethereum_test_types/block_access_list/__init__.py
deleted file mode 100644
index 753aaa44e7..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_types/block_access_list/__init__.py
+++ /dev/null
@@ -1,424 +0,0 @@
-"""
-Block Access List (BAL) models for EIP-7928.
-
-Following the established pattern in the codebase (AccessList, AuthorizationTuple),
-these are simple data classes that can be composed together.
-"""
-
-from functools import cached_property
-from typing import Any, Callable, ClassVar, Dict, List
-
-import ethereum_rlp as eth_rlp
-from pydantic import Field, PrivateAttr
-
-from ethereum_test_base_types import (
- Address,
- Bytes,
- CamelModel,
- EthereumTestRootModel,
- HexNumber,
- Number,
- RLPSerializable,
- StorageKey,
-)
-from ethereum_test_base_types.serialization import to_serializable_element
-
-
-def compose(
- *modifiers: Callable[["BlockAccessList"], "BlockAccessList"],
-) -> Callable[["BlockAccessList"], "BlockAccessList"]:
- """Compose multiple modifiers into a single modifier."""
-
- def composed(bal: BlockAccessList) -> BlockAccessList:
- result = bal
- for modifier in modifiers:
- result = modifier(result)
- return result
-
- return composed
-
-
-class BalNonceChange(CamelModel, RLPSerializable):
- """Represents a nonce change in the block access list."""
-
- tx_index: Number = Field(..., description="Transaction index where the change occurred")
- post_nonce: Number = Field(..., description="Nonce value after the transaction")
-
- rlp_fields: ClassVar[List[str]] = ["tx_index", "post_nonce"]
-
-
-class BalBalanceChange(CamelModel, RLPSerializable):
- """Represents a balance change in the block access list."""
-
- tx_index: Number = Field(..., description="Transaction index where the change occurred")
- post_balance: HexNumber = Field(..., description="Balance after the transaction")
-
- rlp_fields: ClassVar[List[str]] = ["tx_index", "post_balance"]
-
-
-class BalCodeChange(CamelModel, RLPSerializable):
- """Represents a code change in the block access list."""
-
- tx_index: Number = Field(..., description="Transaction index where the change occurred")
- new_code: Bytes = Field(..., description="New code bytes")
-
- rlp_fields: ClassVar[List[str]] = ["tx_index", "new_code"]
-
-
-class BalStorageChange(CamelModel, RLPSerializable):
- """Represents a change to a specific storage slot."""
-
- tx_index: Number = Field(..., description="Transaction index where the change occurred")
- post_value: StorageKey = Field(..., description="Value after the transaction")
-
- rlp_fields: ClassVar[List[str]] = ["tx_index", "post_value"]
-
-
-class BalStorageSlot(CamelModel, RLPSerializable):
- """Represents all changes to a specific storage slot."""
-
- slot: StorageKey = Field(..., description="Storage slot key")
- slot_changes: List[BalStorageChange] = Field(
- default_factory=list, description="List of changes to this slot"
- )
-
- rlp_fields: ClassVar[List[str]] = ["slot", "slot_changes"]
-
-
-class BalAccountChange(CamelModel, RLPSerializable):
- """Represents all changes to a specific account in a block."""
-
- address: Address = Field(..., description="Account address")
- nonce_changes: List[BalNonceChange] = Field(
- default_factory=list, description="List of nonce changes"
- )
- balance_changes: List[BalBalanceChange] = Field(
- default_factory=list, description="List of balance changes"
- )
- code_changes: List[BalCodeChange] = Field(
- default_factory=list, description="List of code changes"
- )
- storage_changes: List[BalStorageSlot] = Field(
- default_factory=list, description="List of storage changes"
- )
- storage_reads: List[StorageKey] = Field(
- default_factory=list, description="List of storage slots that were read"
- )
-
- rlp_fields: ClassVar[List[str]] = [
- "address",
- "storage_changes",
- "storage_reads",
- "balance_changes",
- "nonce_changes",
- "code_changes",
- ]
-
-
-class BlockAccessList(EthereumTestRootModel[List[BalAccountChange]]):
- """
- Block Access List for t8n tool communication and fixtures.
-
- This model represents the BAL exactly as defined in EIP-7928 - it is itself a list
- of account changes (root model), not a container. Used for:
- - Communication with t8n tools
- - Fixture generation
- - RLP encoding for hash verification
-
- Example:
- bal = BlockAccessList([
- BalAccountChange(address=alice, nonce_changes=[...]),
- BalAccountChange(address=bob, balance_changes=[...])
- ])
-
- """
-
- root: List[BalAccountChange] = Field(default_factory=list)
-
- def to_list(self) -> List[Any]:
- """Return the list for RLP encoding per EIP-7928."""
- return to_serializable_element(self.root)
-
- @cached_property
- def rlp(self) -> Bytes:
- """Return the RLP encoded block access list for hash verification."""
- return Bytes(eth_rlp.encode(self.to_list()))
-
- @cached_property
- def rlp_hash(self) -> Bytes:
- """Return the hash of the RLP encoded block access list."""
- return self.rlp.keccak256()
-
-
-class BalAccountExpectation(CamelModel):
- """
- Represents expected changes to a specific account in a block.
-
- Same as BalAccountChange but without the address field, used for expectations.
- """
-
- nonce_changes: List[BalNonceChange] = Field(
- default_factory=list, description="List of expected nonce changes"
- )
- balance_changes: List[BalBalanceChange] = Field(
- default_factory=list, description="List of expected balance changes"
- )
- code_changes: List[BalCodeChange] = Field(
- default_factory=list, description="List of expected code changes"
- )
- storage_changes: List[BalStorageSlot] = Field(
- default_factory=list, description="List of expected storage changes"
- )
- storage_reads: List[StorageKey] = Field(
- default_factory=list, description="List of expected read storage slots"
- )
-
-
-class BlockAccessListExpectation(CamelModel):
- """
- Block Access List expectation model for test writing.
-
- This model is used to define expected BAL values in tests. It supports:
- - Partial validation (only checks explicitly set fields)
- - Convenient test syntax with named parameters
- - Verification against actual BAL from t8n
- - Explicit exclusion of addresses (using None values)
-
- Example:
- # In test definition
- expected_block_access_list = BlockAccessListExpectation(
- account_expectations={
- alice: BalAccountExpectation(
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]
- ),
- bob: None, # Bob should NOT be in the BAL
- }
- )
-
- """
-
- model_config = CamelModel.model_config | {"extra": "forbid"}
-
- account_expectations: Dict[Address, BalAccountExpectation | None] = Field(
- default_factory=dict, description="Expected account changes or exclusions to verify"
- )
-
- _modifier: Callable[["BlockAccessList"], "BlockAccessList"] | None = PrivateAttr(default=None)
-
- def modify(
- self, *modifiers: Callable[["BlockAccessList"], "BlockAccessList"]
- ) -> "BlockAccessListExpectation":
- """
- Create a new expectation with a modifier for invalid test cases.
-
- Args:
- modifiers: One or more functions that take and return a BlockAccessList
-
- Returns:
- A new BlockAccessListExpectation instance with the modifiers applied
-
- Example:
- from ethereum_test_types.block_access_list.modifiers import remove_nonces
-
- expectation = BlockAccessListExpectation(
- account_expectations={...}
- ).modify(remove_nonces(alice))
-
- """
- new_instance = self.model_copy(deep=True)
- new_instance._modifier = compose(*modifiers)
- return new_instance
-
- def to_fixture_bal(self, t8n_bal: "BlockAccessList") -> "BlockAccessList":
- """
- Convert t8n BAL to fixture BAL, optionally applying transformations.
-
- 1. First validates expectations are met (if any)
- 2. Then applies modifier if specified (for invalid tests)
-
- Args:
- t8n_bal: The BlockAccessList from t8n tool
-
- Returns:
- The potentially transformed BlockAccessList for the fixture
-
- """
- if self.account_expectations:
- self.verify_against(t8n_bal)
-
- # Apply modifier if present (for invalid tests)
- if self._modifier:
- return self._modifier(t8n_bal)
-
- return t8n_bal
-
- def verify_against(self, actual_bal: "BlockAccessList") -> None:
- """
- Verify that the actual BAL from the client matches this expected BAL.
-
- Args:
- actual_bal: The BlockAccessList model from the client
-
- Raises:
- Exception: If verification fails
-
- """
- actual_accounts_by_addr = {acc.address: acc for acc in actual_bal.root}
-
- for address, expectation in self.account_expectations.items():
- if expectation is None:
- # check explicit exclusion of address when set to `None`
- if address in actual_accounts_by_addr:
- raise Exception(f"Address {address} should not be in BAL but was found")
- else:
- # Address should be in BAL with expected values
- if address not in actual_accounts_by_addr:
- raise Exception(f"Expected address {address} not found in actual BAL")
-
- actual_account = actual_accounts_by_addr[address]
- try:
- self._compare_account_expectations(expectation, actual_account)
- except AssertionError as e:
- raise Exception(f"Account {address}: {str(e)}") from e
-
- def _compare_account_expectations(
- self, expected: BalAccountExpectation, actual: BalAccountChange
- ) -> None:
- """
- Compare expected account changes with actual BAL account entry.
-
- Only validates fields that were explicitly set in the expected model,
- using model_fields_set to determine what was intentionally specified.
- """
- # Only check fields that were explicitly set in the expected model
- for field_name in expected.model_fields_set:
- expected_value = getattr(expected, field_name)
- actual_value = getattr(actual, field_name)
-
- # empty list explicitly set (no changes expected)
- if not expected_value:
- if actual_value:
- raise AssertionError(
- f"Expected {field_name} to be empty but found: {actual_value}"
- )
- continue
-
- if field_name == "storage_reads":
- # Convert to comparable format (both are lists of 32-byte values)
- expected_set = {bytes(v) if hasattr(v, "__bytes__") else v for v in expected_value}
- actual_set = {bytes(v) if hasattr(v, "__bytes__") else v for v in actual_value}
- if expected_set != actual_set:
- missing = expected_set - actual_set
- extra = actual_set - expected_set
- msg = "Storage reads mismatch."
- if missing:
- missing_str = [
- v.hex() if isinstance(v, bytes) else str(v) for v in missing
- ]
- msg += f" Missing: {missing_str}."
- if extra:
- extra_str = [v.hex() if isinstance(v, bytes) else str(v) for v in extra]
- msg += f" Extra: {extra_str}."
- raise AssertionError(msg)
-
- elif isinstance(expected_value, list):
- # For lists of changes, use the model_dump approach for comparison
- expected_data = [
- item.model_dump() if hasattr(item, "model_dump") else item
- for item in expected_value
- ]
- actual_data = [
- item.model_dump() if hasattr(item, "model_dump") else item
- for item in actual_value
- ]
-
- if not self._compare_change_lists(field_name, expected_data, actual_data):
- # The comparison method will raise with details
- pass
-
- @staticmethod
- def _compare_change_lists(field_name: str, expected: List, actual: List) -> bool:
- """Compare lists of change objects using set operations for better error messages."""
- if field_name == "storage_changes":
- # Storage changes are nested (slot -> changes)
- expected_by_slot = {slot["slot"]: slot["slot_changes"] for slot in expected}
- actual_by_slot = {slot["slot"]: slot["slot_changes"] for slot in actual}
-
- missing_slots = set(expected_by_slot.keys()) - set(actual_by_slot.keys())
- if missing_slots:
- raise AssertionError(f"Missing storage slots: {missing_slots}")
-
- for slot, exp_changes in expected_by_slot.items():
- act_changes = actual_by_slot.get(slot, [])
- # Handle Hash/bytes for post_value comparison
- exp_set = {
- (
- c["tx_index"],
- bytes(c["post_value"])
- if hasattr(c["post_value"], "__bytes__")
- else c["post_value"],
- )
- for c in exp_changes
- }
- act_set = {
- (
- c["tx_index"],
- bytes(c["post_value"])
- if hasattr(c["post_value"], "__bytes__")
- else c["post_value"],
- )
- for c in act_changes
- }
-
- if exp_set != act_set:
- missing = exp_set - act_set
- extra = act_set - exp_set
- msg = f"Slot {slot} changes mismatch."
- if missing:
- msg += f" Missing: {missing}."
- if extra:
- msg += f" Extra: {extra}."
- raise AssertionError(msg)
- else:
- # Create comparable tuples for each change type
- if field_name == "nonce_changes":
- expected_set = {(c["tx_index"], c["post_nonce"]) for c in expected}
- actual_set = {(c["tx_index"], c["post_nonce"]) for c in actual}
- item_type = "nonce"
- elif field_name == "balance_changes":
- expected_set = {(c["tx_index"], int(c["post_balance"])) for c in expected}
- actual_set = {(c["tx_index"], int(c["post_balance"])) for c in actual}
- item_type = "balance"
- elif field_name == "code_changes":
- expected_set = {(c["tx_index"], bytes(c["new_code"])) for c in expected}
- actual_set = {(c["tx_index"], bytes(c["new_code"])) for c in actual}
- item_type = "code"
- else:
- raise ValueError("Unexpected type")
-
- if expected_set != actual_set:
- missing = expected_set - actual_set
- extra = actual_set - expected_set
- msg = f"{item_type.capitalize()} changes mismatch."
- if missing:
- msg += f" Missing: {missing}."
- if extra:
- msg += f" Extra: {extra}."
- raise AssertionError(msg)
-
- return True
-
-
-__all__ = [
- # Core models
- "BlockAccessList",
- "BlockAccessListExpectation",
- "BalAccountExpectation",
- # Change types
- "BalAccountChange",
- "BalNonceChange",
- "BalBalanceChange",
- "BalCodeChange",
- "BalStorageChange",
- "BalStorageSlot",
-]
diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/constants.py b/src/ethereum_spec_tests/ethereum_test_types/eof/constants.py
deleted file mode 100644
index fbc6e88a6d..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_types/eof/constants.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""
-EVM Object Format generic constants.
-Applicable to all EOF versions.
-"""
-
-EOF_MAGIC = b"\xef\x00"
-"""
-The second byte found on every EOF formatted contract, which was chosen to
-avoid clashes with three contracts which were deployed on Mainnet.
-"""
-EOF_HEADER_TERMINATOR = b"\x00"
-"""
-Byte that terminates the header of the EOF format.
-"""
-LATEST_EOF_VERSION = 1
-"""
-Latest existing EOF version.
-"""
-VERSION_BYTE_LENGTH = 1
-"""
-Length of the version byte.
-"""
-
-MAX_RUNTIME_STACK_HEIGHT = 1024
-"""
-Maximum height of the EVM runtime operand stack.
-Exceeding this value during execution will result in the stack overflow exception.
-This value applies to both legacy EVM and EOF.
-"""
diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_block_access_lists.py b/src/ethereum_spec_tests/ethereum_test_types/tests/test_block_access_lists.py
deleted file mode 100644
index 852894bc25..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_types/tests/test_block_access_lists.py
+++ /dev/null
@@ -1,208 +0,0 @@
-"""Unit tests for BlockAccessListExpectation validation."""
-
-import pytest
-
-from ethereum_test_base_types import Address
-from ethereum_test_types.block_access_list import (
- BalAccountChange,
- BalAccountExpectation,
- BalBalanceChange,
- BalNonceChange,
- BalStorageChange,
- BalStorageSlot,
- BlockAccessList,
- BlockAccessListExpectation,
-)
-
-
-def test_address_exclusion_validation_passes():
- """Test that address exclusion works when address is not in BAL."""
- alice = Address("0x000000000000000000000000000000000000000a")
- bob = Address("0x000000000000000000000000000000000000000b")
-
- actual_bal = BlockAccessList(
- [
- BalAccountChange(
- address=alice,
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- ),
- ]
- )
-
- expectation = BlockAccessListExpectation(
- account_expectations={
- alice: BalAccountExpectation(nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]),
- bob: None, # expect Bob is not in BAL (correctly)
- }
- )
-
- expectation.verify_against(actual_bal)
-
-
-def test_address_exclusion_validation_raises_when_address_is_present():
- """Test that validation fails when excluded address is in BAL."""
- alice = Address("0x000000000000000000000000000000000000000a")
- bob = Address("0x000000000000000000000000000000000000000b")
-
- actual_bal = BlockAccessList(
- [
- BalAccountChange(
- address=alice,
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- ),
- BalAccountChange(
- address=bob,
- balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
- ),
- ]
- )
-
- expectation = BlockAccessListExpectation(
- # explicitly expect Bob to NOT be in BAL (wrongly)
- account_expectations={bob: None},
- )
-
- with pytest.raises(Exception, match="should not be in BAL but was found"):
- expectation.verify_against(actual_bal)
-
-
-def test_empty_list_validation():
- """Test that empty list validates correctly."""
- alice = Address("0x000000000000000000000000000000000000000a")
-
- actual_bal = BlockAccessList(
- [
- BalAccountChange(
- address=alice,
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- balance_changes=[], # no balance changes
- ),
- ]
- )
-
- expectation = BlockAccessListExpectation(
- account_expectations={
- alice: BalAccountExpectation(
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- balance_changes=[], # explicitly expect no balance changes
- ),
- }
- )
-
- expectation.verify_against(actual_bal)
-
-
-def test_empty_list_validation_fails():
- """Test that validation fails when expecting empty but field has values."""
- alice = Address("0x000000000000000000000000000000000000000a")
-
- actual_bal = BlockAccessList(
- [
- BalAccountChange(
- address=alice,
- balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
- ),
- ]
- )
-
- expectation = BlockAccessListExpectation(
- account_expectations={
- # expect no balance changes (wrongly)
- alice: BalAccountExpectation(balance_changes=[]),
- }
- )
-
- with pytest.raises(Exception, match="Expected balance_changes to be empty"):
- expectation.verify_against(actual_bal)
-
-
-def test_partial_validation():
- """Test that unset fields are not validated."""
- alice = Address("0x000000000000000000000000000000000000000a")
-
- # Actual BAL has multiple types of changes
- actual_bal = BlockAccessList(
- [
- BalAccountChange(
- address=alice,
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
- storage_reads=[0x01, 0x02],
- ),
- ]
- )
-
- # Only validate nonce changes, ignore balance and storage
- expectation = BlockAccessListExpectation(
- account_expectations={
- alice: BalAccountExpectation(
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- # balance_changes and storage_reads not set and won't be validated
- ),
- }
- )
-
- expectation.verify_against(actual_bal)
-
-
-def test_storage_changes_validation():
- """Test storage changes validation."""
- contract = Address("0x000000000000000000000000000000000000000c")
-
- # Actual BAL with storage changes
- actual_bal = BlockAccessList(
- [
- BalAccountChange(
- address=contract,
- storage_changes=[
- BalStorageSlot(
- slot=0x01,
- slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
- )
- ],
- ),
- ]
- )
-
- # Expect the same storage changes
- expectation = BlockAccessListExpectation(
- account_expectations={
- contract: BalAccountExpectation(
- storage_changes=[
- BalStorageSlot(
- slot=0x01,
- slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
- )
- ],
- ),
- }
- )
-
- expectation.verify_against(actual_bal)
-
-
-def test_missing_expected_address():
- """Test that validation fails when expected address is missing."""
- alice = Address("0x000000000000000000000000000000000000000a")
- bob = Address("0x000000000000000000000000000000000000000b")
-
- actual_bal = BlockAccessList(
- [
- BalAccountChange(
- address=alice,
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- ),
- ]
- )
-
- expectation = BlockAccessListExpectation(
- account_expectations={
- # wrongly expect Bob to be present
- bob: BalAccountExpectation(
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
- ),
- }
- )
-
- with pytest.raises(Exception, match="Expected address .* not found in actual BAL"):
- expectation.verify_against(actual_bal)
diff --git a/src/ethereum_spec_tests/ethereum_test_vm/helpers.py b/src/ethereum_spec_tests/ethereum_test_vm/helpers.py
deleted file mode 100644
index 7460975f63..0000000000
--- a/src/ethereum_spec_tests/ethereum_test_vm/helpers.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""Helper functions for the EVM."""
-
-from .opcode import Opcodes as Op
-
-
-def call_return_code(opcode: Op, success: bool, *, revert: bool = False) -> int:
- """Return return code for a CALL operation."""
- if opcode in [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]:
- return int(success)
- elif opcode in [Op.EXTCALL, Op.EXTDELEGATECALL, Op.EXTSTATICCALL]:
- if success:
- return 0
- if revert:
- return 1
- return 2
- raise ValueError(f"Not a call opcode: {opcode}")
diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/__init__.py b/src/ethereum_spec_tests/pytest_plugins/execute/__init__.py
deleted file mode 100644
index 08e96f5178..0000000000
--- a/src/ethereum_spec_tests/pytest_plugins/execute/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""A pytest plugin that provides fixtures that execute tests in live devnets/testnets."""
diff --git a/src/ethereum_spec_tests/pytest_plugins/help/__init__.py b/src/ethereum_spec_tests/pytest_plugins/help/__init__.py
deleted file mode 100644
index c1a6507e99..0000000000
--- a/src/ethereum_spec_tests/pytest_plugins/help/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""Pytest plugin that prints help defined in other execution-spec-tests plugins."""
diff --git a/tests/eest/amsterdam/__init__.py b/tests/eest/amsterdam/__init__.py
index b4d638e152..89848292b5 100644
--- a/tests/eest/amsterdam/__init__.py
+++ b/tests/eest/amsterdam/__init__.py
@@ -1 +1,4 @@
-"""Test cases for EVM functionality introduced in Amsterdam, [EIP-7773: Hardfork Meta - Glamsterdam](https://eip.directory/eips/eip-7773).""" # noqa: E501
+"""
+Test cases for EVM functionality introduced in Amsterdam, [EIP-7773: Hardfork
+Meta - Glamsterdam](https://eip.directory/eips/eip-7773).
+"""
diff --git a/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py
index c01cdf698d..ad19a2687b 100644
--- a/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py
+++ b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py
@@ -1,17 +1,22 @@
"""Tests for EIP-7928 using the consistent data class pattern."""
+from typing import Dict
+
import pytest
+from ethereum_test_base_types import AccessList, Address, Hash
+from ethereum_test_forks import Fork
+from ethereum_test_specs.blockchain import Header
from ethereum_test_tools import (
Account,
Alloc,
Block,
BlockchainTestFiller,
- Storage,
+ Initcode,
Transaction,
compute_create_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_types import Environment
from ethereum_test_types.block_access_list import (
BalAccountExpectation,
BalBalanceChange,
@@ -21,14 +26,16 @@
BalStorageSlot,
BlockAccessListExpectation,
)
+from ethereum_test_vm import Opcodes as Op
from .spec import ref_spec_7928
REFERENCE_SPEC_GIT_PATH = ref_spec_7928.git_path
REFERENCE_SPEC_VERSION = ref_spec_7928.version
+pytestmark = pytest.mark.valid_from("Amsterdam")
+
-@pytest.mark.valid_from("Amsterdam")
def test_bal_nonce_changes(
pre: Alloc,
blockchain_test: BlockchainTestFiller,
@@ -64,7 +71,6 @@ def test_bal_nonce_changes(
)
-@pytest.mark.valid_from("Amsterdam")
def test_bal_balance_changes(
pre: Alloc,
blockchain_test: BlockchainTestFiller,
@@ -124,37 +130,63 @@ def test_bal_balance_changes(
)
-@pytest.mark.valid_from("Amsterdam")
-def test_bal_storage_writes(
+def test_bal_code_changes(
pre: Alloc,
blockchain_test: BlockchainTestFiller,
):
- """Ensure BAL captures storage writes."""
- storage = Storage({0x01: 0}) # type: ignore
- storage_contract = pre.deploy_contract(
- code=Op.SSTORE(0x01, 0x42) + Op.STOP,
- # pre-fill with canary value to detect writes in post-state
- storage=storage.canary(),
+ """Ensure BAL captures changes to account code."""
+ runtime_code = Op.STOP
+ runtime_code_bytes = bytes(runtime_code)
+
+ init_code = (
+ Op.PUSH1(len(runtime_code_bytes)) # size = 1
+ + Op.DUP1 # duplicate size for return
+ + Op.PUSH1(0x0C) # offset in init code where runtime code starts
+ + Op.PUSH1(0x00) # dest offset
+ + Op.CODECOPY # copy runtime code to memory
+ + Op.PUSH1(0x00) # memory offset for return
+ + Op.RETURN # return runtime code
+ + runtime_code # the actual runtime code to deploy
+ )
+ init_code_bytes = bytes(init_code)
+
+ # Factory contract that uses CREATE to deploy
+ factory_code = (
+ # Push init code to memory
+ Op.PUSH32(init_code_bytes)
+ + Op.PUSH1(0x00)
+ + Op.MSTORE # Store at memory position 0
+ # CREATE parameters: value, offset, size
+ + Op.PUSH1(len(init_code_bytes)) # size of init code
+ + Op.PUSH1(32 - len(init_code_bytes)) # offset in memory (account for padding)
+ + Op.PUSH1(0x00) # value = 0 (no ETH sent)
+ + Op.CREATE # Deploy the contract
+ + Op.STOP
)
+
+ factory_contract = pre.deploy_contract(code=factory_code)
alice = pre.fund_eoa()
tx = Transaction(
sender=alice,
- to=storage_contract,
- gas_limit=100000,
+ to=factory_contract,
+ gas_limit=500000,
)
+ created_contract = compute_create_address(address=factory_contract, nonce=1)
+
block = Block(
txs=[tx],
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
- storage_contract: BalAccountExpectation(
- storage_changes=[
- BalStorageSlot(
- slot=0x01,
- slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
- )
- ],
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ factory_contract: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=2)],
+ ),
+ created_contract: BalAccountExpectation(
+ code_changes=[BalCodeChange(tx_index=1, new_code=runtime_code_bytes)],
),
}
),
@@ -165,95 +197,258 @@ def test_bal_storage_writes(
blocks=[block],
post={
alice: Account(nonce=1),
- storage_contract: Account(storage={0x01: 0x42}),
+ factory_contract: Account(nonce=2), # incremented by CREATE to 2
+ created_contract: Account(
+ code=runtime_code_bytes,
+ storage={},
+ ),
},
)
-@pytest.mark.valid_from("Amsterdam")
-def test_bal_storage_reads(
+@pytest.mark.parametrize("self_destruct_in_same_tx", [True, False], ids=["same_tx", "new_tx"])
+@pytest.mark.parametrize("pre_funded", [True, False], ids=["pre_funded", "not_pre_funded"])
+def test_bal_self_destruct(
pre: Alloc,
blockchain_test: BlockchainTestFiller,
+ self_destruct_in_same_tx: bool,
+ pre_funded: bool,
):
- """Ensure BAL captures storage reads."""
- storage_contract = pre.deploy_contract(
- code=Op.SLOAD(0x01) + Op.STOP,
- storage={0x01: 0x42},
- )
+ """Ensure BAL captures balance changes caused by `SELFDESTRUCT`."""
alice = pre.fund_eoa()
+ bob = pre.fund_eoa(amount=0)
+
+ selfdestruct_code = (
+ Op.SLOAD(0x01) # Read from storage slot 0x01
+ + Op.SSTORE(0x02, 0x42) # Write to storage slot 0x02
+ + Op.SELFDESTRUCT(bob)
+ )
+ # A pre existing self-destruct contract with initial storage
+ kaboom = pre.deploy_contract(code=selfdestruct_code, storage={0x01: 0x123})
+
+ # A template for self-destruct contract
+ self_destruct_init_code = Initcode(deploy_code=selfdestruct_code)
+ template = pre.deploy_contract(code=self_destruct_init_code)
+
+ transfer_amount = expected_recipient_balance = 100
+ pre_fund_amount = 10
+
+ if self_destruct_in_same_tx:
+ # The goal is to create a self-destructing contract in the same
+ # transaction to trigger deletion of code as per EIP-6780.
+ # The factory contract below creates a new self-destructing
+ # contract and calls it in this transaction.
+
+ bytecode_size = len(self_destruct_init_code)
+ factory_bytecode = (
+ # Clone template memory
+ Op.EXTCODECOPY(template, 0, 0, bytecode_size)
+ # Fund 100 wei and deploy the clone
+ + Op.CREATE(transfer_amount, 0, bytecode_size)
+ # Call the clone, which self-destructs
+ + Op.CALL(100_000, Op.DUP6, 0, 0, 0, 0, 0)
+ + Op.STOP
+ )
+
+ factory = pre.deploy_contract(code=factory_bytecode)
+ kaboom_same_tx = compute_create_address(address=factory, nonce=1)
+
+ # Determine which account will be self-destructed
+ self_destructed_account = kaboom_same_tx if self_destruct_in_same_tx else kaboom
+
+ if pre_funded:
+ expected_recipient_balance += pre_fund_amount
+ pre.fund_address(address=self_destructed_account, amount=pre_fund_amount)
tx = Transaction(
sender=alice,
- to=storage_contract,
- gas_limit=100000,
+ to=factory if self_destruct_in_same_tx else kaboom,
+ value=transfer_amount,
+ gas_limit=1_000_000,
+ gas_price=0xA,
)
block = Block(
txs=[tx],
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
- storage_contract: BalAccountExpectation(
- storage_reads=[0x01],
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ bob: BalAccountExpectation(
+ balance_changes=[
+ BalBalanceChange(tx_index=1, post_balance=expected_recipient_balance)
+ ]
+ ),
+ self_destructed_account: BalAccountExpectation(
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=0)]
+ if pre_funded
+ else [],
+ # Accessed slots for same-tx are recorded as reads (0x02)
+ storage_reads=[0x01, 0x02] if self_destruct_in_same_tx else [0x01],
+ # Storage changes are recorded for non-same-tx
+ # self-destructs
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x02, slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)]
+ )
+ ]
+ if not self_destruct_in_same_tx
+ else [],
+ code_changes=[], # should not be present
+ nonce_changes=[], # should not be present
),
}
),
)
+ post: Dict[Address, Account] = {
+ alice: Account(nonce=1),
+ bob: Account(balance=expected_recipient_balance),
+ }
+
+ # If the account was self-destructed in the same transaction,
+ # we expect the account to non-existent and its balance to be 0.
+ if self_destruct_in_same_tx:
+ post.update(
+ {
+ factory: Account(
+ nonce=2, # incremented after CREATE
+ balance=0, # spent on CREATE
+ code=factory_bytecode,
+ ),
+ kaboom_same_tx: Account.NONEXISTENT, # type: ignore
+ # The pre-existing contract remains unaffected
+ kaboom: Account(balance=0, code=selfdestruct_code, storage={0x01: 0x123}),
+ }
+ )
+ else:
+ post.update(
+ {
+ # This contract was self-destructed in a separate tx.
+ # From EIP 6780: `SELFDESTRUCT` does not delete any data
+ # (including storage keys, code, or the account itself).
+ kaboom: Account(
+ balance=0, code=selfdestruct_code, storage={0x01: 0x123, 0x2: 0x42}
+ ),
+ }
+ )
+
blockchain_test(
pre=pre,
blocks=[block],
- post={
- alice: Account(nonce=1),
- storage_contract: Account(storage={0x01: 0x42}),
- },
+ post=post,
)
-@pytest.mark.valid_from("Amsterdam")
-def test_bal_code_changes(
+@pytest.mark.parametrize(
+ "account_access_opcode",
+ [
+ pytest.param(lambda target_addr: Op.BALANCE(target_addr), id="balance"),
+ pytest.param(lambda target_addr: Op.EXTCODESIZE(target_addr), id="extcodesize"),
+ pytest.param(lambda target_addr: Op.EXTCODECOPY(target_addr, 0, 0, 32), id="extcodecopy"),
+ pytest.param(lambda target_addr: Op.EXTCODEHASH(target_addr), id="extcodehash"),
+ pytest.param(lambda target_addr: Op.CALL(0, target_addr, 0, 0, 0, 0, 0), id="call"),
+ pytest.param(
+ lambda target_addr: Op.CALLCODE(0, target_addr, 0, 0, 0, 0, 0), id="callcode"
+ ),
+ pytest.param(
+ lambda target_addr: Op.DELEGATECALL(0, target_addr, 0, 0, 0, 0), id="delegatecall"
+ ),
+ pytest.param(
+ lambda target_addr: Op.STATICCALL(0, target_addr, 0, 0, 0, 0), id="staticcall"
+ ),
+ ],
+)
+def test_bal_account_access_target(
pre: Alloc,
blockchain_test: BlockchainTestFiller,
+ account_access_opcode,
):
- """Ensure BAL captures changes to account code."""
- runtime_code = Op.STOP
- runtime_code_bytes = bytes(runtime_code)
+ """Ensure BAL captures target address of account access opcodes."""
+ alice = pre.fund_eoa()
+ target_contract = pre.deploy_contract(code=Op.STOP)
- init_code = (
- Op.PUSH1(len(runtime_code_bytes)) # size = 1
- + Op.DUP1 # duplicate size for return
- + Op.PUSH1(0x0C) # offset in init code where runtime code starts
- + Op.PUSH1(0x00) # dest offset
- + Op.CODECOPY # copy runtime code to memory
- + Op.PUSH1(0x00) # memory offset for return
- + Op.RETURN # return runtime code
- + runtime_code # the actual runtime code to deploy
+ oracle_contract = pre.deploy_contract(
+ balance=100,
+ code=account_access_opcode(target_contract),
)
- init_code_bytes = bytes(init_code)
- # Factory contract that uses CREATE to deploy
- factory_code = (
- # Push init code to memory
- Op.PUSH32(init_code_bytes)
- + Op.PUSH1(0x00)
- + Op.MSTORE # Store at memory position 0
- # CREATE parameters: value, offset, size
- + Op.PUSH1(len(init_code_bytes)) # size of init code
- + Op.PUSH1(32 - len(init_code_bytes)) # offset in memory (account for padding)
- + Op.PUSH1(0x00) # value = 0 (no ETH sent)
- + Op.CREATE # Deploy the contract
- + Op.STOP
+ tx = Transaction(sender=alice, to=oracle_contract, gas_limit=5_000_000, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]
+ ),
+ target_contract: BalAccountExpectation.empty(),
+ oracle_contract: BalAccountExpectation.empty(),
+ }
+ ),
)
- factory_contract = pre.deploy_contract(code=factory_code)
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+def test_bal_call_with_value_transfer(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+):
+ """
+ Ensure BAL captures balance changes from CALL opcode with
+ value transfer.
+ """
alice = pre.fund_eoa()
+ bob = pre.fund_eoa(amount=0)
- tx = Transaction(
- sender=alice,
- to=factory_contract,
- gas_limit=500000,
+ # Oracle contract that uses CALL to transfer 100 wei to Bob
+ oracle_code = Op.CALL(0, bob, 100, 0, 0, 0, 0)
+ oracle_contract = pre.deploy_contract(code=oracle_code, balance=200)
+
+ tx = Transaction(sender=alice, to=oracle_contract, gas_limit=1_000_000, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ oracle_contract: BalAccountExpectation(
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
+ ),
+ bob: BalAccountExpectation(
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
+ ),
+ }
+ ),
)
- created_contract = compute_create_address(address=factory_contract, nonce=1)
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+def test_bal_callcode_with_value_transfer(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+):
+ """
+ Ensure BAL captures balance changes from CALLCODE opcode with
+ value transfer.
+ """
+ alice = pre.fund_eoa()
+ bob = pre.fund_eoa(amount=0)
+
+ # TargetContract sends 100 wei to bob
+ target_code = Op.CALL(0, bob, 100, 0, 0, 0, 0)
+ target_contract = pre.deploy_contract(code=target_code)
+
+ # Oracle contract that uses CALLCODE to execute TargetContract's code
+ oracle_code = Op.CALLCODE(50_000, target_contract, 100, 0, 0, 0, 0)
+ oracle_contract = pre.deploy_contract(code=oracle_code, balance=200)
+
+ tx = Transaction(sender=alice, to=oracle_contract, gas_limit=1_000_000, gas_price=0xA)
block = Block(
txs=[tx],
@@ -262,25 +457,703 @@ def test_bal_code_changes(
alice: BalAccountExpectation(
nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
),
- factory_contract: BalAccountExpectation(
- nonce_changes=[BalNonceChange(tx_index=1, post_nonce=2)],
+ oracle_contract: BalAccountExpectation(
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
),
- created_contract: BalAccountExpectation(
- code_changes=[BalCodeChange(tx_index=1, new_code=runtime_code_bytes)],
+ bob: BalAccountExpectation(
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
),
+ target_contract: BalAccountExpectation.empty(),
}
),
)
- blockchain_test(
- pre=pre,
- blocks=[block],
- post={
- alice: Account(nonce=1),
- factory_contract: Account(nonce=2), # incremented by CREATE to 2
- created_contract: Account(
- code=runtime_code_bytes,
- storage={},
- ),
- },
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+@pytest.mark.parametrize(
+ "delegated_opcode",
+ [
+ pytest.param(
+ lambda target_addr: Op.DELEGATECALL(50000, target_addr, 0, 0, 0, 0), id="delegatecall"
+ ),
+ pytest.param(
+ lambda target_addr: Op.CALLCODE(50000, target_addr, 0, 0, 0, 0, 0), id="callcode"
+ ),
+ ],
+)
+def test_bal_delegated_storage_writes(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ delegated_opcode,
+):
+ """
+ Ensure BAL captures delegated storage writes via
+ DELEGATECALL and CALLCODE.
+ """
+ alice = pre.fund_eoa()
+
+ # TargetContract that writes 0x42 to slot 0x01
+ target_code = Op.SSTORE(0x01, 0x42)
+ target_contract = pre.deploy_contract(code=target_code)
+
+ # Oracle contract that uses delegated opcode to execute
+ # TargetContract's code
+ oracle_code = delegated_opcode(target_contract)
+ oracle_contract = pre.deploy_contract(code=oracle_code)
+
+ tx = Transaction(
+ sender=alice,
+ to=oracle_contract,
+ gas_limit=1_000_000,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ oracle_contract: BalAccountExpectation(
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
+ )
+ ],
+ ),
+ target_contract: BalAccountExpectation.empty(),
+ }
+ ),
+ )
+
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+@pytest.mark.parametrize(
+ "delegated_opcode",
+ [
+ pytest.param(
+ lambda target_addr: Op.DELEGATECALL(50000, target_addr, 0, 0, 0, 0), id="delegatecall"
+ ),
+ pytest.param(
+ lambda target_addr: Op.CALLCODE(50000, target_addr, 0, 0, 0, 0, 0), id="callcode"
+ ),
+ ],
+)
+def test_bal_delegated_storage_reads(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ delegated_opcode,
+):
+ """
+ Ensure BAL captures delegated storage reads via
+ DELEGATECALL and CALLCODE.
+ """
+ alice = pre.fund_eoa()
+
+ # TargetContract that reads from slot 0x01
+ target_code = Op.SLOAD(0x01) + Op.STOP
+ target_contract = pre.deploy_contract(code=target_code)
+
+ # Oracle contract with storage slot 0x01 = 0x42,
+ # uses delegated opcode to execute TargetContract's code
+ oracle_code = delegated_opcode(target_contract)
+ oracle_contract = pre.deploy_contract(code=oracle_code, storage={0x01: 0x42})
+
+ tx = Transaction(
+ sender=alice,
+ to=oracle_contract,
+ gas_limit=1_000_000,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ oracle_contract: BalAccountExpectation(
+ storage_reads=[0x01],
+ ),
+ target_contract: BalAccountExpectation.empty(),
+ }
+ ),
)
+
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+def test_bal_block_rewards(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork,
+):
+ """Ensure BAL captures fee recipient balance changes from block rewards."""
+ alice_initial_balance = 1_000_000
+ alice = pre.fund_eoa(amount=alice_initial_balance)
+ bob = pre.fund_eoa(amount=0)
+ charlie = pre.fund_eoa(amount=0) # fee recipient
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas = intrinsic_gas_calculator(
+ calldata=b"",
+ contract_creation=False,
+ access_list=[],
+ )
+ tx_gas_limit = intrinsic_gas + 1000 # add a small buffer
+ gas_price = 0xA
+
+ tx = Transaction(
+ sender=alice,
+ to=bob,
+ value=100,
+ gas_limit=tx_gas_limit,
+ gas_price=gas_price,
+ )
+
+ # EIP-1559 fee calculation:
+ # - Total gas cost
+ total_gas_cost = intrinsic_gas * gas_price
+ # - Tip portion
+
+ genesis_env = Environment(base_fee_per_gas=0x7)
+ base_fee_per_gas = fork.base_fee_per_gas_calculator()(
+ parent_base_fee_per_gas=genesis_env.base_fee_per_gas,
+ parent_gas_used=0,
+ parent_gas_limit=genesis_env.gas_limit,
+ )
+ tip_to_charlie = (gas_price - base_fee_per_gas) * intrinsic_gas
+
+ alice_final_balance = alice_initial_balance - 100 - total_gas_cost
+
+ block = Block(
+ txs=[tx],
+ fee_recipient=charlie, # Set Charlie as the fee recipient
+ header_verify=Header(base_fee_per_gas=base_fee_per_gas),
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ balance_changes=[
+ BalBalanceChange(tx_index=1, post_balance=alice_final_balance)
+ ],
+ ),
+ bob: BalAccountExpectation(
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)],
+ ),
+ charlie: BalAccountExpectation(
+ balance_changes=[BalBalanceChange(tx_index=1, post_balance=tip_to_charlie)],
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={},
+ genesis_environment=genesis_env,
+ )
+
+
+def test_bal_2930_account_listed_but_untouched(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+):
+ """Ensure BAL excludes untouched access list accounts."""
+ alice = pre.fund_eoa()
+ bob = pre.fund_eoa()
+ oracle = pre.deploy_contract(code=Op.STOP)
+
+ access_list = AccessList(
+ address=oracle,
+ storage_keys=[Hash(0x1)],
+ )
+
+ gas_limit = 1_000_000
+
+ tx = Transaction(ty=1, sender=alice, to=bob, gas_limit=gas_limit, access_list=[access_list])
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ # The address excluded from BAL since state is not accessed
+ oracle: None,
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ },
+ )
+
+
+def test_bal_2930_slot_listed_but_untouched(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork,
+):
+ """Ensure BAL excludes untouched access list storage slots."""
+ alice = pre.fund_eoa()
+ pure_calculator = pre.deploy_contract(
+ # Pure add operation
+ Op.ADD(35, 7)
+ )
+
+ access_list = AccessList(
+ address=pure_calculator,
+ storage_keys=[Hash(0x1)],
+ )
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ gas_limit = (
+ intrinsic_gas_calculator(
+ calldata=b"",
+ contract_creation=False,
+ access_list=[access_list],
+ )
+ + 1000
+ ) # intrinsic + buffer
+
+ tx = Transaction(
+ ty=1, sender=alice, to=pure_calculator, gas_limit=gas_limit, access_list=[access_list]
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ # The account was loaded.
+ pure_calculator: BalAccountExpectation.empty(),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ },
+ )
+
+
+def test_bal_2930_slot_listed_and_unlisted_writes(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork,
+):
+ """
+ Ensure BAL includes storage writes regardless of access list presence.
+ """
+ alice = pre.fund_eoa()
+ storage_writer = pre.deploy_contract(code=Op.SSTORE(0x01, 0x42) + Op.SSTORE(0x02, 0x43))
+
+ # Access list only includes slot 0x01, but contract writes to both
+ # 0x01 and 0x02
+ access_list = AccessList(
+ address=storage_writer,
+ storage_keys=[Hash(0x01)],
+ )
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ gas_limit = (
+ intrinsic_gas_calculator(
+ calldata=b"",
+ contract_creation=False,
+ access_list=[access_list],
+ )
+ + 50000
+ ) # intrinsic + buffer for storage writes
+
+ tx = Transaction(
+ ty=1, sender=alice, to=storage_writer, gas_limit=gas_limit, access_list=[access_list]
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ storage_writer: BalAccountExpectation(
+ storage_changes=[
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
+ ),
+ BalStorageSlot(
+ slot=0x02,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x43)],
+ ),
+ ],
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ storage_writer: Account(storage={0x01: 0x42, 0x02: 0x43}),
+ },
+ )
+
+
+def test_bal_2930_slot_listed_and_unlisted_reads(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork,
+):
+ """Ensure BAL includes storage reads regardless of access list presence."""
+ alice = pre.fund_eoa()
+ storage_reader = pre.deploy_contract(
+ code=Op.SLOAD(0x01) + Op.SLOAD(0x02),
+ storage={0x01: 0x42, 0x02: 0x43}, # Pre-populate storage with values
+ )
+
+ # Access list only includes slot 0x01, but contract reads from both
+ # 0x01 and 0x02
+ access_list = AccessList(
+ address=storage_reader,
+ storage_keys=[Hash(0x01)],
+ )
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ gas_limit = (
+ intrinsic_gas_calculator(
+ calldata=b"",
+ contract_creation=False,
+ access_list=[access_list],
+ )
+ + 50000
+ ) # intrinsic + buffer for storage reads
+
+ tx = Transaction(
+ ty=1, sender=alice, to=storage_reader, gas_limit=gas_limit, access_list=[access_list]
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ storage_reader: BalAccountExpectation(
+ storage_reads=[0x01, 0x02],
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ storage_reader: Account(storage={0x01: 0x42, 0x02: 0x43}),
+ },
+ )
+
+
+def test_bal_self_transfer(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork,
+):
+ """Test that BAL correctly handles self-transfers."""
+ start_balance = 1_000_000
+ alice = pre.fund_eoa(amount=start_balance)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ tx = Transaction(
+ sender=alice, to=alice, gas_limit=intrinsic_gas_cost, value=100, gas_price=0xA
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ balance_changes=[
+ BalBalanceChange(
+ tx_index=1,
+ post_balance=start_balance - intrinsic_gas_cost * tx.gas_price,
+ )
+ ],
+ )
+ }
+ ),
+ )
+
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+def test_bal_zero_value_transfer(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork,
+):
+ """Test that BAL correctly handles zero-value transfers."""
+ start_balance = 1_000_000
+ alice = pre.fund_eoa(amount=start_balance)
+ bob = pre.fund_eoa(amount=100)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ tx = Transaction(sender=alice, to=bob, gas_limit=intrinsic_gas_cost, value=0, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ balance_changes=[
+ BalBalanceChange(
+ tx_index=1,
+ post_balance=start_balance - intrinsic_gas_cost * tx.gas_price,
+ )
+ ],
+ ),
+ # Include the address; omit from balance_changes.
+ bob: BalAccountExpectation(balance_changes=[]),
+ }
+ ),
+ )
+
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+def test_bal_pure_contract_call(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+):
+ """Test that BAL captures contract access for pure computation calls."""
+ alice = pre.fund_eoa()
+ pure_contract = pre.deploy_contract(code=Op.ADD(0x3, 0x2))
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ gas_limit = intrinsic_gas_calculator() + 5_000 # Buffer
+
+ tx = Transaction(sender=alice, to=pure_contract, gas_limit=gas_limit, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ # Ensure called contract is tracked
+ pure_contract: BalAccountExpectation.empty(),
+ }
+ ),
+ )
+
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+def test_bal_noop_storage_write(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+):
+ """Test that BAL correctly handles no-op storage write."""
+ alice = pre.fund_eoa()
+ storage_contract = pre.deploy_contract(code=Op.SSTORE(0x01, 0x42), storage={0x01: 0x42})
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ gas_limit = (
+ intrinsic_gas_calculator()
+ # Sufficient gas for write
+ + fork.gas_costs().G_COLD_SLOAD
+ + fork.gas_costs().G_COLD_ACCOUNT_ACCESS
+ + fork.gas_costs().G_STORAGE_SET
+ + fork.gas_costs().G_BASE * 10 # Buffer for push
+ )
+
+ tx = Transaction(sender=alice, to=storage_contract, gas_limit=gas_limit, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ storage_contract: BalAccountExpectation(
+ storage_reads=[0x01],
+ storage_changes=[],
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(pre=pre, blocks=[block], post={})
+
+
+@pytest.mark.parametrize(
+ "abort_opcode",
+ [
+ pytest.param(Op.REVERT(0, 0), id="revert"),
+ pytest.param(Op.INVALID, id="invalid"),
+ ],
+)
+def test_bal_aborted_storage_access(
+ pre: Alloc, blockchain_test: BlockchainTestFiller, abort_opcode: Op
+):
+ """Ensure BAL captures storage access in aborted transactions correctly."""
+ alice = pre.fund_eoa()
+ storage_contract = pre.deploy_contract(
+ code=Op.SLOAD(0x01) + Op.SSTORE(0x02, 0x42) + abort_opcode,
+ storage={0x01: 0x10}, # Pre-existing value in slot 0x01
+ )
+
+ tx = Transaction(sender=alice, to=storage_contract, gas_limit=5_000_000, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]
+ ),
+ storage_contract: BalAccountExpectation(
+ storage_changes=[],
+ storage_reads=[0x01, 0x02],
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={},
+ )
+
+
+@pytest.mark.parametrize(
+ "account_access_opcode",
+ [
+ pytest.param(lambda target_addr: Op.BALANCE(target_addr), id="balance"),
+ pytest.param(lambda target_addr: Op.EXTCODESIZE(target_addr), id="extcodesize"),
+ pytest.param(lambda target_addr: Op.EXTCODECOPY(target_addr, 0, 0, 32), id="extcodecopy"),
+ pytest.param(lambda target_addr: Op.EXTCODEHASH(target_addr), id="extcodehash"),
+ pytest.param(lambda target_addr: Op.CALL(0, target_addr, 50, 0, 0, 0, 0), id="call"),
+ pytest.param(
+ lambda target_addr: Op.CALLCODE(0, target_addr, 50, 0, 0, 0, 0), id="callcode"
+ ),
+ pytest.param(
+ lambda target_addr: Op.DELEGATECALL(0, target_addr, 0, 0, 0, 0), id="delegatecall"
+ ),
+ pytest.param(
+ lambda target_addr: Op.STATICCALL(0, target_addr, 0, 0, 0, 0), id="staticcall"
+ ),
+ ],
+)
+@pytest.mark.parametrize(
+ "abort_opcode",
+ [
+ pytest.param(Op.REVERT(0, 0), id="revert"),
+ pytest.param(Op.INVALID, id="invalid"),
+ ],
+)
+def test_bal_aborted_account_access(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ account_access_opcode,
+ abort_opcode: Op,
+):
+ """Ensure BAL captures account access in aborted transactions."""
+ alice = pre.fund_eoa()
+ target_contract = pre.deploy_contract(code=Op.STOP)
+
+ abort_contract = pre.deploy_contract(
+ balance=100,
+ code=account_access_opcode(target_contract) + abort_opcode,
+ )
+
+ tx = Transaction(sender=alice, to=abort_contract, gas_limit=5_000_000, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)]
+ ),
+ target_contract: BalAccountExpectation.empty(),
+ abort_contract: BalAccountExpectation.empty(),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={},
+ )
+
+
+def test_bal_fully_unmutated_account(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+):
+ """
+ Test that BAL captures account that has zero net mutations.
+
+ oracle account:
+ 1. Storage read and write the same value (no net change).
+ 2. Receives `0` value transfer (no net change).
+ """
+ alice = pre.fund_eoa()
+ # Deploy Oracle contract with pre-existing storage value
+ oracle = pre.deploy_contract(
+ code=Op.SSTORE(0x01, 0x42) + Op.STOP,
+ storage={0x01: 0x42}, # Pre-existing value
+ )
+
+ tx = Transaction(sender=alice, to=oracle, gas_limit=1_000_000, value=0, gas_price=0xA)
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ alice: BalAccountExpectation(
+ nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)],
+ ),
+ oracle: BalAccountExpectation(
+ storage_changes=[], # No net storage changes
+ storage_reads=[0x01], # But storage was accessed
+ balance_changes=[], # No net balance changes
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(pre=pre, blocks=[block], post={})
diff --git a/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py
index f86b7af401..34ae52f903 100644
--- a/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py
+++ b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py
@@ -1,7 +1,7 @@
"""
Test cases for invalid Block Access Lists.
-These tests verify that clients properly reject blocks with corrupted BALs
+These tests verify that clients properly reject blocks with corrupted BALs.
"""
import pytest
@@ -52,7 +52,10 @@ def test_bal_invalid_missing_nonce(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL is missing required nonce changes."""
+ """
+ Test that clients reject blocks where BAL is missing required nonce
+ changes.
+ """
sender = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
@@ -72,7 +75,7 @@ def test_bal_invalid_missing_nonce(
blocks=[
Block(
txs=[tx],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BLOCK_ACCESS_LIST,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
sender: BalAccountExpectation(
@@ -91,7 +94,9 @@ def test_bal_invalid_nonce_value(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL contains incorrect nonce value."""
+ """
+ Test that clients reject blocks where BAL contains incorrect nonce value.
+ """
sender = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
@@ -111,7 +116,7 @@ def test_bal_invalid_nonce_value(
blocks=[
Block(
txs=[tx],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BLOCK_ACCESS_LIST,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
sender: BalAccountExpectation(
@@ -130,7 +135,10 @@ def test_bal_invalid_storage_value(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL contains incorrect storage values."""
+ """
+ Test that clients reject blocks where BAL contains incorrect storage
+ values.
+ """
sender = pre.fund_eoa(amount=10**18)
# Simple storage contract with canary values
@@ -155,7 +163,7 @@ def test_bal_invalid_storage_value(
blocks=[
Block(
txs=[tx],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BLOCK_ACCESS_LIST,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
contract: BalAccountExpectation(
@@ -190,7 +198,10 @@ def test_bal_invalid_tx_order(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL has incorrect transaction ordering."""
+ """
+ Test that clients reject blocks where BAL has incorrect transaction
+ ordering.
+ """
sender1 = pre.fund_eoa(amount=10**18)
sender2 = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
@@ -219,7 +230,7 @@ def test_bal_invalid_tx_order(
blocks=[
Block(
txs=[tx1, tx2],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BLOCK_ACCESS_LIST,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
sender1: BalAccountExpectation(
@@ -247,7 +258,10 @@ def test_bal_invalid_account(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL contains accounts that don't exist."""
+ """
+ Test that clients reject blocks where BAL contains accounts that don't
+ exist.
+ """
sender = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
phantom = pre.fund_eoa(amount=0)
@@ -269,7 +283,7 @@ def test_bal_invalid_account(
blocks=[
Block(
txs=[tx],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BAL_EXTRA_ACCOUNT,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
sender: BalAccountExpectation(
@@ -295,7 +309,10 @@ def test_bal_invalid_duplicate_account(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL contains duplicate account entries."""
+ """
+ Test that clients reject blocks where BAL contains duplicate account
+ entries.
+ """
sender = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
@@ -337,7 +354,9 @@ def test_bal_invalid_account_order(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL has incorrect account ordering."""
+ """
+ Test that clients reject blocks where BAL has incorrect account ordering.
+ """
sender = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
@@ -412,7 +431,7 @@ def test_bal_invalid_complex_corruption(
blocks=[
Block(
txs=[tx1, tx2],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BLOCK_ACCESS_LIST,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
sender: BalAccountExpectation(
@@ -454,7 +473,9 @@ def test_bal_invalid_missing_account(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL is missing an entire account."""
+ """
+ Test that clients reject blocks where BAL is missing an entire account.
+ """
sender = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
@@ -474,7 +495,7 @@ def test_bal_invalid_missing_account(
blocks=[
Block(
txs=[tx],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BAL_MISSING_ACCOUNT,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
sender: BalAccountExpectation(
@@ -496,7 +517,9 @@ def test_bal_invalid_balance_value(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test that clients reject blocks where BAL contains incorrect balance value."""
+ """
+ Test that clients reject blocks where BAL contains incorrect balance value.
+ """
sender = pre.fund_eoa(amount=10**18)
receiver = pre.fund_eoa(amount=0)
@@ -516,7 +539,7 @@ def test_bal_invalid_balance_value(
blocks=[
Block(
txs=[tx],
- exception=BlockException.INCORRECT_BLOCK_FORMAT,
+ exception=BlockException.INVALID_BLOCK_ACCESS_LIST,
expected_block_access_list=BlockAccessListExpectation(
account_expectations={
receiver: BalAccountExpectation(
diff --git a/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py
new file mode 100644
index 0000000000..1bfb3fcb63
--- /dev/null
+++ b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py
@@ -0,0 +1,545 @@
+"""
+Tests for EIP-7928 Block Access Lists with single-opcode success and OOG
+scenarios.
+
+Block access lists (BAL) are generated via a client's state tracing journal.
+Residual journal entries may persist when opcodes run out of gas, resulting
+in a bloated BAL payload.
+
+Issues identified in:
+https://github.com/paradigmxyz/reth/issues/17765
+https://github.com/bluealloy/revm/pull/2903
+
+These tests ensure out-of-gas operations are not recorded in BAL,
+preventing consensus issues.
+"""
+
+import pytest
+
+from ethereum_test_forks import Fork
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ Block,
+ BlockchainTestFiller,
+ Transaction,
+)
+from ethereum_test_tools import (
+ Opcodes as Op,
+)
+from ethereum_test_types.block_access_list import (
+ BalAccountExpectation,
+ BalStorageChange,
+ BalStorageSlot,
+ BlockAccessListExpectation,
+)
+from ethereum_test_vm import Bytecode
+
+from .spec import ref_spec_7928
+
+REFERENCE_SPEC_GIT_PATH = ref_spec_7928.git_path
+REFERENCE_SPEC_VERSION = ref_spec_7928.version
+
+
+pytestmark = pytest.mark.valid_from("Amsterdam")
+
+
+@pytest.mark.parametrize(
+ "fails_at_sstore", [True, False], ids=["oog_at_sstore", "successful_sstore"]
+)
+def test_bal_sstore_and_oog(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+ fails_at_sstore: bool,
+):
+ """
+ Ensure BAL handles SSTORE and OOG during SSTORE appropriately.
+ """
+ alice = pre.fund_eoa()
+ gas_costs = fork.gas_costs()
+
+ # Create contract that attempts SSTORE to cold storage slot 0x01
+ storage_contract_code = Bytecode(
+ Op.PUSH1(0x42) # Value to store
+ + Op.PUSH1(0x01) # Storage slot (cold)
+ + Op.SSTORE # Store value in slot - this will OOG
+ + Op.STOP
+ )
+
+ storage_contract = pre.deploy_contract(code=storage_contract_code)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ # Costs:
+ # - PUSH1 (value and slot) = G_VERY_LOW * 2
+ # - SSTORE cold (to zero slot) = G_STORAGE_SET + G_COLD_SLOAD
+ sstore_cold_cost = gas_costs.G_STORAGE_SET + gas_costs.G_COLD_SLOAD
+ push_cost = gas_costs.G_VERY_LOW * 2
+ tx_gas_limit = intrinsic_gas_cost + push_cost + sstore_cold_cost
+
+ if fails_at_sstore:
+ # subtract 1 gas to ensure OOG at SSTORE
+ tx_gas_limit -= 1
+
+ tx = Transaction(
+ sender=alice,
+ to=storage_contract,
+ gas_limit=tx_gas_limit,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ storage_contract: BalAccountExpectation(
+ storage_changes=[]
+ if fails_at_sstore
+ else [
+ BalStorageSlot(
+ slot=0x01,
+ slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)],
+ ),
+ ]
+ )
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ storage_contract: Account(storage={} if fails_at_sstore else {0x01: 0x42}),
+ },
+ )
+
+
+@pytest.mark.parametrize(
+ "fails_at_sload",
+ [True, False],
+ ids=["oog_at_sload", "successful_sload"],
+)
+def test_bal_sload_and_oog(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+ fails_at_sload: bool,
+):
+ """
+ Ensure BAL handles SLOAD and OOG during SLOAD appropriately.
+ """
+ alice = pre.fund_eoa()
+ gas_costs = fork.gas_costs()
+
+ # Create contract that attempts SLOAD from cold storage slot 0x01
+ storage_contract_code = Bytecode(
+ Op.PUSH1(0x01) # Storage slot (cold)
+ + Op.SLOAD # Load value from slot - this will OOG
+ + Op.STOP
+ )
+
+ storage_contract = pre.deploy_contract(code=storage_contract_code)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ # Costs:
+ # - PUSH1 (slot) = G_VERY_LOW
+ # - SLOAD cold = G_COLD_SLOAD
+ push_cost = gas_costs.G_VERY_LOW
+ sload_cold_cost = gas_costs.G_COLD_SLOAD
+ tx_gas_limit = intrinsic_gas_cost + push_cost + sload_cold_cost
+
+ if fails_at_sload:
+ # subtract 1 gas to ensure OOG at SLOAD
+ tx_gas_limit -= 1
+
+ tx = Transaction(
+ sender=alice,
+ to=storage_contract,
+ gas_limit=tx_gas_limit,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ storage_contract: BalAccountExpectation(
+ storage_reads=[] if fails_at_sload else [0x01],
+ )
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ storage_contract: Account(storage={}),
+ },
+ )
+
+
+@pytest.mark.parametrize(
+ "fails_at_balance", [True, False], ids=["oog_at_balance", "successful_balance"]
+)
+def test_bal_balance_and_oog(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+ fails_at_balance: bool,
+):
+ """Ensure BAL handles BALANCE and OOG during BALANCE appropriately."""
+ alice = pre.fund_eoa()
+ bob = pre.fund_eoa()
+ gas_costs = fork.gas_costs()
+
+ # Create contract that attempts to check Bob's balance
+ balance_checker_code = Bytecode(
+ Op.PUSH20(bob) # Bob's address
+ + Op.BALANCE # Check balance (cold access)
+ + Op.STOP
+ )
+
+ balance_checker = pre.deploy_contract(code=balance_checker_code)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ # Costs:
+ # - PUSH20 = G_VERY_LOW
+ # - BALANCE cold = G_COLD_ACCOUNT_ACCESS
+ push_cost = gas_costs.G_VERY_LOW
+ balance_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS
+ tx_gas_limit = intrinsic_gas_cost + push_cost + balance_cold_cost
+
+ if fails_at_balance:
+ # subtract 1 gas to ensure OOG at BALANCE
+ tx_gas_limit -= 1
+
+ tx = Transaction(
+ sender=alice,
+ to=balance_checker,
+ gas_limit=tx_gas_limit,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ balance_checker: BalAccountExpectation.empty(),
+ # Bob should only appear in BAL if BALANCE succeeded
+ **({} if fails_at_balance else {bob: BalAccountExpectation.empty()}),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ bob: Account(),
+ balance_checker: Account(),
+ },
+ )
+
+
+@pytest.mark.parametrize(
+ "fails_at_extcodesize", [True, False], ids=["oog_at_extcodesize", "successful_extcodesize"]
+)
+def test_bal_extcodesize_and_oog(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+ fails_at_extcodesize: bool,
+):
+ """
+ Ensure BAL handles EXTCODESIZE and OOG during EXTCODESIZE appropriately.
+ """
+ alice = pre.fund_eoa()
+ gas_costs = fork.gas_costs()
+
+ # Create target contract with some code
+ target_contract = pre.deploy_contract(code=Bytecode(Op.STOP))
+
+ # Create contract that checks target's code size
+ codesize_checker_code = Bytecode(
+ Op.PUSH20(target_contract) # Target contract address
+ + Op.EXTCODESIZE # Check code size (cold access)
+ + Op.STOP
+ )
+
+ codesize_checker = pre.deploy_contract(code=codesize_checker_code)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ # Costs:
+ # - PUSH20 = G_VERY_LOW
+ # - EXTCODESIZE cold = G_COLD_ACCOUNT_ACCESS
+ push_cost = gas_costs.G_VERY_LOW
+ extcodesize_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS
+ tx_gas_limit = intrinsic_gas_cost + push_cost + extcodesize_cold_cost
+
+ if fails_at_extcodesize:
+ # subtract 1 gas to ensure OOG at EXTCODESIZE
+ tx_gas_limit -= 1
+
+ tx = Transaction(
+ sender=alice,
+ to=codesize_checker,
+ gas_limit=tx_gas_limit,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ codesize_checker: BalAccountExpectation.empty(),
+ # Target should only appear if EXTCODESIZE succeeded
+ **(
+ {}
+ if fails_at_extcodesize
+ else {target_contract: BalAccountExpectation.empty()}
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ codesize_checker: Account(),
+ target_contract: Account(),
+ },
+ )
+
+
+@pytest.mark.parametrize("fails_at_call", [True, False], ids=["oog_at_call", "successful_call"])
+def test_bal_call_and_oog(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+ fails_at_call: bool,
+):
+ """Ensure BAL handles CALL and OOG during CALL appropriately."""
+ alice = pre.fund_eoa()
+ bob = pre.fund_eoa()
+ gas_costs = fork.gas_costs()
+
+ # Create contract that attempts to call Bob
+ call_contract_code = Bytecode(
+ Op.PUSH1(0) # retSize
+ + Op.PUSH1(0) # retOffset
+ + Op.PUSH1(0) # argsSize
+ + Op.PUSH1(0) # argsOffset
+ + Op.PUSH1(0) # value
+ + Op.PUSH20(bob) # address
+ + Op.PUSH2(0xFFFF) # gas (provide enough for the call)
+ + Op.CALL # Call (cold account access)
+ + Op.STOP
+ )
+
+ call_contract = pre.deploy_contract(code=call_contract_code)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ # Costs:
+ # - 7 PUSH operations = G_VERY_LOW * 7
+ # - CALL cold = G_COLD_ACCOUNT_ACCESS (minimum for account access)
+ push_cost = gas_costs.G_VERY_LOW * 7
+ call_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS
+ tx_gas_limit = intrinsic_gas_cost + push_cost + call_cold_cost
+
+ if fails_at_call:
+ # subtract 1 gas to ensure OOG at CALL
+ tx_gas_limit -= 1
+
+ tx = Transaction(
+ sender=alice,
+ to=call_contract,
+ gas_limit=tx_gas_limit,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ call_contract: BalAccountExpectation.empty(),
+ # Bob should only appear if CALL succeeded
+ **({} if fails_at_call else {bob: BalAccountExpectation.empty()}),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ call_contract: Account(),
+ },
+ )
+
+
+@pytest.mark.parametrize(
+ "fails_at_delegatecall", [True, False], ids=["oog_at_delegatecall", "successful_delegatecall"]
+)
+def test_bal_delegatecall_and_oog(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+ fails_at_delegatecall: bool,
+):
+ """
+ Ensure BAL handles DELEGATECALL and OOG during DELEGATECALL
+ appropriately.
+ """
+ alice = pre.fund_eoa()
+ gas_costs = fork.gas_costs()
+
+ # Create target contract
+ target_contract = pre.deploy_contract(code=Bytecode(Op.STOP))
+
+ # Create contract that attempts delegatecall to target
+ delegatecall_contract_code = Bytecode(
+ Op.PUSH1(0) # retSize
+ + Op.PUSH1(0) # retOffset
+ + Op.PUSH1(0) # argsSize
+ + Op.PUSH1(0) # argsOffset
+ + Op.PUSH20(target_contract) # address
+ + Op.PUSH2(0xFFFF) # gas (provide enough for the call)
+ + Op.DELEGATECALL # Delegatecall (cold account access)
+ + Op.STOP
+ )
+
+ delegatecall_contract = pre.deploy_contract(code=delegatecall_contract_code)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ # Costs:
+ # - 6 PUSH operations = G_VERY_LOW * 6
+ # - DELEGATECALL cold = G_COLD_ACCOUNT_ACCESS
+ push_cost = gas_costs.G_VERY_LOW * 6
+ delegatecall_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS
+ tx_gas_limit = intrinsic_gas_cost + push_cost + delegatecall_cold_cost
+
+ if fails_at_delegatecall:
+ # subtract 1 gas to ensure OOG at DELEGATECALL
+ tx_gas_limit -= 1
+
+ tx = Transaction(
+ sender=alice,
+ to=delegatecall_contract,
+ gas_limit=tx_gas_limit,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ delegatecall_contract: BalAccountExpectation.empty(),
+ # Target should only appear if DELEGATECALL succeeded
+ **(
+ {}
+ if fails_at_delegatecall
+ else {target_contract: BalAccountExpectation.empty()}
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ delegatecall_contract: Account(),
+ target_contract: Account(),
+ },
+ )
+
+
+@pytest.mark.parametrize(
+ "fails_at_extcodecopy", [True, False], ids=["oog_at_extcodecopy", "successful_extcodecopy"]
+)
+def test_bal_extcodecopy_and_oog(
+ pre: Alloc,
+ blockchain_test: BlockchainTestFiller,
+ fork: Fork,
+ fails_at_extcodecopy: bool,
+):
+ """
+ Ensure BAL handles EXTCODECOPY and OOG during EXTCODECOPY appropriately.
+ """
+ alice = pre.fund_eoa()
+ gas_costs = fork.gas_costs()
+
+ # Create target contract with some code
+ target_contract = pre.deploy_contract(code=Bytecode(Op.PUSH1(0x42) + Op.STOP))
+
+ # Create contract that attempts to copy code from target
+ extcodecopy_contract_code = Bytecode(
+ Op.PUSH1(0) # size - copy 0 bytes to minimize memory expansion cost
+ + Op.PUSH1(0) # codeOffset
+ + Op.PUSH1(0) # destOffset
+ + Op.PUSH20(target_contract) # address
+ + Op.EXTCODECOPY # Copy code (cold access + base cost)
+ + Op.STOP
+ )
+
+ extcodecopy_contract = pre.deploy_contract(code=extcodecopy_contract_code)
+
+ intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
+ intrinsic_gas_cost = intrinsic_gas_calculator()
+
+ # Costs:
+ # - 4 PUSH operations = G_VERY_LOW * 4
+ # - EXTCODECOPY cold = G_COLD_ACCOUNT_ACCESS + G_COPY (base cost)
+ push_cost = gas_costs.G_VERY_LOW * 4
+ extcodecopy_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + gas_costs.G_COPY
+ tx_gas_limit = intrinsic_gas_cost + push_cost + extcodecopy_cold_cost
+
+ if fails_at_extcodecopy:
+ # subtract 1 gas to ensure OOG at EXTCODECOPY
+ tx_gas_limit -= 1
+
+ tx = Transaction(
+ sender=alice,
+ to=extcodecopy_contract,
+ gas_limit=tx_gas_limit,
+ )
+
+ block = Block(
+ txs=[tx],
+ expected_block_access_list=BlockAccessListExpectation(
+ account_expectations={
+ extcodecopy_contract: BalAccountExpectation.empty(),
+ # Target should only appear if EXTCODECOPY succeeded
+ **(
+ {}
+ if fails_at_extcodecopy
+ else {target_contract: BalAccountExpectation.empty()}
+ ),
+ }
+ ),
+ )
+
+ blockchain_test(
+ pre=pre,
+ blocks=[block],
+ post={
+ alice: Account(nonce=1),
+ extcodecopy_contract: Account(),
+ target_contract: Account(),
+ },
+ )
diff --git a/tests/eest/amsterdam/eip7928_block_level_access_lists/test_cases.md b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_cases.md
index 3c371be939..033e37d5ca 100644
--- a/tests/eest/amsterdam/eip7928_block_level_access_lists/test_cases.md
+++ b/tests/eest/amsterdam/eip7928_block_level_access_lists/test_cases.md
@@ -7,12 +7,30 @@
| `test_bal_storage_writes` | Ensure BAL captures storage writes | Alice calls contract that writes to storage slot `0x01` | BAL MUST include storage changes with correct slot and value | ✅ Completed |
| `test_bal_storage_reads` | Ensure BAL captures storage reads | Alice calls contract that reads from storage slot `0x01` | BAL MUST include storage access for the read operation | ✅ Completed |
| `test_bal_code_changes` | Ensure BAL captures changes to account code | Alice deploys factory contract that creates new contract | BAL MUST include code changes for newly deployed contract | ✅ Completed |
-| `test_bal_2930_slot_listed_but_untouched` | Ensure 2930 access list alone doesn’t appear in BAL | Include `(KV, S=0x01)` in tx’s EIP-2930 access list; tx executes code that does **no** `SLOAD`/`SSTORE` to `S` (e.g., pure arithmetic/log). | BAL **MUST NOT** contain any entry for `(KV, S)` — neither reads nor writes — because the slot wasn’t touched. | 🟡 Planned |
-| `test_bal_2930_slot_listed_and_modified` | Ensure BAL records writes only because the slot is touched | Same access list as above, but tx executes `SSTORE` to `S`. | BAL **MUST** include `storage_changes` for `(KV, S)` (and no separate read record for that slot if implementation deduplicates). Presence in the access list is irrelevant; inclusion is due to the actual write. | 🟡 Planned |
+| `test_bal_self_destruct` | Ensure BAL captures storage access and balance changes caused by `SELFDESTRUCT` | Parameterized test: Alice interacts with a contract (either existing or created same-tx) that reads from storage slot 0x01, writes to storage slot 0x02, then executes `SELFDESTRUCT` with Bob as recipient. Contract may be pre-funded with 10 wei | BAL MUST include Alice's nonce change (increment) and Bob's balance change (100 or 110 depending on pre-funding). For the self-destructing contract: storage_reads=[0x01], empty storage_changes=[], and if pre-funded, balance_changes with post_balance=0; if not pre-funded, no balance change recorded. MUST NOT have code_changes or nonce_changes entries | ✅ Completed |
+| `test_bal_account_access_target` | Ensure BAL captures target addresses of account access opcodes | Alice calls `Oracle` contract which uses account access opcodes (`BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) on `TargetContract`. | BAL MUST include Alice, `Oracle`, and `TargetContract` with empty changes for `TargetContract` and nonce changes for Alice. | ✅ Completed |
+| `test_bal_call_with_value_transfer` | Ensure BAL captures balance changes from `CALL` opcode with value transfer | Alice calls `Oracle` contract (200 wei balance) which uses `CALL` opcode to transfer 100 wei to Bob (0 wei balance). | BAL MUST include Alice (nonce changes), Oracle (balance change to 100 wei), and Bob (balance change to 100 wei). | ✅ Completed |
+| `test_bal_callcode_with_value_transfer` | Ensure BAL captures balance changes from `CALLCODE` opcode with value transfer | Alice calls `Oracle` contract (200 wei balance) which uses `CALLCODE` opcode to execute `TargetContract`'s code with 100 wei value transfer to Bob (0 wei balance). | BAL MUST include Alice (nonce changes), `Oracle` (balance change to 100 wei), Bob (balance change to 100 wei), and `TargetContract` (empty changes). | ✅ Completed |
+| `test_bal_delegated_storage_writes` | Ensure BAL captures delegated storage writes via `DELEGATECALL` and `CALLCODE` | Alice calls `Oracle` contract which uses `DELEGATECALL`/`CALLCODE` to `TargetContract` that writes `0x42` to slot `0x01`. | BAL MUST include Alice (nonce changes), `Oracle` (storage changes for slot `0x01` = `0x42`), and `TargetContract` (empty changes). | ✅ Completed |
+| `test_bal_delegated_storage_reads` | Ensure BAL captures delegated storage reads via `DELEGATECALL` and `CALLCODE` | Alice calls `Oracle` contract (with slot `0x01` = `0x42`) which uses `DELEGATECALL`/`CALLCODE` to `TargetContract` that reads from slot `0x01`. | BAL MUST include Alice (nonce changes), `Oracle` (storage reads for slot `0x01`), and `TargetContract` (empty changes). | ✅ Completed |
+| `test_bal_block_rewards` | BAL tracks fee recipient balance changes from block rewards | Alice sends 100 wei to Bob with Charlie as fee recipient | BAL MUST include fee recipient Charlie with `balance_changes` reflecting transaction fees collected from the block. | ✅ Completed |
+| `test_bal_2930_account_listed_but_untouched` | Ensure BAL excludes listed but untouched account | Alice sends a simple eth transfer tx to Bob with EIP-2930 access list including `Oracle` | BAL MUST NOT include any entry for `Oracle` because it wasn't accessed. | ✅ Completed |
+| `test_bal_2930_slot_listed_but_untouched` | Ensure BAL excludes listed but untouched storage slots | Alice sends tx with EIP-2930 access list including `(PureCalculator, slot=0x01)`; PureCalculator executes pure arithmetic (adding two numbers) without touching slot `0x01` | BAL MUST NOT include any entry for PureCalculator's slot `0x01` because it doesn't access state | ✅ Completed |
+| `test_bal_2930_slot_listed_and_unlisted_writes` | Ensure BAL includes storage writes regardless of access list presence | Alice sends tx with EIP-2930 access list including `(StorageWriter, slot=0x01)`; StorageWriter executes `SSTORE` to slots `0x01` and `0x02` | BAL MUST include `storage_changes` for StorageWriter's slots `0x01` and `0x02` | ✅ Completed |
+| `test_bal_2930_slot_listed_and_unlisted_reads` | Ensure BAL includes storage reads regardless of access list presence | Alice sends tx with EIP-2930 access list including `(StorageReader, slot=0x01)`; StorageReader executes `SLOAD` from slots `0x01` and `0x02` | BAL MUST include `storage_reads` for StorageReader's slots `0x01` and `0x02` | ✅ Completed |
| `test_bal_7702_delegated_create` | BAL tracks EIP-7702 delegation indicator write and contract creation | Alice sends a type-4 (7702) tx authorizing herself to delegate to `Deployer` code which executes `CREATE` | BAL MUST include for **Alice**: `code_changes` (delegation indicator), `nonce_changes` (increment from 7702 processing), and `balance_changes` (post-gas). For **Child**: `code_changes` (runtime bytecode) and `nonce_changes = 1`. | 🟡 Planned |
-| `test_bal_self_transfer` | BAL handles self-transfers correctly | Alice sends `1 ETH` to **Alice** | BAL MUST include **one** entry for Alice with `balance_changes` reflecting **gas only** (value cancels out) and a nonce change; Coinbase balance updated for fees; no separate recipient row. | 🟡 Planned |
+| `test_bal_self_transfer` | BAL handles self-transfers correctly | Alice sends `100 wei` to Alice | BAL **MUST** include one entry for Alice with `balance_changes` reflecting gas cost only (value cancels out) and nonce change. | ✅ Completed |
+| `test_bal_zero_value_transfer` | BAL handles zero-value transfers correctly | Alice sends `0 wei` to Bob | BAL **MUST** include Alice with `balance_changes` (gas cost only) and nonce change, and Bob in `account_changes` with empty `balance_changes`. | ✅ Completed |
| `test_bal_system_contracts_2935_4788` | BAL includes pre-exec system writes for parent hash & beacon root | Build a block with `N` normal txs; 2935 & 4788 active | BAL MUST include `HISTORY_STORAGE_ADDRESS` (EIP-2935) and `BEACON_ROOTS_ADDRESS` (EIP-4788) with `storage_changes` to ring-buffer slots; each write uses `tx_index = N` (system op). | 🟡 Planned |
| `test_bal_system_dequeue_withdrawals_eip7002` | BAL tracks post-exec system dequeues for withdrawals | Pre-populate EIP-7002 withdrawal requests; produce a block where dequeues occur | BAL MUST include the 7002 system contract with `storage_changes` (queue head/tail slots 0–3) using `tx_index = len(txs)` and balance changes for withdrawal recipients. | 🟡 Planned |
| `test_bal_system_dequeue_consolidations_eip7251` | BAL tracks post-exec system dequeues for consolidations | Pre-populate EIP-7251 consolidation requests; produce a block where dequeues occur | BAL MUST include the 7251 system contract with `storage_changes` (queue slots 0–3) using `tx_index = len(txs)`. | 🟡 Planned |
+| `test_bal_aborted_storage_access` | Ensure BAL captures storage access in aborted transactions correctly | Alice calls contract that reads storage slot `0x01`, writes to slot `0x02`, then aborts with `REVERT`/`INVALID` | BAL MUST include storage_reads for slots `0x01` and `0x02` (aborted writes become reads), empty storage_changes. Only nonce changes for Alice. | ✅ Completed |
+| `test_bal_aborted_account_access` | Ensure BAL captures account access in aborted transactions for all account accessing opcodes | Alice calls `AbortContract` that performs account access operations (`BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) on `TargetContract` and aborts via `REVERT`/`INVALID` | BAL MUST include Alice, `TargetContract`, and `AbortContract` in account_changes and nonce changes for Alice. | ✅ Completed |
+| `test_bal_pure_contract_call` | Ensure BAL captures contract access for pure computation calls | Alice calls `PureContract` that performs pure arithmetic (ADD operation) without storage or balance changes | BAL MUST include Alice and `PureContract` in `account_changes`, and `nonce_changes` for Alice. | ✅ Completed |
+| `test_bal_create2_to_A_read_then_selfdestruct` | BAL records balance change for A and storage access (no persistent change) | Tx0: Alice sends ETH to address **A**. Tx1: Deployer `CREATE2` a contract **at A**; contract does `SLOAD(B)` and immediately `SELFDESTRUCT(beneficiary=X)` in the same tx. | BAL **MUST** include **A** with `balance_changes` (funding in Tx0 and transfer on selfdestruct in Tx1). BAL **MUST** include storage key **B** as an accessed `StorageKey`, and **MUST NOT** include **B** under `storage_changes` (no persistence due to same-tx create+destruct). | 🟡 Planned |
+| `test_bal_create2_to_A_write_then_selfdestruct` | BAL records balance change for A and storage access even if a write occurred (no persistent change) | Tx0: Alice sends ETH to **A**. Tx1: Deployer `CREATE2` contract **at A**; contract does `SSTORE(B, v)` (optionally `SLOAD(B)`), then `SELFDESTRUCT(beneficiary=Y)` in the same tx. | BAL **MUST** include **A** with `balance_changes` (Tx0 fund; Tx1 outflow to `Y`). BAL **MUST** include **B** as `StorageKey` accessed, and **MUST NOT** include **B** under `storage_changes` (ephemeral write discarded because the contract was created and destroyed in the same tx). | 🟡 Planned |
+| `test_bal_precompile_funded_then_called` | BAL records precompile with balance change (fund) and access (call) | **Tx0**: Alice sends `1 ETH` to `ecrecover` (0x01). **Tx1**: Alice (or Bob) calls `ecrecover` with valid input and `0 ETH`. | BAL **MUST** include address `0x01` with `balance_changes` (from Tx0). No `storage_changes` or `code_changes`. | 🟡 Planned |
+| `test_bal_precompile_call_only` | BAL records precompile when called with no balance change | Alice calls `ecrecover` (0x01) with a valid input, sending **0 ETH**. | BAL **MUST** include address `0x01` in access list, with **no** `balance_changes`, `storage_changes`, or `code_changes`. | 🟡 Planned |
+| `test_bal_fully_unmutated_account` | Ensure BAL captures account that has zero net mutations | Alice sends 0 wei to `Oracle` which writes same pre-existing value to storage | BAL MUST include Alice with `nonce_changes` and balance changes (gas), `Oracle` with `storage_reads` for accessed slot but empty `storage_changes`. | ✅ Completed |
> ℹ️ Scope describes whether a test spans a single transaction (`tx`) or entire block (`blk`).
diff --git a/tests/eest/benchmark/__init__.py b/tests/eest/benchmark/__init__.py
index 8c37b7d6e0..ce3a8eda04 100644
--- a/tests/eest/benchmark/__init__.py
+++ b/tests/eest/benchmark/__init__.py
@@ -1,8 +1,9 @@
"""
-abstract: Benchmark tests for EVMs.
- Benchmark tests aim to maximize the usage of a specific opcode,
- precompile, or operation within a transaction or block. These can
- be executed against EVM implementations to ensure they handle
- pathological cases efficiently and correctly, allowing Ethereum to
- safely [Scale the L1](https://protocol.ethereum.foundation/).
+Benchmark tests for EVMs.
+
+Benchmark tests aim to maximize the usage of a specific opcode, precompile,
+or operation within a transaction or block. These can be executed against
+EVM implementations to ensure they handle pathological cases efficiently
+and correctly, allowing Ethereum to safely
+[Scale the L1](https://protocol.ethereum.foundation/).
"""
diff --git a/tests/eest/benchmark/conftest.py b/tests/eest/benchmark/conftest.py
index 3af1bf9ade..d4225107ae 100644
--- a/tests/eest/benchmark/conftest.py
+++ b/tests/eest/benchmark/conftest.py
@@ -4,11 +4,16 @@
import pytest
+from ethereum_test_forks import Fork
+
DEFAULT_BENCHMARK_FORK = "Prague"
def pytest_generate_tests(metafunc):
- """Modify test generation to enforce default benchmark fork for benchmark tests."""
+ """
+ Modify test generation to enforce default benchmark fork for benchmark
+ tests.
+ """
benchmark_dir = Path(__file__).parent
test_file_path = Path(metafunc.definition.fspath)
@@ -33,8 +38,10 @@ def pytest_collection_modifyitems(config, items):
if gen_docs:
for item in items:
- if benchmark_dir in Path(item.fspath).parents and not item.get_closest_marker(
- "benchmark"
+ if (
+ benchmark_dir in Path(item.fspath).parents
+ and not item.get_closest_marker("benchmark")
+ and not item.get_closest_marker("stateful")
):
item.add_marker(benchmark_marker)
return
@@ -42,12 +49,18 @@ def pytest_collection_modifyitems(config, items):
marker_expr = config.getoption("-m", default="")
run_benchmarks = (
marker_expr and "benchmark" in marker_expr and "not benchmark" not in marker_expr
- ) or config.getoption("--gas-benchmark-values", default=None)
+ )
+ run_stateful_tests = (
+ marker_expr and "stateful" in marker_expr and "not stateful" not in marker_expr
+ )
items_for_removal = []
for i, item in enumerate(items):
is_in_benchmark_dir = benchmark_dir in Path(item.fspath).parents
- is_benchmark_test = is_in_benchmark_dir or item.get_closest_marker("benchmark")
+ has_stateful_marker = item.get_closest_marker("stateful")
+ is_benchmark_test = (
+ is_in_benchmark_dir and not has_stateful_marker
+ ) or item.get_closest_marker("benchmark")
if is_benchmark_test:
if is_in_benchmark_dir and not item.get_closest_marker("benchmark"):
@@ -56,6 +69,14 @@ def pytest_collection_modifyitems(config, items):
items_for_removal.append(i)
elif run_benchmarks:
items_for_removal.append(i)
+ elif is_in_benchmark_dir and has_stateful_marker and not run_stateful_tests:
+ items_for_removal.append(i)
for i in reversed(items_for_removal):
items.pop(i)
+
+
+@pytest.fixture
+def tx_gas_limit_cap(fork: Fork, gas_benchmark_value: int) -> int:
+ """Return the transaction gas limit cap."""
+ return fork.transaction_gas_limit_cap() or gas_benchmark_value
diff --git a/tests/eest/benchmark/helpers.py b/tests/eest/benchmark/helpers.py
index 833a5dd1ec..c0e7f80ac6 100644
--- a/tests/eest/benchmark/helpers.py
+++ b/tests/eest/benchmark/helpers.py
@@ -2,14 +2,15 @@
from ethereum_test_forks import Fork
from ethereum_test_tools import Bytecode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
def code_loop_precompile_call(calldata: Bytecode, attack_block: Bytecode, fork: Fork):
"""Create a code loop that calls a precompile with the given calldata."""
max_code_size = fork.max_code_size()
- # The attack contract is: CALLDATA_PREP + #JUMPDEST + [attack_block]* + JUMP(#)
+ # The attack contract is: CALLDATA_PREP + #JUMPDEST + [attack_block]* +
+ # JUMP(#)
jumpdest = Op.JUMPDEST
jump_back = Op.JUMP(len(calldata))
max_iters_loop = (max_code_size - len(calldata) - len(jumpdest) - len(jump_back)) // len(
diff --git a/tests/eest/benchmark/stateful/__init__.py b/tests/eest/benchmark/stateful/__init__.py
new file mode 100644
index 0000000000..f06e177ebd
--- /dev/null
+++ b/tests/eest/benchmark/stateful/__init__.py
@@ -0,0 +1 @@
+"""Benchmark state tests package."""
diff --git a/tests/eest/benchmark/stateful/bloatnet/__init__.py b/tests/eest/benchmark/stateful/bloatnet/__init__.py
new file mode 100644
index 0000000000..ec32f5790d
--- /dev/null
+++ b/tests/eest/benchmark/stateful/bloatnet/__init__.py
@@ -0,0 +1 @@
+"""Bloatnet benchmark tests package."""
diff --git a/tests/eest/benchmark/stateful/bloatnet/test_bloatnet.py b/tests/eest/benchmark/stateful/bloatnet/test_bloatnet.py
new file mode 100644
index 0000000000..e489de3aaf
--- /dev/null
+++ b/tests/eest/benchmark/stateful/bloatnet/test_bloatnet.py
@@ -0,0 +1,6 @@
+"""
+abstract: Tests benchmark worst-case bloatnet scenarios.
+ Tests benchmark worst-case bloatnet scenarios.
+
+Tests running worst-case bloatnet scenarios for benchmarking purposes.
+"""
diff --git a/tests/eest/benchmark/stateful/bloatnet/test_multi_opcode.py b/tests/eest/benchmark/stateful/bloatnet/test_multi_opcode.py
new file mode 100644
index 0000000000..ea6f987264
--- /dev/null
+++ b/tests/eest/benchmark/stateful/bloatnet/test_multi_opcode.py
@@ -0,0 +1,467 @@
+"""
+abstract: BloatNet bench cases extracted from https://hackmd.io/9icZeLN7R0Sk5mIjKlZAHQ.
+
+ The idea of all these tests is to stress client implementations to find out
+ where the limits of processing are focusing specifically on state-related
+ operations.
+"""
+
+import pytest
+
+from ethereum_test_forks import Fork
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ Block,
+ BlockchainTestFiller,
+ Transaction,
+ While,
+)
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
+
+REFERENCE_SPEC_GIT_PATH = "DUMMY/bloatnet.md"
+REFERENCE_SPEC_VERSION = "1.0"
+
+
+# BLOATNET ARCHITECTURE:
+#
+# [Initcode Contract] [Factory Contract] [24KB Contracts]
+# (9.5KB) (116B) (N x 24KB each)
+# │ │ │
+# │ EXTCODECOPY │ CREATE2(salt++) │
+# └──────────────► ├──────────────────► Contract_0
+# ├──────────────────► Contract_1
+# ├──────────────────► Contract_2
+# └──────────────────► Contract_N
+#
+# [Attack Contract] ──STATICCALL──► [Factory.getConfig()]
+# │ returns: (N, hash)
+# └─► Loop(i=0 to N):
+# 1. Generate CREATE2 addr: keccak256(0xFF|factory|i|hash)[12:]
+# 2. BALANCE(addr) → 2600 gas (cold access)
+# 3. EXTCODESIZE(addr) → 100 gas (warm access)
+#
+# HOW IT WORKS:
+# 1. Factory uses EXTCODECOPY to load initcode, avoiding PC-relative jumps
+# 2. Each CREATE2 deployment produces unique 24KB bytecode (via ADDRESS)
+# 3. All contracts share same initcode hash for deterministic addresses
+# 4. Attack rapidly accesses all contracts, stressing client's state handling
+
+
+@pytest.mark.parametrize(
+ "balance_first",
+ [True, False],
+ ids=["balance_extcodesize", "extcodesize_balance"],
+)
+@pytest.mark.valid_from("Prague")
+def test_bloatnet_balance_extcodesize(
+ blockchain_test: BlockchainTestFiller,
+ pre: Alloc,
+ fork: Fork,
+ gas_benchmark_value: int,
+ balance_first: bool,
+):
+ """
+ BloatNet test using BALANCE + EXTCODESIZE with "on-the-fly" CREATE2
+ address generation.
+
+ This test:
+ 1. Assumes contracts are already deployed via the factory (salt 0 to N-1)
+ 2. Generates CREATE2 addresses dynamically during execution
+ 3. Calls BALANCE and EXTCODESIZE (order controlled by balance_first param)
+ 4. Maximizes cache eviction by accessing many contracts
+ """
+ gas_costs = fork.gas_costs()
+
+ # Calculate gas costs
+ intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(calldata=b"")
+
+ # Cost per contract access with CREATE2 address generation
+ cost_per_contract = (
+ gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30)
+ + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6)
+ + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600)
+ + gas_costs.G_BASE # POP first result (2)
+ + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access (100)
+ + gas_costs.G_BASE # POP second result (2)
+ + gas_costs.G_BASE # DUP1 before first op (3)
+ + gas_costs.G_VERY_LOW * 4 # PUSH1 operations (4 * 3)
+ + gas_costs.G_LOW # MLOAD for salt (3)
+ + gas_costs.G_VERY_LOW # ADD for increment (3)
+ + gas_costs.G_LOW # MSTORE salt back (3)
+ + 10 # While loop overhead
+ )
+
+ # Calculate how many contracts to access based on available gas
+ available_gas = gas_benchmark_value - intrinsic_gas - 1000 # Reserve for cleanup
+ contracts_needed = int(available_gas // cost_per_contract)
+
+ # Deploy factory using stub contract - NO HARDCODED VALUES
+ # The stub "bloatnet_factory" must be provided via --address-stubs flag
+ # The factory at that address MUST have:
+ # - Slot 0: Number of deployed contracts
+ # - Slot 1: Init code hash for CREATE2 address calculation
+ factory_address = pre.deploy_contract(
+ code=Bytecode(), # Required parameter, but will be ignored for stubs
+ stub="bloatnet_factory",
+ )
+
+ # Log test requirements - deployed count read from factory storage
+ print(
+ f"Test needs {contracts_needed} contracts for "
+ f"{gas_benchmark_value / 1_000_000:.1f}M gas. "
+ f"Factory storage will be checked during execution."
+ )
+
+ # Define operations that differ based on parameter
+ balance_op = Op.POP(Op.BALANCE)
+ extcodesize_op = Op.POP(Op.EXTCODESIZE)
+ benchmark_ops = (
+ (balance_op + extcodesize_op) if balance_first else (extcodesize_op + balance_op)
+ )
+
+ # Build attack contract that reads config from factory and performs attack
+ attack_code = (
+ # Call getConfig() on factory to get num_deployed and init_code_hash
+ Op.STATICCALL(
+ gas=Op.GAS,
+ address=factory_address,
+ args_offset=0,
+ args_size=0,
+ ret_offset=96,
+ ret_size=64,
+ )
+ # Check if call succeeded
+ + Op.ISZERO
+ + Op.PUSH2(0x1000) # Jump to error handler if failed (far jump)
+ + Op.JUMPI
+ # Load results from memory
+ # Memory[96:128] = num_deployed_contracts
+ # Memory[128:160] = init_code_hash
+ + Op.MLOAD(96) # Load num_deployed_contracts
+ + Op.MLOAD(128) # Load init_code_hash
+ # Setup memory for CREATE2 address generation
+ # Memory layout at 0: 0xFF + factory_addr(20) + salt(32) + hash(32)
+ + Op.MSTORE(0, factory_address) # Store factory address at memory position 0
+ + Op.MSTORE8(11, 0xFF) # Store 0xFF prefix at position (32 - 20 - 1)
+ + Op.MSTORE(32, 0) # Store salt at position 32
+ # Stack now has: [num_contracts, init_code_hash]
+ + Op.PUSH1(64) # Push memory position
+ + Op.MSTORE # Store init_code_hash at memory[64]
+ # Stack now has: [num_contracts]
+ # Main attack loop - iterate through all deployed contracts
+ + While(
+ body=(
+ # Generate CREATE2 addr: keccak256(0xFF+factory+salt+hash)
+ Op.SHA3(11, 85) # Generate CREATE2 address from memory[11:96]
+ # The address is now on the stack
+ + Op.DUP1 # Duplicate for second operation
+ + benchmark_ops # Execute operations in specified order
+ # Increment salt for next iteration
+ + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) # Increment and store salt
+ ),
+ # Continue while we haven't reached the limit
+ condition=Op.DUP1 + Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO,
+ )
+ + Op.POP # Clean up counter
+ )
+
+ # Deploy attack contract
+ attack_address = pre.deploy_contract(code=attack_code)
+
+ # Run the attack
+ attack_tx = Transaction(
+ to=attack_address,
+ gas_limit=gas_benchmark_value,
+ sender=pre.fund_eoa(),
+ )
+
+ # Post-state: just verify attack contract exists
+ post = {
+ attack_address: Account(storage={}),
+ }
+
+ blockchain_test(
+ pre=pre,
+ blocks=[Block(txs=[attack_tx])],
+ post=post,
+ )
+
+
+@pytest.mark.parametrize(
+ "balance_first",
+ [True, False],
+ ids=["balance_extcodecopy", "extcodecopy_balance"],
+)
+@pytest.mark.valid_from("Prague")
+def test_bloatnet_balance_extcodecopy(
+ blockchain_test: BlockchainTestFiller,
+ pre: Alloc,
+ fork: Fork,
+ gas_benchmark_value: int,
+ balance_first: bool,
+):
+ """
+ BloatNet test using BALANCE + EXTCODECOPY with on-the-fly CREATE2
+ address generation.
+
+ This test forces actual bytecode reads from disk by:
+ 1. Assumes contracts are already deployed via the factory
+ 2. Generating CREATE2 addresses dynamically during execution
+ 3. Using BALANCE and EXTCODECOPY (order controlled by balance_first param)
+ 4. Reading 1 byte from the END of the bytecode to force full contract load
+ """
+ gas_costs = fork.gas_costs()
+ max_contract_size = fork.max_code_size()
+
+ # Calculate costs
+ intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(calldata=b"")
+
+ # Cost per contract with EXTCODECOPY and CREATE2 address generation
+ cost_per_contract = (
+ gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30)
+ + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6)
+ + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600)
+ + gas_costs.G_BASE # POP first result (2)
+ + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access base (100)
+ + gas_costs.G_COPY * 1 # Copy cost for 1 byte (3)
+ + gas_costs.G_BASE * 2 # DUP1 before first op, DUP4 for address (6)
+ + gas_costs.G_VERY_LOW * 8 # PUSH operations (8 * 3 = 24)
+ + gas_costs.G_LOW * 2 # MLOAD for salt twice (6)
+ + gas_costs.G_VERY_LOW * 2 # ADD operations (6)
+ + gas_costs.G_LOW # MSTORE salt back (3)
+ + gas_costs.G_BASE # POP after second op (2)
+ + 10 # While loop overhead
+ )
+
+ # Calculate how many contracts to access
+ available_gas = gas_benchmark_value - intrinsic_gas - 1000
+ contracts_needed = int(available_gas // cost_per_contract)
+
+ # Deploy factory using stub contract - NO HARDCODED VALUES
+ # The stub "bloatnet_factory" must be provided via --address-stubs flag
+ # The factory at that address MUST have:
+ # - Slot 0: Number of deployed contracts
+ # - Slot 1: Init code hash for CREATE2 address calculation
+ factory_address = pre.deploy_contract(
+ code=Bytecode(), # Required parameter, but will be ignored for stubs
+ stub="bloatnet_factory",
+ )
+
+ # Log test requirements - deployed count read from factory storage
+ print(
+ f"Test needs {contracts_needed} contracts for "
+ f"{gas_benchmark_value / 1_000_000:.1f}M gas. "
+ f"Factory storage will be checked during execution."
+ )
+
+ # Define operations that differ based on parameter
+ balance_op = Op.POP(Op.BALANCE)
+ extcodecopy_op = (
+ Op.PUSH1(1) # size (1 byte)
+ + Op.PUSH2(max_contract_size - 1) # code offset (last byte)
+ + Op.ADD(Op.MLOAD(32), 96) # unique memory offset
+ + Op.DUP4 # address (duplicated earlier)
+ + Op.EXTCODECOPY
+ + Op.POP # clean up address
+ )
+ benchmark_ops = (
+ (balance_op + extcodecopy_op) if balance_first else (extcodecopy_op + balance_op)
+ )
+
+ # Build attack contract that reads config from factory and performs attack
+ attack_code = (
+ # Call getConfig() on factory to get num_deployed and init_code_hash
+ Op.STATICCALL(
+ gas=Op.GAS,
+ address=factory_address,
+ args_offset=0,
+ args_size=0,
+ ret_offset=96,
+ ret_size=64,
+ )
+ # Check if call succeeded
+ + Op.ISZERO
+ + Op.PUSH2(0x1000) # Jump to error handler if failed (far jump)
+ + Op.JUMPI
+ # Load results from memory
+ # Memory[96:128] = num_deployed_contracts
+ # Memory[128:160] = init_code_hash
+ + Op.MLOAD(96) # Load num_deployed_contracts
+ + Op.MLOAD(128) # Load init_code_hash
+ # Setup memory for CREATE2 address generation
+ # Memory layout at 0: 0xFF + factory_addr(20) + salt(32) + hash(32)
+ + Op.MSTORE(0, factory_address) # Store factory address at memory position 0
+ + Op.MSTORE8(11, 0xFF) # Store 0xFF prefix at position (32 - 20 - 1)
+ + Op.MSTORE(32, 0) # Store salt at position 32
+ # Stack now has: [num_contracts, init_code_hash]
+ + Op.PUSH1(64) # Push memory position
+ + Op.MSTORE # Store init_code_hash at memory[64]
+ # Stack now has: [num_contracts]
+ # Main attack loop - iterate through all deployed contracts
+ + While(
+ body=(
+ # Generate CREATE2 address
+ Op.SHA3(11, 85) # Generate CREATE2 address from memory[11:96]
+ # The address is now on the stack
+ + Op.DUP1 # Duplicate for later operations
+ + benchmark_ops # Execute operations in specified order
+ # Increment salt for next iteration
+ + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) # Increment and store salt
+ ),
+ # Continue while counter > 0
+ condition=Op.DUP1 + Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO,
+ )
+ + Op.POP # Clean up counter
+ )
+
+ # Deploy attack contract
+ attack_address = pre.deploy_contract(code=attack_code)
+
+ # Run the attack
+ attack_tx = Transaction(
+ to=attack_address,
+ gas_limit=gas_benchmark_value,
+ sender=pre.fund_eoa(),
+ )
+
+ # Post-state
+ post = {
+ attack_address: Account(storage={}),
+ }
+
+ blockchain_test(
+ pre=pre,
+ blocks=[Block(txs=[attack_tx])],
+ post=post,
+ )
+
+
+@pytest.mark.parametrize(
+ "balance_first",
+ [True, False],
+ ids=["balance_extcodehash", "extcodehash_balance"],
+)
+@pytest.mark.valid_from("Prague")
+def test_bloatnet_balance_extcodehash(
+ blockchain_test: BlockchainTestFiller,
+ pre: Alloc,
+ fork: Fork,
+ gas_benchmark_value: int,
+ balance_first: bool,
+):
+ """
+ BloatNet test using BALANCE + EXTCODEHASH with on-the-fly CREATE2
+ address generation.
+
+ This test:
+ 1. Assumes contracts are already deployed via the factory
+ 2. Generates CREATE2 addresses dynamically during execution
+ 3. Calls BALANCE and EXTCODEHASH (order controlled by balance_first param)
+ 4. Forces client to compute code hash for 24KB bytecode
+ """
+ gas_costs = fork.gas_costs()
+
+ # Calculate gas costs
+ intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(calldata=b"")
+
+ # Cost per contract access with CREATE2 address generation
+ cost_per_contract = (
+ gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30)
+ + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6)
+ + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600)
+ + gas_costs.G_BASE # POP first result (2)
+ + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access (100)
+ + gas_costs.G_BASE # POP second result (2)
+ + gas_costs.G_BASE # DUP1 before first op (3)
+ + gas_costs.G_VERY_LOW * 4 # PUSH1 operations (4 * 3)
+ + gas_costs.G_LOW # MLOAD for salt (3)
+ + gas_costs.G_VERY_LOW # ADD for increment (3)
+ + gas_costs.G_LOW # MSTORE salt back (3)
+ + 10 # While loop overhead
+ )
+
+ # Calculate how many contracts to access based on available gas
+ available_gas = gas_benchmark_value - intrinsic_gas - 1000 # Reserve for cleanup
+ contracts_needed = int(available_gas // cost_per_contract)
+
+ # Deploy factory using stub contract
+ factory_address = pre.deploy_contract(
+ code=Bytecode(),
+ stub="bloatnet_factory",
+ )
+
+ # Log test requirements
+ print(
+ f"Test needs {contracts_needed} contracts for "
+ f"{gas_benchmark_value / 1_000_000:.1f}M gas. "
+ f"Factory storage will be checked during execution."
+ )
+
+ # Define operations that differ based on parameter
+ balance_op = Op.POP(Op.BALANCE)
+ extcodehash_op = Op.POP(Op.EXTCODEHASH)
+ benchmark_ops = (
+ (balance_op + extcodehash_op) if balance_first else (extcodehash_op + balance_op)
+ )
+
+ # Build attack contract that reads config from factory and performs attack
+ attack_code = (
+ # Call getConfig() on factory to get num_deployed and init_code_hash
+ Op.STATICCALL(
+ gas=Op.GAS,
+ address=factory_address,
+ args_offset=0,
+ args_size=0,
+ ret_offset=96,
+ ret_size=64,
+ )
+ # Check if call succeeded
+ + Op.ISZERO
+ + Op.PUSH2(0x1000) # Jump to error handler if failed
+ + Op.JUMPI
+ # Load results from memory
+ + Op.MLOAD(96) # Load num_deployed_contracts
+ + Op.MLOAD(128) # Load init_code_hash
+ # Setup memory for CREATE2 address generation
+ + Op.MSTORE(0, factory_address)
+ + Op.MSTORE8(11, 0xFF)
+ + Op.MSTORE(32, 0) # Initial salt
+ + Op.PUSH1(64)
+ + Op.MSTORE # Store init_code_hash
+ # Main attack loop
+ + While(
+ body=(
+ # Generate CREATE2 address
+ Op.SHA3(11, 85)
+ + Op.DUP1 # Duplicate for second operation
+ + benchmark_ops # Execute operations in specified order
+ # Increment salt
+ + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1))
+ ),
+ condition=Op.DUP1 + Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO,
+ )
+ + Op.POP # Clean up counter
+ )
+
+ # Deploy attack contract
+ attack_address = pre.deploy_contract(code=attack_code)
+
+ # Run the attack
+ attack_tx = Transaction(
+ to=attack_address,
+ gas_limit=gas_benchmark_value,
+ sender=pre.fund_eoa(),
+ )
+
+ # Post-state
+ post = {
+ attack_address: Account(storage={}),
+ }
+
+ blockchain_test(
+ pre=pre,
+ blocks=[Block(txs=[attack_tx])],
+ post=post,
+ )
diff --git a/tests/eest/benchmark/stateful/conftest.py b/tests/eest/benchmark/stateful/conftest.py
new file mode 100644
index 0000000000..d208dee4e4
--- /dev/null
+++ b/tests/eest/benchmark/stateful/conftest.py
@@ -0,0 +1,66 @@
+"""Pytest configuration for state tests."""
+
+from pathlib import Path
+
+import pytest
+
+DEFAULT_BENCHMARK_FORK = "Prague"
+
+
+def pytest_generate_tests(metafunc):
+ """
+ Add default valid_from marker to state tests without explicit fork
+ specification.
+ """
+ state_dir = Path(__file__).parent
+ test_file_path = Path(metafunc.definition.fspath)
+
+ if state_dir in test_file_path.parents:
+ has_valid_from = any(
+ marker.name == "valid_from" for marker in metafunc.definition.iter_markers()
+ )
+ if not has_valid_from:
+ metafunc.definition.add_marker(pytest.mark.valid_from(DEFAULT_BENCHMARK_FORK))
+
+
+def pytest_collection_modifyitems(config, items):
+ """Manage stateful test markers and filtering."""
+ state_dir = Path(__file__).parent
+ gen_docs = config.getoption("--gen-docs", default=False)
+
+ if gen_docs:
+ _add_stateful_markers_for_docs(items, state_dir)
+ return
+
+ marker_expr = config.getoption("-m", default="")
+
+ items_to_remove = []
+
+ for i, item in enumerate(items):
+ item_path = Path(item.fspath)
+ is_in_state_dir = state_dir in item_path.parents
+
+ # Add stateful marker to tests in state directory that don't have it
+ if is_in_state_dir and not item.get_closest_marker("stateful"):
+ item.add_marker(pytest.mark.stateful)
+
+ has_stateful_marker = item.get_closest_marker("stateful")
+
+ run_stateful = (
+ marker_expr and ("stateful" in marker_expr) and ("not stateful" not in marker_expr)
+ )
+
+ # When not running stateful tests, remove all stateful tests
+ if not run_stateful and has_stateful_marker:
+ items_to_remove.append(i)
+
+ for i in reversed(items_to_remove):
+ items.pop(i)
+
+
+def _add_stateful_markers_for_docs(items, state_dir):
+ """Add stateful markers for documentation generation."""
+ for item in items:
+ item_path = Path(item.fspath)
+ if state_dir in item_path.parents and not item.get_closest_marker("stateful"):
+ item.add_marker(pytest.mark.stateful)
diff --git a/tests/eest/benchmark/test_worst_blocks.py b/tests/eest/benchmark/test_worst_blocks.py
index 38e6d5f71e..3bb85cdddd 100644
--- a/tests/eest/benchmark/test_worst_blocks.py
+++ b/tests/eest/benchmark/test_worst_blocks.py
@@ -1,31 +1,34 @@
"""
-abstract: Tests that benchmark EVMs in worst-case block scenarios.
- Tests that benchmark EVMs in worst-case block scenarios.
-
-Tests running worst-case block scenarios for EVMs.
+Tests that benchmark EVMs in worst-case block scenarios.
"""
import random
import pytest
+from ethereum_test_base_types import Account
from ethereum_test_forks import Fork
from ethereum_test_tools import (
AccessList,
- Account,
Address,
Alloc,
+ AuthorizationTuple,
Block,
BlockchainTestFiller,
+ Environment,
Hash,
StateTestFiller,
Transaction,
)
+from ethereum_test_vm import Opcodes as Op
@pytest.fixture
def iteration_count(intrinsic_cost: int, gas_benchmark_value: int):
- """Calculate the number of iterations based on the gas limit and intrinsic cost."""
+ """
+ Calculate the number of iterations based on the gas limit and intrinsic
+ cost.
+ """
return gas_benchmark_value // intrinsic_cost
@@ -112,11 +115,13 @@ def ether_transfer_case(
def test_block_full_of_ether_transfers(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
+ env: Environment,
case_id: str,
ether_transfer_case,
iteration_count: int,
transfer_amount: int,
intrinsic_cost: int,
+ gas_benchmark_value: int,
):
"""
Single test for ether transfer scenarios.
@@ -153,10 +158,10 @@ def test_block_full_of_ether_transfers(
)
blockchain_test(
+ genesis_environment=env,
pre=pre,
post=post_state,
blocks=[Block(txs=txs)],
- exclude_full_post_state_in_output=True,
expected_benchmark_gas_used=iteration_count * intrinsic_cost,
)
@@ -183,12 +188,14 @@ def test_block_full_data(
gas_benchmark_value: int,
):
"""Test a block with empty payload."""
- # Gas cost calculation based on EIP-7683: (https://eips.ethereum.org/EIPS/eip-7683)
+ # Gas cost calculation based on EIP-7683:
+ # (https://eips.ethereum.org/EIPS/eip-7683)
#
# tx.gasUsed = 21000 + max(
# STANDARD_TOKEN_COST * tokens_in_calldata
# + execution_gas_used
- # + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata)),
+ # + isContractCreation * (32000 +
+ # INITCODE_WORD_COST * words(calldata)),
# TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata)
#
# Simplified in this test case:
@@ -205,7 +212,8 @@ def test_block_full_data(
# Token accounting:
# tokens_in_calldata = zero_bytes + 4 * non_zero_bytes
#
- # So we calculate how many bytes we can fit into calldata based on available gas.
+ # So we calculate how many bytes we can fit into calldata based on
+ # available gas.
gas_available = gas_benchmark_value - intrinsic_cost
@@ -237,7 +245,10 @@ def test_block_full_access_list_and_data(
fork: Fork,
gas_benchmark_value: int,
):
- """Test a block with access lists (60% gas) and calldata (40% gas) using random mixed bytes."""
+ """
+ Test a block with access lists (60% gas) and calldata (40% gas) using
+ random mixed bytes.
+ """
attack_gas_limit = gas_benchmark_value
gas_available = attack_gas_limit - intrinsic_cost
@@ -268,7 +279,8 @@ def test_block_full_access_list_and_data(
)
]
- # Calculate calldata with 29% of gas for zero bytes and 71% for non-zero bytes
+ # Calculate calldata with 29% of gas for zero bytes and 71% for non-zero
+ # bytes
# Token accounting: tokens_in_calldata = zero_bytes + 4 * non_zero_bytes
# We want to split the gas budget:
# - 29% of gas_for_calldata for zero bytes
@@ -284,7 +296,8 @@ def test_block_full_access_list_and_data(
# Zero bytes: 1 token per byte
# Non-zero bytes: 4 tokens per byte
num_zero_bytes = tokens_for_zero_bytes # 1 token = 1 zero byte
- num_non_zero_bytes = tokens_for_non_zero_bytes // 4 # 4 tokens = 1 non-zero byte
+ # 4 tokens = 1 non-zero byte
+ num_non_zero_bytes = tokens_for_non_zero_bytes // 4
# Create calldata with mixed bytes
calldata = bytearray()
@@ -319,3 +332,59 @@ def test_block_full_access_list_and_data(
access_list=access_list,
),
)
+
+
+@pytest.mark.parametrize("empty_authority", [True, False])
+@pytest.mark.parametrize("zero_delegation", [True, False])
+def test_worst_case_auth_block(
+ blockchain_test: BlockchainTestFiller,
+ pre: Alloc,
+ intrinsic_cost: int,
+ gas_benchmark_value: int,
+ fork: Fork,
+ empty_authority: bool,
+ zero_delegation: bool,
+):
+ """Test an auth block."""
+ gas_costs = fork.gas_costs()
+
+ iteration_count = (gas_benchmark_value - intrinsic_cost) // gas_costs.G_AUTHORIZATION
+
+ code = Op.STOP * fork.max_code_size()
+ auth_target = Address(0) if zero_delegation else pre.deploy_contract(code=code)
+
+ auth_tuples = []
+ for _ in range(iteration_count):
+ signer = (
+ pre.fund_eoa(amount=0, delegation=None)
+ if empty_authority
+ else pre.fund_eoa(amount=0, delegation=auth_target)
+ )
+ auth_tuple = AuthorizationTuple(address=auth_target, nonce=signer.nonce, signer=signer)
+ auth_tuples.append(auth_tuple)
+
+ tx = Transaction(
+ to=pre.empty_account(),
+ gas_limit=gas_benchmark_value,
+ sender=pre.fund_eoa(),
+ authorization_list=auth_tuples,
+ )
+
+ gas_used = fork.transaction_intrinsic_cost_calculator()(
+ authorization_list_or_count=auth_tuples
+ )
+
+ refund = 0
+ if not empty_authority:
+ refund = min(
+ gas_used // 5,
+ (gas_costs.G_AUTHORIZATION - gas_costs.R_AUTHORIZATION_EXISTING_AUTHORITY)
+ * iteration_count,
+ )
+
+ blockchain_test(
+ pre=pre,
+ post={},
+ blocks=[Block(txs=[tx])],
+ expected_benchmark_gas_used=gas_used - refund,
+ )
diff --git a/tests/eest/benchmark/test_worst_bytecode.py b/tests/eest/benchmark/test_worst_bytecode.py
index 67b1eca89a..1422739404 100644
--- a/tests/eest/benchmark/test_worst_bytecode.py
+++ b/tests/eest/benchmark/test_worst_bytecode.py
@@ -1,7 +1,4 @@
"""
-abstract: Tests that benchmark EVMs in worst-case opcode scenarios.
- Tests that benchmark EVMs in worst-case opcode scenarios.
-
Tests that benchmark EVMs in worst-case opcode scenarios.
"""
@@ -23,8 +20,8 @@
While,
compute_create2_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.helpers import compute_create_address
+from ethereum_test_vm import Opcodes as Op
from .helpers import code_loop_precompile_call
@@ -56,30 +53,30 @@ def test_worst_bytecode_single_opcode(
gas_benchmark_value: int,
):
"""
- Test a block execution where a single opcode execution maxes out the gas limit,
- and the opcodes access a huge amount of contract code.
+ Test a block execution where a single opcode execution maxes out the gas
+ limit, and the opcodes access a huge amount of contract code.
- We first use a single block to deploy a factory contract that will be used to deploy
- a large number of contracts.
+ We first use a single block to deploy a factory contract that will be used
+ to deploy a large number of contracts.
This is done to avoid having a big pre-allocation size for the test.
- The test is performed in the last block of the test, and the entire block gas limit is
- consumed by repeated opcode executions.
+ The test is performed in the last block of the test, and the entire block
+ gas limit is consumed by repeated opcode executions.
"""
- # The attack gas limit is the gas limit which the target tx will use
- # The test will scale the block gas limit to setup the contracts accordingly to be
- # able to pay for the contract deposit. This has to take into account the 200 gas per byte,
- # but also the quadratic memory expansion costs which have to be paid each time the
- # memory is being setup
+ # The attack gas limit is the gas limit which the target tx will use The
+ # test will scale the block gas limit to setup the contracts accordingly to
+ # be able to pay for the contract deposit. This has to take into account
+ # the 200 gas per byte, but also the quadratic memory expansion costs which
+ # have to be paid each time the memory is being setup
attack_gas_limit = gas_benchmark_value
max_contract_size = fork.max_code_size()
gas_costs = fork.gas_costs()
- # Calculate the absolute minimum gas costs to deploy the contract
- # This does not take into account setting up the actual memory (using KECCAK256 and XOR)
- # so the actual costs of deploying the contract is higher
+ # Calculate the absolute minimum gas costs to deploy the contract This does
+ # not take into account setting up the actual memory (using KECCAK256 and
+ # XOR) so the actual costs of deploying the contract is higher
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
memory_gas_minimum = memory_expansion_gas_calculator(new_bytes=len(bytes(max_contract_size)))
code_deposit_gas_minimum = (
@@ -90,7 +87,8 @@ def test_worst_bytecode_single_opcode(
# Calculate the loop cost of the attacker to query one address
loop_cost = (
gas_costs.G_KECCAK_256 # KECCAK static cost
- + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic cost for CREATE2
+ + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic
+ # cost for CREATE2
+ gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs
+ gas_costs.G_COLD_ACCOUNT_ACCESS # Opcode cost
+ 30 # ~Gluing opcodes
@@ -101,8 +99,9 @@ def test_worst_bytecode_single_opcode(
attack_gas_limit - intrinsic_gas_cost_calc() - gas_costs.G_VERY_LOW * 4
) // loop_cost
- # Set the block gas limit to a relative high value to ensure the code deposit tx
- # fits in the block (there is enough gas available in the block to execute this)
+ # Set the block gas limit to a relative high value to ensure the code
+ # deposit tx fits in the block (there is enough gas available in the block
+ # to execute this)
minimum_gas_limit = code_deposit_gas_minimum * 2 * num_contracts
if env.gas_limit < minimum_gas_limit:
raise Exception(
@@ -111,16 +110,17 @@ def test_worst_bytecode_single_opcode(
"optimizing gas usage during the setup phase of this test."
)
- # The initcode will take its address as a starting point to the input to the keccak
- # hash function.
- # It will reuse the output of the hash function in a loop to create a large amount of
- # seemingly random code, until it reaches the maximum contract size.
+ # The initcode will take its address as a starting point to the input to
+ # the keccak hash function. It will reuse the output of the hash function
+ # in a loop to create a large amount of seemingly random code, until it
+ # reaches the maximum contract size.
initcode = (
Op.MSTORE(0, Op.ADDRESS)
+ While(
body=(
Op.SHA3(Op.SUB(Op.MSIZE, 32), 32)
- # Use a xor table to avoid having to call the "expensive" sha3 opcode as much
+ # Use a xor table to avoid having to call the "expensive" sha3
+ # opcode as much
+ sum(
(Op.PUSH32[xor_value] + Op.XOR + Op.DUP1 + Op.MSIZE + Op.MSTORE)
for xor_value in XOR_TABLE
@@ -129,16 +129,16 @@ def test_worst_bytecode_single_opcode(
),
condition=Op.LT(Op.MSIZE, max_contract_size),
)
- # Despite the whole contract has random bytecode, we make the first opcode be a STOP
- # so CALL-like attacks return as soon as possible, while EXTCODE(HASH|SIZE) work as
- # intended.
+ # Despite the whole contract has random bytecode, we make the first
+ # opcode be a STOP so CALL-like attacks return as soon as possible,
+ # while EXTCODE(HASH|SIZE) work as intended.
+ Op.MSTORE8(0, 0x00)
+ Op.RETURN(0, max_contract_size)
)
initcode_address = pre.deploy_contract(code=initcode)
- # The factory contract will simply use the initcode that is already deployed,
- # and create a new contract and return its address if successful.
+ # The factory contract will simply use the initcode that is already
+ # deployed, and create a new contract and return its address if successful.
factory_code = (
Op.EXTCODECOPY(
address=initcode_address,
@@ -160,8 +160,8 @@ def test_worst_bytecode_single_opcode(
)
factory_address = pre.deploy_contract(code=factory_code)
- # The factory caller will call the factory contract N times, creating N new contracts.
- # Calldata should contain the N value.
+ # The factory caller will call the factory contract N times, creating N new
+ # contracts. Calldata should contain the N value.
factory_caller_code = Op.CALLDATALOAD(0) + While(
body=Op.POP(Op.CALL(address=factory_address)),
condition=Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO,
@@ -208,8 +208,8 @@ def test_worst_bytecode_single_opcode(
)
if len(attack_code) > max_contract_size:
- # TODO: A workaround could be to split the opcode code into multiple contracts
- # and call them in sequence.
+ # TODO: A workaround could be to split the opcode code into multiple
+ # contracts and call them in sequence.
raise ValueError(
f"Code size {len(attack_code)} exceeds maximum code size {max_contract_size}"
)
@@ -254,17 +254,18 @@ def test_worst_initcode_jumpdest_analysis(
"""
Test the jumpdest analysis performance of the initcode.
- This benchmark places a very long initcode in the memory and then invoke CREATE instructions
- with this initcode up to the block gas limit. The initcode itself has minimal execution time
- but forces the EVM to perform the full jumpdest analysis on the parametrized byte pattern.
- The initicode is modified by mixing-in the returned create address between CREATE invocations
- to prevent caching.
+ This benchmark places a very long initcode in the memory and then invoke
+ CREATE instructions with this initcode up to the block gas limit. The
+ initcode itself has minimal execution time but forces the EVM to perform
+ the full jumpdest analysis on the parametrized byte pattern. The initicode
+ is modified by mixing-in the returned create address between CREATE
+ invocations to prevent caching.
"""
max_code_size = fork.max_code_size()
initcode_size = fork.max_initcode_size()
- # Expand the initcode pattern to the transaction data so it can be used in CALLDATACOPY
- # in the main contract. TODO: tune the tx_data_len param.
+ # Expand the initcode pattern to the transaction data so it can be used in
+ # CALLDATACOPY in the main contract. TODO: tune the tx_data_len param.
tx_data_len = 1024
tx_data = pattern * (tx_data_len // len(pattern))
tx_data += (tx_data_len - len(tx_data)) * bytes(Op.JUMPDEST)
@@ -332,8 +333,9 @@ def test_worst_initcode_jumpdest_analysis(
@pytest.mark.parametrize(
"max_code_size_ratio, non_zero_data, value",
[
- # To avoid a blowup of combinations, the value dimension is only explored for
- # the non-zero data case, so isn't affected by code size influence.
+ # To avoid a blowup of combinations, the value dimension is only
+ # explored for the non-zero data case, so isn't affected by code size
+ # influence.
pytest.param(0, False, 0, id="0 bytes without value"),
pytest.param(0, False, 1, id="0 bytes with value"),
pytest.param(0.25, True, 0, id="0.25x max code size with non-zero data"),
@@ -356,7 +358,9 @@ def test_worst_create(
value: int,
gas_benchmark_value: int,
):
- """Test the CREATE and CREATE2 performance with different configurations."""
+ """
+ Test the CREATE and CREATE2 performance with different configurations.
+ """
max_code_size = fork.max_code_size()
code_size = int(max_code_size * max_code_size_ratio)
@@ -381,7 +385,9 @@ def test_worst_create(
# Create the benchmark contract which has the following design:
# ```
# PUSH(value)
- # [EXTCODECOPY(full initcode_template_contract) -- Conditional that non_zero_data is True]`
+ # [EXTCODECOPY(full initcode_template_contract)
+ # -> Conditional that non_zero_data is True]
+ #
# JUMPDEST (#)
# (CREATE|CREATE2)
# (CREATE|CREATE2)
@@ -407,10 +413,11 @@ def test_worst_create(
# - DUP3 refers to PUSH1(value) above.
Op.POP(Op.CREATE(value=Op.DUP3, offset=0, size=Op.DUP2))
if opcode == Op.CREATE
- # For CREATE2: we manually push the arguments because we leverage the return value of
- # previous CREATE2 calls as salt for the next CREATE2 call.
- # - DUP4 is targeting the PUSH1(value) from the code_prefix.
- # - DUP3 is targeting the EXTCODESIZE value pushed in code_prefix.
+ # For CREATE2: we manually push the arguments because we leverage the
+ # return value of previous CREATE2 calls as salt for the next CREATE2
+ # call.
+ # - DUP4 is targeting the PUSH1(value) from the code_prefix.
+ # - DUP3 is targeting the EXTCODESIZE value pushed in code_prefix.
else Op.DUP3 + Op.PUSH0 + Op.DUP4 + Op.CREATE2
)
code = code_loop_precompile_call(code_prefix, attack_block, fork)
@@ -444,20 +451,20 @@ def test_worst_creates_collisions(
gas_benchmark_value: int,
):
"""Test the CREATE and CREATE2 collisions performance."""
- # We deploy a "proxy contract" which is the contract that will be called in a loop
- # using all the gas in the block. This "proxy contract" is the one executing CREATE2
- # failing with a collision.
- # The reason why we need a "proxy contract" is that CREATE(2) failing with a collision will
- # consume all the available gas. If we try to execute the CREATE(2) directly without being
- # wrapped **and capped in gas** in a previous CALL, we would run out of gas very fast!
- #
- # The proxy contract calls CREATE(2) with empty initcode. The current call frame gas will
- # be exhausted because of the collision. For this reason the caller will carefully give us
- # the minimal gas necessary to execute the CREATE(2) and not waste any extra gas in the
- # CREATE(2)-failure.
- #
- # Note that these CREATE(2) calls will fail because in (**) below we pre-alloc contracts
- # with the same address as the ones that CREATE(2) will try to create.
+ # We deploy a "proxy contract" which is the contract that will be called in
+ # a loop using all the gas in the block. This "proxy contract" is the one
+ # executing CREATE2 failing with a collision. The reason why we need a
+ # "proxy contract" is that CREATE(2) failing with a collision will consume
+ # all the available gas. If we try to execute the CREATE(2) directly
+ # without being wrapped **and capped in gas** in a previous CALL, we would
+ # run out of gas very fast!
+ # The proxy contract calls CREATE(2) with empty initcode. The current call
+ # frame gas will be exhausted because of the collision. For this reason the
+ # caller will carefully give us the minimal gas necessary to execute the
+ # CREATE(2) and not waste any extra gas in the CREATE(2)-failure.
+ # Note that these CREATE(2) calls will fail because in (**) below we pre-
+ # alloc contracts with the same address as the ones that CREATE(2) will try
+ # to create.
proxy_contract = pre.deploy_contract(
code=Op.CREATE2(value=Op.PUSH0, salt=Op.PUSH0, offset=Op.PUSH0, size=Op.PUSH0)
if opcode == Op.CREATE2
@@ -465,8 +472,8 @@ def test_worst_creates_collisions(
)
gas_costs = fork.gas_costs()
- # The CALL to the proxy contract needs at a minimum gas corresponding to the CREATE(2)
- # plus extra required PUSH0s for arguments.
+ # The CALL to the proxy contract needs at a minimum gas corresponding to
+ # the CREATE(2) plus extra required PUSH0s for arguments.
min_gas_required = gas_costs.G_CREATE + gas_costs.G_BASE * (3 if opcode == Op.CREATE else 4)
code_prefix = Op.PUSH20(proxy_contract) + Op.PUSH3(min_gas_required)
attack_block = Op.POP(
@@ -477,7 +484,8 @@ def test_worst_creates_collisions(
code = code_loop_precompile_call(code_prefix, attack_block, fork)
tx_target = pre.deploy_contract(code=code)
- # (**) We deploy the contract that CREATE(2) will attempt to create so any attempt will fail.
+ # (**) We deploy the contract that CREATE(2) will attempt to create so any
+ # attempt will fail.
if opcode == Op.CREATE2:
addr = compute_create2_address(address=proxy_contract, salt=0, initcode=[])
pre.deploy_contract(address=addr, code=Op.INVALID)
diff --git a/tests/eest/benchmark/test_worst_compute.py b/tests/eest/benchmark/test_worst_compute.py
index 90ce819a7e..3de15e61cc 100644
--- a/tests/eest/benchmark/test_worst_compute.py
+++ b/tests/eest/benchmark/test_worst_compute.py
@@ -1,8 +1,5 @@
"""
-abstract: Tests that benchmark EVMs in worst-case compute scenarios.
- Tests that benchmark EVMs in worst-case compute scenarios.
-
-Tests that benchmark EVMs when running worst-case compute opcodes and precompile scenarios.
+Tests that benchmark EVMs in worst-case compute scenarios.
"""
import math
@@ -15,10 +12,12 @@
from py_ecc.bn128 import G1, G2, multiply
from ethereum_test_base_types.base_types import Bytes
+from ethereum_test_benchmark.benchmark_code_generator import JumpLoopGenerator
from ethereum_test_forks import Fork
from ethereum_test_tools import (
Address,
Alloc,
+ BenchmarkTestFiller,
Block,
BlockchainTestFiller,
Bytecode,
@@ -27,9 +26,9 @@
Transaction,
add_kzg_version,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types import TransactionType
-from ethereum_test_vm.opcode import Opcode
+from ethereum_test_vm import Opcode
+from ethereum_test_vm import Opcodes as Op
from ..byzantium.eip198_modexp_precompile.test_modexp import ModExpInput
from ..cancun.eip4844_blobs.spec import Spec as BlobsSpec
@@ -55,8 +54,8 @@ def neg(x: int) -> int:
def make_dup(index: int) -> Opcode:
"""
- Create a DUP instruction which duplicates the index-th (counting from 0) element
- from the top of the stack. E.g. make_dup(0) → DUP1.
+ Create a DUP instruction which duplicates the index-th (counting from 0)
+ element from the top of the stack. E.g. make_dup(0) → DUP1.
"""
assert 0 <= index < 16
return Opcode(0x80 + index, pushed_stack_items=1, min_stack_height=index + 1)
@@ -156,9 +155,9 @@ def test_worst_callvalue(
"""
Test running a block with as many CALLVALUE opcodes as possible.
- The `non_zero_value` parameter controls whether opcode must return non-zero value.
- The `from_origin` parameter controls whether the call frame is the immediate from the
- transaction or a previous CALL.
+ The `non_zero_value` parameter controls whether opcode must return non-zero
+ value. The `from_origin` parameter controls whether the call frame is the
+ immediate from the transaction or a previous CALL.
"""
max_code_size = fork.max_code_size()
@@ -220,11 +219,12 @@ def test_worst_returndatasize_nonzero(
gas_benchmark_value: int,
):
"""
- Test running a block which execute as many RETURNDATASIZE opcodes which return a non-zero
- buffer as possible.
+ Test running a block which execute as many RETURNDATASIZE opcodes which
+ return a non-zero buffer as possible.
- The `returned_size` parameter indicates the size of the returned data buffer.
- The `return_data_style` indicates how returned data is produced for the opcode caller.
+ The `returned_size` parameter indicates the size of the returned data
+ buffer. The `return_data_style` indicates how returned data is produced for
+ the opcode caller.
"""
max_code_size = fork.max_code_size()
@@ -269,7 +269,10 @@ def test_worst_returndatasize_zero(
fork: Fork,
gas_benchmark_value: int,
):
- """Test running a block with as many RETURNDATASIZE opcodes as possible with a zero buffer."""
+ """
+ Test running a block with as many RETURNDATASIZE opcodes as possible with a
+ zero buffer.
+ """
max_code_size = fork.max_code_size()
dummy_contract_call = Bytecode()
@@ -349,40 +352,44 @@ def test_worst_keccak(
max_code_size = fork.max_code_size()
- # Discover the optimal input size to maximize keccak-permutations, not keccak calls.
- # The complication of the discovery arises from the non-linear gas cost of memory expansion.
+ # Discover the optimal input size to maximize keccak-permutations, not
+ # keccak calls. The complication of the discovery arises from the non-
+ # linear gas cost of memory expansion.
max_keccak_perm_per_block = 0
optimal_input_length = 0
for i in range(1, 1_000_000, 32):
iteration_gas_cost = (
2 * gsc.G_VERY_LOW # PUSHN + PUSH1
+ gsc.G_KECCAK_256 # KECCAK256 static cost
- + math.ceil(i / 32) * gsc.G_KECCAK_256_WORD # KECCAK256 dynamic cost
+ + math.ceil(i / 32) * gsc.G_KECCAK_256_WORD # KECCAK256 dynamic
+ # cost
+ gsc.G_BASE # POP
)
- # From the available gas, we subtract the mem expansion costs considering we know the
- # current input size length i.
+ # From the available gas, we subtract the mem expansion costs
+ # considering we know the current input size length i.
available_gas_after_expansion = max(0, available_gas - mem_exp_gas_calculator(new_bytes=i))
# Calculate how many calls we can do.
num_keccak_calls = available_gas_after_expansion // iteration_gas_cost
# KECCAK does 1 permutation every 136 bytes.
num_keccak_permutations = num_keccak_calls * math.ceil(i / KECCAK_RATE)
- # If we found an input size that is better (reg permutations/gas), then save it.
+ # If we found an input size that is better (reg permutations/gas), then
+ # save it.
if num_keccak_permutations > max_keccak_perm_per_block:
max_keccak_perm_per_block = num_keccak_permutations
optimal_input_length = i
- # max_iters_loop contains how many keccak calls can be done per loop.
- # The loop is as big as possible bounded by the maximum code size.
+ # max_iters_loop contains how many keccak calls can be done per loop. The
+ # loop is as big as possible bounded by the maximum code size.
#
# The loop structure is: JUMPDEST + [attack iteration] + PUSH0 + JUMP
#
# Now calculate available gas for [attack iteration]:
- # Numerator = max_code_size-3. The -3 is for the JUMPDEST, PUSH0 and JUMP.
- # Denominator = (PUSHN + PUSH1 + KECCAK256 + POP) + PUSH1_DATA + PUSHN_DATA
- # TODO: the testing framework uses PUSH1(0) instead of PUSH0 which is suboptimal for the
- # attack, whenever this is fixed adjust accordingly.
+ # Numerator = max_code_size-3. The -3 is for the JUMPDEST, PUSH0 and JUMP
+ # Denominator = (PUSHN + PUSH1 + KECCAK256 + POP) + PUSH1_DATA + PUSHN_DATA
+ #
+ # TODO: the testing framework uses PUSH1(0) instead of PUSH0 which is
+ # suboptimal for the attack, whenever this is fixed adjust accordingly.
start_code = Op.JUMPDEST + Op.PUSH20[optimal_input_length]
loop_code = Op.POP(Op.SHA3(Op.PUSH0, Op.DUP1))
end_code = Op.POP + Op.JUMP(Op.PUSH0)
@@ -425,7 +432,10 @@ def test_worst_precompile_only_data_input(
bytes_per_unit_of_work: int,
gas_benchmark_value: int,
):
- """Test running a block with as many precompile calls which have a single `data` input."""
+ """
+ Test running a block with as many precompile calls which have a single
+ `data` input.
+ """
# Intrinsic gas cost is paid once.
intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
available_gas = gas_benchmark_value - intrinsic_gas_calculator()
@@ -433,7 +443,8 @@ def test_worst_precompile_only_data_input(
gsc = fork.gas_costs()
mem_exp_gas_calculator = fork.memory_expansion_gas_calculator()
- # Discover the optimal input size to maximize precompile work, not precompile calls.
+ # Discover the optimal input size to maximize precompile work, not
+ # precompile calls.
max_work = 0
optimal_input_length = 0
for input_length in range(1, 1_000_000, 32):
@@ -448,11 +459,12 @@ def test_worst_precompile_only_data_input(
iteration_gas_cost = (
parameters_gas
+ +static_cost # Precompile static cost
- + math.ceil(input_length / 32) * per_word_dynamic_cost # Precompile dynamic cost
+ + math.ceil(input_length / 32) * per_word_dynamic_cost
+ # Precompile dynamic cost
+ gsc.G_BASE # POP
)
- # From the available gas, we subtract the mem expansion costs considering we know the
- # current input size length.
+ # From the available gas, we subtract the mem expansion costs
+ # considering we know the current input size length.
available_gas_after_expansion = max(
0, available_gas - mem_exp_gas_calculator(new_bytes=input_length)
)
@@ -460,7 +472,8 @@ def test_worst_precompile_only_data_input(
num_calls = available_gas_after_expansion // iteration_gas_cost
total_work = num_calls * math.ceil(input_length / bytes_per_unit_of_work)
- # If we found an input size that is better (reg permutations/gas), then save it.
+ # If we found an input size that is better (reg permutations/gas), then
+ # save it.
if total_work > max_work:
max_work = total_work
optimal_input_length = input_length
@@ -639,7 +652,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_odd_32b_exp_cover_windows",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L38
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L38
pytest.param(
ModExpInput(
base=192 * "FF",
@@ -648,7 +662,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_min_gas_base_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L40
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L40
pytest.param(
ModExpInput(
base=8 * "FF",
@@ -657,7 +672,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_min_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L42
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L42
pytest.param(
ModExpInput(
base=40 * "FF",
@@ -666,7 +682,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_min_gas_balanced",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L44
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L44
pytest.param(
ModExpInput(
base=32 * "FF",
@@ -675,7 +692,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_exp_208_gas_balanced",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L46
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L46
pytest.param(
ModExpInput(
base=8 * "FF",
@@ -684,7 +702,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_exp_215_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L48
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L48
pytest.param(
ModExpInput(
base=8 * "FF",
@@ -693,7 +712,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_exp_298_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L50
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L50
pytest.param(
ModExpInput(
base=16 * "FF",
@@ -702,7 +722,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_pawel_2",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L52
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L52
pytest.param(
ModExpInput(
base=24 * "FF",
@@ -711,7 +732,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_pawel_3",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L54
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L54
pytest.param(
ModExpInput(
base=32 * "FF",
@@ -720,7 +742,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_pawel_4",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L56
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L56
pytest.param(
ModExpInput(
base=280 * "FF",
@@ -729,7 +752,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_408_gas_base_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L58
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L58
pytest.param(
ModExpInput(
base=16 * "FF",
@@ -738,7 +762,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_400_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L60
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L60
pytest.param(
ModExpInput(
base=48 * "FF",
@@ -747,7 +772,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_408_gas_balanced",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L62
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L62
pytest.param(
ModExpInput(
base=344 * "FF",
@@ -756,7 +782,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_616_gas_base_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L64
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L64
pytest.param(
ModExpInput(
base=16 * "FF",
@@ -765,7 +792,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_600_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L66
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L66
pytest.param(
ModExpInput(
base=48 * "FF",
@@ -774,7 +802,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_600_gas_balanced",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L68
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L68
pytest.param(
ModExpInput(
base=392 * "FF",
@@ -783,7 +812,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_800_gas_base_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L70
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L70
pytest.param(
ModExpInput(
base=16 * "FF",
@@ -792,7 +822,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_800_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L72
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L72
pytest.param(
ModExpInput(
base=56 * "FF",
@@ -801,7 +832,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_767_gas_balanced",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L74
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L74
pytest.param(
ModExpInput(
base=16 * "FF",
@@ -810,7 +842,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_852_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L76
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L76
pytest.param(
ModExpInput(
base=408 * "FF",
@@ -819,7 +852,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_867_gas_base_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L78
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L78
pytest.param(
ModExpInput(
base=56 * "FF",
@@ -828,7 +862,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_996_gas_balanced",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L80
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L80
pytest.param(
ModExpInput(
base=448 * "FF",
@@ -837,7 +872,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_1045_gas_base_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L82
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L82
pytest.param(
ModExpInput(
base=32 * "FF",
@@ -846,7 +882,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_677_gas_base_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L84
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L84
pytest.param(
ModExpInput(
base=24 * "FF",
@@ -855,7 +892,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_765_gas_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L86
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L86
pytest.param(
ModExpInput(
base=32 * "FF",
@@ -952,7 +990,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_1024_exp_2",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L122
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L122
pytest.param(
ModExpInput(
base="03",
@@ -961,7 +1000,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_example_1",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L124
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L124
pytest.param(
ModExpInput(
base="",
@@ -970,7 +1010,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_example_2",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L126
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L126
pytest.param(
ModExpInput(
base="e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5",
@@ -979,7 +1020,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_1_square",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L128
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L128
pytest.param(
ModExpInput(
base="e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5",
@@ -988,7 +1030,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_1_qube",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L130
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L130
pytest.param(
ModExpInput(
base="e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5",
@@ -997,7 +1040,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_1_pow_0x10001",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L132
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L132
pytest.param(
ModExpInput(
base="cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51",
@@ -1006,7 +1050,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_2_square",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L134
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L134
pytest.param(
ModExpInput(
base="cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51",
@@ -1015,7 +1060,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_2_qube",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L136
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L136
pytest.param(
ModExpInput(
base="cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51",
@@ -1024,7 +1070,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_2_pow_0x10001",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L138
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L138
pytest.param(
ModExpInput(
base="c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb",
@@ -1033,7 +1080,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_3_square",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L140
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L140
pytest.param(
ModExpInput(
base="c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb",
@@ -1042,7 +1090,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_3_qube",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L142
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L142
pytest.param(
ModExpInput(
base="c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb",
@@ -1051,7 +1100,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_3_pow_0x10001",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L144
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L144
pytest.param(
ModExpInput(
base="db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81",
@@ -1060,7 +1110,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_4_square",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L146
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L146
pytest.param(
ModExpInput(
base="db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81",
@@ -1069,7 +1120,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_4_qube",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L148
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L148
pytest.param(
ModExpInput(
base="db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81",
@@ -1078,7 +1130,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_4_pow_0x10001",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L150
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L150
pytest.param(
ModExpInput(
base="c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf",
@@ -1087,7 +1140,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_5_square",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L152
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L152
pytest.param(
ModExpInput(
base="c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf",
@@ -1096,7 +1150,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_5_qube",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L154
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L154
pytest.param(
ModExpInput(
base="c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf",
@@ -1105,7 +1160,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_nagydani_5_pow_0x10001",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L156
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L156
pytest.param(
ModExpInput(
base="ffffff",
@@ -1114,7 +1170,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_marius_1_even",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L158
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L158
pytest.param(
ModExpInput(
base="ffffffffffffffff76ffffffffffffff",
@@ -1123,7 +1180,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_guido_1_even",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L160
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L160
pytest.param(
ModExpInput(
base="e0060000a921212121212121ff000021",
@@ -1132,7 +1190,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_guido_2_even",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L162
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L162
pytest.param(
ModExpInput(
base="0193585a48e18aad777e9c1b54221a0f58140392e4f091cd5f42b2e8644a9384fbd58ae1edec2477ebf7edbf7c0a3f8bd21d1890ee87646feab3c47be716f842cc3da9b940af312dc54450a960e3fc0b86e56abddd154068e10571a96fff6259431632bc15695c6c8679057e66c2c25c127e97e64ee5de6ea1fc0a4a0e431343fed1daafa072c238a45841da86a9806680bc9f298411173210790359209cd454b5af7b4d5688b4403924e5f863d97e2c5349e1a04b54fcf385b1e9d7714bab8fbf5835f6ff9ed575e77dff7af5cbb641db5d537933bae1fa6555d6c12d6fb31ca27b57771f4aebfbe0bf95e8990c0108ffe7cbdaf370be52cf3ade594543af75ad9329d2d11a402270b5b9a6bf4b83307506e118fca4862749d04e916fc7a039f0d13f2a02e0eedb800199ec95df15b4ccd8669b52586879624d51219e72102fad810b5909b1e372ddf33888fb9beb09b416e4164966edbabd89e4a286be36277fc576ed519a15643dac602e92b63d0b9121f0491da5b16ef793a967f096d80b6c81ecaaffad7e3f06a4a5ac2796f1ed9f68e6a0fd5cf191f0c5c2eec338952ff8d31abc68bf760febeb57e088995ba1d7726a2fdd6d8ca28a181378b8b4ab699bfd4b696739bbf17a9eb2df6251143046137fdbbfacac312ebf67a67da9741b59600000000000",
@@ -1141,7 +1200,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_guido_3_even",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L166
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L166
pytest.param(
ModExpInput(
base="ffffffffffffffff",
@@ -1150,7 +1210,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_pawel_1_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L168
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L168
pytest.param(
ModExpInput(
base="ffffffffffffffffffffffffffffffff",
@@ -1159,7 +1220,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_pawel_2_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L170
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L170
pytest.param(
ModExpInput(
base="ffffffffffffffffffffffffffffffffffffffffffffffff",
@@ -1174,7 +1236,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_pawel_3_exp_8",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L172
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L172
pytest.param(
ModExpInput(
base="ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@@ -1183,7 +1246,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_pawel_4_exp_heavy",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L174
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L174
pytest.param(
ModExpInput(
base="29356abadad68ad986c416de6f620bda0e1818b589e84f853a97391694d35496",
@@ -1192,7 +1256,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_common_1360n1",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L176
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L176
pytest.param(
ModExpInput(
base="d41afaeaea32f7409827761b68c41b6e535da4ede1f0800bfb4a6aed18394f6b",
@@ -1201,7 +1266,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_common_1360n2",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L178
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L178
pytest.param(
ModExpInput(
base="1a5be8fae3b3fda9ea329494ae8689c04fae4978ecccfa6a6bfb9f04b25846c0",
@@ -1210,7 +1276,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_common_1349n1",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L182
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L182
pytest.param(
ModExpInput(
base="0000000000000000000000000000000000000000000000000000000000000003",
@@ -1219,7 +1286,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_common_1152n1",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L184
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L184
pytest.param(
ModExpInput(
base="1fb473dd1171cf88116aa77ab3612c2c7d2cf466cc2386cc456130e2727c70b4",
@@ -1228,7 +1296,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_common_200n1",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L186
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L186
pytest.param(
ModExpInput(
base="1951441010b2b95a6e47a6075066a50a036f5ba978c050f2821df86636c0facb",
@@ -1237,7 +1306,8 @@ def test_worst_precompile_only_data_input(
),
id="mod_vul_common_200n2",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L188
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L188
pytest.param(
ModExpInput(
base="288254ba43e713afbe36c9f03b54c00fae4c0a82df1cf165eb46a21c20a48ca2",
@@ -1264,14 +1334,15 @@ def test_worst_modexp(
gas_benchmark_value: int,
):
"""
- Test running a block with as many calls to the MODEXP (5) precompile as possible.
- All the calls have the same parametrized input.
+ Test running a block with as many calls to the MODEXP (5) precompile as
+ possible. All the calls have the same parametrized input.
"""
# Skip the trailing zeros from the input to make EVM work even harder.
calldata = bytes(mod_exp_input).rstrip(b"\x00")
code = code_loop_precompile_call(
- Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE), # Copy the input to the memory.
+ Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE), # Copy the input to the
+ # memory.
Op.POP(Op.STATICCALL(Op.GAS, 0x5, Op.PUSH0, Op.CALLDATASIZE, Op.PUSH0, Op.PUSH0)),
fork,
)
@@ -1296,8 +1367,8 @@ def test_worst_modexp(
pytest.param(
0x01,
[
- # The inputs below are a valid signature, thus ECRECOVER call won't
- # be short-circuited by validations and do actual work.
+ # The inputs below are a valid signature, thus ECRECOVER call
+ # won't be short-circuited by validations and do actual work.
"38D18ACB67D25C8BB9942764B62F18E17054F66A817BD4295423ADF9ED98873E",
"000000000000000000000000000000000000000000000000000000000000001B",
"38D18ACB67D25C8BB9942764B62F18E17054F66A817BD4295423ADF9ED98873E",
@@ -1315,7 +1386,8 @@ def test_worst_modexp(
],
id="bn128_add",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L326
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L326
pytest.param(
0x06,
[
@@ -1326,7 +1398,8 @@ def test_worst_modexp(
],
id="bn128_add_infinities",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L329
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L329
pytest.param(
0x06,
[
@@ -1346,7 +1419,8 @@ def test_worst_modexp(
],
id="bn128_mul",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L335
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L335
pytest.param(
0x07,
[
@@ -1356,7 +1430,8 @@ def test_worst_modexp(
],
id="bn128_mul_infinities_2_scalar",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L338
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L338
pytest.param(
0x07,
[
@@ -1366,7 +1441,8 @@ def test_worst_modexp(
],
id="bn128_mul_infinities_32_byte_scalar",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L341
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L341
pytest.param(
0x07,
[
@@ -1376,7 +1452,8 @@ def test_worst_modexp(
],
id="bn128_mul_1_2_2_scalar",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L344
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L344
pytest.param(
0x07,
[
@@ -1386,7 +1463,8 @@ def test_worst_modexp(
],
id="bn128_mul_1_2_32_byte_scalar",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L347
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L347
pytest.param(
0x07,
[
@@ -1396,7 +1474,8 @@ def test_worst_modexp(
],
id="bn128_mul_32_byte_coord_and_2_scalar",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L350
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L350
pytest.param(
0x07,
[
@@ -1439,7 +1518,8 @@ def test_worst_modexp(
],
id="bn128_one_pairing",
),
- # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L353
+ # Ported from
+ # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L353
pytest.param(0x08, [], id="ec_pairing_zero_input"),
pytest.param(
0x08,
@@ -1638,9 +1718,10 @@ def test_worst_modexp(
pytest.param(
bls12381_spec.Spec.G2MSM,
[
- # TODO: the //2 is required due to a limitation of the max contract size limit.
- # In a further iteration we can insert the inputs as calldata or storage and avoid
- # having to do PUSHes which has this limitation. This also applies to G1MSM.
+ # TODO: the //2 is required due to a limitation of the max
+ # contract size limit. In a further iteration we can insert the
+ # inputs as calldata or storage and avoid having to do PUSHes
+ # which has this limitation. This also applies to G1MSM.
(bls12381_spec.Spec.P2 + bls12381_spec.Scalar(bls12381_spec.Spec.Q))
* (len(bls12381_spec.Spec.G2MSM_DISCOUNT_TABLE) // 2),
],
@@ -1680,6 +1761,28 @@ def test_worst_modexp(
id="p256verify",
marks=[pytest.mark.eip_checklist("precompile/test/excessive_gas_usage", eip=[7951])],
),
+ pytest.param(
+ p256verify_spec.Spec.P256VERIFY,
+ [
+ "235060CAFE19A407880C272BC3E73600E3A12294F56143ED61929C2FF4525ABB",
+ "182E5CBDF96ACCB859E8EEA1850DE5FF6E430A19D1D9A680ECD5946BBEA8A32B",
+ "76DDFAE6797FA6777CAAB9FA10E75F52E70A4E6CEB117B3C5B2F445D850BD64C",
+ "3828736CDFC4C8696008F71999260329AD8B12287846FEDCEDE3BA1205B12729",
+ "3E5141734E971A8D55015068D9B3666760F4608A49B11F92E500ACEA647978C7",
+ ],
+ id="p256verify_wrong_endianness",
+ ),
+ pytest.param(
+ p256verify_spec.Spec.P256VERIFY,
+ [
+ "BB5A52F42F9C9261ED4361F59422A1E30036E7C32B270C8807A419FECA605023",
+ "000000000000000000000000000000004319055358E8617B0C46353D039CDAAB",
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E",
+ "0AD99500288D466940031D72A9F5445A4D43784640855BF0A69874D2DE5FE103",
+ "C5011E6EF2C42DCD50D5D3D29F99AE6EBA2C80C9244F4C5422F0979FF0C3BA5E",
+ ],
+ id="p256verify_modular_comp_x_coordinate_exceeds_n",
+ ),
],
)
def test_worst_precompile_fixed_cost(
@@ -1820,30 +1923,14 @@ def test_worst_jumpis(
@pytest.mark.slow
def test_worst_jumpdests(
- state_test: StateTestFiller,
+ benchmark_test: BenchmarkTestFiller,
pre: Alloc,
- fork: Fork,
- gas_benchmark_value: int,
):
"""Test running a JUMPDEST-intensive contract."""
- max_code_size = fork.max_code_size()
-
- # Create and deploy a contract with many JUMPDESTs
- code_suffix = Op.JUMP(Op.PUSH0)
- code_body = Op.JUMPDEST * (max_code_size - len(code_suffix))
- code = code_body + code_suffix
- jumpdests_address = pre.deploy_contract(code=code)
-
- tx = Transaction(
- to=jumpdests_address,
- gas_limit=gas_benchmark_value,
- sender=pre.fund_eoa(),
- )
-
- state_test(
+ benchmark_test(
pre=pre,
post={},
- tx=tx,
+ code_generator=JumpLoopGenerator(attack_block=Op.JUMPDEST),
)
@@ -1865,7 +1952,8 @@ def test_worst_jumpdests(
DEFAULT_BINOP_ARGS,
),
(
- # This has the cycle of 2, after two SUBs values are back to initials.
+ # This has the cycle of 2, after two SUBs values are back to
+ # initials.
Op.SUB,
DEFAULT_BINOP_ARGS,
),
@@ -1878,8 +1966,8 @@ def test_worst_jumpdests(
(
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,
# We want the first divisor to be slightly bigger than 2**128:
- # this is the worst case for the division algorithm with optimized paths
- # for division by 1 and 2 words.
+ # this is the worst case for the division algorithm with
+ # optimized paths for division by 1 and 2 words.
0x100000000000000000000000000000033,
),
),
@@ -1889,13 +1977,14 @@ def test_worst_jumpdests(
(
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,
# We want the first divisor to be slightly bigger than 2**64:
- # this is the worst case for the division algorithm with an optimized path
- # for division by 1 word.
+ # this is the worst case for the division algorithm with an
+ # optimized path for division by 1 word.
0x10000000000000033,
),
),
(
- # Same as DIV-0, but the numerator made positive, and the divisor made negative.
+ # Same as DIV-0, but the numerator made positive, and the divisor
+ # made negative.
Op.SDIV,
(
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,
@@ -1903,7 +1992,8 @@ def test_worst_jumpdests(
),
),
(
- # Same as DIV-1, but the numerator made positive, and the divisor made negative.
+ # Same as DIV-1, but the numerator made positive, and the divisor
+ # made negative.
Op.SDIV,
(
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,
@@ -1911,17 +2001,20 @@ def test_worst_jumpdests(
),
),
(
- # This scenario is not suitable for MOD because the values quickly become 0.
+ # This scenario is not suitable for MOD because the values quickly
+ # become 0.
Op.MOD,
DEFAULT_BINOP_ARGS,
),
(
- # This scenario is not suitable for SMOD because the values quickly become 0.
+ # This scenario is not suitable for SMOD because the values quickly
+ # become 0.
Op.SMOD,
DEFAULT_BINOP_ARGS,
),
(
- # This keeps the values unchanged, pow(2**256-1, 2**256-1, 2**256) == 2**256-1.
+ # This keeps the values unchanged, pow(2**256-1, 2**256-1, 2**256)
+ # == 2**256-1.
Op.EXP,
(
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
@@ -1998,9 +2091,9 @@ def test_worst_binop_simple(
gas_benchmark_value: int,
):
"""
- Test running a block with as many binary instructions (takes two args, produces one value)
- as possible. The execution starts with two initial values on the stack, and the stack is
- balanced by the DUP2 instruction.
+ Test running a block with as many binary instructions (takes two args,
+ produces one value) as possible. The execution starts with two initial
+ values on the stack, and the stack is balanced by the DUP2 instruction.
"""
max_code_size = fork.max_code_size()
@@ -2036,8 +2129,8 @@ def test_worst_unop(
gas_benchmark_value: int,
):
"""
- Test running a block with as many unary instructions (takes one arg, produces one value)
- as possible.
+ Test running a block with as many unary instructions (takes one arg,
+ produces one value) as possible.
"""
max_code_size = fork.max_code_size()
@@ -2063,7 +2156,8 @@ def test_worst_unop(
# `key_mut` indicates the key isn't fixed.
@pytest.mark.parametrize("key_mut", [True, False])
-# `val_mut` indicates that at the end of each big-loop, the value of the target key changes.
+# `val_mut` indicates that at the end of each big-loop, the value of the target
+# key changes.
@pytest.mark.parametrize("val_mut", [True, False])
def test_worst_tload(
state_test: StateTestFiller,
@@ -2090,7 +2184,8 @@ def test_worst_tload(
if not key_mut and val_mut:
code_prefix = Op.JUMPDEST
loop_iter = Op.POP(Op.TLOAD(Op.CALLVALUE))
- code_val_mut = Op.TSTORE(Op.CALLVALUE, Op.GAS) # CALLVALUE configured in the tx
+ code_val_mut = Op.TSTORE(Op.CALLVALUE, Op.GAS) # CALLVALUE configured
+ # in the tx
if not key_mut and not val_mut:
code_prefix = Op.JUMPDEST
loop_iter = Op.POP(Op.TLOAD(Op.CALLVALUE))
@@ -2132,12 +2227,13 @@ def test_worst_tstore(
init_key = 42
code_prefix = Op.PUSH1(init_key) + Op.JUMPDEST
- # If `key_mut` is True, we mutate the key on every iteration of the big loop.
+ # If `key_mut` is True, we mutate the key on every iteration of the big
+ # loop.
code_key_mut = Op.POP + Op.GAS if key_mut else Bytecode()
code_suffix = code_key_mut + Op.JUMP(len(code_prefix) - 1)
- # If `dense_val_mut` is set, we use GAS as a cheap way of always storing a different value than
- # the previous one.
+ # If `dense_val_mut` is set, we use GAS as a cheap way of always storing a
+ # different value than the previous one.
loop_iter = Op.TSTORE(Op.DUP2, Op.GAS if dense_val_mut else Op.DUP1)
code_body_len = (max_code_size - len(code_prefix) - len(code_suffix)) // len(loop_iter)
@@ -2167,9 +2263,10 @@ def test_worst_shifts(
gas_benchmark_value: int,
):
"""
- Test running a block with as many shift instructions with non-trivial arguments.
- This test generates left-right pairs of shifts to avoid zeroing the argument.
- The shift amounts are randomly pre-selected from the constant pool of 15 values on the stack.
+ Test running a block with as many shift instructions with non-trivial
+ arguments. This test generates left-right pairs of shifts to avoid zeroing
+ the argument. The shift amounts are randomly pre-selected from the constant
+ pool of 15 values on the stack.
"""
max_code_size = fork.max_code_size()
@@ -2197,10 +2294,12 @@ def sar(x, s):
raise ValueError(f"Unexpected shift op: {shift_right}")
rng = random.Random(1) # Use random with a fixed seed.
- initial_value = 2**256 - 1 # The initial value to be shifted; should be negative for SAR.
+ initial_value = 2**256 - 1 # The initial value to be shifted; should be
+ # negative for SAR.
- # Create the list of shift amounts with 15 elements (max reachable by DUPs instructions).
- # For the worst case keep the values small and omit values divisible by 8.
+ # Create the list of shift amounts with 15 elements (max reachable by DUPs
+ # instructions). For the worst case keep the values small and omit values
+ # divisible by 8.
shift_amounts = [x + (x >= 8) + (x >= 15) for x in range(1, 16)]
code_prefix = sum(Op.PUSH1[sh] for sh in shift_amounts) + Op.JUMPDEST + Op.CALLDATALOAD(0)
@@ -2315,20 +2414,25 @@ def test_worst_mod(
gas_benchmark_value: int,
):
"""
- Test running a block with as many MOD instructions with arguments of the parametrized range.
+ Test running a block with as many MOD instructions with arguments of the
+ parametrized range.
+
The test program consists of code segments evaluating the "MOD chain":
mod[0] = calldataload(0)
mod[1] = numerators[indexes[0]] % mod[0]
mod[2] = numerators[indexes[1]] % mod[1] ...
- The "numerators" is a pool of 15 constants pushed to the EVM stack at the program start.
- The order of accessing the numerators is selected in a way the mod value remains in the range
- as long as possible.
+
+ The "numerators" is a pool of 15 constants pushed to the EVM stack at the
+ program start.
+
+ The order of accessing the numerators is selected in a way the mod value
+ remains in the range as long as possible.
"""
max_code_size = fork.max_code_size()
- # For SMOD we negate both numerator and modulus. The underlying computation is the same,
- # just the SMOD implementation will have to additionally handle the sign bits.
- # The result stays negative.
+ # For SMOD we negate both numerator and modulus. The underlying computation
+ # is the same, just the SMOD implementation will have to additionally
+ # handle the sign bits. The result stays negative.
should_negate = op == Op.SMOD
num_numerators = 15
@@ -2336,12 +2440,13 @@ def test_worst_mod(
numerator_max = 2**numerator_bits - 1
numerator_min = 2 ** (numerator_bits - 1)
- # Pick the modulus min value so that it is _unlikely_ to drop to the lower word count.
+ # Pick the modulus min value so that it is _unlikely_ to drop to the lower
+ # word count.
assert mod_bits >= 63
mod_min = 2 ** (mod_bits - 63)
- # Select the random seed giving the longest found MOD chain.
- # You can look for a longer one by increasing the numerators_min_len. This will activate
+ # Select the random seed giving the longest found MOD chain. You can look
+ # for a longer one by increasing the numerators_min_len. This will activate
# the while loop below.
match op, mod_bits:
case Op.MOD, 255:
@@ -2384,18 +2489,22 @@ def test_worst_mod(
mod = initial_mod
indexes = []
while mod >= mod_min:
- results = [n % mod for n in numerators] # Compute results for each numerator.
- i = max(range(len(results)), key=results.__getitem__) # And pick the best one.
+ # Compute results for each numerator.
+ results = [n % mod for n in numerators]
+ # And pick the best one.
+ i = max(range(len(results)), key=results.__getitem__)
mod = results[i]
indexes.append(i)
- assert len(indexes) > numerators_min_len # Disable if you want to find longer MOD chains.
+ # Disable if you want to find longer MOD chains.
+ assert len(indexes) > numerators_min_len
if len(indexes) > numerators_min_len:
break
seed += 1
print(f"{seed=}")
- # TODO: Don't use fixed PUSH32. Let Bytecode helpers to select optimal push opcode.
+ # TODO: Don't use fixed PUSH32. Let Bytecode helpers to select optimal push
+ # opcode.
code_constant_pool = sum((Op.PUSH32[n] for n in numerators), Bytecode())
code_prefix = code_constant_pool + Op.JUMPDEST
code_suffix = Op.JUMP(len(code_constant_pool))
@@ -2440,7 +2549,9 @@ def test_worst_memory_access(
big_memory_expansion: bool,
gas_benchmark_value: int,
):
- """Test running a block with as many memory access instructions as possible."""
+ """
+ Test running a block with as many memory access instructions as possible.
+ """
max_code_size = fork.max_code_size()
mem_exp_code = Op.MSTORE8(10 * 1024, 1) if big_memory_expansion else Bytecode()
@@ -2480,29 +2591,32 @@ def test_worst_modarith(
gas_benchmark_value: int,
):
"""
- Test running a block with as many "op" instructions with arguments of the parametrized range.
+ Test running a block with as many "op" instructions with arguments of the
+ parametrized range.
The test program consists of code segments evaluating the "op chain":
mod[0] = calldataload(0)
mod[1] = (fixed_arg op args[indexes[0]]) % mod[0]
mod[2] = (fixed_arg op args[indexes[1]]) % mod[1]
- The "args" is a pool of 15 constants pushed to the EVM stack at the program start.
+ The "args" is a pool of 15 constants pushed to the EVM stack at the program
+ start.
The "fixed_arg" is the 0xFF...FF constant added to the EVM stack by PUSH32
just before executing the "op".
- The order of accessing the numerators is selected in a way the mod value remains in the range
- as long as possible.
+ The order of accessing the numerators is selected in a way the mod value
+ remains in the range as long as possible.
"""
fixed_arg = 2**256 - 1
num_args = 15
max_code_size = fork.max_code_size()
- # Pick the modulus min value so that it is _unlikely_ to drop to the lower word count.
+ # Pick the modulus min value so that it is _unlikely_ to drop to the lower
+ # word count.
assert mod_bits >= 63
mod_min = 2 ** (mod_bits - 63)
- # Select the random seed giving the longest found op chain.
- # You can look for a longer one by increasing the op_chain_len. This will activate
- # the while loop below.
+ # Select the random seed giving the longest found op chain. You can look
+ # for a longer one by increasing the op_chain_len. This will activate the
+ # while loop below.
op_chain_len = 666
match op, mod_bits:
case Op.ADDMOD, 255:
@@ -2520,7 +2634,8 @@ def test_worst_modarith(
case Op.MULMOD, 127:
seed = 5
case Op.MULMOD, 63:
- # For this setup we were not able to find an op-chain longer than 600.
+ # For this setup we were not able to find an op-chain longer than
+ # 600.
seed = 4193
op_chain_len = 600
case _:
@@ -2537,11 +2652,13 @@ def test_worst_modarith(
indexes: list[int] = []
while mod >= mod_min and len(indexes) < op_chain_len:
results = [op_fn(a, fixed_arg) % mod for a in args]
- i = max(range(len(results)), key=results.__getitem__) # And pick the best one.
+ # And pick the best one.
+ i = max(range(len(results)), key=results.__getitem__)
mod = results[i]
indexes.append(i)
- assert len(indexes) == op_chain_len # Disable if you want to find longer op chains.
+ # Disable if you want to find longer op chains.
+ assert len(indexes) == op_chain_len
if len(indexes) == op_chain_len:
break
seed += 1
@@ -2553,8 +2670,8 @@ def test_worst_modarith(
+ sum(make_dup(len(args) - i) + Op.PUSH32[fixed_arg] + op for i in indexes)
+ Op.POP
)
- # Construct the final code. Because of the usage of PUSH32 the code segment is very long,
- # so don't try to include multiple of these.
+ # Construct the final code. Because of the usage of PUSH32 the code segment
+ # is very long, so don't try to include multiple of these.
code = code_constant_pool + Op.JUMPDEST + code_segment + Op.JUMP(len(code_constant_pool))
assert (max_code_size - len(code_segment)) < len(code) <= max_code_size
@@ -2600,8 +2717,9 @@ def test_amortized_bn128_pairings(
intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
mem_exp_gas_calculator = fork.memory_expansion_gas_calculator()
- # This is a theoretical maximum number of pairings that can be done in a block.
- # It is only used for an upper bound for calculating the optimal number of pairings below.
+ # This is a theoretical maximum number of pairings that can be done in a
+ # block. It is only used for an upper bound for calculating the optimal
+ # number of pairings below.
maximum_number_of_pairings = (gas_benchmark_value - base_cost) // pairing_cost
# Discover the optimal number of pairings balancing two dimensions:
@@ -2612,19 +2730,21 @@ def test_amortized_bn128_pairings(
for i in range(1, maximum_number_of_pairings + 1):
# We'll pass all pairing arguments via calldata.
available_gas_after_intrinsic = gas_benchmark_value - intrinsic_gas_calculator(
- calldata=[0xFF] * size_per_pairing * i # 0xFF is to indicate non-zero bytes.
+ calldata=[0xFF] * size_per_pairing * i # 0xFF is to indicate non-
+ # zero bytes.
)
available_gas_after_expansion = max(
0,
available_gas_after_intrinsic - mem_exp_gas_calculator(new_bytes=i * size_per_pairing),
)
- # This is ignoring "glue" opcodes, but helps to have a rough idea of the right
- # cutting point.
+ # This is ignoring "glue" opcodes, but helps to have a rough idea of
+ # the right cutting point.
approx_gas_cost_per_call = gsc.G_WARM_ACCOUNT_ACCESS + base_cost + i * pairing_cost
num_precompile_calls = available_gas_after_expansion // approx_gas_cost_per_call
- num_pairings_done = num_precompile_calls * i # Each precompile call does i pairings.
+ num_pairings_done = num_precompile_calls * i # Each precompile call
+ # does i pairings.
if num_pairings_done > max_pairings:
max_pairings = num_pairings_done
@@ -2742,31 +2862,17 @@ def test_worst_calldataload(
],
)
def test_worst_swap(
- state_test: StateTestFiller,
+ benchmark_test: BenchmarkTestFiller,
pre: Alloc,
- fork: Fork,
opcode: Opcode,
- gas_benchmark_value: int,
):
"""Test running a block with as many SWAP as possible."""
- max_code_size = fork.max_code_size()
-
- code_prefix = Op.JUMPDEST + Op.PUSH0 * opcode.min_stack_height
- code_suffix = Op.PUSH0 + Op.JUMP
- opcode_sequence = opcode * (max_code_size - len(code_prefix) - len(code_suffix))
- code = code_prefix + opcode_sequence + code_suffix
- assert len(code) <= max_code_size
-
- tx = Transaction(
- to=pre.deploy_contract(code=code),
- gas_limit=gas_benchmark_value,
- sender=pre.fund_eoa(),
- )
-
- state_test(
+ benchmark_test(
pre=pre,
post={},
- tx=tx,
+ code_generator=JumpLoopGenerator(
+ attack_block=opcode, setup=Op.PUSH0 * opcode.min_stack_height
+ ),
)
@@ -2872,13 +2978,20 @@ def test_worst_push(
):
"""Test running a block with as many PUSH as possible."""
op = opcode[1] if opcode.has_data_portion() else opcode
- opcode_sequence = op * fork.max_stack_height()
- target_contract_address = pre.deploy_contract(code=opcode_sequence)
+
+ op_seq = Bytecode()
+ for _ in range(fork.max_stack_height()):
+ if len(op_seq) + len(op) > fork.max_code_size():
+ break
+ op_seq += op
+
+ target_contract_address = pre.deploy_contract(code=op_seq)
calldata = Bytecode()
attack_block = Op.POP(Op.STATICCALL(Op.GAS, target_contract_address, 0, 0, 0, 0))
code = code_loop_precompile_call(calldata, attack_block, fork)
+
code_address = pre.deploy_contract(code=code)
tx = Transaction(
@@ -2927,8 +3040,9 @@ def test_worst_return_revert(
# opcode(returned_size)
#
# ```
- # Filling the contract up to the max size is a cheap way of leveraging CODECOPY to return
- # non-zero bytes if requested. Note that since this is a pre-deploy this cost isn't
+ # Filling the contract up to the max size is a cheap way of leveraging
+ # CODECOPY to return non-zero bytes if requested. Note that since this
+ # is a pre-deploy this cost isn't
# relevant for the benchmark.
mem_preparation = Op.CODECOPY(size=return_size) if return_non_zero_data else Bytecode()
executable_code = mem_preparation + opcode(size=return_size)
@@ -3005,7 +3119,9 @@ def test_worst_clz_diff_input(
gas_benchmark_value: int,
env: Environment,
):
- """Test running a block with as many CLZ with different input as possible."""
+ """
+ Test running a block with as many CLZ with different input as possible.
+ """
tx_gas_limit = fork.transaction_gas_limit_cap() or env.gas_limit
max_code_size = fork.max_code_size()
diff --git a/tests/eest/benchmark/test_worst_memory.py b/tests/eest/benchmark/test_worst_memory.py
index 4a1797097a..689dcf0632 100644
--- a/tests/eest/benchmark/test_worst_memory.py
+++ b/tests/eest/benchmark/test_worst_memory.py
@@ -1,7 +1,4 @@
"""
-abstract: Tests that benchmark EVMs in the worst-case memory opcodes.
- Tests that benchmark EVMs in the worst-case memory opcodes.
-
Tests that benchmark EVMs in the worst-case memory opcodes.
"""
@@ -15,7 +12,7 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .helpers import code_loop_precompile_call
@@ -74,8 +71,9 @@ def test_worst_calldatacopy(
if size == 0 and non_zero_data:
pytest.skip("Non-zero data with size 0 is not applicable.")
- # If `non_zero_data` is True, we fill the calldata with deterministic random data.
- # Note that if `size == 0` and `non_zero_data` is a skipped case.
+ # If `non_zero_data` is True, we fill the calldata with deterministic
+ # random data. Note that if `size == 0` and `non_zero_data` is a skipped
+ # case.
data = Bytes([i % 256 for i in range(size)]) if non_zero_data else Bytes()
intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
@@ -83,10 +81,11 @@ def test_worst_calldatacopy(
if min_gas > gas_benchmark_value:
pytest.skip("Minimum gas required for calldata ({min_gas}) is greater than the gas limit")
- # We create the contract that will be doing the CALLDATACOPY multiple times.
- #
- # If `non_zero_data` is True, we leverage CALLDATASIZE for the copy length. Otherwise, since we
- # don't send zero data explicitly via calldata, PUSH the target size and use DUP1 to copy it.
+ # We create the contract that will be doing the CALLDATACOPY multiple
+ # times.
+ # If `non_zero_data` is True, we leverage CALLDATASIZE for the copy length.
+ # Otherwise, since we don't send zero data explicitly via calldata, PUSH
+ # the target size and use DUP1 to copy it.
prefix = Bytecode() if non_zero_data or size == 0 else Op.PUSH3(size)
src_dst = 0 if fixed_src_dst else Op.MOD(Op.GAS, 7)
attack_block = Op.CALLDATACOPY(
@@ -97,11 +96,11 @@ def test_worst_calldatacopy(
tx_target = code_address
- # If the origin is CALL, we need to create a contract that will call the target contract with
- # the calldata.
+ # If the origin is CALL, we need to create a contract that will call the
+ # target contract with the calldata.
if origin == CallDataOrigin.CALL:
- # If `non_zero_data` is False we leverage just using zeroed memory. Otherwise, we
- # copy the calldata received from the transaction.
+ # If `non_zero_data` is False we leverage just using zeroed memory.
+ # Otherwise, we copy the calldata received from the transaction.
prefix = (
Op.CALLDATACOPY(Op.PUSH0, Op.PUSH0, Op.CALLDATASIZE) if non_zero_data else Bytecode()
) + Op.JUMPDEST
@@ -161,9 +160,9 @@ def test_worst_codecopy(
attack_block = Op.CODECOPY(src_dst, src_dst, Op.DUP1) # DUP1 copies size.
code = code_loop_precompile_call(code_prefix, attack_block, fork)
- # The code generated above is not guaranteed to be of max_code_size, so we pad it since
- # a test parameter targets CODECOPYing a contract with max code size. Padded bytecode values
- # are not relevant.
+ # The code generated above is not guaranteed to be of max_code_size, so we
+ # pad it since a test parameter targets CODECOPYing a contract with max
+ # code size. Padded bytecode values are not relevant.
code = code + Op.INVALID * (max_code_size - len(code))
assert len(code) == max_code_size, (
f"Code size {len(code)} is not equal to max code size {max_code_size}."
@@ -209,9 +208,10 @@ def test_worst_returndatacopy(
"""Test running a block filled with RETURNDATACOPY executions."""
max_code_size = fork.max_code_size()
- # Create the contract that will RETURN the data that will be used for RETURNDATACOPY.
- # Random-ish data is injected at different points in memory to avoid making the content
- # predictable. If `size` is 0, this helper contract won't be used.
+ # Create the contract that will RETURN the data that will be used for
+ # RETURNDATACOPY. Random-ish data is injected at different points in memory
+ # to avoid making the content predictable. If `size` is 0, this helper
+ # contract won't be used.
code = (
Op.MSTORE8(0, Op.GAS)
+ Op.MSTORE8(size // 2, Op.GAS)
@@ -220,7 +220,8 @@ def test_worst_returndatacopy(
)
helper_contract = pre.deploy_contract(code=code)
- # We create the contract that will be doing the RETURNDATACOPY multiple times.
+ # We create the contract that will be doing the RETURNDATACOPY multiple
+ # times.
returndata_gen = Op.STATICCALL(address=helper_contract) if size > 0 else Bytecode()
dst = 0 if fixed_dst else Op.MOD(Op.GAS, 7)
attack_iter = Op.RETURNDATACOPY(dst, Op.PUSH0, Op.RETURNDATASIZE)
@@ -236,8 +237,8 @@ def test_worst_returndatacopy(
# STATICCALL(address=helper_contract)
# JUMP(#)
# ```
- # The goal is that once per (big) loop iteration, the helper contract is called to
- # generate fresh returndata to continue calling RETURNDATACOPY.
+ # The goal is that once per (big) loop iteration, the helper contract is
+ # called to generate fresh returndata to continue calling RETURNDATACOPY.
max_iters_loop = (
max_code_size - 2 * len(returndata_gen) - len(jumpdest) - len(jump_back)
) // len(attack_iter)
diff --git a/tests/eest/benchmark/test_worst_opcode.py b/tests/eest/benchmark/test_worst_opcode.py
index f41321fb89..9ee805a628 100644
--- a/tests/eest/benchmark/test_worst_opcode.py
+++ b/tests/eest/benchmark/test_worst_opcode.py
@@ -1,8 +1,5 @@
"""
-abstract: Tests benchmark worst-case opcode scenarios.
- Tests benchmark worst-case opcode scenarios.
-
-Tests running worst-case opcodes scenarios for benchmarking purposes.
+Tests benchmark worst-case opcode scenarios.
"""
import pytest
@@ -14,8 +11,8 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
-from ethereum_test_vm.opcode import Opcode
+from ethereum_test_vm import Opcode
+from ethereum_test_vm import Opcodes as Op
from .helpers import code_loop_precompile_call
diff --git a/tests/eest/benchmark/test_worst_stateful_opcodes.py b/tests/eest/benchmark/test_worst_stateful_opcodes.py
index 8146175ae7..f5cd6c0289 100644
--- a/tests/eest/benchmark/test_worst_stateful_opcodes.py
+++ b/tests/eest/benchmark/test_worst_stateful_opcodes.py
@@ -1,7 +1,4 @@
"""
-abstract: Tests that benchmark EVMs for worst-case stateful opcodes.
- Tests that benchmark EVMs for worst-case stateful opcodes.
-
Tests that benchmark EVMs for worst-case stateful opcodes.
"""
@@ -25,7 +22,7 @@
compute_create2_address,
compute_create_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .helpers import code_loop_precompile_call
@@ -55,14 +52,17 @@ def test_worst_address_state_cold(
env: Environment,
gas_benchmark_value: int,
):
- """Test running a block with as many stateful opcodes accessing cold accounts."""
+ """
+ Test running a block with as many stateful opcodes accessing cold accounts.
+ """
attack_gas_limit = gas_benchmark_value
gas_costs = fork.gas_costs()
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
- # For calculation robustness, the calculation below ignores "glue" opcodes like PUSH and POP.
- # It should be considered a worst-case number of accounts, and a few of them might not be
- # targeted before the attacking transaction runs out of gas.
+ # For calculation robustness, the calculation below ignores "glue" opcodes
+ # like PUSH and POP. It should be considered a worst-case number of
+ # accounts, and a few of them might not be targeted before the attacking
+ # transaction runs out of gas.
num_target_accounts = (
attack_gas_limit - intrinsic_gas_cost_calc()
) // gas_costs.G_COLD_ACCOUNT_ACCESS
@@ -70,10 +70,10 @@ def test_worst_address_state_cold(
blocks = []
post = {}
- # Setup
- # The target addresses are going to be constructed (in the case of absent=False) and called
- # as addr_offset + i, where i is the index of the account. This is to avoid
- # collisions with the addresses indirectly created by the testing framework.
+ # Setup The target addresses are going to be constructed (in the case of
+ # absent=False) and called as addr_offset + i, where i is the index of the
+ # account. This is to avoid collisions with the addresses indirectly
+ # created by the testing framework.
addr_offset = int.from_bytes(pre.fund_eoa(amount=0))
if not absent_accounts:
@@ -142,7 +142,10 @@ def test_worst_address_state_warm(
absent_target: bool,
gas_benchmark_value: int,
):
- """Test running a block with as many stateful opcodes doing warm access for an account."""
+ """
+ Test running a block with as many stateful opcodes doing warm access for an
+ account.
+ """
max_code_size = fork.max_code_size()
attack_gas_limit = gas_benchmark_value
@@ -253,7 +256,9 @@ def test_worst_storage_access_cold(
gas_benchmark_value: int,
tx_result: TransactionResult,
):
- """Test running a block with as many cold storage slot accesses as possible."""
+ """
+ Test running a block with as many cold storage slot accesses as possible.
+ """
gas_costs = fork.gas_costs()
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
attack_gas_limit = gas_benchmark_value
@@ -280,7 +285,8 @@ def test_worst_storage_access_cold(
execution_code_body = Op.SSTORE(Op.DUP1, Op.DUP1)
loop_cost += gas_costs.G_VERY_LOW * 2
elif storage_action == StorageAction.WRITE_NEW_VALUE:
- # The new value 2^256-1 is guaranteed to be different from the initial value.
+ # The new value 2^256-1 is guaranteed to be different from the initial
+ # value.
execution_code_body = Op.SSTORE(Op.DUP2, Op.NOT(0))
loop_cost += gas_costs.G_VERY_LOW * 3
elif storage_action == StorageAction.READ:
@@ -336,8 +342,9 @@ def test_worst_storage_access_cold(
condition=Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO,
)
- # To create the contract, we apply the slots_init code to initialize the storage slots
- # (int the case of absent_slots=False) and then copy the execution code to the contract.
+ # To create the contract, we apply the slots_init code to initialize the
+ # storage slots (int the case of absent_slots=False) and then copy the
+ # execution code to the contract.
creation_code = (
slots_init
+ Op.EXTCODECOPY(
@@ -393,7 +400,9 @@ def test_worst_storage_access_warm(
env: Environment,
gas_benchmark_value: int,
):
- """Test running a block with as many warm storage slot accesses as possible."""
+ """
+ Test running a block with as many warm storage slot accesses as possible.
+ """
attack_gas_limit = gas_benchmark_value
blocks = []
@@ -455,7 +464,10 @@ def test_worst_blockhash(
pre: Alloc,
gas_benchmark_value: int,
):
- """Test running a block with as many blockhash accessing oldest allowed block as possible."""
+ """
+ Test running a block with as many blockhash accessing oldest allowed block
+ as possible.
+ """
# Create 256 dummy blocks to fill the blockhash window.
blocks = [Block()] * 256
@@ -560,7 +572,10 @@ def test_worst_selfdestruct_existing(
env: Environment,
gas_benchmark_value: int,
):
- """Test running a block with as many SELFDESTRUCTs as possible for existing contracts."""
+ """
+ Test running a block with as many SELFDESTRUCTs as possible for existing
+ contracts.
+ """
attack_gas_limit = gas_benchmark_value
fee_recipient = pre.fund_eoa(amount=1)
@@ -574,12 +589,14 @@ def test_worst_selfdestruct_existing(
) + Op.RETURN(0, Op.EXTCODESIZE(selfdestructable_contract_addr))
initcode_address = pre.deploy_contract(code=initcode)
- # Calculate the number of contracts that can be deployed with the available gas.
+ # Calculate the number of contracts that can be deployed with the available
+ # gas.
gas_costs = fork.gas_costs()
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
loop_cost = (
gas_costs.G_KECCAK_256 # KECCAK static cost
- + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic cost for CREATE2
+ + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic
+ # cost for CREATE2
+ gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs
+ gas_costs.G_COLD_ACCOUNT_ACCESS # CALL to self-destructing contract
+ gas_costs.G_SELF_DESTRUCT
@@ -598,9 +615,9 @@ def test_worst_selfdestruct_existing(
num_contracts = (attack_gas_limit - base_costs) // loop_cost
expected_benchmark_gas_used = num_contracts * loop_cost + base_costs
- # Create a factory that deployes a new SELFDESTRUCT contract instance pre-funded depending on
- # the value_bearing parameter. We use CREATE2 so the caller contract can easily reproduce
- # the addresses in a loop for CALLs.
+ # Create a factory that deployes a new SELFDESTRUCT contract instance pre-
+ # funded depending on the value_bearing parameter. We use CREATE2 so the
+ # caller contract can easily reproduce the addresses in a loop for CALLs.
factory_code = (
Op.EXTCODECOPY(
address=initcode_address,
@@ -621,7 +638,8 @@ def test_worst_selfdestruct_existing(
+ Op.RETURN(0, 32)
)
- required_balance = num_contracts if value_bearing else 0 # 1 wei per contract
+ required_balance = num_contracts if value_bearing else 0 # 1 wei per
+ # contract
factory_address = pre.deploy_contract(code=factory_code, balance=required_balance)
factory_caller_code = Op.CALLDATALOAD(0) + While(
@@ -648,8 +666,8 @@ def test_worst_selfdestruct_existing(
+ While(
body=Op.POP(Op.CALL(address=Op.SHA3(32 - 20 - 1, 85)))
+ Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)),
- # Only loop if we have enough gas to cover another iteration plus the
- # final storage gas.
+ # Only loop if we have enough gas to cover another iteration plus
+ # the final storage gas.
condition=Op.GT(Op.GAS, final_storage_gas + loop_cost),
)
+ Op.SSTORE(0, 42) # Done for successful tx execution assertion below.
@@ -700,8 +718,8 @@ def test_worst_selfdestruct_created(
gas_benchmark_value: int,
):
"""
- Test running a block with as many SELFDESTRUCTs as possible for deployed contracts in
- the same transaction.
+ Test running a block with as many SELFDESTRUCTs as possible for deployed
+ contracts in the same transaction.
"""
fee_recipient = pre.fund_eoa(amount=1)
env.fee_recipient = fee_recipient
@@ -779,7 +797,8 @@ def test_worst_selfdestruct_created(
sender=pre.fund_eoa(),
)
- post = {code_addr: Account(storage={0: 42})} # Check for successful execution.
+ post = {code_addr: Account(storage={0: 42})} # Check for successful
+ # execution.
state_test(
env=env,
pre=pre,
@@ -798,7 +817,10 @@ def test_worst_selfdestruct_initcode(
env: Environment,
gas_benchmark_value: int,
):
- """Test running a block with as many SELFDESTRUCTs as possible executed in initcode."""
+ """
+ Test running a block with as many SELFDESTRUCTs as possible executed in
+ initcode.
+ """
fee_recipient = pre.fund_eoa(amount=1)
env.fee_recipient = fee_recipient
@@ -861,7 +883,8 @@ def test_worst_selfdestruct_initcode(
sender=pre.fund_eoa(),
)
- post = {code_addr: Account(storage={0: 42})} # Check for successful execution.
+ post = {code_addr: Account(storage={0: 42})} # Check for successful
+ # execution.
state_test(
env=env,
pre=pre,
diff --git a/tests/eest/berlin/eip2929_gas_cost_increases/__init__.py b/tests/eest/berlin/eip2929_gas_cost_increases/__init__.py
index 9646b2063c..baedc1cb64 100644
--- a/tests/eest/berlin/eip2929_gas_cost_increases/__init__.py
+++ b/tests/eest/berlin/eip2929_gas_cost_increases/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929)
- Test cases for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929).
-""" # noqa: E501
+Tests for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929).
+"""
diff --git a/tests/eest/berlin/eip2929_gas_cost_increases/test_call.py b/tests/eest/berlin/eip2929_gas_cost_increases/test_call.py
new file mode 100644
index 0000000000..a285a562a5
--- /dev/null
+++ b/tests/eest/berlin/eip2929_gas_cost_increases/test_call.py
@@ -0,0 +1,71 @@
+"""Test the CALL opcode after EIP-2929."""
+
+import pytest
+
+from ethereum_test_forks import Fork
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ CodeGasMeasure,
+ Environment,
+ StateTestFiller,
+ Transaction,
+)
+from ethereum_test_vm import Opcodes as Op
+
+REFERENCE_SPEC_GIT_PATH = "EIPS/eip-2929.md"
+REFERENCE_SPEC_VERSION = "0e11417265a623adb680c527b15d0cb6701b870b"
+
+
+@pytest.mark.valid_from("Berlin")
+def test_call_insufficient_balance(
+ state_test: StateTestFiller, pre: Alloc, env: Environment, fork: Fork
+):
+ """
+ Test a regular CALL to see if it warms the destination with insufficient
+ balance.
+ """
+ gas_costs = fork.gas_costs()
+ destination = pre.fund_eoa(1)
+ contract_address = pre.deploy_contract(
+ # Perform the aborted external calls
+ Op.SSTORE(
+ 0,
+ Op.CALL(
+ gas=Op.GAS,
+ address=destination,
+ value=1,
+ args_offset=0,
+ args_size=0,
+ ret_offset=0,
+ ret_size=0,
+ ),
+ )
+ # Measure the gas cost for BALANCE operation
+ + CodeGasMeasure(
+ code=Op.BALANCE(destination),
+ overhead_cost=gas_costs.G_VERY_LOW, # PUSH20 costs 3 gas
+ extra_stack_items=1, # BALANCE puts balance on stack
+ sstore_key=1,
+ ),
+ balance=0,
+ )
+
+ tx = Transaction(
+ to=contract_address,
+ gas_limit=100_000,
+ sender=pre.fund_eoa(),
+ )
+
+ post = {
+ destination: Account(
+ balance=1,
+ ),
+ contract_address: Account(
+ storage={
+ 0: 0, # The CALL is aborted
+ 1: gas_costs.G_WARM_ACCOUNT_ACCESS, # Warm access cost
+ },
+ ),
+ }
+ state_test(env=env, pre=pre, post=post, tx=tx)
diff --git a/tests/eest/berlin/eip2929_gas_cost_increases/test_precompile_warming.py b/tests/eest/berlin/eip2929_gas_cost_increases/test_precompile_warming.py
index 41fda5771d..a4f2270c04 100644
--- a/tests/eest/berlin/eip2929_gas_cost_increases/test_precompile_warming.py
+++ b/tests/eest/berlin/eip2929_gas_cost_increases/test_precompile_warming.py
@@ -1,7 +1,10 @@
"""
-abstract: Tests [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929)
- Test cases for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929).
-""" # noqa: E501
+Tests EIP-2929 precompile warming behavior.
+
+Tests precompile warming behavior across fork transitions from
+[EIP-2929: Gas cost increases for state access opcodes]
+ (https://eips.ethereum.org/EIPS/eip-2929).
+"""
from typing import Iterator, Tuple
@@ -21,7 +24,7 @@
BlockchainTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-2929.md"
REFERENCE_SPEC_VERSION = "0e11417265a623adb680c527b15d0cb6701b870b"
@@ -31,14 +34,17 @@ def precompile_addresses_in_predecessor_successor(
fork: Fork,
) -> Iterator[Tuple[Address, bool, bool]]:
"""
- Yield the addresses of precompiled contracts and whether they existed in the parent fork.
+ Yield the addresses of precompiled contracts and whether they existed in
+ the parent fork.
Args:
- fork (Fork): The transition fork instance containing precompiled contract information.
+ fork (Fork): The transition 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 has existed in the predecessor.
+ Iterator[Tuple[str, bool]]: A tuple containing the address in
+ hexadecimal format and a boolean indicating whether the address
+ has existed in the predecessor.
"""
precompile_range = range(0x01, 0x100)
@@ -73,6 +79,7 @@ def precompile_addresses_in_predecessor_successor(
)
@EIPChecklist.Precompile.Test.ForkTransition.Before.Cold(eip=[7951])
@EIPChecklist.Precompile.Test.ForkTransition.After.Warm(eip=[7951])
+@pytest.mark.slow()
def test_precompile_warming(
blockchain_test: BlockchainTestFiller,
fork: Fork,
@@ -84,14 +91,16 @@ def test_precompile_warming(
"""
Call BALANCE of a precompile addresses before and after a fork.
- According to EIP-2929, when a transaction begins, accessed_addresses is initialized to include:
+ According to EIP-2929, when a transaction begins, accessed_addresses is
+ initialized to include:
- tx.sender, tx.to
- and the set of all precompiles
This test verifies that:
- 1. Precompiles that exist in the predecessor fork are always "warm" (lower gas cost)
- 2. New precompiles added in a fork are "cold" before the fork and become "warm" after
-
+ 1. Precompiles that exist in the predecessor fork are always "warm" (lower
+ gas cost).
+ 2. New precompiles added in a fork are "cold" before the fork and become
+ "warm" after.
"""
sender = pre.fund_eoa()
call_cost_slot = 0
diff --git a/tests/eest/berlin/eip2930_access_list/__init__.py b/tests/eest/berlin/eip2930_access_list/__init__.py
index 24be6dfd09..25187646f7 100644
--- a/tests/eest/berlin/eip2930_access_list/__init__.py
+++ b/tests/eest/berlin/eip2930_access_list/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930)
- Test cases for [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930).
+Tests for [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930).
"""
diff --git a/tests/eest/berlin/eip2930_access_list/test_acl.py b/tests/eest/berlin/eip2930_access_list/test_acl.py
index 8b9899026a..a1f52e5da6 100644
--- a/tests/eest/berlin/eip2930_access_list/test_acl.py
+++ b/tests/eest/berlin/eip2930_access_list/test_acl.py
@@ -253,3 +253,67 @@ def test_transaction_intrinsic_gas_cost(
),
}
state_test(env=env, pre=pre, post=post, tx=tx)
+
+
+def test_repeated_address_acl(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ fork: Fork,
+):
+ """
+ Tests that slots are warmed correctly in an access list that has the same
+ address repeated more than once, each time with different slots.
+
+ Difference with other ACL tests is that we actually try to
+ access both slots at runtime. We also measure the gas cost
+ of each access in order to make debugging easier.
+ """
+ sender = pre.fund_eoa()
+ gsc = fork.gas_costs()
+
+ sload0_measure = CodeGasMeasure(
+ code=Op.SLOAD(0),
+ overhead_cost=gsc.G_VERY_LOW * len(Op.SLOAD.kwargs), # Cost of pushing SLOAD args
+ extra_stack_items=1, # SLOAD pushes 1 item to the stack
+ sstore_key=0,
+ stop=False, # Because it's the first CodeGasMeasure
+ )
+
+ sload1_measure = CodeGasMeasure(
+ code=Op.SLOAD(1),
+ overhead_cost=gsc.G_VERY_LOW * len(Op.SLOAD.kwargs), # Cost of pushing SLOAD args
+ extra_stack_items=1, # SLOAD pushes 1 item to the stack
+ sstore_key=1,
+ )
+
+ contract = pre.deploy_contract(sload0_measure + sload1_measure)
+
+ tx = Transaction(
+ gas_limit=500_000,
+ to=contract,
+ value=0,
+ sender=sender,
+ access_list=[
+ AccessList(
+ address=contract,
+ storage_keys=[0],
+ ),
+ AccessList(
+ address=contract,
+ storage_keys=[1],
+ ),
+ ],
+ )
+
+ sload_cost = gsc.G_WARM_ACCOUNT_ACCESS
+
+ state_test(
+ env=Environment(),
+ pre=pre,
+ tx=tx,
+ post={
+ contract: Account(
+ storage={0: sload_cost, 1: sload_cost},
+ )
+ },
+ )
diff --git a/tests/eest/berlin/eip2930_access_list/test_tx_intrinsic_gas.py b/tests/eest/berlin/eip2930_access_list/test_tx_intrinsic_gas.py
index 77ec323172..d0a55054d2 100644
--- a/tests/eest/berlin/eip2930_access_list/test_tx_intrinsic_gas.py
+++ b/tests/eest/berlin/eip2930_access_list/test_tx_intrinsic_gas.py
@@ -1,6 +1,8 @@
"""
-abstract: Tests [EIP-2930: Access list transaction](https://eips.ethereum.org/EIPS/eip-2930).
-Original test by Ori: https://github.com/ethereum/tests/blob/v15.0/src/GeneralStateTestsFiller/stEIP1559/intrinsicGen.js.
+Tests [EIP-2930: Access list transaction](https://eips.ethereum.org/EIPS/eip-2930).
+
+Original test by Ori:
+https://github.com/ethereum/tests/blob/v15.0/src/GeneralStateTestsFiller/stEIP1559/intrinsicGen.js.
"""
from typing import List
@@ -143,6 +145,7 @@
],
)
@pytest.mark.with_all_tx_types(selector=lambda tx_type: tx_type in [1, 2])
+@pytest.mark.slow()
def test_tx_intrinsic_gas(
state_test: StateTestFiller,
tx_type: int,
@@ -163,7 +166,8 @@ def test_tx_intrinsic_gas(
if data_floor_gas_cost > intrinsic_gas_cost:
exception = TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST
elif data_floor_gas_cost == intrinsic_gas_cost:
- # Depending on the implementation, client might raise either exception.
+ # Depending on the implementation, client might raise either
+ # exception.
exception = [
TransactionException.INTRINSIC_GAS_TOO_LOW,
TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST,
diff --git a/tests/eest/byzantium/eip198_modexp_precompile/helpers.py b/tests/eest/byzantium/eip198_modexp_precompile/helpers.py
index 9cc44fd25a..6439c3bfe0 100644
--- a/tests/eest/byzantium/eip198_modexp_precompile/helpers.py
+++ b/tests/eest/byzantium/eip198_modexp_precompile/helpers.py
@@ -1,4 +1,6 @@
-"""Helper functions for the EIP-198 ModExp precompile tests."""
+"""
+Helper functions for the EIP-198 ModExp precompile tests.
+"""
from typing import Tuple
@@ -9,15 +11,16 @@
class ModExpInput(TestParameterGroup):
"""
- Helper class that defines the MODEXP precompile inputs and creates the
- call data from them.
+ Helper class that defines the MODEXP precompile inputs and creates the call
+ data from them.
Attributes:
base (str): The base value for the MODEXP precompile.
exponent (str): The exponent value for the MODEXP precompile.
modulus (str): The modulus value for the MODEXP precompile.
- extra_data (str): Defines extra padded data to be added at the end of the calldata
- to the precompile. Defaults to an empty string.
+ extra_data (str): Defines extra padded data to be added at the end of
+ the calldata to the precompile.
+ Defaults to an empty string.
"""
@@ -134,9 +137,11 @@ class ModExpOutput(TestParameterGroup):
Expected test result.
Attributes:
- call_success (bool): The return_code from CALL, 0 indicates unsuccessful call
- (out-of-gas), 1 indicates call succeeded.
- returned_data (str): The output returnData is the expected output of the call
+ call_success (bool): The return_code from CALL, 0 indicates
+ unsuccessful call (out-of-gas), 1 indicates call
+ succeeded.
+ returned_data(str): The output returnData is the expected
+ output of the call.
"""
diff --git a/tests/eest/byzantium/eip198_modexp_precompile/test_modexp.py b/tests/eest/byzantium/eip198_modexp_precompile/test_modexp.py
index 98c6a07058..2af5a203be 100644
--- a/tests/eest/byzantium/eip198_modexp_precompile/test_modexp.py
+++ b/tests/eest/byzantium/eip198_modexp_precompile/test_modexp.py
@@ -1,7 +1,8 @@
"""
-abstract: Test [EIP-198: MODEXP Precompile](https://eips.ethereum.org/EIPS/eip-198)
- Tests the MODEXP precompile, located at address 0x0000..0005. Test cases from the EIP are
- labelled with `EIP-198-caseX` in the test id.
+Test [EIP-198: MODEXP Precompile](https://eips.ethereum.org/EIPS/eip-198).
+
+Tests the MODEXP precompile, located at address 0x0000..0005. Test cases
+from the EIP are labelled with `EIP-198-caseX` in the test id.
"""
import pytest
@@ -15,7 +16,7 @@
Transaction,
compute_create_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .helpers import ModExpInput, ModExpOutput
@@ -71,6 +72,16 @@
ModExpInput(base="", exponent="", modulus="0001"),
ModExpOutput(returned_data="0x0000"),
),
+ (
+ ModExpInput(
+ base="",
+ exponent="",
+ modulus="",
+ declared_exponent_length=2**32,
+ declared_modulus_length=1,
+ ),
+ ModExpOutput(returned_data="0x00", call_success=False),
+ ),
# Test cases from EIP 198.
pytest.param(
ModExpInput(
@@ -94,7 +105,8 @@
),
id="EIP-198-case2",
),
- pytest.param( # Note: This is the only test case which goes out-of-gas.
+ pytest.param( # Note: This is the only test case which goes out-of-
+ # gas.
Bytes(
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000020"
@@ -135,7 +147,8 @@
id="EIP-198-case5-raw-input",
),
],
- ids=lambda param: param.__repr__(), # only required to remove parameter names (input/output)
+ ids=lambda param: param.__repr__(), # only required to remove parameter
+ # names (input/output)
)
def test_modexp(
state_test: StateTestFiller,
@@ -153,17 +166,18 @@ def test_modexp(
# Store the returned CALL status (success = 1, fail = 0) into slot 0:
+ Op.SSTORE(
0,
- # Setup stack to CALL into ModExp with the CALLDATA and CALL into it (+ pop value)
+ # Setup stack to CALL into ModExp with the CALLDATA and CALL into
+ # it (+ pop value)
Op.CALL(Op.GAS(), 0x05, 0, 0, Op.CALLDATASIZE(), 0, 0),
)
- # Store contract deployment code to deploy the returned data from ModExp as
- # contract code (16 bytes)
+ # Store contract deployment code to deploy the returned data from
+ # ModExp as contract code (16 bytes)
+ Op.MSTORE(
0,
(
- # Need to `ljust` this PUSH32 in order to ensure the code starts
- # in memory at offset 0 (memory right-aligns stack items which are not
- # 32 bytes)
+ # Need to `ljust` this PUSH32 in order to ensure the code
+ # starts in memory at offset 0 (memory right-aligns stack items
+ # which are not 32 bytes)
Op.PUSH32(
bytes(
Op.CODECOPY(0, 16, Op.SUB(Op.CODESIZE(), 16))
@@ -172,9 +186,11 @@ def test_modexp(
)
),
)
- # RETURNDATACOPY the returned data from ModExp into memory (offset 16 bytes)
+ # RETURNDATACOPY the returned data from ModExp into memory (offset 16
+ # bytes)
+ Op.RETURNDATACOPY(16, 0, Op.RETURNDATASIZE())
- # CREATE contract with the deployment code + the returned data from ModExp
+ # CREATE contract with the deployment code + the returned data from
+ # ModExp
+ Op.CREATE(0, 0, Op.ADD(16, Op.RETURNDATASIZE()))
# STOP (handy for tracing)
+ Op.STOP(),
diff --git a/tests/eest/cancun/eip1153_tstore/__init__.py b/tests/eest/cancun/eip1153_tstore/__init__.py
index 1ef8a2efb7..dabae5a7d5 100644
--- a/tests/eest/cancun/eip1153_tstore/__init__.py
+++ b/tests/eest/cancun/eip1153_tstore/__init__.py
@@ -1,4 +1,6 @@
-"""EIP-1153 Tests."""
+"""
+[EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) Tests.
+"""
from enum import Enum, unique
from pprint import pprint
@@ -13,8 +15,8 @@ class PytestParameterEnum(Enum):
"""
Helper class for defining Pytest parameters used in test cases.
- This class helps define enum `value`s as `pytest.param` objects that then can
- be used to create a parametrize decorator that can be applied to tests,
+ This class helps define enum `value`s as `pytest.param` objects that then
+ can be used to create a parametrize decorator that can be applied to tests,
for example,
```python
@@ -23,25 +25,23 @@ def test_function(test_value):
pass
```
- Classes which derive from this class must define each test case as a different enum
- field with a dictionary as value.
+ Classes which derive from this class must define each test case as a
+ different enum field with a dictionary as value.
The dictionary must contain:
- i. A `description` key with a string value describing the test case.
- ii. (Optional) A `pytest_marks` key with a single mark or list of pytest
- marks to apply to the test case. For example,
-
- ```
- pytest_marks=pytest.mark.xfail
- ```
- or
-
- ```
- pytest_marks=[pytest.mark.xfail, pytest.mark.skipif]
- ```
- iii. (Optional) An `id` key with the name of the test.
-
- The rest of the keys in the dictionary are the parameters of the test case.
+ i. A `description` key with a string value describing the test case.
+ ii. (Optional) A `pytest_marks` key with a single mark or list of pytest
+ marks to apply to the test case. For example:
+ ```
+ pytest_marks=pytest.mark.xfail
+ ```
+ or
+ ```
+ pytest_marks=[pytest.mark.xfail, pytest.mark.skipif]
+ ```
+ iii. (Optional) An `id` key with the name of the test.
+
+ The rest of the keys in the dictionary are the parameters of the test case.
The test case ID is set as the enum name converted to lowercase.
"""
@@ -67,11 +67,15 @@ def param(self, names: List[str]):
@classmethod
def special_keywords(cls) -> List[str]:
- """Return the special dictionary keywords that are not test parameters."""
+ """
+ Return the special dictionary keywords that are not test parameters.
+ """
return ["description", "pytest_marks", "pytest_id"]
def names(self) -> List[str]:
- """Return the names of all the parameters included in the enum value dict."""
+ """
+ Return the names of all the parameters included in the enum value dict.
+ """
return sorted([k for k in self._value_.keys() if k not in self.special_keywords()])
@property
diff --git a/tests/eest/cancun/eip1153_tstore/test_basic_tload.py b/tests/eest/cancun/eip1153_tstore/test_basic_tload.py
index 0f93f0f6d0..0b797913a8 100644
--- a/tests/eest/cancun/eip1153_tstore/test_basic_tload.py
+++ b/tests/eest/cancun/eip1153_tstore/test_basic_tload.py
@@ -8,7 +8,7 @@
import pytest
from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .spec import Spec, ref_spec_1153
diff --git a/tests/eest/cancun/eip1153_tstore/test_tload_calls.py b/tests/eest/cancun/eip1153_tstore/test_tload_calls.py
index 6d3492624d..120f2060d6 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tload_calls.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tload_calls.py
@@ -1,13 +1,12 @@
"""
-Ethereum Transient Storage EIP Tests
-https://eips.ethereum.org/EIPS/eip-1153.
+[EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) Transient Storage tests.
"""
import pytest
from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Bytecode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md"
REFERENCE_SPEC_VERSION = "1eb863b534a5a3e19e9c196ab2a7f3db4bb9da17"
@@ -26,11 +25,11 @@ def test_tload_calls(state_test: StateTestFiller, pre: Alloc, call_type: Op):
"""
Ported .json vectors.
- (04_tloadAfterCallFiller.yml)
- Loading a slot after a call to another contract is 0.
+ (04_tloadAfterCallFiller.yml) Loading a slot after a call to another
+ contract is 0.
- (12_tloadDelegateCallFiller.yml)
- delegatecall reads transient storage in the context of the current address
+ (12_tloadDelegateCallFiller.yml) delegatecall reads transient storage in
+ the context of the current address
"""
# Storage variables
slot_a_tload_after_subcall_result = 0
@@ -71,10 +70,12 @@ def make_call(call_type: Op, address: Address) -> Bytecode:
post = {
address_to: Account(
storage={
- # other calls don't change context, there for tload updated in this account
+ # other calls don't change context, there for tload updated in
+ # this account
slot_a_tload_after_subcall_result: 10 if call_type == Op.CALL else 20,
slot_a_subcall_result: 1,
- # since context unchanged the subcall works as if continued execution
+ # since context unchanged the subcall works as if continued
+ # execution
slot_b_subcall_tload_result: 0 if call_type == Op.CALL else 10,
slot_b_subcall_updated_tload_result: 0 if call_type == Op.CALL else 20,
}
diff --git a/tests/eest/cancun/eip1153_tstore/test_tload_reentrancy.py b/tests/eest/cancun/eip1153_tstore/test_tload_reentrancy.py
index 3a8a52092b..e0d7cc9909 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tload_reentrancy.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tload_reentrancy.py
@@ -1,6 +1,5 @@
"""
-Ethereum Transient Storage EIP Tests
-https://eips.ethereum.org/EIPS/eip-1153.
+[EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) Transient Storage tests.
"""
from enum import Enum
@@ -18,9 +17,9 @@
Switch,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Bytecode
-from ethereum_test_tools.vm.opcode import Macros as Om
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Macros as Om
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md"
REFERENCE_SPEC_VERSION = "1eb863b534a5a3e19e9c196ab2a7f3db4bb9da17"
@@ -53,8 +52,8 @@ def test_tload_reentrancy(
"""
Ported .json vectors.
- (05_tloadReentrancyFiller.yml)
- Reentrant calls access the same transient storage
+ (05_tloadReentrancyFiller.yml) Reentrant calls access the same transient
+ storage
"""
tload_value = 44
empty_value = 0
@@ -138,7 +137,8 @@ def make_call(call_type: Op) -> Bytecode:
slot_tload_in_subcall_result: (
0xFF # if call OOG, we fail to obtain the result
if call_return == Om.OOG
- # else delegate and callcode are working in the same context so tload works
+ # else delegate and callcode are working in the same
+ # context so tload works
else (
tload_value
if call_type == Op.DELEGATECALL or call_type == Op.CALLCODE
diff --git a/tests/eest/cancun/eip1153_tstore/test_tstorage.py b/tests/eest/cancun/eip1153_tstore/test_tstorage.py
index 0b84b63857..95b576bd0f 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tstorage.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tstorage.py
@@ -1,9 +1,9 @@
"""
-abstract: Tests [EIP-1153: Transient Storage Opcodes](https://eips.ethereum.org/EIPS/eip-1153)
- Test [EIP-1153: Transient Storage Opcodes](https://eips.ethereum.org/EIPS/eip-1153). Ports
- and extends some tests from
- [ethereum/tests/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage).
-""" # noqa: E501
+EIP-1153 Transient Storage opcode tests.
+
+Ports and extends some tests from
+[ethereum/tests/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage).
+"""
from enum import unique
@@ -33,11 +33,15 @@
def test_transient_storage_unset_values(state_test: StateTestFiller, pre: Alloc):
"""
- Test that tload returns zero for unset values. Loading an arbitrary value is
- 0 at beginning of transaction: TLOAD(x) is 0.
-
- Based on [ethereum/tests/.../01_tloadBeginningTxnFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/01_tloadBeginningTxnFiller.yml)",
- """ # noqa: E501
+ Test that tload returns zero for unset values. Loading an arbitrary value
+ is 0 at beginning of transaction: TLOAD(x) is 0.
+
+ Based on
+ [ethereum/tests/.../01_tloadBeginningTxnFiller.yml]
+ (https://github.com/ethereum/tests/blob/
+ 9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/
+ stEIP1153-transientStorage/01_tloadBeginningTxnFiller.yml)",
+ """
env = Environment()
slots_under_test = [0, 1, 2, 2**128, 2**256 - 1]
@@ -45,7 +49,7 @@ def test_transient_storage_unset_values(state_test: StateTestFiller, pre: Alloc)
code_address = pre.deploy_contract(
code=code, # type: ignore
- storage={slot: 1 for slot in slots_under_test},
+ storage=dict.fromkeys(slots_under_test, 1),
)
tx = Transaction(
@@ -54,7 +58,7 @@ def test_transient_storage_unset_values(state_test: StateTestFiller, pre: Alloc)
gas_limit=1_000_000,
)
- post = {code_address: Account(storage={slot: 0 for slot in slots_under_test})}
+ post = {code_address: Account(storage=dict.fromkeys(slots_under_test, 0))}
state_test(
env=env,
@@ -69,8 +73,12 @@ def test_tload_after_tstore(state_test: StateTestFiller, pre: Alloc):
Loading after storing returns the stored value: TSTORE(x, y), TLOAD(x)
returns y.
- Based on [ethereum/tests/.../02_tloadAfterTstoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/02_tloadAfterTstoreFiller.yml)",
- """ # noqa: E501
+ Based on
+ [ethereum/tests/.../02_tloadAfterTstoreFiller.yml]
+ (https://github.com/ethereum/tests/blob/
+ 9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/
+ stEIP1153-transientStorage/02_tloadAfterTstoreFiller.yml)",
+ """
env = Environment()
slots_under_test = [0, 1, 2, 2**128, 2**256 - 1]
@@ -79,7 +87,7 @@ def test_tload_after_tstore(state_test: StateTestFiller, pre: Alloc):
)
code_address = pre.deploy_contract(
code=code, # type: ignore
- storage={slot: 0xFF for slot in slots_under_test},
+ storage=dict.fromkeys(slots_under_test, 0xFF),
)
tx = Transaction(
@@ -103,8 +111,13 @@ def test_tload_after_sstore(state_test: StateTestFiller, pre: Alloc):
Loading after storing returns the stored value: TSTORE(x, y), TLOAD(x)
returns y.
- Based on [ethereum/tests/.../18_tloadAfterStoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/18_tloadAfterStoreFiller.yml)",
- """ # noqa: E501
+ Based on
+ [ethereum/tests/.../18_tloadAfterStoreFiller.yml]
+ (https://github.com/ethereum/tests/blob/
+ 9b00b68593f5869eb51a6659e1cc983e875e616b/src/
+ EIPTestsFiller/StateTests/stEIP1153-transientStorage/
+ 18_tloadAfterStoreFiller.yml)",
+ """
env = Environment()
slots_under_test = [1, 3, 2**128, 2**256 - 1]
@@ -114,7 +127,7 @@ def test_tload_after_sstore(state_test: StateTestFiller, pre: Alloc):
)
code_address = pre.deploy_contract(
code=code, # type: ignore
- storage={slot: 1 for slot in slots_under_test},
+ storage=dict.fromkeys(slots_under_test, 1),
)
tx = Transaction(
@@ -127,7 +140,7 @@ def test_tload_after_sstore(state_test: StateTestFiller, pre: Alloc):
code_address: Account(
code=code,
storage={slot - 1: 0xFF for slot in slots_under_test}
- | {slot: 0 for slot in slots_under_test},
+ | dict.fromkeys(slots_under_test, 0),
)
}
@@ -143,8 +156,12 @@ def test_tload_after_tstore_is_zero(state_test: StateTestFiller, pre: Alloc):
"""
Test that tload returns zero after tstore is called with zero.
- Based on [ethereum/tests/.../03_tloadAfterStoreIs0Filler.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/03_tloadAfterStoreIs0Filler.yml)",
- """ # noqa: E501
+ Based on [ethereum/tests/.../03_tloadAfterStoreIs0Filler.yml]
+ (https://github.com/ethereum/tests/blob/
+ 9b00b68593f5869eb51a6659e1cc983e875e616b/src/
+ EIPTestsFiller/StateTests/
+ stEIP1153-transientStorage/03_tloadAfterStoreIs0Filler.yml)",
+ """
env = Environment()
slots_to_write = [1, 4, 2**128, 2**256 - 2]
@@ -157,7 +174,7 @@ def test_tload_after_tstore_is_zero(state_test: StateTestFiller, pre: Alloc):
code_address = pre.deploy_contract(
code=code, # type: ignore
- storage={slot: 0xFFFF for slot in slots_to_write + slots_to_read},
+ storage=dict.fromkeys(slots_to_write + slots_to_read, 0xFFFF),
)
tx = Transaction(
@@ -168,7 +185,7 @@ def test_tload_after_tstore_is_zero(state_test: StateTestFiller, pre: Alloc):
post = {
code_address: Account(
- storage={slot: 0 for slot in slots_to_read} | {slot: 0xFFFF for slot in slots_to_write}
+ storage=dict.fromkeys(slots_to_read, 0) | dict.fromkeys(slots_to_write, 0xFFFF)
)
}
diff --git a/tests/eest/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py b/tests/eest/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py
index 725941db67..fc7e75fd48 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py
@@ -1,7 +1,4 @@
-"""
-Ethereum Transient Storage EIP Tests
-https://eips.ethereum.org/EIPS/eip-1153.
-"""
+"""EIP-1153 Transient Storage tests."""
from typing import Optional
@@ -17,8 +14,8 @@
Initcode,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container
+from ethereum_test_vm import Opcodes as Op
from .spec import ref_spec_1153
@@ -34,10 +31,10 @@ def test_tstore_clear_after_deployment_tx(
evm_code_type: EVMCodeType,
):
"""
- First creates a contract, which TSTOREs a value 1 in slot 1.
- After creating the contract, a new tx will call this contract, storing TLOAD(1) into slot 1.
- The transient storage should be cleared after creating the contract (at tx-level), so
- the storage should stay empty.
+ First creates a contract, which TSTOREs a value 1 in slot 1. After creating
+ the contract, a new tx will call this contract, storing TLOAD(1) into slot
+ 1. The transient storage should be cleared after creating the contract (at
+ tx-level), so the storage should stay empty.
"""
env = Environment()
@@ -81,9 +78,9 @@ def test_tstore_clear_after_tx(
pre: Alloc,
):
"""
- First SSTOREs the TLOAD value of key 1 in slot 1. Then, it TSTOREs 1 in slot 1.
- The second tx will re-call the contract. The storage should stay empty,
- because the transient storage is cleared after the transaction.
+ First SSTOREs the TLOAD value of key 1 in slot 1. Then, it TSTOREs 1 in
+ slot 1. The second tx will re-call the contract. The storage should stay
+ empty, because the transient storage is cleared after the transaction.
"""
env = Environment()
diff --git a/tests/eest/cancun/eip1153_tstore/test_tstorage_create_contexts.py b/tests/eest/cancun/eip1153_tstore/test_tstorage_create_contexts.py
index 5ce6c65c68..efe83bcd13 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tstorage_create_contexts.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tstorage_create_contexts.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153)
- Test cases for `TSTORE` and `TLOAD` opcode calls in contract initcode.
-""" # noqa: E501
+Test transient storage in contract creation contexts.
+"""
from enum import unique
@@ -32,8 +31,8 @@
@unique
class InitcodeTestCases(PytestParameterEnum):
"""
- Defines test cases for transient storage opcode usage in contract constructor
- and deployed code.
+ Defines test cases for transient storage opcode usage in contract
+ constructor and deployed code.
"""
ONLY_CONSTRUCTOR_CODE = {
@@ -41,9 +40,11 @@ class InitcodeTestCases(PytestParameterEnum):
"Test TLOAD and TSTORE behavior in contract constructor without deployed code"
),
"constructor_code": (
- # test creator's transient storage inaccessible from constructor code
+ # test creator's transient storage inaccessible from constructor
+ # code
Op.SSTORE(0, Op.TLOAD(0))
- # test constructor code can use its own transient storage & creator storage unaffected
+ # test constructor code can use its own transient storage & creator
+ # storage unaffected
+ Op.TSTORE(0, 1)
+ Op.SSTORE(1, Op.TLOAD(0))
),
@@ -53,13 +54,15 @@ class InitcodeTestCases(PytestParameterEnum):
IN_CONSTRUCTOR_AND_DEPLOYED_CODE = {
"description": "Test TLOAD and TSTORE behavior in contract constructor and deployed code",
"constructor_code": (
- # test creator's transient storage inaccessible from constructor code
+ # test creator's transient storage inaccessible from constructor
+ # code
Op.SSTORE(0, Op.TLOAD(0))
),
"deploy_code": (
# test creator's transient storage inaccessible from deployed code
Op.SSTORE(1, Op.TLOAD(0))
- # test deploy code can use its own transient storage & creator storage unaffected
+ # test deploy code can use its own transient storage & creator
+ # storage unaffected
+ Op.TSTORE(1, 1)
+ Op.SSTORE(2, Op.TLOAD(1))
),
@@ -68,15 +71,18 @@ class InitcodeTestCases(PytestParameterEnum):
ACROSS_CONSTRUCTOR_AND_DEPLOYED_CODE_V0 = {
"description": ("Test TSTORE behavior across contract constructor and deploy code. "),
"constructor_code": (
- # constructor code should be able to store its own transient storage
+ # constructor code should be able to store its own transient
+ # storage
Op.TSTORE(1, 1)
),
"deploy_code": (
# test creator's transient storage inaccessible from deployed code
Op.SSTORE(0, Op.TLOAD(0))
- # test deploy code can use its own transient storage stored from constructor code
+ # test deploy code can use its own transient storage stored from
+ # constructor code
+ Op.SSTORE(1, Op.TLOAD(1))
- # test deploy code can use its own transient storage stored from deployed code
+ # test deploy code can use its own transient storage stored from
+ # deployed code
+ Op.TSTORE(2, 1)
+ Op.SSTORE(2, Op.TLOAD(2))
),
@@ -89,17 +95,19 @@ class InitcodeTestCases(PytestParameterEnum):
"constructor_code": (
# test creator's transient storage inaccessible from constructor
Op.SSTORE(0, Op.TLOAD(0))
- # constructor code should be able to use its own transient storage / creator storage
- # unaffected
+ # constructor code should be able to use its own transient storage
+ # / creator storage unaffected
+ Op.TSTORE(1, 1)
+ Op.SSTORE(1, Op.TLOAD(1))
),
"deploy_code": (
# test creator's transient storage inaccessible from deployed code
Op.SSTORE(2, Op.TLOAD(0))
- # test deploy code can use its own transient storage stored from constructor code
+ # test deploy code can use its own transient storage stored from
+ # constructor code
+ Op.SSTORE(3, Op.TLOAD(1))
- # test deploy code can use its own transient storage stored from deployed code
+ # test deploy code can use its own transient storage stored from
+ # deployed code
+ Op.TSTORE(2, 1)
+ Op.SSTORE(4, Op.TLOAD(2))
),
@@ -113,7 +121,8 @@ class InitcodeTestCases(PytestParameterEnum):
"deploy_code": (
# test creator's transient storage inaccessible from deployed code
Op.SSTORE(0, Op.TLOAD(0))
- # test deployed code can use its own transient storage & creator storage unaffected
+ # test deployed code can use its own transient storage & creator
+ # storage unaffected
+ Op.TSTORE(0, 1)
+ Op.SSTORE(1, Op.TLOAD(0))
),
@@ -126,10 +135,12 @@ class InitcodeTestCases(PytestParameterEnum):
class TestTransientStorageInContractCreation:
"""
Test transient storage in contract creation contexts.
- - TSTORE/TLOAD in initcode should not be able to access the creator's transient storage.
- - TSTORE/TLOAD in initcode should be able to access the created contract's transient
- storage.
- - TSTORE/TLOAD in creator contract should be able to use its own transient storage.
+ - TSTORE/TLOAD in initcode should not be able to access the creator's
+ transient storage.
+ - TSTORE/TLOAD in initcode should be able to access the created contract's
+ transient storage.
+ - TSTORE/TLOAD in creator contract should be able to use its own
+ transient storage.
"""
@pytest.fixture()
@@ -165,8 +176,8 @@ def creator_contract_code( # noqa: D102
)
),
)
- # Save the state of transient storage following call to storage; the transient
- # storage should not have been overwritten
+ # Save the state of transient storage following call to storage;
+ # the transient storage should not have been overwritten
+ Op.SSTORE(0, Op.TLOAD(0))
+ Op.SSTORE(1, Op.TLOAD(1))
+ Op.SSTORE(2, Op.TLOAD(2))
diff --git a/tests/eest/cancun/eip1153_tstore/test_tstorage_execution_contexts.py b/tests/eest/cancun/eip1153_tstore/test_tstorage_execution_contexts.py
index 99c83f0556..b710ff493e 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tstorage_execution_contexts.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tstorage_execution_contexts.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153)
- Test cases for `TSTORE` and `TLOAD` opcode calls in different execution contexts.
-""" # noqa: E501
+Test EIP-1153 Transient Storage in execution contexts.
+"""
from enum import EnumMeta, unique
from typing import Dict, Mapping
@@ -33,9 +32,9 @@
class DynamicCallContextTestCases(EnumMeta):
"""
- Create dynamic transient storage test cases for contract sub-calls
- using CALLCODE and DELEGATECALL (these opcodes share the same
- signatures and test cases).
+ Create dynamic transient storage test cases for contract sub-calls using
+ CALLCODE and DELEGATECALL (these opcodes share the same signatures and test
+ cases).
"""
def __new__(cls, name, bases, classdict): # noqa: D102
@@ -258,14 +257,14 @@ class CallContextTestCases(PytestParameterEnum, metaclass=DynamicCallContextTest
+ Op.SSTORE(1, Op.TLOAD(0))
+ Op.STOP
),
- "callee_bytecode": Op.TSTORE(0, unchecked=True) # calling with stack underflow still fails
- + Op.STOP,
+ # calling with stack underflow still fails
+ "callee_bytecode": Op.TSTORE(0, unchecked=True) + Op.STOP,
"expected_caller_storage": {0: 0, 1: 420},
"expected_callee_storage": {},
}
STATICCALL_CAN_CALL_TLOAD = {
- # TODO: Not a very useful test; consider removing after implementing ethereum/tests
- # staticcall tests
+ # TODO: Not a very useful test; consider removing after implementing
+ # ethereum/tests staticcall tests
"pytest_id": "staticcalled_context_can_call_tload",
"description": ("A STATICCALL callee can not use transient storage."),
"caller_bytecode": (
@@ -274,7 +273,8 @@ class CallContextTestCases(PytestParameterEnum, metaclass=DynamicCallContextTest
+ Op.SSTORE(1, Op.TLOAD(0))
+ Op.STOP
),
- "callee_bytecode": Op.TLOAD(0) + Op.STOP, # calling tload does not cause the call to fail
+ # calling tload does not cause the call to fail
+ "callee_bytecode": Op.TLOAD(0) + Op.STOP,
"expected_caller_storage": {0: 1, 1: 420},
"expected_callee_storage": {},
}
diff --git a/tests/eest/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py b/tests/eest/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py
index 18fed8cea9..05044ef8ac 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153)
- Test cases for `TSTORE` and `TLOAD` opcode calls in reentrancy contexts.
-""" # noqa: E501
+Tests transient storage in reentrancy contexts.
+"""
from enum import EnumMeta, unique
from typing import Dict
@@ -59,11 +58,15 @@ def __new__(cls, name, bases, classdict): # noqa: D102
classdict[f"TSTORE_BEFORE_{opcode._name_}_HAS_NO_EFFECT"] = {
"description": (
- f"{opcode._name_} undoes the transient storage write from the failed call: "
- f"TSTORE(x, y), CALL(self, ...), TSTORE(x, z), {opcode._name_}, TLOAD(x) "
- "returns y."
- "",
- "Based on [ethereum/tests/.../08_revertUndoesTransientStoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/08_revertUndoesTransientStoreFiller.yml)", # noqa: E501
+ f"{opcode._name_} undoes the transient storage write "
+ "from the failed call: "
+ "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), "
+ f"{opcode._name_}, TLOAD(x) returns y.",
+ "Based on [ethereum/tests/.../08_revertUndoes"
+ "TransientStoreFiller.yml](https://github.com/ethereum/"
+ "tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src"
+ "/EIPTestsFiller/StateTests/stEIP1153-transientStorage/"
+ "08_revertUndoesTransientStoreFiller.yml)",
),
"bytecode": Conditional(
condition=SETUP_CONDITION,
@@ -84,11 +87,13 @@ def __new__(cls, name, bases, classdict): # noqa: D102
classdict[f"{opcode._name_}_UNDOES_ALL"] = {
"description": (
- f"{opcode._name_} undoes all the transient storage writes to the same key ",
- "from a failed call. TSTORE(x, y), CALL(self, ...), TSTORE(x, z), ",
- f"TSTORE(x, z + 1) {opcode._name_}, TLOAD(x) returns y.",
+ f"{opcode._name_} undoes all the transient storage writes "
+ "to the same key from a failed call. "
+ "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), "
+ f"TSTORE(x, z + 1) {opcode._name_}, TLOAD(x) returns y."
"",
- "Based on [ethereum/tests/.../09_revertUndoesAllFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/09_revertUndoesAllFiller.yml).", # noqa: E501
+ "Based on "
+ "[ethereum/tests/.../09_revertUndoesAllFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/09_revertUndoesAllFiller.yml).",
),
"bytecode": Conditional(
condition=SETUP_CONDITION,
@@ -106,7 +111,8 @@ def __new__(cls, name, bases, classdict): # noqa: D102
),
# reenter
if_false=(
- # store twice and revert/invalid; none of the stores should take effect
+ # store twice and revert/invalid; none of the stores
+ # should take effect
Op.TSTORE(0xFE, 0x201)
+ Op.TSTORE(0xFE, 0x202)
+ Op.TSTORE(0xFF, 0x201)
@@ -128,11 +134,17 @@ def __new__(cls, name, bases, classdict): # noqa: D102
classdict[f"{opcode._name_}_UNDOES_TSTORAGE_AFTER_SUCCESSFUL_CALL"] = {
"description": (
- f"{opcode._name_} undoes transient storage writes from inner calls that "
- "successfully returned. TSTORE(x, y), CALL(self, ...), CALL(self, ...), "
- f"TSTORE(x, y + 1), RETURN, {opcode._name_}, TLOAD(x) returns y."
- "",
- "Based on [ethereum/tests/.../10_revertUndoesStoreAfterReturnFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/10_revertUndoesStoreAfterReturnFiller.yml).", # noqa: E501
+ f"{opcode._name_} undoes transient storage writes from "
+ "inner calls that successfully returned. "
+ "TSTORE(x, y), CALL(self, ...), CALL(self, ...), "
+ f"TSTORE(x, y + 1), RETURN, {opcode._name_}, TLOAD(x) "
+ "returns y.",
+ "Based on [ethereum/tests/.../"
+ "10_revertUndoesStoreAfterReturnFiller.yml]"
+ "(https://github.com/ethereum/tests/blob/"
+ "9b00b68593f5869eb51a6659e1cc983e875e616b/src/"
+ "EIPTestsFiller/StateTests/stEIP1153-transientStorage/"
+ "10_revertUndoesStoreAfterReturnFiller.yml).",
),
"bytecode": Switch(
default_action=( # setup; make first reentrant sub-call
@@ -149,11 +161,13 @@ def __new__(cls, name, bases, classdict): # noqa: D102
ret_size=32,
),
)
- + Op.SSTORE(1, Op.MLOAD(32)) # should be 1 (successful call)
+ + Op.SSTORE(1, Op.MLOAD(32)) # should be 1 (successful
+ # call)
+ Op.SSTORE(3, Op.TLOAD(0xFF))
),
cases=[
- # the first, reentrant call, which reverts/receives invalid
+ # the first, reentrant call, which reverts/receives
+ # invalid
CalldataCase(
value=2,
action=(
@@ -162,7 +176,8 @@ def __new__(cls, name, bases, classdict): # noqa: D102
+ opcode_call
),
),
- # the second, reentrant call, which returns successfully
+ # the second, reentrant call, which returns
+ # successfully
CalldataCase(
value=3,
action=Op.TSTORE(0xFF, 0x101),
@@ -184,7 +199,10 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
"Reentrant calls access the same transient storage: "
"TSTORE(x, y), CALL(self, ...), TLOAD(x) returns y."
""
- "Based on [ethereum/tests/.../05_tloadReentrancyFiller.yml](https://github.com/ethereum/tests/tree/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage).", # noqa: E501
+ "Based on [ethereum/tests/.../05_tloadReentrancyFiller.yml]"
+ "(https://github.com/ethereum/tests/tree/"
+ "9b00b68593f5869eb51a6659e1cc983e875e616b/src/"
+ "EIPTestsFiller/StateTests/stEIP1153-transientStorage).",
),
"bytecode": Conditional(
condition=SETUP_CONDITION,
@@ -197,10 +215,16 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
}
TLOAD_AFTER_REENTRANT_TSTORE = {
"description": (
- "Successfully returned calls do not revert transient storage writes: "
- "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), RETURN, TLOAD(x) returns z."
- ""
- "Based on [ethereum/tests/.../07_tloadAfterReentrancyStoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/07_tloadAfterReentrancyStoreFiller.yml).", # noqa: E501
+ "Successfully returned calls do not revert transient "
+ "storage writes: "
+ "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), RETURN, TLOAD(x) "
+ "returns z."
+ "Based on [ethereum/tests/.../"
+ "07_tloadAfterReentrancyStoreFiller.yml](https://github.com/"
+ "ethereum/tests/blob/"
+ "9b00b68593f5869eb51a6659e1cc983e875e616b/src/"
+ "EIPTestsFiller/StateTests/stEIP1153-transientStorage/"
+ "07_tloadAfterReentrancyStoreFiller.yml).",
),
"bytecode": Conditional(
condition=SETUP_CONDITION,
@@ -209,7 +233,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
Op.TSTORE(0xFF, 0x100)
+ Op.SSTORE(1, Op.TLOAD(0xFF))
+ REENTRANT_CALL
- + Op.SSTORE(2, Op.TLOAD(0xFF)) # test value updated during reentrant call
+ + Op.SSTORE(2, Op.TLOAD(0xFF)) # test value updated during
+ # reentrant call
),
# reenter
if_false=Op.TSTORE(0xFF, 0x101),
@@ -221,7 +246,11 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
"Reentrant calls can manipulate the same transient storage: "
"TSTORE(x, y), CALL(self, ...), TSTORE(x, z), TLOAD(x) returns z."
""
- "Based on [ethereum/tests/.../06_tstoreInReentrancyCallFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/06_tstoreInReentrancyCallFiller.yml).", # noqa: E501
+ "Based on [ethereum/tests/.../06_tstoreInReentrancyCallFiller.yml]"
+ "(https://github.com/ethereum/tests/blob/"
+ "9b00b68593f5869eb51a6659e1cc983e875e616b/src/"
+ "EIPTestsFiller/StateTests/stEIP1153-transientStorage/"
+ "06_tstoreInReentrancyCallFiller.yml).",
),
"bytecode": Conditional(
condition=SETUP_CONDITION,
@@ -230,7 +259,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
Op.TSTORE(0xFF, 0x100)
+ Op.SSTORE(1, Op.TLOAD(0xFF))
+ REENTRANT_CALL
- + Op.SSTORE(3, Op.TLOAD(0xFF)) # test value updated during reentrant call
+ + Op.SSTORE(3, Op.TLOAD(0xFF)) # test value updated during
+ # reentrant call
),
# reenter
if_false=Op.TSTORE(0xFF, 0x101) + Op.SSTORE(2, Op.TLOAD(0xFF)),
@@ -239,9 +269,16 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
}
TSTORE_IN_CALL_THEN_TLOAD_RETURN_IN_STATICCALL = {
"description": (
- "A reentrant call followed by a reentrant subcall can call tload correctly: "
- "TSTORE(x, y), CALL(self, ...), STATICCALL(self, ...), TLOAD(x), RETURN returns y."
- "Based on [ethereum/tests/.../10_revertUndoesStoreAfterReturnFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/10_revertUndoesStoreAfterReturnFiller.yml).", # noqa: E501
+ "A reentrant call followed by a reentrant subcall can "
+ "call tload correctly: "
+ "TSTORE(x, y), CALL(self, ...), STATICCALL(self, ...), "
+ "TLOAD(x), RETURN returns y."
+ "Based on [ethereum/tests/.../"
+ "10_revertUndoesStoreAfterReturnFiller.yml]"
+ "(https://github.com/ethereum/tests/blob/"
+ "9b00b68593f5869eb51a6659e1cc983e875e616b/src/"
+ "EIPTestsFiller/StateTests/stEIP1153-transientStorage/"
+ "10_revertUndoesStoreAfterReturnFiller.yml).",
),
"bytecode": Switch(
default_action=( # setup; make first reentrant sub-call
@@ -252,7 +289,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
+ Op.SSTORE(4, Op.TLOAD(0xFE))
),
cases=[
- # the first, reentrant call which calls tstore and a further reentrant staticcall
+ # the first, reentrant call which calls tstore and a further
+ # reentrant staticcall
CalldataCase(
value=2,
action=(
@@ -264,7 +302,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa
+ Op.SSTORE(3, Op.MLOAD(0))
),
),
- # the second, reentrant call, which calls tload and return returns successfully
+ # the second, reentrant call, which calls tload and return
+ # returns successfully
CalldataCase(
value=3,
action=Op.MSTORE(0, Op.TLOAD(0xFE)) + Op.RETURN(0, 32),
diff --git a/tests/eest/cancun/eip1153_tstore/test_tstorage_selfdestruct.py b/tests/eest/cancun/eip1153_tstore/test_tstorage_selfdestruct.py
index fadd9fde03..6237c83099 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tstorage_selfdestruct.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tstorage_selfdestruct.py
@@ -1,8 +1,9 @@
"""
-abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153)
- Test cases for `TSTORE` and `TLOAD` opcode calls in reentrancy after self-destruct, taking into
- account the changes in EIP-6780.
-""" # noqa: E501
+EIP-1153 Transient Storage with selfdestruct tests.
+
+Test cases for `TSTORE` and `TLOAD` opcode calls in reentrancy after
+self-destruct, taking into account the changes in EIP-6780.
+"""
from enum import unique
from typing import Dict
@@ -36,7 +37,10 @@
def call_option(option_number: int) -> Bytecode:
- """Return the bytecode for a call to the callee contract with the given option number."""
+ """
+ Return the bytecode for a call to the callee contract with the given option
+ number.
+ """
return Op.MSTORE(value=option_number) + Op.CALL(
address=Op.SLOAD(0),
args_offset=0,
@@ -49,8 +53,8 @@ def call_option(option_number: int) -> Bytecode:
@unique
class SelfDestructCases(PytestParameterEnum):
"""
- Transient storage test cases for different reentrancy calls which involve the contract
- self-destructing.
+ Transient storage test cases for different reentrancy calls which involve
+ the contract self-destructing.
"""
TLOAD_AFTER_SELFDESTRUCT_PRE_EXISTING_CONTRACT = {
@@ -225,7 +229,10 @@ def test_reentrant_selfdestructing_call(
callee_bytecode: Bytecode,
expected_storage: Dict,
):
- """Test transient storage in different reentrancy contexts after selfdestructing."""
+ """
+ Test transient storage in different reentrancy contexts after
+ selfdestructing.
+ """
env = Environment()
caller_address = pre.deploy_contract(code=caller_bytecode)
diff --git a/tests/eest/cancun/eip1153_tstore/test_tstore_reentrancy.py b/tests/eest/cancun/eip1153_tstore/test_tstore_reentrancy.py
index b371ea9314..557eb211ee 100644
--- a/tests/eest/cancun/eip1153_tstore/test_tstore_reentrancy.py
+++ b/tests/eest/cancun/eip1153_tstore/test_tstore_reentrancy.py
@@ -1,7 +1,4 @@
-"""
-Ethereum Transient Storage EIP Tests
-https://eips.ethereum.org/EIPS/eip-1153.
-"""
+"""EIP-1153 Transient Storage tests."""
from enum import Enum
@@ -18,9 +15,9 @@
Switch,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Bytecode
-from ethereum_test_tools.vm.opcode import Macros as Om
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Macros as Om
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md"
REFERENCE_SPEC_VERSION = "1eb863b534a5a3e19e9c196ab2a7f3db4bb9da17"
@@ -69,10 +66,12 @@ def test_tstore_reentrancy(
Revert undoes the transient storage writes from a call.
(09_revertUndoesAllFiller.yml)
- Revert undoes all the transient storage writes to the same key from the failed call.
+ Revert undoes all the transient storage writes to the same key
+ from the failed call.
(11_tstoreDelegateCallFiller.yml)
- delegatecall manipulates transient storage in the context of the current address.
+ delegatecall manipulates transient storage in the context of
+ the current address.
(13_tloadStaticCallFiller.yml)
Transient storage cannot be manipulated in a static context, tstore reverts
@@ -200,7 +199,8 @@ def make_call(call_type: Op) -> Bytecode:
if call_type == Op.STATICCALL or call_return == Om.OOG
else tload_value_set_in_call
),
- # external tstore overrides value in upper level only in delegate and callcode
+ # external tstore overrides value in upper level only in
+ # delegate and callcode
slot_tload_after_call: (
tload_value_set_in_call
if on_successful_delegate_or_callcode
@@ -208,7 +208,8 @@ def make_call(call_type: Op) -> Bytecode:
),
slot_tload_1_after_call: 12 if on_successful_delegate_or_callcode else 0,
slot_tstore_overwrite: 50,
- # tstore in static call not allowed, reentrancy means external call here
+ # tstore in static call not allowed, reentrancy means
+ # external call here
slot_subcall_worked: 0 if on_failing_calls else 1,
}
)
diff --git a/tests/eest/cancun/eip4788_beacon_root/conftest.py b/tests/eest/cancun/eip4788_beacon_root/conftest.py
index 3a28b279ce..12497eead1 100644
--- a/tests/eest/cancun/eip4788_beacon_root/conftest.py
+++ b/tests/eest/cancun/eip4788_beacon_root/conftest.py
@@ -34,7 +34,10 @@ def timestamp() -> int: # noqa: D103
@pytest.fixture
def beacon_roots() -> Iterator[bytes]:
- """By default, return an iterator that returns the keccak of an internal counter."""
+ """
+ By default, return an iterator that returns the keccak of an internal
+ counter.
+ """
class BeaconRoots:
def __init__(self) -> None:
@@ -97,7 +100,8 @@ def contract_call_code(call_type: Op, call_value: int, call_gas: int) -> Bytecod
if call_type == Op.CALL or call_type == Op.CALLCODE:
contract_call_code += Op.SSTORE(
0x00, # store the result of the contract call in storage[0]
- call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501
+ # https://github.com/ethereum/execution-spec-tests/issues/348
+ call_type( # type: ignore
call_gas,
Spec.BEACON_ROOTS_ADDRESS,
call_value,
@@ -111,7 +115,8 @@ def contract_call_code(call_type: Op, call_value: int, call_gas: int) -> Bytecod
# delegatecall and staticcall use one less argument
contract_call_code += Op.SSTORE(
0x00,
- call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501
+ # https://github.com/ethereum/execution-spec-tests/issues/348
+ call_type( # type: ignore
call_gas,
Spec.BEACON_ROOTS_ADDRESS,
args_start,
@@ -181,7 +186,9 @@ def auto_access_list() -> bool:
@pytest.fixture
def access_list(auto_access_list: bool, timestamp: int) -> List[AccessList]:
- """Access list included in the transaction to call the beacon root contract."""
+ """
+ Access list included in the transaction to call the beacon root contract.
+ """
if auto_access_list:
return [
AccessList(
@@ -204,7 +211,8 @@ def tx_data(timestamp: int) -> bytes:
@pytest.fixture
def tx_type() -> int:
"""
- Transaction type to call the caller contract or the beacon root contract directly.
+ Transaction type to call the caller contract or the beacon root contract
+ directly.
By default use a type 2 transaction.
"""
@@ -263,8 +271,8 @@ def post(
call_beacon_root_contract: bool,
) -> Dict:
"""
- Prepare expected post state for a single contract call based upon the success or
- failure of the call, and the validity of the timestamp input.
+ Prepare expected post state for a single contract call based upon the
+ success or failure of the call, and the validity of the timestamp input.
"""
storage = Storage()
if not call_beacon_root_contract:
diff --git a/tests/eest/cancun/eip4788_beacon_root/spec.py b/tests/eest/cancun/eip4788_beacon_root/spec.py
index 9a4c4ba99f..4cbd2975de 100644
--- a/tests/eest/cancun/eip4788_beacon_root/spec.py
+++ b/tests/eest/cancun/eip4788_beacon_root/spec.py
@@ -58,7 +58,7 @@ def expected_storage(
- validity of the timestamp input used within the call.
"""
# By default assume the call is unsuccessful and all keys are zero
- storage = Storage({k: 0 for k in range(4)}) # type: ignore
+ storage = Storage(dict.fromkeys(range(4), 0)) # type: ignore
if valid_call and valid_input:
# beacon root contract call is successful
storage[0] = 1
diff --git a/tests/eest/cancun/eip4788_beacon_root/test_beacon_root_contract.py b/tests/eest/cancun/eip4788_beacon_root/test_beacon_root_contract.py
index d9e6f57a70..bc91bc93f2 100644
--- a/tests/eest/cancun/eip4788_beacon_root/test_beacon_root_contract.py
+++ b/tests/eest/cancun/eip4788_beacon_root/test_beacon_root_contract.py
@@ -1,21 +1,20 @@
"""
-abstract: Tests beacon block root for [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788)
- Test the exposed beacon chain root in the EVM for [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788).
+Tests beacon block root for [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788).
-note: Adding a new test
- Add a function that is named `test_` and takes at least the following arguments:
+Note: To add a new test, add a function that is named `test_`.
- - state_test
- - env
- - pre
- - tx
- - post
- - valid_call
+It must take at least the following arguments:
- All other `pytest.fixtures` can be parametrized to generate new combinations and test
- cases.
+- `state_test`
+- `env`
+- `pre`
+- `tx`
+- `post`
+- `valid_call`
-""" # noqa: E501
+All other `pytest.fixtures` can be parametrized to generate new
+combinations and test cases.
+"""
from itertools import count
from typing import Callable, Dict, Iterator, List
@@ -35,7 +34,7 @@
Transaction,
Withdrawal,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .spec import Spec, ref_spec_4788
@@ -44,7 +43,10 @@
def count_factory(start: int, step: int = 1) -> Callable[[], Iterator[int]]:
- """Create a factory that returns fresh count iterators to avoid state persistence."""
+ """
+ Create a factory that returns fresh count iterators to avoid state
+ persistence.
+ """
return lambda: count(start, step)
@@ -80,7 +82,9 @@ def test_beacon_root_contract_calls(
post: Dict,
):
"""
- Tests the beacon root contract call using various call contexts:
+ Test calling the beacon root contract in various call contexts.
+
+ These call contexts are tested:
- `CALL`
- `DELEGATECALL`
- `CALLCODE`
@@ -90,10 +94,10 @@ def test_beacon_root_contract_calls(
- extra gas (valid call)
- insufficient gas (invalid call).
- The expected result is that the contract call will be executed if the gas amount is met
- and return the correct`parent_beacon_block_root`. Otherwise the call will be invalid, and not
- be executed. This is highlighted within storage by storing the return value of each call
- context.
+ The expected result is that the contract call will be executed if the gas
+ amount is met and return the correct`parent_beacon_block_root`. Otherwise
+ the call will be invalid, and not be executed. This is highlighted within
+ storage by storing the return value of each call context.
"""
blockchain_test(
pre=pre,
@@ -153,11 +157,12 @@ def test_beacon_root_contract_timestamps(
post: Dict,
):
"""
- Tests the beacon root contract call across for various valid and invalid timestamps.
+ Tests the beacon root contract call across for various valid and invalid
+ timestamps.
The expected result is that the contract call will return the correct
- `parent_beacon_block_root` for a valid input timestamp and return the zero'd 32 bytes value
- for an invalid input timestamp.
+ `parent_beacon_block_root` for a valid input timestamp and return the
+ zero'd 32 bytes value for an invalid input timestamp.
"""
blockchain_test(
pre=pre,
@@ -187,7 +192,9 @@ def test_calldata_lengths(
tx: Transaction,
post: Dict,
):
- """Tests the beacon root contract call using multiple invalid input lengths."""
+ """
+ Tests the beacon root contract call using multiple invalid input lengths.
+ """
blockchain_test(
pre=pre,
blocks=[Block(txs=[tx], parent_beacon_block_root=beacon_root, timestamp=timestamp)],
@@ -216,10 +223,11 @@ def test_beacon_root_equal_to_timestamp(
post: Dict,
):
"""
- Tests the beacon root contract call where the beacon root is equal to the timestamp.
+ Tests the beacon root contract call where the beacon root is equal to the
+ timestamp.
- The expected result is that the contract call will return the `parent_beacon_block_root`,
- as all timestamps used are valid.
+ The expected result is that the contract call will return the
+ `parent_beacon_block_root`, as all timestamps used are valid.
"""
blockchain_test(
pre=pre,
@@ -240,7 +248,10 @@ def test_tx_to_beacon_root_contract(
tx: Transaction,
post: Dict,
):
- """Tests the beacon root contract using a transaction with different types and data lengths."""
+ """
+ Tests the beacon root contract using a transaction with different types and
+ data lengths.
+ """
blockchain_test(
pre=pre,
blocks=[Block(txs=[tx], parent_beacon_block_root=beacon_root, timestamp=timestamp)],
@@ -288,7 +299,10 @@ def test_beacon_root_selfdestruct(
tx: Transaction,
post: Dict,
):
- """Tests that self destructing the beacon root address transfers actors balance correctly."""
+ """
+ Tests that self destructing the beacon root address transfers actors
+ balance correctly.
+ """
# self destruct actor
self_destruct_actor_address = pre.deploy_contract(
Op.SELFDESTRUCT(Spec.BEACON_ROOTS_ADDRESS),
@@ -373,17 +387,20 @@ def test_multi_block_beacon_root_timestamp_calls(
call_value: int,
):
"""
- Tests multiple blocks where each block writes a timestamp to storage and contains one
- transaction that calls the beacon root contract multiple times.
+ Tests multiple blocks where each block writes a timestamp to storage and
+ contains one transaction that calls the beacon root contract multiple
+ times.
- The blocks might overwrite the historical roots buffer, or not, depending on the `timestamps`,
- and whether they increment in multiples of `Spec.HISTORY_BUFFER_LENGTH` or not.
+ The blocks might overwrite the historical roots buffer, or not, depending
+ on the `timestamps`, and whether they increment in multiples of
+ `Spec.HISTORY_BUFFER_LENGTH` or not.
By default, the beacon roots are the keccak of the block number.
- Each transaction checks the current timestamp and also all previous timestamps, and verifies
- that the beacon root is correct for all of them if the timestamp is supposed to be in the
- buffer, which might have been overwritten by a later block.
+ Each transaction checks the current timestamp and also all previous
+ timestamps, and verifies that the beacon root is correct for all of them if
+ the timestamp is supposed to be in the buffer, which might have been
+ overwritten by a later block.
"""
# Create fresh iterator to avoid state persistence between test phases
timestamps = timestamps_factory()
@@ -415,9 +432,9 @@ def test_multi_block_beacon_root_timestamp_calls(
current_call_account_code = Bytecode()
current_call_account_expected_storage = Storage()
- # We are going to call the beacon roots contract once for every timestamp of the current
- # and all previous blocks, and check that the returned beacon root is still correct only
- # if it was not overwritten.
+ # We are going to call the beacon roots contract once for every
+ # timestamp of the current and all previous blocks, and check that the
+ # returned beacon root is still correct only if it was not overwritten.
for t in all_timestamps:
current_call_account_code += Op.MSTORE(0, t)
call_valid = (
@@ -462,7 +479,8 @@ def test_multi_block_beacon_root_timestamp_calls(
parent_beacon_block_root=beacon_root,
timestamp=timestamp,
withdrawals=[
- # Also withdraw to the beacon root contract and the system address
+ # Also withdraw to the beacon root contract and the system
+ # address
Withdrawal(
address=Spec.BEACON_ROOTS_ADDRESS,
amount=1,
@@ -503,8 +521,9 @@ def test_beacon_root_transition(
fork: Fork,
):
"""
- Tests the fork transition to cancun and verifies that blocks with timestamp lower than the
- transition timestamp do not contain beacon roots in the pre-deployed contract.
+ Tests the fork transition to cancun and verifies that blocks with timestamp
+ lower than the transition timestamp do not contain beacon roots in the
+ pre-deployed contract.
"""
# Create fresh iterator to avoid state persistence between test phases
timestamps = timestamps_factory()
@@ -525,9 +544,10 @@ def test_beacon_root_transition(
):
timestamp_index = timestamp % Spec.HISTORY_BUFFER_LENGTH
- transitioned = fork.header_beacon_root_required(i, timestamp)
+ transitioned = fork.header_beacon_root_required(block_number=i, timestamp=timestamp)
if transitioned:
- # We've transitioned, the current timestamp must contain a value in the contract
+ # We've transitioned, the current timestamp must contain a value in
+ # the contract
timestamps_in_beacon_root_contract.append(timestamp)
timestamps_storage[timestamp_index] = timestamp
roots_storage[timestamp_index] = beacon_root
@@ -539,9 +559,10 @@ def test_beacon_root_transition(
current_call_account_code = Bytecode()
current_call_account_expected_storage = Storage()
- # We are going to call the beacon roots contract once for every timestamp of the current
- # and all previous blocks, and check that the returned beacon root is correct only
- # if it was after the transition timestamp.
+ # We are going to call the beacon roots contract once for every
+ # timestamp of the current and all previous blocks, and check that the
+ # returned beacon root is correct only if it was after the transition
+ # timestamp.
for t in all_timestamps:
current_call_account_code += Op.MSTORE(0, t)
call_valid = (
@@ -586,7 +607,8 @@ def test_beacon_root_transition(
parent_beacon_block_root=beacon_root if transitioned else None,
timestamp=timestamp,
withdrawals=[
- # Also withdraw to the beacon root contract and the system address
+ # Also withdraw to the beacon root contract and the system
+ # address
Withdrawal(
address=Spec.BEACON_ROOTS_ADDRESS,
amount=1,
@@ -625,17 +647,18 @@ def test_no_beacon_root_contract_at_transition(
fork: Fork,
):
"""
- Tests the fork transition to cancun in the case where the beacon root pre-deploy was not
- deployed in time for the fork.
+ Tests the fork transition to cancun in the case where the beacon root
+ pre-deploy was not deployed in time for the fork.
"""
- assert fork.header_beacon_root_required(1, timestamp)
+ assert fork.header_beacon_root_required(block_number=1, timestamp=timestamp)
blocks: List[Block] = [
Block(
txs=[tx],
parent_beacon_block_root=next(beacon_roots),
timestamp=timestamp,
withdrawals=[
- # Also withdraw to the beacon root contract and the system address
+ # Also withdraw to the beacon root contract and the system
+ # address
Withdrawal(
address=Spec.BEACON_ROOTS_ADDRESS,
amount=1,
@@ -652,7 +675,8 @@ def test_no_beacon_root_contract_at_transition(
)
]
pre[Spec.BEACON_ROOTS_ADDRESS] = Account(
- code=b"", # Remove the code that is automatically allocated on Cancun fork
+ code=b"", # Remove the code that is automatically allocated on Cancun
+ # fork
nonce=0,
balance=0,
)
@@ -667,9 +691,8 @@ def test_no_beacon_root_contract_at_transition(
balance=int(1e9),
),
caller_address: Account(
- storage={
- 0: 1
- }, # Successful call because the contract is not there, but nothing else is stored
+ storage={0: 1}, # Successful call because the contract is not there, but
+ # nothing else is stored
),
}
blockchain_test(
@@ -704,10 +727,10 @@ def test_beacon_root_contract_deploy(
fork: Fork,
):
"""
- Tests the fork transition to cancun deploying the contract during Shanghai and verifying the
- code deployed and its functionality after Cancun.
+ Tests the fork transition to cancun deploying the contract during Shanghai
+ and verifying the code deployed and its functionality after Cancun.
"""
- assert fork.header_beacon_root_required(1, timestamp)
+ assert fork.header_beacon_root_required(block_number=1, timestamp=timestamp)
tx_gas_limit = 0x3D090
tx_gas_price = 0xE8D4A51000
deployer_required_balance = tx_gas_limit * tx_gas_price
@@ -741,12 +764,15 @@ def test_beacon_root_contract_deploy(
txs=[deploy_tx],
parent_beacon_block_root=(
beacon_root
- if fork.header_beacon_root_required(1, current_timestamp)
+ if fork.header_beacon_root_required(
+ block_number=1, timestamp=current_timestamp
+ )
else None
),
timestamp=timestamp // 2,
withdrawals=[
- # Also withdraw to the beacon root contract and the system address
+ # Also withdraw to the beacon root contract and the
+ # system address
Withdrawal(
address=Spec.BEACON_ROOTS_ADDRESS,
amount=1,
@@ -773,7 +799,8 @@ def test_beacon_root_contract_deploy(
parent_beacon_block_root=beacon_root,
timestamp=timestamp,
withdrawals=[
- # Also withdraw to the beacon root contract and the system address
+ # Also withdraw to the beacon root contract and the
+ # system address
Withdrawal(
address=Spec.BEACON_ROOTS_ADDRESS,
amount=1,
@@ -800,7 +827,8 @@ def test_beacon_root_contract_deploy(
expected_code = fork.pre_allocation_blockchain()[Spec.BEACON_ROOTS_ADDRESS]["code"]
pre[Spec.BEACON_ROOTS_ADDRESS] = Account(
- code=b"", # Remove the code that is automatically allocated on Cancun fork
+ code=b"", # Remove the code that is automatically allocated on Cancun
+ # fork
nonce=0,
balance=0,
)
diff --git a/tests/eest/cancun/eip4844_blobs/conftest.py b/tests/eest/cancun/eip4844_blobs/conftest.py
index 2388a053c8..6da44f93c1 100644
--- a/tests/eest/cancun/eip4844_blobs/conftest.py
+++ b/tests/eest/cancun/eip4844_blobs/conftest.py
@@ -64,7 +64,9 @@ def parent_excess_blob_gas(
parent_excess_blobs: int | None,
blob_gas_per_blob: int,
) -> int | None:
- """Calculate the excess blob gas of the parent block from the excess blobs."""
+ """
+ Calculate the excess blob gas of the parent block from the excess blobs.
+ """
if parent_excess_blobs is None:
return None
assert parent_excess_blobs >= 0
@@ -79,7 +81,8 @@ def excess_blob_gas(
block_base_fee_per_gas: int,
) -> int | None:
"""
- Calculate the excess blob gas of the block under test from the parent block.
+ Calculate the excess blob gas of the block under test from the parent
+ block.
Value can be overloaded by a test case to provide a custom excess blob gas.
"""
@@ -100,7 +103,8 @@ def correct_excess_blob_gas(
block_base_fee_per_gas: int,
) -> int:
"""
- Calculate the correct excess blob gas of the block under test from the parent block.
+ Calculate the correct excess blob gas of the block under test from the
+ parent block.
Should not be overloaded by a test case.
"""
@@ -160,7 +164,9 @@ def env(
block_base_fee_per_gas: int,
genesis_excess_blob_gas: int,
) -> Environment:
- """Prepare the environment of the genesis block for all blockchain tests."""
+ """
+ Prepare the environment of the genesis block for all blockchain tests.
+ """
return Environment(
excess_blob_gas=genesis_excess_blob_gas,
blob_gas_used=0,
@@ -213,7 +219,8 @@ def tx_max_priority_fee_per_gas() -> int:
@pytest.fixture
def tx_max_fee_per_blob_gas_multiplier() -> int:
"""
- Return default max fee per blob gas multiplier for transactions sent during test.
+ Return default max fee per blob gas multiplier for transactions sent during
+ test.
Can be overloaded by a test case to provide a custom max fee per blob gas
multiplier.
@@ -224,7 +231,8 @@ def tx_max_fee_per_blob_gas_multiplier() -> int:
@pytest.fixture
def tx_max_fee_per_blob_gas_delta() -> int:
"""
- Return default max fee per blob gas delta for transactions sent during test.
+ Return default max fee per blob gas delta for transactions sent during
+ test.
Can be overloaded by a test case to provide a custom max fee per blob gas
delta.
@@ -263,22 +271,21 @@ def non_zero_blob_gas_used_genesis_block(
block_base_fee_per_gas: int,
) -> Block | None:
"""
- For test cases with a non-zero blobGasUsed field in the
- original genesis block header we must instead utilize an
- intermediate block to act on its behalf.
-
- Genesis blocks with a non-zero blobGasUsed field are invalid as
- they do not have any blob txs.
-
- For the intermediate block to align with default genesis values,
- we must add TARGET_BLOB_GAS_PER_BLOCK to the excessBlobGas of the
- genesis value, expecting an appropriate drop to the intermediate block.
- Similarly, we must add parent_blobs to the intermediate block within
- a blob tx such that an equivalent blobGasUsed field is wrote.
-
- For forks >= Osaka where the MAX_BLOBS_PER_TX is introduced, we
- split the blobs across multiple transactions to respect the
- MAX_BLOBS_PER_TX limit.
+ For test cases with a non-zero blobGasUsed field in the original genesis
+ block header we must instead utilize an intermediate block to act on its
+ behalf.
+
+ Genesis blocks with a non-zero blobGasUsed field are invalid as they do not
+ have any blob txs.
+
+ For the intermediate block to align with default genesis values, we must
+ add TARGET_BLOB_GAS_PER_BLOCK to the excessBlobGas of the genesis value,
+ expecting an appropriate drop to the intermediate block. Similarly, we must
+ add parent_blobs to the intermediate block within a blob tx such that an
+ equivalent blobGasUsed field is wrote.
+
+ For forks >= Osaka where the MAX_BLOBS_PER_TX is introduced, we split the
+ blobs across multiple transactions to respect the MAX_BLOBS_PER_TX limit.
"""
if parent_blobs == 0:
return None
@@ -300,9 +307,10 @@ def non_zero_blob_gas_used_genesis_block(
empty_account_destination = pre.fund_eoa(0)
blob_gas_price_calculator = fork.blob_gas_price_calculator(block_number=1)
- # Split blobs into chunks when MAX_BLOBS_PER_TX < MAX_BLOBS_PER_BLOCK to respect per-tx limits.
- # Allows us to keep single txs for forks where per-tx and per-block limits are equal, hitting
- # coverage for block level blob gas validation when parent_blobs > MAX_BLOBS_PER_BLOCK.
+ # Split blobs into chunks when MAX_BLOBS_PER_TX < MAX_BLOBS_PER_BLOCK to
+ # respect per-tx limits. Allows us to keep single txs for forks where per-
+ # tx and per-block limits are equal, hitting coverage for block level blob
+ # gas validation when parent_blobs > MAX_BLOBS_PER_BLOCK.
max_blobs_per_tx = (
fork.max_blobs_per_tx()
if fork.max_blobs_per_tx() < fork.max_blobs_per_block()
diff --git a/tests/eest/cancun/eip4844_blobs/spec.py b/tests/eest/cancun/eip4844_blobs/spec.py
index 5eb5a29a7e..a531fb81ac 100644
--- a/tests/eest/cancun/eip4844_blobs/spec.py
+++ b/tests/eest/cancun/eip4844_blobs/spec.py
@@ -87,8 +87,8 @@ def get_min_excess_blob_gas_for_blob_gas_price(
blob_gas_price: int,
) -> int:
"""
- Get the minimum required excess blob gas value to get a given blob gas cost in a
- block.
+ Get the minimum required excess blob gas value to get a given blob gas
+ cost in a block.
"""
current_excess_blob_gas = 0
current_blob_gas_price = 1
@@ -106,7 +106,10 @@ def get_min_excess_blobs_for_blob_gas_price(
fork: Fork,
blob_gas_price: int,
) -> int:
- """Get the minimum required excess blobs to get a given blob gas cost in a block."""
+ """
+ Get the minimum required excess blobs to get a given blob gas cost in a
+ block.
+ """
gas_per_blob = fork.blob_gas_per_blob()
return (
cls.get_min_excess_blob_gas_for_blob_gas_price(
@@ -122,23 +125,27 @@ def get_blob_combinations(
blob_count: int,
max_blobs_per_tx: int,
) -> List[Tuple[int, ...]]:
- """Get all possible combinations of blobs that result in a given blob count."""
+ """
+ Get all possible combinations of blobs that result in a given blob
+ count.
+ """
combinations = [
seq
for i in range(
blob_count + 1, 0, -1
- ) # We can have from 1 to at most MAX_BLOBS_PER_BLOCK blobs per block
+ ) # We can have from 1 to at most MAX_BLOBS_PER_BLOCK blobs per
+ # block
for seq in itertools.combinations_with_replacement(
range(1, min(blob_count + 1, max_blobs_per_tx) + 1), i
) # We iterate through all possible combinations
- if sum(seq)
- == blob_count # And we only keep the ones that match the expected blob count
- and all(tx_blobs <= max_blobs_per_tx for tx_blobs in seq) # Validate each tx
+ # And we only keep the ones that match the expected blob count
+ if sum(seq) == blob_count and all(tx_blobs <= max_blobs_per_tx for tx_blobs in seq)
+ # Validate each tx
]
- # We also add the reversed version of each combination, only if it's not
- # already in the list. E.g. (4, 1) is added from (1, 4) but not
- # (1, 1, 1, 1, 1) because its reversed version is identical.
+ # We also add the reversed version of each combination, only if it's
+ # not already in the list. E.g. (4, 1) is added from (1, 4) but not (1,
+ # 1, 1, 1, 1) because its reversed version is identical.
combinations += [
tuple(reversed(x)) for x in combinations if tuple(reversed(x)) not in combinations
]
@@ -147,8 +154,8 @@ def get_blob_combinations(
@classmethod
def all_valid_blob_combinations(cls, fork: Fork) -> List[Tuple[int, ...]]:
"""
- Return all valid blob tx combinations for a given block,
- assuming the given MAX_BLOBS_PER_BLOCK, whilst respecting MAX_BLOBS_PER_TX.
+ Return all valid blob tx combinations for a given block, assuming the
+ given MAX_BLOBS_PER_BLOCK, whilst respecting MAX_BLOBS_PER_TX.
"""
max_blobs_per_block = fork.max_blobs_per_block()
max_blobs_per_tx = fork.max_blobs_per_tx()
diff --git a/tests/eest/cancun/eip4844_blobs/test_blob_txs.py b/tests/eest/cancun/eip4844_blobs/test_blob_txs.py
index 166fb5ced4..4ce5104580 100644
--- a/tests/eest/cancun/eip4844_blobs/test_blob_txs.py
+++ b/tests/eest/cancun/eip4844_blobs/test_blob_txs.py
@@ -1,19 +1,18 @@
"""
-abstract: Tests blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
- Test blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+Tests blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+Note: To add a new test, add a function that is named `test_`.
-note: Adding a new test
- Add a function that is named `test_` and takes at least the following arguments:
+It must at least use the following arguments:
- - blockchain_test or state_test
- - pre
- - env
- - block or txs
+- `blockchain_test` or `state_test`
+- `pre`
+- `env`
+- `block` or `txs`.
- All other `pytest.fixture` fixtures can be parametrized to generate new combinations and test cases.
-
-""" # noqa: E501
+All other `pytest.fixture` fixtures can be parametrized to generate new
+combinations and test cases.
+"""
from typing import List, Optional, Tuple
@@ -126,8 +125,8 @@ def total_account_minimum_balance( # noqa: D103
blob_hashes_per_tx: List[List[bytes]],
) -> int:
"""
- Calculate minimum balance required for the account to be able to send
- the transactions in the block of the test.
+ Calculate minimum balance required for the account to be able to send the
+ transactions in the block of the test.
"""
minimum_cost = 0
for tx_blob_count in [len(x) for x in blob_hashes_per_tx]:
@@ -147,7 +146,9 @@ def total_account_transactions_fee( # noqa: D103
tx_max_priority_fee_per_gas: int,
blob_hashes_per_tx: List[List[bytes]],
) -> int:
- """Calculate actual fee for the blob transactions in the block of the test."""
+ """
+ Calculate actual fee for the blob transactions in the block of the test.
+ """
total_cost = 0
for tx_blob_count in [len(x) for x in blob_hashes_per_tx]:
blob_cost = blob_gas_price * blob_gas_per_blob * tx_blob_count
@@ -175,8 +176,8 @@ def tx_error() -> Optional[TransactionException]:
"""
Error produced by the block transactions (no error).
- Can be overloaded on test cases where the transactions are expected
- to fail.
+ Can be overloaded on test cases where the transactions are expected to
+ fail.
"""
return None
@@ -230,8 +231,8 @@ def txs( # noqa: D103
@pytest.fixture
def account_balance_modifier() -> int:
"""
- Account balance modifier for the source account of all tests.
- See `pre` fixture.
+ Account balance modifier for the source account of all tests. See `pre`
+ fixture.
"""
return 0
@@ -243,9 +244,9 @@ def state_env(
"""
Prepare the environment for all state test cases.
- Main difference is that the excess blob gas is not increased by the target, as
- there is no genesis block -> block 1 transition, and therefore the excess blob gas
- is not decreased by the target.
+ Main difference is that the excess blob gas is not increased by the target,
+ as there is no genesis block -> block 1 transition, and therefore the
+ excess blob gas is not decreased by the target.
"""
return Environment(
excess_blob_gas=excess_blob_gas if excess_blob_gas else 0,
@@ -255,8 +256,8 @@ def state_env(
@pytest.fixture
def engine_api_error_code() -> Optional[EngineAPIError]:
"""
- Engine API error code to be returned by the client on consumption
- of the erroneous block in hive.
+ Engine API error code to be returned by the client on consumption of the
+ erroneous block in hive.
"""
return None
@@ -268,8 +269,8 @@ def block_error(
"""
Error produced by the block transactions (no error).
- Can be overloaded on test cases where the transactions are expected
- to fail.
+ Can be overloaded on test cases where the transactions are expected to
+ fail.
"""
return tx_error
@@ -385,15 +386,16 @@ def test_valid_blob_tx_combinations(
block: Block,
):
"""
- Test all valid blob combinations in a single block, assuming a given value of
- `MAX_BLOBS_PER_BLOCK`.
+ Test all valid blob combinations in a single block, assuming a given value
+ of `MAX_BLOBS_PER_BLOCK`.
- This assumes a block can include from 1 and up to `MAX_BLOBS_PER_BLOCK` transactions where all
- transactions contain at least 1 blob, and the sum of all blobs in a block is at
- most `MAX_BLOBS_PER_BLOCK`.
+ This assumes a block can include from 1 and up to `MAX_BLOBS_PER_BLOCK`
+ transactions where all transactions contain at least 1 blob, and the sum of
+ all blobs in a block is at most `MAX_BLOBS_PER_BLOCK`.
- This test is parametrized with all valid blob transaction combinations for a given block, and
- therefore if value of `MAX_BLOBS_PER_BLOCK` changes, this test is automatically updated.
+ This test is parametrized with all valid blob transaction combinations for
+ a given block, and therefore if value of `MAX_BLOBS_PER_BLOCK` changes,
+ this test is automatically updated.
"""
blockchain_test(
pre=pre,
@@ -407,8 +409,8 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests(
fork: Fork,
) -> List:
"""
- Return a list of tests for invalid blob transactions due to insufficient max fee per blob gas
- parametrized for each different fork.
+ Return a list of tests for invalid blob transactions due to insufficient
+ max fee per blob gas parametrized for each different fork.
"""
min_base_fee_per_blob_gas = fork.min_base_fee_per_blob_gas()
minimum_excess_blobs_for_first_increment = SpecHelpers.get_min_excess_blobs_for_blob_gas_price(
@@ -422,9 +424,12 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests(
tests = []
tests.append(
pytest.param(
- minimum_excess_blobs_for_first_increment - 1, # blob gas price is 1
- fork.target_blobs_per_block() + 1, # blob gas cost increases to above the minimum
- min_base_fee_per_blob_gas, # tx max_blob_gas_cost is the minimum
+ # blob gas price is 1
+ minimum_excess_blobs_for_first_increment - 1,
+ # blob gas cost increases to above the minimum
+ fork.target_blobs_per_block() + 1,
+ # tx max_blob_gas_cost is the minimum
+ min_base_fee_per_blob_gas,
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
id="insufficient_max_fee_per_blob_gas",
marks=pytest.mark.exception_test,
@@ -433,11 +438,12 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests(
if (next_base_fee_per_blob_gas - min_base_fee_per_blob_gas) > 1:
tests.append(
pytest.param(
- minimum_excess_blobs_for_first_increment
- - 1, # blob gas price is one less than the minimum
- fork.target_blobs_per_block() + 1, # blob gas cost increases to above the minimum
- next_base_fee_per_blob_gas
- - 1, # tx max_blob_gas_cost is one less than the minimum
+ # blob gas price is one less than the minimum
+ minimum_excess_blobs_for_first_increment - 1,
+ # blob gas cost increases to above the minimum
+ fork.target_blobs_per_block() + 1,
+ # tx max_blob_gas_cost is one less than the minimum
+ next_base_fee_per_blob_gas - 1,
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
id="insufficient_max_fee_per_blob_gas_one_less_than_next",
marks=pytest.mark.exception_test,
@@ -448,7 +454,8 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests(
pytest.param(
0, # blob gas price is the minimum
0, # blob gas cost stays put at 1
- min_base_fee_per_blob_gas - 1, # tx max_blob_gas_cost is one less than the minimum
+ # tx max_blob_gas_cost is one less than the minimum
+ min_base_fee_per_blob_gas - 1,
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
id="insufficient_max_fee_per_blob_gas_one_less_than_min",
marks=pytest.mark.exception_test,
@@ -589,12 +596,12 @@ def test_invalid_block_blob_count(
block: Block,
):
"""
- Test all invalid blob combinations in a single block, where the sum of all blobs in a block is
- at `MAX_BLOBS_PER_BLOCK + 1`.
+ Test all invalid blob combinations in a single block, where the sum of all
+ blobs in a block is at `MAX_BLOBS_PER_BLOCK + 1`.
This test is parametrized with all blob transaction combinations exceeding
- `MAX_BLOBS_PER_BLOCK` by one for a given block, and
- therefore if value of `MAX_BLOBS_PER_BLOCK` changes, this test is automatically updated.
+ `MAX_BLOBS_PER_BLOCK` by one for a given block, and therefore if value of
+ `MAX_BLOBS_PER_BLOCK` changes, this test is automatically updated.
"""
blockchain_test(
pre=pre,
@@ -622,6 +629,7 @@ def test_invalid_block_blob_count(
@pytest.mark.parametrize("tx_error", [TransactionException.INSUFFICIENT_ACCOUNT_FUNDS], ids=[""])
@pytest.mark.exception_test
@pytest.mark.valid_from("Cancun")
+@pytest.mark.slow()
def test_insufficient_balance_blob_tx(
state_test: StateTestFiller,
state_env: Environment,
@@ -636,7 +644,8 @@ def test_insufficient_balance_blob_tx(
- Transactions with and without priority fee
- Transactions with and without value
- Transactions with and without calldata
- - Transactions with max fee per blob gas lower or higher than the priority fee
+ - Transactions with max fee per blob gas lower or higher than the priority
+ fee
"""
assert len(txs) == 1
state_test(
@@ -677,14 +686,15 @@ def test_sufficient_balance_blob_tx(
txs: List[Transaction],
):
"""
- Check that transaction is accepted when user can exactly afford the blob gas specified (and
- max_fee_per_gas would be enough for current block).
+ Check that transaction is accepted when user can exactly afford the blob
+ gas specified (and max_fee_per_gas would be enough for current block).
- Transactions with max fee equal or higher than current block base fee
- Transactions with and without priority fee
- Transactions with and without value
- Transactions with and without calldata
- - Transactions with max fee per blob gas lower or higher than the priority fee
+ - Transactions with max fee per blob gas lower or higher than the priority
+ fee
"""
assert len(txs) == 1
state_test(
@@ -728,15 +738,16 @@ def test_sufficient_balance_blob_tx_pre_fund_tx(
header_verify: Optional[Header],
):
"""
- Check that transaction is accepted when user can exactly afford the blob gas specified (and
- max_fee_per_gas would be enough for current block) because a funding transaction is
- prepended in the same block.
+ Check that transaction is accepted when user can exactly afford the blob
+ gas specified (and max_fee_per_gas would be enough for current block)
+ because a funding transaction is prepended in the same block.
- Transactions with max fee equal or higher than current block base fee
- Transactions with and without priority fee
- Transactions with and without value
- Transactions with and without calldata
- - Transactions with max fee per blob gas lower or higher than the priority fee
+ - Transactions with max fee per blob gas lower or higher than the priority
+ fee
"""
pre_funding_sender = pre.fund_eoa(amount=(21_000 * 100) + total_account_minimum_balance)
txs = [
@@ -808,14 +819,16 @@ def test_blob_gas_subtraction_tx(
total_account_transactions_fee: int,
):
"""
- Check that the blob gas fee for a transaction is subtracted from the sender balance before the
- transaction is executed.
+ Check that the blob gas fee for a transaction is subtracted from the sender
+ balance before the transaction is executed.
- Transactions with max fee equal or higher than current block base fee
- Transactions with and without value
- Transactions with and without calldata
- - Transactions with max fee per blob gas lower or higher than the priority fee
- - Transactions where an externally owned account sends funds to the sender mid execution
+ - Transactions with max fee per blob gas lower or higher than the priority
+ fee
+ - Transactions where an externally owned account sends funds to the sender
+ mid execution
"""
assert len(txs) == 1
post = {
@@ -851,10 +864,11 @@ def test_insufficient_balance_blob_tx_combinations(
block: Block,
):
"""
- Reject all valid blob transaction combinations in a block, but block is invalid.
+ Reject all valid blob transaction combinations in a block, but block is
+ invalid.
- - The amount of blobs is correct but the user cannot afford the
- transaction total cost
+ - The amount of blobs is correct but the user cannot afford the transaction
+ total cost
"""
blockchain_test(
pre=pre,
@@ -867,7 +881,10 @@ def test_insufficient_balance_blob_tx_combinations(
def generate_invalid_tx_blob_count_tests(
fork: Fork,
) -> List:
- """Return a list of tests for invalid blob transactions due to invalid blob counts."""
+ """
+ Return a list of tests for invalid blob transactions due to invalid blob
+ counts.
+ """
return [
pytest.param(
[0],
@@ -1007,7 +1024,8 @@ def test_invalid_blob_hash_versioning_multiple_txs(
- Multiple blob transactions with single blob all with invalid version
- Multiple blob transactions with multiple blobs all with invalid version
- - Multiple blob transactions with multiple blobs only one with invalid version
+ - Multiple blob transactions with multiple blobs only one with invalid
+ version
"""
blockchain_test(
pre=pre,
@@ -1029,10 +1047,14 @@ def test_invalid_blob_tx_contract_creation(
txs: List[Transaction],
header_verify: Optional[Header],
):
- """Reject blocks that include blob transactions that have nil to value (contract creating)."""
+ """
+ Reject blocks that include blob transactions that have nil to value
+ (contract creating).
+ """
assert len(txs) == 1
assert txs[0].blob_versioned_hashes is not None and len(txs[0].blob_versioned_hashes) == 1
- # Replace the transaction with a contract creating one, only in the RLP version
+ # Replace the transaction with a contract creating one, only in the RLP
+ # version
contract_creating_tx = txs[0].copy(to=None).with_signature_and_sender()
txs[0].rlp_override = contract_creating_tx.rlp()
blockchain_test(
@@ -1047,8 +1069,8 @@ def test_invalid_blob_tx_contract_creation(
],
header_verify=header_verify,
# Skipped due to the T8N not receiving the invalid transaction,
- # instead we are passing a valid transaction to T8N and then the transaction
- # is replaced directly in the block RLP.
+ # instead we are passing a valid transaction to T8N and then
+ # the transaction is replaced directly in the block RLP.
skip_exception_verification=True,
)
],
@@ -1071,7 +1093,10 @@ def opcode(
tx_max_priority_fee_per_gas: int,
tx_value: int,
) -> Tuple[Bytecode, Storage.StorageDictType]:
- """Build bytecode and post to test each opcode that accesses transaction information."""
+ """
+ Build bytecode and post to test each opcode that accesses transaction
+ information.
+ """
if request.param == Op.ORIGIN:
return (
Op.SSTORE(0, Op.ORIGIN),
@@ -1137,7 +1162,8 @@ def test_blob_tx_attribute_opcodes(
state_env: Environment,
):
"""
- Test opcodes that read transaction attributes work properly for blob type transactions.
+ Test opcodes that read transaction attributes work properly for blob type
+ transactions.
- ORIGIN
- CALLER
@@ -1189,7 +1215,9 @@ def test_blob_tx_attribute_value_opcode(
opcode: Tuple[Bytecode, Storage.StorageDictType],
state_env: Environment,
):
- """Test the VALUE opcode with different blob type transaction value amounts."""
+ """
+ Test the VALUE opcode with different blob type transaction value amounts.
+ """
code, storage = opcode
destination_account = pre.deploy_contract(code=code)
tx = Transaction(
@@ -1255,7 +1283,8 @@ def test_blob_tx_attribute_calldata_opcodes(
state_env: Environment,
):
"""
- Test calldata related opcodes to verify their behavior is not affected by blobs.
+ Test calldata related opcodes to verify their behavior is not affected by
+ blobs.
- CALLDATALOAD
- CALLDATASIZE
@@ -1289,9 +1318,12 @@ def test_blob_tx_attribute_calldata_opcodes(
)
-@pytest.mark.parametrize("tx_max_priority_fee_per_gas", [0, 2]) # always below data fee
-@pytest.mark.parametrize("tx_max_fee_per_blob_gas_delta", [0, 1]) # normal and above priority fee
-@pytest.mark.parametrize("tx_max_fee_per_gas", [100]) # always above priority fee (FOR CANCUN)
+# always below data fee:
+@pytest.mark.parametrize("tx_max_priority_fee_per_gas", [0, 2])
+# normal and above priority fee:
+@pytest.mark.parametrize("tx_max_fee_per_blob_gas_delta", [0, 1])
+# always above priority fee (FOR CANCUN)
+@pytest.mark.parametrize("tx_max_fee_per_gas", [100])
@pytest.mark.parametrize("opcode", [Op.GASPRICE], indirect=True)
@pytest.mark.parametrize("tx_gas", [500_000])
@pytest.mark.valid_from("Cancun")
@@ -1311,7 +1343,8 @@ def test_blob_tx_attribute_gasprice_opcode(
state_env: Environment,
):
"""
- Test GASPRICE opcode to sanity check that the blob gas fee does not affect its calculation.
+ Test GASPRICE opcode to sanity check that the blob gas fee does not affect
+ its calculation.
- No priority fee
- Priority fee below data fee
@@ -1373,6 +1406,7 @@ def test_blob_tx_attribute_gasprice_opcode(
)
@pytest.mark.exception_test
@pytest.mark.valid_at_transition_to("Cancun")
+@pytest.mark.slow()
def test_blob_type_tx_pre_fork(
state_test: StateTestFiller,
pre: Alloc,
@@ -1382,8 +1416,9 @@ def test_blob_type_tx_pre_fork(
"""
Reject blocks with blob type transactions before Cancun fork.
- Blocks sent by NewPayloadV2 (Shanghai) that contain blob type transactions, furthermore blobs
- field within NewPayloadV2 method must be computed as INVALID, due to an invalid block hash.
+ Blocks sent by NewPayloadV2 (Shanghai) that contain blob type transactions,
+ furthermore blobs field within NewPayloadV2 method must be computed as
+ INVALID, due to an invalid block hash.
"""
assert len(txs) == 1
state_test(
diff --git a/tests/eest/cancun/eip4844_blobs/test_blob_txs_full.py b/tests/eest/cancun/eip4844_blobs/test_blob_txs_full.py
index ba6c091a70..d71b81f22c 100644
--- a/tests/eest/cancun/eip4844_blobs/test_blob_txs_full.py
+++ b/tests/eest/cancun/eip4844_blobs/test_blob_txs_full.py
@@ -1,8 +1,4 @@
-"""
-abstract: Tests full blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
- Test full blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
-
-""" # noqa: E501
+"""Tests full blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)."""
from typing import List, Optional
@@ -135,10 +131,10 @@ def tx_max_fee_per_blob_gas( # noqa: D103
@pytest.fixture
def tx_error() -> Optional[TransactionException]:
"""
- Even though the final block we are producing in each of these tests is invalid, and some of the
- transactions will be invalid due to the format in the final block, none of the transactions
- should be rejected by the transition tool because they are being sent to it with the correct
- format.
+ Even though the final block we are producing in each of these tests is
+ invalid, and some of the transactions will be invalid due to the format in
+ the final block, none of the transactions should be rejected by the
+ transition tool because they are being sent to it with the correct format.
"""
return None
@@ -214,8 +210,8 @@ def blocks(
header_blob_gas_used = 0
block_error = None
if any(txs_wrapped_blobs):
- # This is a block exception because the invalid block is only created in the RLP version,
- # not in the transition tool.
+ # This is a block exception because the invalid block is only created
+ # in the RLP version, not in the transition tool.
block_error = [
BlockException.RLP_STRUCTURES_ENCODING,
TransactionException.TYPE_3_TX_WITH_FULL_BLOBS,
@@ -289,8 +285,8 @@ def test_reject_valid_full_blob_in_block_rlp(
blocks: List[Block],
):
"""
- Test valid blob combinations where one or more txs in the block
- serialized version contain a full blob (network version) tx.
+ Test valid blob combinations where one or more txs in the block serialized
+ version contain a full blob (network version) tx.
"""
blockchain_test(
pre=pre,
diff --git a/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode.py b/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode.py
index b33d5540c8..c265bd0214 100644
--- a/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode.py
+++ b/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode.py
@@ -1,21 +1,21 @@
"""
-abstract: Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
- Test cases for the `BLOBHASH` opcode in
- [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
-note: Adding a new test
- Add a function that is named `test_` and takes at least the following arguments:
+Note: Adding a new test Add a function that is named `test_` and
+takes at least the following arguments.
- - blockchain_test
- - pre
- - tx
- - post
+Required arguments:
+- `blockchain_test`
+- `pre`
+- `tx`
+- `post`
- Additional custom `pytest.fixture` fixtures can be added and parametrized for new test cases.
+Additional custom `pytest.fixture` fixtures can be added and parametrized
+for
+new test cases.
- There is no specific structure to follow within this test module.
-
-""" # noqa: E501
+There is no specific structure to follow within this test module.
+"""
from typing import List
@@ -81,11 +81,10 @@ class BlobhashScenario:
@staticmethod
def create_blob_hashes_list(length: int, max_blobs_per_tx: int) -> List[List[Hash]]:
"""
- Create list of MAX_BLOBS_PER_TX blob hashes
- using `random_blob_hashes`.
+ Create list of MAX_BLOBS_PER_TX blob hashes using `random_blob_hashes`.
- Cycle over random_blob_hashes to get a large list of
- length: MAX_BLOBS_PER_TX * length
+ Cycle over random_blob_hashes to get a large list of length:
+ MAX_BLOBS_PER_TX * length
-> [0x01, 0x02, 0x03, 0x04, ..., 0x0A, 0x0B, 0x0C, 0x0D]
Then split list into smaller chunks of MAX_BLOBS_PER_TX
@@ -104,9 +103,8 @@ def blobhash_sstore(index: int, max_blobs_per_tx: int):
"""
Return BLOBHASH sstore to the given index.
- If the index is out of the valid bounds, 0x01 is written
- in storage, as we later check it is overwritten by
- the BLOBHASH sstore.
+ If the index is out of the valid bounds, 0x01 is written in storage, as
+ we later check it is overwritten by the BLOBHASH sstore.
"""
invalidity_check = Op.SSTORE(index, 0x01)
if index < 0 or index >= max_blobs_per_tx:
@@ -158,9 +156,9 @@ def test_blobhash_gas_cost(
"""
Tests `BLOBHASH` opcode gas cost using a variety of indexes.
- Asserts that the gas consumption of the `BLOBHASH` opcode is correct by ensuring
- it matches `HASH_OPCODE_GAS = 3`. Includes both valid and invalid random
- index sizes from the range `[0, 2**256-1]`, for tx types 2 and 3.
+ Asserts that the gas consumption of the `BLOBHASH` opcode is correct by
+ ensuring it matches `HASH_OPCODE_GAS = 3`. Includes both valid and invalid
+ random index sizes from the range `[0, 2**256-1]`, for tx types 2 and 3.
"""
gas_measure_code = CodeGasMeasure(
code=Op.BLOBHASH(blobhash_index),
@@ -279,11 +277,11 @@ def test_blobhash_invalid_blob_index(
max_blobs_per_tx: int,
):
"""
- Tests that the `BLOBHASH` opcode returns a zeroed `bytes32` value for invalid
- indexes.
+ Tests that the `BLOBHASH` opcode returns a zeroed `bytes32` value for
+ invalid indexes.
- Includes cases where the index is negative (`index < 0`) or
- exceeds the maximum number of `blob_versioned_hash` values stored:
+ Includes cases where the index is negative (`index < 0`) or exceeds the
+ maximum number of `blob_versioned_hash` values stored:
(`index >= len(tx.message.blob_versioned_hashes)`).
It confirms that the returned value is a zeroed `bytes32` for each case.
@@ -387,7 +385,7 @@ def blob_tx(address: Address, tx_type: int):
storage={i: random_blob_hashes[i] for i in range(max_blobs_per_tx)}
)
if address in (addresses[1], addresses[3])
- else Account(storage={i: 0 for i in range(max_blobs_per_tx)})
+ else Account(storage=dict.fromkeys(range(max_blobs_per_tx), 0))
for address in addresses
}
blockchain_test(
diff --git a/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py b/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py
index b3ca64fd9c..41d85d2b25 100644
--- a/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py
+++ b/tests/eest/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py
@@ -1,9 +1,6 @@
"""
-abstract: Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
- Test case for `BLOBHASH` opcode calls across different contexts
- in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
-
-""" # noqa: E501
+Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+"""
from enum import Enum
from typing import Iterable, List
@@ -34,8 +31,8 @@
class BlobhashContext(Enum):
"""
- A utility class for mapping common EVM opcodes in different contexts
- to specific bytecode (with BLOBHASH), addresses and contracts.
+ A utility class for mapping common EVM opcodes in different contexts to
+ specific bytecode (with BLOBHASH), addresses and contracts.
"""
BLOBHASH_SSTORE = "blobhash_sstore"
@@ -52,9 +49,7 @@ def code(self, *, indexes=Iterable[int]):
"""
Map opcode context to bytecode that utilizes the BLOBHASH opcode.
- Args:
- indexes: The indexes to request using the BLOBHASH opcode
-
+ Args: indexes: The indexes to request using the BLOBHASH opcode
"""
match self:
case BlobhashContext.BLOBHASH_SSTORE:
@@ -82,8 +77,8 @@ def deploy_contract(
Deploy a contract with the given context and indexes.
Args:
- pre: The pre state to deploy the contract on
- indexes: The indexes to request using the BLOBHASH opcode
+ pre: The pre state to deploy the contract on
+ indexes: The indexes to request using the BLOBHASH opcode
"""
match self:
@@ -147,7 +142,9 @@ def deploy_contract(
def simple_blob_hashes(
max_blobs_per_tx: int,
) -> List[Hash]:
- """Return a simple list of blob versioned hashes ranging from bytes32(1 to 4)."""
+ """
+ Return a simple list of blob versioned hashes ranging from bytes32(1 to 4).
+ """
return add_kzg_version(
[(1 << x) for x in range(max_blobs_per_tx)],
Spec.BLOB_COMMITMENT_VERSION_KZG,
@@ -177,11 +174,13 @@ def test_blobhash_opcode_contexts(
state_test: StateTestFiller,
):
"""
- Tests that the `BLOBHASH` opcode functions correctly when called in different contexts.
+ Tests that the `BLOBHASH` opcode functions correctly when called in
+ different contexts.
- `BLOBHASH` opcode on the top level of the call stack.
- `BLOBHASH` opcode on the max value.
- - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and `CALLCODE`.
+ - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and
+ `CALLCODE`.
- `BLOBHASH` opcode on Initcode.
- `BLOBHASH` opcode on `CREATE` and `CREATE2`.
- `BLOBHASH` opcode on transaction types 0, 1 and 2.
@@ -292,11 +291,13 @@ def test_blobhash_opcode_contexts_tx_types(
state_test: StateTestFiller,
):
"""
- Tests that the `BLOBHASH` opcode functions correctly when called in different contexts.
+ Tests that the `BLOBHASH` opcode functions correctly when called in
+ different contexts.
- `BLOBHASH` opcode on the top level of the call stack.
- `BLOBHASH` opcode on the max value.
- - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and `CALLCODE`.
+ - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and
+ `CALLCODE`.
- `BLOBHASH` opcode on Initcode.
- `BLOBHASH` opcode on `CREATE` and `CREATE2`.
- `BLOBHASH` opcode on transaction types 0, 1 and 2.
diff --git a/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas.py b/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas.py
index b25ebc0dc0..92f6efc8f5 100644
--- a/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas.py
+++ b/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas.py
@@ -1,25 +1,29 @@
"""
-abstract: Tests `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
- Test `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
-
-note: Adding a new test
- Add a function that is named `test_` and takes at least the following arguments:
-
- - blockchain_test
- - env
- - pre
- - blocks
- - post
- - correct_excess_blob_gas
-
- The following arguments can be parametrized to generate new combinations and test cases:
-
- - new_blobs: Number of blobs in the block (automatically split across transactions as needed)
-
- All other `pytest.fixture` fixtures can be parametrized to generate new combinations and test
- cases.
-
-""" # noqa: E501
+Tests `excessBlobGas` and `blobGasUsed` block fields for EIP-4844.
+
+Tests `excessBlobGas` and `blobGasUsed` block fields for
+[EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
+Note: Adding a new test Add a function that is named `test_` and
+takes at least the following arguments.
+
+Required arguments:
+- `blockchain_test`
+- `env`
+- `pre`
+- `blocks`
+- `post`
+- `correct_excess_blob_gas`
+
+The following arguments can be parametrized to generate new combinations
+and
+test cases:
+
+- new_blobs: Number of blobs in the block (automatically split across
+transactions as needed)
+
+All other `pytest.fixture` fixtures can be parametrized to generate new
+combinations and test cases.
+"""
import itertools
from typing import Callable, Dict, Iterator, List, Mapping, Optional, Tuple
@@ -55,7 +59,9 @@
@pytest.fixture
def parent_excess_blobs(fork: Fork) -> int: # noqa: D103
- """By default we start with an intermediate value between the target and max."""
+ """
+ By default we start with an intermediate value between the target and max.
+ """
return (fork.max_blobs_per_block() + fork.target_blobs_per_block()) // 2 + 1
@@ -304,12 +310,14 @@ def test_correct_excess_blob_gas_calculation(
correct_excess_blob_gas: int,
):
"""
- Test calculation of the `excessBlobGas` increase/decrease across
- multiple blocks with and without blobs.
+ Test calculation of the `excessBlobGas` increase/decrease across multiple
+ blocks with and without blobs.
- With parent block containing `[0, MAX_BLOBS_PER_BLOCK]` blobs
- - With parent block containing `[0, TARGET_BLOBS_PER_BLOCK]` equivalent value of excess blob gas
- """ # noqa: E501
+
+ - With parent block containing `[0, TARGET_BLOBS_PER_BLOCK]` equivalent
+ value of excess blob gas
+ """
blockchain_test(
pre=pre,
post=post,
@@ -321,8 +329,8 @@ def test_correct_excess_blob_gas_calculation(
def generate_blob_gas_cost_increases_tests(delta: int) -> Callable[[Fork], List[int]]:
"""
- Generate a list of block excess blob gas values where the blob gas price increases
- based on fork properties.
+ Generate a list of block excess blob gas values where the blob gas price
+ increases based on fork properties.
"""
def generator_function(fork: Fork) -> List[int]:
@@ -365,8 +373,8 @@ def test_correct_increasing_blob_gas_costs(
correct_excess_blob_gas: int,
):
"""
- Test calculation of the `excessBlobGas` and blob gas tx costs at
- value points where the cost increases to interesting amounts.
+ Test calculation of the `excessBlobGas` and blob gas tx costs at value
+ points where the cost increases to interesting amounts.
- At the first blob gas cost increase (1 to 2)
- At total transaction data cost increase to `> 2^32`
@@ -402,8 +410,8 @@ def test_correct_decreasing_blob_gas_costs(
correct_excess_blob_gas: int,
):
"""
- Test calculation of the `excessBlobGas` and blob gas tx costs at
- value points where the cost decreases to interesting amounts.
+ Test calculation of the `excessBlobGas` and blob gas tx costs at value
+ points where the cost decreases to interesting amounts.
See test_correct_increasing_blob_gas_costs.
"""
@@ -433,8 +441,8 @@ def test_invalid_zero_excess_blob_gas_in_header(
):
"""
Test rejection of blocks where the `excessBlobGas` in the header drops to
- zero in a block with or without data blobs, but the excess blobs in the parent are
- greater than target.
+ zero in a block with or without data blobs, but the excess blobs in the
+ parent are greater than target.
"""
if header_excess_blob_gas is None:
raise Exception("test case is badly formatted")
@@ -472,6 +480,7 @@ def all_invalid_blob_gas_used_combinations(fork: Fork) -> Iterator[Tuple[int, in
)
@pytest.mark.parametrize("parent_blobs", [0])
@pytest.mark.exception_test
+@pytest.mark.slow()
def test_invalid_blob_gas_used_in_header(
blockchain_test: BlockchainTestFiller,
env: Environment,
@@ -529,8 +538,10 @@ def test_invalid_excess_blob_gas_above_target_change(
"""
Test rejection of blocks where the `excessBlobGas`.
- - decreases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block with zero blobs
- - increases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block with max blobs
+ - decreases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block
+ with zero blobs.
+ - increases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block
+ with max blobs.
"""
if header_excess_blob_gas is None:
raise Exception("test case is badly formatted")
@@ -572,8 +583,8 @@ def test_invalid_static_excess_blob_gas(
parent_excess_blob_gas: int,
):
"""
- Test rejection of blocks where the `excessBlobGas` remains unchanged
- but the parent blobs included are not `TARGET_BLOBS_PER_BLOCK`.
+ Test rejection of blocks where the `excessBlobGas` remains unchanged but
+ the parent blobs included are not `TARGET_BLOBS_PER_BLOCK`.
Test is parametrized to `MAX_BLOBS_PER_BLOCK` and `TARGET_BLOBS_PER_BLOCK`.
"""
@@ -659,7 +670,8 @@ def test_invalid_static_excess_blob_gas_from_zero_on_blobs_above_target(
Test rejection of blocks where the `excessBlobGas` does not increase from
zero, even when the included blobs is above target.
- Test is parametrized to `[TARGET_BLOBS_PER_BLOCK+1, MAX_BLOBS_PER_BLOCK]` new blobs.
+ Test is parametrized to `[TARGET_BLOBS_PER_BLOCK+1, MAX_BLOBS_PER_BLOCK]`
+ new blobs.
"""
if header_excess_blob_gas is None:
raise Exception("test case is badly formatted")
@@ -708,9 +720,9 @@ def test_invalid_excess_blob_gas_change(
Test rejection of blocks where the `excessBlobGas` changes to an invalid
value.
- Given a parent block containing `[0, MAX_BLOBS_PER_BLOCK]` blobs, test an invalid
- `excessBlobGas` value by changing it by `[-TARGET_BLOBS_PER_BLOCK, TARGET_BLOBS_PER_BLOCK]`
- from the correct value.
+ Given a parent block containing `[0, MAX_BLOBS_PER_BLOCK]` blobs, test an
+ invalid `excessBlobGas` value by changing it by `[-TARGET_BLOBS_PER_BLOCK,
+ TARGET_BLOBS_PER_BLOCK]` from the correct value.
"""
if header_excess_blob_gas is None:
raise Exception("test case is badly formatted")
@@ -748,6 +760,7 @@ def test_invalid_excess_blob_gas_change(
lambda fork: range(fork.target_blobs_per_block()),
)
@pytest.mark.exception_test
+@pytest.mark.slow()
def test_invalid_negative_excess_blob_gas(
blockchain_test: BlockchainTestFiller,
env: Environment,
@@ -760,8 +773,8 @@ def test_invalid_negative_excess_blob_gas(
Test rejection of blocks where the `excessBlobGas` changes to the two's
complement equivalent of the negative value after subtracting target blobs.
- Reasoning is that the `excessBlobGas` is a `uint64`, so it cannot be negative, and
- we test for a potential underflow here.
+ Reasoning is that the `excessBlobGas` is a `uint64`, so it cannot be
+ negative, and we test for a potential underflow here.
"""
if header_excess_blob_gas is None:
raise Exception("test case is badly formatted")
@@ -798,6 +811,7 @@ def test_invalid_negative_excess_blob_gas(
lambda fork: [fork.target_blobs_per_block() + 1],
)
@pytest.mark.exception_test
+@pytest.mark.slow()
def test_invalid_non_multiple_excess_blob_gas(
blockchain_test: BlockchainTestFiller,
env: Environment,
@@ -810,8 +824,10 @@ def test_invalid_non_multiple_excess_blob_gas(
Test rejection of blocks where the `excessBlobGas` changes to a value that
is not a multiple of Spec.GAS_PER_BLOB`.
- - Parent block contains `TARGET_BLOBS_PER_BLOCK + 1` blobs, but `excessBlobGas` is off by +/-1
- - Parent block contains `TARGET_BLOBS_PER_BLOCK - 1` blobs, but `excessBlobGas` is off by +/-1
+ - Parent block contains `TARGET_BLOBS_PER_BLOCK + 1` blobs, but
+ `excessBlobGas` is off by +/-1
+ - Parent block contains `TARGET_BLOBS_PER_BLOCK - 1` blobs, but
+ `excessBlobGas` is off by +/-1
"""
if header_excess_blob_gas is None:
raise Exception("test case is badly formatted")
diff --git a/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py b/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py
index d2231f4a0f..115a0569e0 100644
--- a/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py
+++ b/tests/eest/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py
@@ -1,8 +1,8 @@
"""
-abstract: Tests `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) at fork transition.
- Test `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) at fork
- transition.
-""" # noqa: E501
+Test `excessBlobGas` & `blobGasUsed` block fields at fork transition.
+
+Tests for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+"""
from typing import List, Mapping
@@ -47,7 +47,11 @@ def block_gas_limit(fork: Fork) -> int: # noqa: D103
@pytest.fixture
-def genesis_environment(block_gas_limit: int, block_base_fee_per_gas: int) -> Environment: # noqa: D103
+def genesis_environment(block_gas_limit: int, block_base_fee_per_gas: int) -> Environment:
+ """
+ Genesis environment that enables existing transition tests to be used of
+ BPO forks. Compatible with all fork transitions.
+ """
return Environment(
base_fee_per_gas=(block_base_fee_per_gas * BASE_FEE_MAX_CHANGE_DENOMINATOR) // 7,
gas_limit=block_gas_limit,
@@ -154,8 +158,8 @@ def pre_fork_excess_blobs(
pre_fork_blocks: List[Block],
) -> int:
"""
- Return the cumulative excess blobs up until the fork given the pre_fork_blobs_per_block
- and the target blobs in the fork prior.
+ Return the cumulative excess blobs up until the fork given the
+ pre_fork_blobs_per_block and the target blobs in the fork prior.
"""
if not fork.supports_blobs(timestamp=0):
return 0
@@ -320,18 +324,19 @@ def post( # noqa: D103
@pytest.mark.exception_test
def test_invalid_pre_fork_block_with_blob_fields(
blockchain_test: BlockchainTestFiller,
- env: Environment,
+ genesis_environment: Environment,
pre: Alloc,
pre_fork_blocks: List[Block],
excess_blob_gas_present: bool,
blob_gas_used_present: bool,
):
"""
- Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are present on a pre-fork
- block.
+ Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are
+ present on a pre-fork block.
- Blocks sent by NewPayloadV2 (Shanghai) that contain `excessBlobGas` and `blobGasUsed` fields
- must be rejected with the appropriate `EngineAPIError.InvalidParams` error error.
+ Blocks sent by NewPayloadV2 (Shanghai) that contain `excessBlobGas` and
+ `blobGasUsed` fields must be rejected with the appropriate
+ `EngineAPIError.InvalidParams` error error.
"""
header_modifier = Header(
excess_blob_gas=0 if excess_blob_gas_present else None,
@@ -349,7 +354,7 @@ def test_invalid_pre_fork_block_with_blob_fields(
engine_api_error_code=EngineAPIError.InvalidParams,
)
],
- genesis_environment=env,
+ genesis_environment=genesis_environment,
)
@@ -365,18 +370,19 @@ def test_invalid_pre_fork_block_with_blob_fields(
@pytest.mark.exception_test
def test_invalid_post_fork_block_without_blob_fields(
blockchain_test: BlockchainTestFiller,
- env: Environment,
+ genesis_environment: Environment,
pre: Alloc,
pre_fork_blocks: List[Block],
excess_blob_gas_missing: bool,
blob_gas_used_missing: bool,
):
"""
- Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are missing on a
- post-fork block.
+ Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are
+ missing on a post-fork block.
- Blocks sent by NewPayloadV3 (Cancun) without `excessBlobGas` and `blobGasUsed` fields must be
- rejected with the appropriate `EngineAPIError.InvalidParams` error.
+ Blocks sent by NewPayloadV3 (Cancun) without `excessBlobGas` and
+ `blobGasUsed` fields must be rejected with the appropriate
+ `EngineAPIError.InvalidParams` error.
"""
header_modifier = Header()
if excess_blob_gas_missing:
@@ -395,7 +401,7 @@ def test_invalid_post_fork_block_without_blob_fields(
engine_api_error_code=EngineAPIError.InvalidParams,
)
],
- genesis_environment=env,
+ genesis_environment=genesis_environment,
)
@@ -419,7 +425,7 @@ def test_invalid_post_fork_block_without_blob_fields(
)
def test_fork_transition_excess_blob_gas_at_blob_genesis(
blockchain_test: BlockchainTestFiller,
- env: Environment,
+ genesis_environment: Environment,
pre: Alloc,
pre_fork_blocks: List[Block],
post_fork_blocks: List[Block],
@@ -428,14 +434,14 @@ def test_fork_transition_excess_blob_gas_at_blob_genesis(
"""
Test `excessBlobGas` calculation in the header when the fork is activated.
- Also produce enough blocks to test the blob gas price increase when the block is full with
- `SpecHelpers.max_blobs_per_block()` blobs.
+ Also produce enough blocks to test the blob gas price increase when the
+ block is full with `SpecHelpers.max_blobs_per_block()` blobs.
"""
blockchain_test(
pre=pre,
post=post,
blocks=pre_fork_blocks + post_fork_blocks,
- genesis_environment=env,
+ genesis_environment=genesis_environment,
)
@@ -495,7 +501,9 @@ def test_fork_transition_excess_blob_gas_post_blob_genesis(
post_fork_blocks: List[Block],
post: Mapping[Address, Account],
):
- """Test `excessBlobGas` calculation in the header when the fork is activated."""
+ """
+ Test `excessBlobGas` calculation in the header when the fork is activated.
+ """
blockchain_test(
pre=pre,
post=post,
diff --git a/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile.py b/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile.py
index cf218a5dea..4e650b8ffd 100644
--- a/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile.py
+++ b/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile.py
@@ -1,31 +1,31 @@
"""
-abstract: Tests point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
- Test point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+Tests point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
-note: Adding a new test
- Add a function that is named `test_` and takes at least the following arguments:
+Note: Adding a new test Add a function that is named `test_` and
+takes at least the following arguments.
- - blockchain_test | state_test
- - pre
- - tx
- - post
+Required arguments:
+- `blockchain_test` or `state_test`
+- `pre`
+- `tx`
+- `post`
- The following arguments *need* to be parametrized or the test will not be generated:
+The following arguments *need* to be parametrized or the test will not be
+generated:
- - versioned_hash
- - kzg_commitment
- - z
- - y
- - kzg_proof
- - result
+- `versioned_hash`
+- `kzg_commitment`
+- `z`
+- `y`
+- `kzg_proof`
+- `result`
- These values correspond to a single call of the precompile, and `result` refers to
- whether the call should succeed or fail.
+These values correspond to a single call of the precompile, and `result`
+refers to whether the call should succeed or fail.
- All other `pytest.fixture` fixtures can be parametrized to generate new combinations and test
- cases.
-
-""" # noqa: E501
+All other `pytest.fixture` fixtures can be parametrized to generate new
+combinations and test cases.
+"""
import glob
import json
@@ -53,7 +53,7 @@
TransactionReceipt,
call_return_code,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .common import INF_POINT, Z_Y_VALID_ENDIANNESS, Z
from .spec import Spec, ref_spec_4844
@@ -110,8 +110,8 @@ def call_gas() -> int:
"""
Amount of gas to pass to the precompile.
- Defaults to Spec.POINT_EVALUATION_PRECOMPILE_GAS, but can be parametrized to
- test different amounts.
+ Defaults to Spec.POINT_EVALUATION_PRECOMPILE_GAS, but can be parametrized
+ to test different amounts.
"""
return Spec.POINT_EVALUATION_PRECOMPILE_GAS
@@ -144,7 +144,8 @@ def precompile_caller_code(call_opcode: Op, call_gas: int) -> Bytecode:
precompile_caller_code = Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE)
precompile_caller_code += Op.SSTORE(
key_call_return_code,
- call_opcode( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501
+ # https://github.com/ethereum/execution-spec-tests/issues/348
+ call_opcode( # type: ignore
gas=call_gas,
address=Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS,
args_offset=0x00,
@@ -226,8 +227,8 @@ def post(
precompile_input: bytes,
) -> Dict:
"""
- Prepare expected post for each test, depending on the success or
- failure of the precompile call.
+ Prepare expected post for each test, depending on the success or failure of
+ the precompile call.
"""
expected_storage: Storage.StorageDictType = {}
# CALL operation return code
@@ -291,8 +292,9 @@ def test_valid_inputs(
"""
Test valid sanity precompile calls that are expected to succeed.
- - `kzg_commitment` and `kzg_proof` are set to values such that `p(z)==0` for all values of `z`,
- hence `y` is tested to be zero, and call to be successful.
+ - `kzg_commitment` and `kzg_proof` are set to values such that `p(z)==0`
+ for all values of `z`, hence `y` is tested to be zero, and call to be
+ successful.
"""
state_test(
env=Environment(),
@@ -348,7 +350,8 @@ def test_invalid_inputs(
- Correct proof, commitment, z and y, but incorrect lengths
- Null inputs
- Zero inputs
- - Correct proof, commitment, z and y, but incorrect version versioned hash
+ - Correct proof, commitment, z and y, but incorrect version versioned
+ hash
"""
state_test(
env=Environment(),
@@ -425,8 +428,8 @@ def get_point_evaluation_test_files_in_directory(path: str) -> list[str]:
def all_external_vectors() -> List:
"""
- Test for the Point Evaluation Precompile from external sources,
- contained in ./point_evaluation_vectors/.
+ Test for the Point Evaluation Precompile from external sources, contained
+ in ./point_evaluation_vectors/.
"""
test_cases = []
@@ -446,6 +449,7 @@ def all_external_vectors() -> List:
)
@pytest.mark.parametrize("versioned_hash", [None])
@pytest.mark.valid_from("Cancun")
+@pytest.mark.slow()
def test_external_vectors(
state_test: StateTestFiller,
pre: Alloc,
@@ -453,7 +457,8 @@ def test_external_vectors(
post: Dict,
):
"""
- Test precompile calls using external test vectors compiled from different sources.
+ Test precompile calls using external test vectors compiled from different
+ sources.
- `go_kzg_4844_verify_kzg_proof.json`: test vectors from the
[go-kzg-4844](https://github.com/crate-crypto/go-kzg-4844) repository.
@@ -531,16 +536,17 @@ def test_tx_entry_point(
proof_correct: bool,
):
"""
- Test calling the Point Evaluation Precompile directly as
- transaction entry point, and measure the gas consumption.
+ Test calling the Point Evaluation Precompile directly as transaction entry
+ point, and measure the gas consumption.
- - Using `gas_limit` with exact necessary gas, insufficient gas and extra gas.
+ - Using `gas_limit` with exact necessary gas, insufficient gas and extra
+ gas.
- Using correct and incorrect proofs
"""
sender = pre.fund_eoa()
- # Starting from EIP-7623, we need to use an access list to raise the intrinsic gas cost to be
- # above the floor data cost.
+ # Starting from EIP-7623, we need to use an access list to raise the
+ # intrinsic gas cost to be above the floor data cost.
access_list = [AccessList(address=Address(i), storage_keys=[]) for i in range(1, 10)]
# Gas is appended the intrinsic gas cost of the transaction
@@ -614,7 +620,9 @@ def test_precompile_before_fork(
tx: Transaction,
precompile_caller_address: Address,
):
- """Test calling the Point Evaluation Precompile before the appropriate fork."""
+ """
+ Test calling the Point Evaluation Precompile before the appropriate fork.
+ """
post = {
precompile_caller_address: Account(
storage={1: 1},
@@ -667,7 +675,9 @@ def test_precompile_during_fork(
precompile_input: bytes,
sender: EOA,
):
- """Test calling the Point Evaluation Precompile during the appropriate fork."""
+ """
+ Test calling the Point Evaluation Precompile during the appropriate fork.
+ """
# Blocks before fork
blocks = [
Block(
@@ -700,7 +710,7 @@ def test_precompile_during_fork(
post = {
precompile_caller_address: Account(
- storage={b: 1 for b in range(1, len(PRE_FORK_BLOCK_RANGE) + 1)},
+ storage=dict.fromkeys(range(1, len(PRE_FORK_BLOCK_RANGE) + 1), 1),
# Only the call in the last block's tx fails; storage 0 by default.
),
Address(Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS): Account(
diff --git a/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py b/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py
index 22ff6476c0..f8eb3d96f2 100644
--- a/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py
+++ b/tests/eest/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py
@@ -1,8 +1,9 @@
"""
-abstract: Tests gas usage on point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844)
- Test gas usage on point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+Tests gas usage on point evaluation precompile for EIP-4844.
-""" # noqa: E501
+Tests gas usage on point evaluation precompile for
+[EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).
+"""
from typing import Dict, Literal
@@ -20,7 +21,7 @@
Transaction,
ceiling_division,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .common import INF_POINT, Z
from .spec import Spec, ref_spec_4844
@@ -103,7 +104,8 @@ def precompile_caller_code(
+ copy_opcode_cost(fork, len(precompile_input))
)
if call_type == Op.CALL or call_type == Op.CALLCODE:
- precompile_caller_code += call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501
+ # https://github.com/ethereum/execution-spec-tests/issues/348
+ precompile_caller_code += call_type( # type: ignore
call_gas,
Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS,
0x00,
@@ -115,7 +117,8 @@ def precompile_caller_code(
overhead_cost += (push_operations_cost * 6) + (calldatasize_cost * 1)
elif call_type == Op.DELEGATECALL or call_type == Op.STATICCALL:
# Delegatecall and staticcall use one less argument
- precompile_caller_code += call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501
+ # https://github.com/ethereum/execution-spec-tests/issues/348
+ precompile_caller_code += call_type( # type: ignore
call_gas,
Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS,
0x00,
@@ -163,8 +166,8 @@ def post(
call_gas: int,
) -> Dict:
"""
- Prepare expected post for each test, depending on the success or
- failure of the precompile call and the gas usage.
+ Prepare expected post for each test, depending on the success or failure of
+ the precompile call and the gas usage.
"""
if proof == "correct":
expected_gas_usage = (
@@ -205,11 +208,12 @@ def test_point_evaluation_precompile_gas_usage(
post: Dict,
):
"""
- Test point evaluation precompile gas usage under different call contexts and gas limits.
+ Test point evaluation precompile gas usage under different call contexts
+ and gas limits.
- - Test using all call types (CALL, DELEGATECALL, CALLCODE, STATICCALL)
- - Test using different gas limits (exact gas, insufficient gas, extra gas)
- - Test using correct and incorrect proofs
+ - Test using all call types (CALL, DELEGATECALL, CALLCODE, STATICCALL) -
+ Test using different gas limits (exact gas, insufficient gas, extra gas) -
+ Test using correct and incorrect proofs
"""
state_test(
env=Environment(),
diff --git a/tests/eest/cancun/eip5656_mcopy/common.py b/tests/eest/cancun/eip5656_mcopy/common.py
index 1c975f4f84..a4aef625ca 100644
--- a/tests/eest/cancun/eip5656_mcopy/common.py
+++ b/tests/eest/cancun/eip5656_mcopy/common.py
@@ -1,7 +1,7 @@
"""
-Common procedures to test
-[EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656).
-""" # noqa: E501
+Common procedures to test [EIP-5656: MCOPY - Memory copying
+instruction](https://eips.ethereum.org/EIPS/eip-5656).
+"""
from copy import copy
@@ -16,7 +16,8 @@ def mcopy(*, src: int, dest: int, length: int, memory: bytes) -> bytes:
res = bytearray(copy(memory))
- # If the destination or source are larger than the memory, we need to extend the memory
+ # If the destination or source are larger than the memory, we need to
+ # extend the memory
max_byte_index = max(src, dest) + length
if max_byte_index > len(memory):
res.extend(b"\x00" * (max_byte_index - len(memory)))
diff --git a/tests/eest/cancun/eip5656_mcopy/test_mcopy.py b/tests/eest/cancun/eip5656_mcopy/test_mcopy.py
index cd1fdda802..0ad3967960 100644
--- a/tests/eest/cancun/eip5656_mcopy/test_mcopy.py
+++ b/tests/eest/cancun/eip5656_mcopy/test_mcopy.py
@@ -1,8 +1,6 @@
"""
-abstract: Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656)
- Test copy operations of [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656).
-
-""" # noqa: E501
+Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656).
+"""
from typing import Mapping
@@ -54,8 +52,8 @@ def code_bytecode(
code_storage: Storage,
) -> Bytecode:
"""
- Prepare bytecode and storage for the test, based on the starting memory and the final
- memory that resulted from the copy.
+ Prepare bytecode and storage for the test, based on the starting memory and
+ the final memory that resulted from the copy.
"""
bytecode = Bytecode()
@@ -90,8 +88,8 @@ def code_bytecode(
Op.MLOAD(w * 0x20),
)
- # If the memory was extended beyond the initial range, store the last word of the resulting
- # memory into storage too
+ # If the memory was extended beyond the initial range, store the last word
+ # of the resulting memory into storage too
if len(final_memory) > len(initial_memory):
last_word = ceiling_division(len(final_memory), 0x20) - 1
bytecode += Op.SSTORE(
@@ -187,7 +185,8 @@ def test_valid_mcopy_operations(
tx: Transaction,
):
"""
- Perform MCOPY operations using different offsets and lengths:
+ Perform MCOPY operations using different offsets and lengths.
+
- Zero inputs
- Memory rewrites (copy from and to the same location)
- Memory overwrites (copy from and to different locations)
@@ -214,7 +213,10 @@ def test_mcopy_on_empty_memory(
post: Mapping[str, Account],
tx: Transaction,
):
- """Perform MCOPY operations on an empty memory, using different offsets and lengths."""
+ """
+ Perform MCOPY operations on an empty memory, using different offsets and
+ lengths.
+ """
state_test(
env=Environment(),
pre=pre,
diff --git a/tests/eest/cancun/eip5656_mcopy/test_mcopy_contexts.py b/tests/eest/cancun/eip5656_mcopy/test_mcopy_contexts.py
index 8504912809..33dcc5e3c7 100644
--- a/tests/eest/cancun/eip5656_mcopy/test_mcopy_contexts.py
+++ b/tests/eest/cancun/eip5656_mcopy/test_mcopy_contexts.py
@@ -1,8 +1,8 @@
"""
-abstract: Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656)
- Test memory copy under different call contexts [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656).
+Test memory copy under different call contexts.
-""" # noqa: E501
+Tests for [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656).
+"""
from itertools import cycle, islice
from typing import Mapping
@@ -39,8 +39,8 @@ def callee_bytecode(
call_opcode: Op,
) -> Bytecode:
"""
- Callee simply performs mcopy operations that should not have any effect on the
- caller context.
+ Callee simply performs mcopy operations that should not have any effect on
+ the caller context.
"""
bytecode = Bytecode()
@@ -76,7 +76,8 @@ def initial_memory(
ret = bytes(list(islice(cycle(range(0x01, 0x100)), initial_memory_length)))
if call_opcode in [Op.CREATE, Op.CREATE2]:
- # We also need to put the callee_bytecode as initcode in memory for create operations
+ # We also need to put the callee_bytecode as initcode in memory for
+ # create operations
ret = bytes(callee_bytecode) + ret[len(callee_bytecode) :]
assert len(ret) == initial_memory_length
@@ -97,8 +98,8 @@ def caller_bytecode(
caller_storage: Storage,
) -> Bytecode:
"""
- Prepare bytecode and storage for the test, based on the starting memory and the final
- memory that resulted from the copy.
+ Prepare bytecode and storage for the test, based on the starting memory and
+ the final memory that resulted from the copy.
"""
bytecode = Bytecode()
@@ -116,8 +117,8 @@ def caller_bytecode(
bytecode += Op.SSTORE(100_000, Op.MSIZE())
caller_storage[100_000] = ceiling_division(len(initial_memory), 0x20) * 0x20
- # Store all memory in the initial range to verify the MCOPY in the subcall did not affect
- # this level's memory
+ # Store all memory in the initial range to verify the MCOPY in the subcall
+ # did not affect this level's memory
for w in range(0, len(initial_memory) // 0x20):
bytecode += Op.SSTORE(w, Op.MLOAD(w * 0x20))
caller_storage[w] = initial_memory[w * 0x20 : w * 0x20 + 0x20]
@@ -171,8 +172,8 @@ def test_no_memory_corruption_on_upper_call_stack_levels(
tx: Transaction,
):
"""
- Perform a subcall with any of the following opcodes, which uses MCOPY during its execution,
- and verify that the caller's memory is unaffected.
+ Perform a subcall with any of the following opcodes, which uses MCOPY
+ during its execution, and verify that the caller's memory is unaffected.
"""
state_test(
env=Environment(),
@@ -197,8 +198,8 @@ def test_no_memory_corruption_on_upper_create_stack_levels(
tx: Transaction,
):
"""
- Perform a subcall with any of the following opcodes, which uses MCOPY during its execution,
- and verify that the caller's memory is unaffected:
+ Perform a subcall with any of the following opcodes, which uses MCOPY
+ during its execution, and verify that the caller's memory is unaffected:
- `CREATE`
- `CREATE2`.
diff --git a/tests/eest/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py b/tests/eest/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py
index 639d007542..6a9801d009 100644
--- a/tests/eest/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py
+++ b/tests/eest/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py
@@ -1,9 +1,10 @@
"""
-abstract: Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656)
- Test copy operations of [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656)
- that produce a memory expansion, and potentially an out-of-gas error.
+Test MCOPY with memory expansion and potential OOG errors.
-""" # noqa: E501
+Test copy operations of [EIP-5656: MCOPY - Memory copying
+instruction](https://eips.ethereum.org/EIPS/eip-5656) that produce
+a memory expansion, and potentially an out-of-gas error.
+"""
import itertools
from typing import List, Mapping
@@ -74,11 +75,11 @@ def call_exact_cost(
tx_access_list: List[AccessList],
) -> int:
"""
- Return the exact cost of the subcall, based on the initial memory and the length of the
- copy.
+ Return the exact cost of the subcall, based on the initial memory and the
+ length of the copy.
"""
- # Starting from EIP-7623, we need to use an access list to raise the intrinsic gas cost to be
- # above the floor data cost.
+ # Starting from EIP-7623, we need to use an access list to raise the
+ # intrinsic gas cost to be above the floor data cost.
cost_memory_bytes = fork.memory_expansion_gas_calculator()
gas_costs = fork.gas_costs()
tx_intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
@@ -218,7 +219,10 @@ def test_mcopy_memory_expansion(
post: Mapping[str, Account],
tx: Transaction,
):
- """Perform MCOPY operations that expand the memory, and verify the gas it costs to do so."""
+ """
+ Perform MCOPY operations that expand the memory, and verify the gas it
+ costs to do so.
+ """
state_test(
env=env,
pre=pre,
@@ -279,8 +283,8 @@ def test_mcopy_huge_memory_expansion(
tx: Transaction,
):
"""
- Perform MCOPY operations that expand the memory by huge amounts, and verify that it correctly
- runs out of gas.
+ Perform MCOPY operations that expand the memory by huge amounts, and verify
+ that it correctly runs out of gas.
"""
state_test(
env=env,
diff --git a/tests/eest/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py b/tests/eest/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py
index 3c40ad69d6..d46db3d650 100644
--- a/tests/eest/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py
+++ b/tests/eest/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py
@@ -21,7 +21,7 @@
Transaction,
compute_create2_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-6780.md"
REFERENCE_SPEC_VERSION = "1b6a0e94cc47e859b9866e570391cf37dc55059a"
@@ -51,20 +51,26 @@ def test_dynamic_create2_selfdestruct_collision(
"""
Dynamic Create2->Suicide->Create2 collision scenario.
- Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys,
- then on a different call, in the same tx, perform a self-destruct.
+ Perform a CREATE2, make sure that the initcode sets at least a couple of
+ storage keys, then on a different call, in the same tx, perform a
+ self-destruct.
Then:
- a) on the same tx, attempt to recreate the contract <=== Covered in this test
- 1) and create2 contract already in the state
- 2) and create2 contract is not in the state
- b) on a different tx, attempt to recreate the contract
- Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys,
- then in a different tx, perform a self-destruct.
+ a) on the same tx, attempt to recreate the contract
+ -> Covered in this test
+ 1) and create2 contract already in the state
+ 2) and create2 contract is not in the state
+ b) on a different tx, attempt to recreate the contract
+
+ Perform a CREATE2, make sure that the initcode sets at least a couple
+ of storage keys, then in a different tx, perform a self-destruct.
+
Then:
- a) on the same tx, attempt to recreate the contract
- b) on a different tx, attempt to recreate the contract
- Verify that the test case described in
- https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06+Mainnet+Halting+Event
+ a) on the same tx, attempt to recreate the contract
+ b) on a different tx, attempt to recreate the contract
+
+ Check the test case described in
+ https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/
+ 22156575/2024-01-06+Mainnet+Halting+Event
"""
assert call_create2_contract_in_between or call_create2_contract_at_the_end, "invalid test"
@@ -79,7 +85,8 @@ def test_dynamic_create2_selfdestruct_collision(
create2_salt = 1
# Create EOA for sendall destination (receives selfdestruct funds)
- sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct calls
+ sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct
+ # calls
# Create storage contract that will be called during initialization
address_create2_storage = pre.deploy_contract(
@@ -131,7 +138,8 @@ def test_dynamic_create2_selfdestruct_collision(
+ Op.CALL(100000, address_code, 0, 0, 0, 0, 0)
# Call to the created account to trigger selfdestruct
+ Op.CALL(100000, call_address_in_between, first_call_value, 0, 0, 0, 0)
- # Make a subcall that do CREATE2 collision and returns its address as the result
+ # Make a subcall that do CREATE2 collision and returns its address as
+ # the result
+ Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
+ Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32)
+ Op.SSTORE(
@@ -149,7 +157,8 @@ def test_dynamic_create2_selfdestruct_collision(
sender = pre.fund_eoa(7000000000000000000)
if create2_dest_already_in_state:
- # Create2 address already in the state, e.g. deployed in a previous block
+ # Create2 address already in the state, e.g. deployed in a previous
+ # block
pre[create2_address] = Account(
balance=pre_existing_create2_balance,
nonce=1,
@@ -182,7 +191,8 @@ def test_dynamic_create2_selfdestruct_collision(
}
)
- # Calculate the destination account expected balance for the selfdestruct/sendall calls
+ # Calculate the destination account expected balance for the
+ # selfdestruct/sendall calls
sendall_destination_balance = (
pre_existing_create2_balance if create2_dest_already_in_state else first_create2_value
)
@@ -224,20 +234,28 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
"""
Dynamic Create2->Suicide->Create2 collision scenario.
- Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys,
- then on a different call, in the same tx, perform a self-destruct.
+ Perform a CREATE2, make sure that the initcode sets at least a couple of
+ storage keys, then on a different call, in the same tx, perform a
+ self-destruct.
+
Then:
- a) on the same tx, attempt to recreate the contract
- 1) and create2 contract already in the state
- 2) and create2 contract is not in the state
- b) on a different tx, attempt to recreate the contract <=== Covered in this test
- Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys,
- then in a different tx, perform a self-destruct.
+ a) on the same tx, attempt to recreate the contract
+ 1) and create2 contract already in the state
+ 2) and create2 contract is not in the state
+ b) on a different tx, attempt to recreate the contract
+ -> Covered in this test
+
+ Perform a CREATE2, make sure that the initcode sets at
+ least a couple of storage keys, then in a different tx, perform a
+ self-destruct.
+
Then:
- a) on the same tx, attempt to recreate the contract
- b) on a different tx, attempt to recreate the contract
- Verify that the test case described in
- https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06+Mainnet+Halting+Event
+ a) on the same tx, attempt to recreate the contract
+ b) on a different tx, attempt to recreate the contract
+
+ Check the test case described in
+ https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06
+ +Mainnet+Halting+Event
"""
# assert call_create2_contract_at_the_end, "invalid test"
@@ -252,7 +270,8 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
create2_salt = 1
# Create EOA for sendall destination (receives selfdestruct funds)
- sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct calls
+ sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct
+ # calls
# Create storage contract that will be called during initialization
address_create2_storage = pre.deploy_contract(
@@ -311,7 +330,8 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
# Create the second contract that performs the second transaction
address_to_second = pre.deploy_contract(
code=Op.JUMPDEST()
- # Make a subcall that do CREATE2 collision and returns its address as the result
+ # Make a subcall that do CREATE2 collision and returns its address as
+ # the result
+ Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
+ Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32)
+ Op.SSTORE(
@@ -329,7 +349,8 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
sender = pre.fund_eoa(7000000000000000000)
if create2_dest_already_in_state:
- # Create2 address already in the state, e.g. deployed in a previous block
+ # Create2 address already in the state, e.g. deployed in a previous
+ # block
pre[create2_address] = Account(
balance=pre_existing_create2_balance,
nonce=1,
@@ -350,8 +371,9 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
)
)
- # after Cancun Create2 initcode is only executed if the contract did not already exist
- # and before it will always be executed as the first tx deletes the account
+ # after Cancun Create2 initcode is only executed if the contract did not
+ # already exist and before it will always be executed as the first tx
+ # deletes the account
post[address_create2_storage] = Account(
storage={
create2_constructor_worked: int(fork < Cancun or not create2_dest_already_in_state)
@@ -369,9 +391,12 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
post[address_to_second] = Account(
storage={
code_worked: 0x01,
- # Second create2 will not collide before Cancun as the first tx calls selfdestruct
- # After cancun it will collide only if create2_dest_already_in_state otherwise the
- # first tx creates and deletes it
+ # Second create2 will not collide before Cancun as the first tx
+ # calls selfdestruct
+ #
+ # After cancun it will collide only if
+ # create2_dest_already_in_state otherwise the first tx creates and
+ # deletes it
second_create2_result: (
(0x00 if create2_dest_already_in_state else create2_address)
if fork >= Cancun
@@ -380,14 +405,16 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
}
)
- # Calculate the destination account expected balance for the selfdestruct/sendall calls
+ # Calculate the destination account expected balance for the
+ # selfdestruct/sendall calls
sendall_destination_balance = 0
if create2_dest_already_in_state:
sendall_destination_balance += pre_existing_create2_balance
if fork >= Cancun:
- # first create2 fails, but first calls ok. the account is not removed on cancun
- # therefore with the second create2 it is not successful
+ # first create2 fails, but first calls ok. the account is not
+ # removed on cancun therefore with the second create2 it is not
+ # successful
sendall_destination_balance += first_call_value
else:
# first create2 fails, first calls totally removes the account
@@ -396,8 +423,9 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions(
if call_create2_contract_at_the_end:
sendall_destination_balance += second_create2_value
else:
- # if no account in the state, first create2 successful, first call successful and removes
- # because it is removed in the next transaction second create2 successful
+ # if no account in the state, first create2 successful, first call
+ # successful and removes because it is removed in the next transaction
+ # second create2 successful
sendall_destination_balance = first_create2_value + first_call_value
if call_create2_contract_at_the_end:
sendall_destination_balance += second_create2_value
@@ -448,20 +476,28 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx(
blockchain_test: BlockchainTestFiller,
):
"""
- Dynamic Create2->Suicide->Create2 collision scenario over multiple transactions.
+ Dynamic Create2->Suicide->Create2 collision scenario over multiple
+ transactions.
- Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys,
- then on a different call, in the same or different tx but same block, perform a self-destruct.
+ Perform a CREATE2, make sure that the initcode sets at least a couple of
+ storage keys, then on a different call, in the same or different tx but
+ same block, perform a self-destruct.
Then:
- a) on the same tx, attempt to recreate the contract
- b) on a different tx, attempt to recreate the contract
- Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys,
- then in a different tx, perform a self-destruct.
+ a) on the same tx, attempt to recreate the contract
+ b) on a different tx, attempt to recreate the contract
+
+ Perform a CREATE2, make sure that the initcode sets at least a
+ couple of storage keys, then in a different tx, perform a self-destruct.
+
Then:
- a) on the same tx, attempt to recreate the contract <=== Covered in this test
- b) on a different tx, attempt to recreate the contract <=== Covered in this test
- Verify that the test case described in
- https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06+Mainnet+Halting+Event
+ a) on the same tx, attempt to recreate the contract
+ -> Covered in this test
+ b) on a different tx, attempt to recreate the contract
+ -> Covered in this test
+
+ Check the test case described in
+ https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06
+ +Mainnet+Halting+Event
"""
if recreate_on_first_tx:
assert selfdestruct_on_first_tx, "invalid test"
@@ -477,7 +513,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx(
create2_salt = 1
# Create EOA for sendall destination (receives selfdestruct funds)
- sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct calls
+ sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct
+ # calls
# Create storage contract that will be called during initialization
address_create2_storage = pre.deploy_contract(
@@ -540,7 +577,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx(
if recreate_on_first_tx:
first_tx_code += (
- # Make a subcall that do CREATE2 collision and returns its address as the result
+ # Make a subcall that do CREATE2 collision and returns its address
+ # as the result
Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
+ Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32)
+ Op.SSTORE(
@@ -551,7 +589,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx(
else:
second_tx_code += (
- # Make a subcall that do CREATE2 collision and returns its address as the result
+ # Make a subcall that do CREATE2 collision and returns its address
+ # as the result
Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
+ Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32)
+ Op.SSTORE(
@@ -566,7 +605,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx(
first_tx_code += Op.SSTORE(part_1_worked, 1)
second_tx_code += Op.SSTORE(part_2_worked, 1)
- # Create the main contract that uses conditional logic to handle both transactions
+ # Create the main contract that uses conditional logic to handle both
+ # transactions
address_to = pre.deploy_contract(
code=Conditional(
# Depending on the tx, execute the first or second tx code
@@ -585,8 +625,9 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx(
# Create2 address only exists if it was pre-existing and after cancun
account_will_exist_with_code = not selfdestruct_on_first_tx and fork >= Cancun
- # If the contract is self-destructed and we also attempt to recreate it on the first tx,
- # the second call on the second tx will only place balance in the account
+ # If the contract is self-destructed and we also attempt to recreate it on
+ # the first tx, the second call on the second tx will only place balance in
+ # the account
account_will_exist_with_balance = selfdestruct_on_first_tx and recreate_on_first_tx
post[create2_address] = (
@@ -609,14 +650,16 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx(
part_2_worked: 0x01,
# First create2 always works
first_create2_result: create2_address,
- # Second create2 only works if we successfully self-destructed on the first tx
+ # Second create2 only works if we successfully self-destructed on
+ # the first tx
second_create2_result: (
create2_address if selfdestruct_on_first_tx and not recreate_on_first_tx else 0x00
),
}
)
- # Calculate the destination account expected balance for the selfdestruct/sendall calls
+ # Calculate the destination account expected balance for the
+ # selfdestruct/sendall calls
sendall_destination_balance = first_create2_value + first_call_value
if not account_will_exist_with_balance:
diff --git a/tests/eest/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py b/tests/eest/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py
index 40cc682480..36d13853c4 100644
--- a/tests/eest/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py
+++ b/tests/eest/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py
@@ -1,7 +1,4 @@
-"""
-Suicide scenario requested test
-https://github.com/ethereum/tests/issues/1325.
-"""
+"""Suicide scenario requested test https://github.com/ethereum/tests/issues/1325."""
from typing import SupportsBytes
@@ -18,7 +15,7 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-6780.md"
REFERENCE_SPEC_VERSION = "1b6a0e94cc47e859b9866e570391cf37dc55059a"
@@ -163,12 +160,14 @@ def test_reentrancy_selfdestruct_revert(
if first_suicide in [Op.CALLCODE, Op.DELEGATECALL]:
if fork >= Cancun:
- # On Cancun even callcode/delegatecall does not remove the account, so the value remain
+ # On Cancun even callcode/delegatecall does not remove the account,
+ # so the value remain
post[executor_contract_address] = Account(
storage={
0x01: 0x01, # First call to contract S->suicide success
0x02: 0x00, # Second call to contract S->suicide reverted
- 0x03: 16, # Reverted value to check that revert really worked
+ 0x03: 16, # Reverted value to check that revert really
+ # worked
},
)
else:
@@ -184,7 +183,8 @@ def test_reentrancy_selfdestruct_revert(
balance=executor_contract_init_balance,
)
- # On Cancun suicide no longer destroys the account from state, just cleans the balance
+ # On Cancun suicide no longer destroys the account from state, just cleans
+ # the balance
if first_suicide in [Op.CALL]:
post[executor_contract_address] = Account(
storage={
@@ -194,7 +194,8 @@ def test_reentrancy_selfdestruct_revert(
},
)
if fork >= Cancun:
- # On Cancun suicide does not remove the account, just sends the balance
+ # On Cancun suicide does not remove the account, just sends the
+ # balance
post[selfdestruct_contract_address] = Account(
balance=0, code=selfdestruct_contract_bytecode, storage={}
)
diff --git a/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct.py b/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct.py
index c38220fe00..79daddd8d2 100644
--- a/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct.py
+++ b/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct.py
@@ -1,8 +1,8 @@
"""
-abstract: Tests [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780)
- Tests for [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780).
+SELFDESTRUCT only in same transaction tests.
-""" # noqa: E501
+Tests for [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780).
+"""
from itertools import cycle
from typing import Dict, List
@@ -18,6 +18,7 @@
Block,
BlockchainTestFiller,
Bytecode,
+ Conditional,
Hash,
Initcode,
StateTestFiller,
@@ -25,8 +26,7 @@
Transaction,
compute_create_address,
)
-from ethereum_test_tools.code.generators import Conditional
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-6780.md"
REFERENCE_SPEC_VERSION = "1b6a0e94cc47e859b9866e570391cf37dc55059a"
@@ -37,8 +37,9 @@
Address of a pre-existing contract that self-destructs.
"""
-# Sentinel value to indicate that the self-destructing contract address should be used, only for
-# use in `pytest.mark.parametrize`, not for use within the test method itself.
+# Sentinel value to indicate that the self-destructing contract address should
+# be used, only for use in `pytest.mark.parametrize`, not for use within the
+# test method itself.
SELF_ADDRESS = Address(0x01)
# Sentinel value to indicate that the contract should not self-destruct.
NO_SELFDESTRUCT = Address(0x00)
@@ -59,9 +60,11 @@ def sendall_recipient_addresses(request: pytest.FixtureRequest, pre: Alloc) -> L
"""
List of addresses that receive the SENDALL operation in any test.
- If the test case requires a pre-existing contract, it will be deployed here.
+ If the test case requires a pre-existing contract, it will be deployed
+ here.
- By default the list is a single pre-deployed contract that unconditionally sets storage.
+ By default the list is a single pre-deployed contract that unconditionally
+ sets storage.
"""
address_list = getattr(request, "param", [PRE_DEPLOY_CONTRACT_1])
deployed_contracts: Dict[str, Address] = {}
@@ -88,8 +91,8 @@ def selfdestruct_code_preset(
bytecode = Op.SSTORE(0, Op.ADD(Op.SLOAD(0), 1))
if len(sendall_recipient_addresses) != 1:
- # Load the recipient address from calldata, each test case needs to pass the addresses as
- # calldata
+ # Load the recipient address from calldata, each test case needs to
+ # pass the addresses as calldata
bytecode += Conditional(
# We avoid having the caller to give us our own address by checking
# against a constant that is a magic number
@@ -119,8 +122,8 @@ def selfdestruct_code(
sendall_recipient_addresses: List[Address],
) -> Bytecode:
"""
- Create default self-destructing bytecode,
- which can be modified by each test if necessary.
+ Create default self-destructing bytecode, which can be modified by each
+ test if necessary.
"""
return selfdestruct_code_preset(sendall_recipient_addresses=sendall_recipient_addresses)
@@ -190,19 +193,21 @@ def test_create_selfdestruct_same_tx(
selfdestruct_contract_initial_balance: int,
):
"""
- Use CREATE or CREATE2 to create a self-destructing contract, and call it in the same
- transaction.
+ Use CREATE or CREATE2 to create a self-destructing contract, and call it in
+ the same transaction.
Behavior should be the same before and after EIP-6780.
Test using:
- - Different send-all recipient addresses: single, multiple, including self
+ - Different send-all recipient addresses: single, multiple,
+ including self
- Different initial balances for the self-destructing contract
- Different opcodes: CREATE, CREATE2
"""
selfdestruct_contract_initcode = Initcode(deploy_code=selfdestruct_code)
initcode_copy_from_address = pre.deploy_contract(selfdestruct_contract_initcode)
- # Our entry point is an initcode that in turn creates a self-destructing contract
+ # Our entry point is an initcode that in turn creates a self-destructing
+ # contract
entry_code_storage = Storage()
# Bytecode used to create the contract, can be CREATE or CREATE2
@@ -225,9 +230,11 @@ def test_create_selfdestruct_same_tx(
)
selfdestruct_contract_current_balance = selfdestruct_contract_initial_balance
- # Entry code that will be executed, creates the contract and then calls it in the same tx
+ # Entry code that will be executed, creates the contract and then calls it
+ # in the same tx
entry_code = (
- # Initcode is already deployed at `initcode_copy_from_address`, so just copy it
+ # Initcode is already deployed at `initcode_copy_from_address`, so just
+ # copy it
Op.EXTCODECOPY(
initcode_copy_from_address,
0,
@@ -252,8 +259,8 @@ def test_create_selfdestruct_same_tx(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Call the self-destructing contract multiple times as required, increasing the wei sent each
- # time
+ # Call the self-destructing contract multiple times as required, increasing
+ # the wei sent each time
entry_code_balance = 0
for i, sendall_recipient in zip(range(call_times), cycle(sendall_recipient_addresses)):
entry_code += Op.MSTORE(0, sendall_recipient)
@@ -276,8 +283,9 @@ def test_create_selfdestruct_same_tx(
if sendall_recipient != selfdestruct_contract_address:
sendall_final_balances[sendall_recipient] += selfdestruct_contract_current_balance
- # Self-destructing contract must always have zero balance after the call because the
- # self-destruct always happens in the same transaction in this test
+ # Self-destructing contract must always have zero balance after the
+ # call because the self-destruct always happens in the same transaction
+ # in this test
selfdestruct_contract_current_balance = 0
entry_code += Op.SSTORE(
@@ -296,8 +304,8 @@ def test_create_selfdestruct_same_tx(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Lastly return zero so the entry point contract is created and we can retain the stored
- # values for verification.
+ # Lastly return zero so the entry point contract is created and we can
+ # retain the stored values for verification.
entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1)
tx = Transaction(
@@ -336,7 +344,8 @@ def test_self_destructing_initcode(
selfdestruct_code: Bytecode,
sendall_recipient_addresses: List[Address],
create_opcode: Op,
- call_times: int, # Number of times to call the self-destructing contract in the same tx
+ call_times: int, # Number of times to call the self-destructing contract
+ # in the same tx
selfdestruct_contract_initial_balance: int,
):
"""
@@ -347,10 +356,12 @@ def test_self_destructing_initcode(
Test using:
- Different initial balances for the self-destructing contract
- Different opcodes: CREATE, CREATE2
- - Different number of calls to the self-destructing contract in the same tx
+ - Different number of calls to the self-destructing contract in
+ the same tx
"""
initcode_copy_from_address = pre.deploy_contract(selfdestruct_code)
- # Our entry point is an initcode that in turn creates a self-destructing contract
+ # Our entry point is an initcode that in turn creates a self-destructing
+ # contract
entry_code_storage = Storage()
sendall_amount = 0
@@ -364,9 +375,11 @@ def test_self_destructing_initcode(
opcode=create_opcode,
)
- # Entry code that will be executed, creates the contract and then calls it in the same tx
+ # Entry code that will be executed, creates the contract and then calls it
+ # in the same tx
entry_code = (
- # Initcode is already deployed at `initcode_copy_from_address`, so just copy it
+ # Initcode is already deployed at `initcode_copy_from_address`, so just
+ # copy it
Op.EXTCODECOPY(
initcode_copy_from_address,
0,
@@ -391,8 +404,8 @@ def test_self_destructing_initcode(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Call the self-destructing contract multiple times as required, increasing the wei sent each
- # time
+ # Call the self-destructing contract multiple times as required, increasing
+ # the wei sent each time
entry_code_balance = 0
for i in range(call_times):
entry_code += Op.SSTORE(
@@ -414,8 +427,8 @@ def test_self_destructing_initcode(
Op.BALANCE(selfdestruct_contract_address),
)
- # Lastly return zero so the entry point contract is created and we can retain the stored
- # values for verification.
+ # Lastly return zero so the entry point contract is created and we can
+ # retain the stored values for verification.
entry_code += Op.RETURN(max(len(selfdestruct_code), 32), 1)
if selfdestruct_contract_initial_balance > 0:
@@ -463,8 +476,8 @@ def test_self_destructing_initcode_create_tx(
Behavior should be the same before and after EIP-6780.
Test using:
- - Different initial balances for the self-destructing contract
- - Different transaction value amounts
+ - Different initial balances for the self-destructing contract
+ - Different transaction value amounts
"""
tx = Transaction(
sender=sender,
@@ -476,7 +489,8 @@ def test_self_destructing_initcode_create_tx(
selfdestruct_contract_address = tx.created_contract
pre.fund_address(selfdestruct_contract_address, selfdestruct_contract_initial_balance)
- # Our entry point is an initcode that in turn creates a self-destructing contract
+ # Our entry point is an initcode that in turn creates a self-destructing
+ # contract
sendall_amount = selfdestruct_contract_initial_balance + tx_value
post: Dict[Address, Account] = {
@@ -487,7 +501,8 @@ def test_self_destructing_initcode_create_tx(
state_test(pre=pre, post=post, tx=tx)
-@pytest.mark.parametrize("create_opcode", [Op.CREATE2]) # Can only recreate using CREATE2
+# Can only recreate using CREATE2
+@pytest.mark.parametrize("create_opcode", [Op.CREATE2])
@pytest.mark.parametrize(
"sendall_recipient_addresses",
[
@@ -514,18 +529,20 @@ def test_recreate_self_destructed_contract_different_txs(
selfdestruct_contract_initial_balance: int,
sendall_recipient_addresses: List[Address],
create_opcode: Op,
- recreate_times: int, # Number of times to recreate the contract in different transactions
- call_times: int, # Number of times to call the self-destructing contract in the same tx
+ # Number of times to recreate the contract in different transactions
+ recreate_times: int,
+ # Number of times to call the self-destructing contract in the same tx
+ call_times: int,
):
"""
- Test that a contract can be recreated after it has self-destructed, over the lapse
- of multiple transactions.
+ Test that a contract can be recreated after it has self-destructed, over
+ the lapse of multiple transactions.
Behavior should be the same before and after EIP-6780.
Test using:
- - Different initial balances for the self-destructing contract
- - Contract creating opcodes that are not CREATE
+ - Different initial balances for the self-destructing contract
+ - Contract creating opcodes that are not CREATE
"""
selfdestruct_contract_initcode = Initcode(deploy_code=selfdestruct_code)
initcode_copy_from_address = pre.deploy_contract(selfdestruct_contract_initcode)
@@ -538,7 +555,8 @@ def test_recreate_self_destructed_contract_different_txs(
# Entry code that will be executed, creates the contract and then calls it
entry_code = (
- # Initcode is already deployed at initcode_copy_from_address, so just copy it
+ # Initcode is already deployed at initcode_copy_from_address, so just
+ # copy it
Op.EXTCODECOPY(
initcode_copy_from_address,
0,
@@ -663,15 +681,17 @@ def test_selfdestruct_pre_existing(
call_times: int,
):
"""
- Test calling a previously created account that contains a selfdestruct, and verify its balance
- is sent to the destination address.
+ Test calling a previously created account that contains a selfdestruct, and
+ verify its balance is sent to the destination address.
- After EIP-6780, the balance should be sent to the send-all recipient address, similar to
- the behavior before the EIP, but the account is not deleted.
+ After EIP-6780, the balance should be sent to the send-all recipient
+ address, similar to the behavior before the EIP, but the account is not
+ deleted.
Test using:
- - Different send-all recipient addresses: single, multiple, including self
- - Different initial balances for the self-destructing contract
+ - Different send-all recipient addresses: single, multiple,
+ including self
+ - Different initial balances for the self-destructing contract
"""
selfdestruct_contract_address = pre.deploy_contract(
selfdestruct_code, balance=selfdestruct_contract_initial_balance
@@ -688,12 +708,12 @@ def test_selfdestruct_pre_existing(
)
selfdestruct_contract_current_balance = selfdestruct_contract_initial_balance
- # Entry code in this case will simply call the pre-existing self-destructing contract,
- # as many times as required
+ # Entry code in this case will simply call the pre-existing self-
+ # destructing contract, as many times as required
entry_code = Bytecode()
- # Call the self-destructing contract multiple times as required, increasing the wei sent each
- # time
+ # Call the self-destructing contract multiple times as required, increasing
+ # the wei sent each time
entry_code_balance = 0
for i, sendall_recipient in zip(range(call_times), cycle(sendall_recipient_addresses)):
entry_code += Op.MSTORE(0, sendall_recipient)
@@ -716,8 +736,9 @@ def test_selfdestruct_pre_existing(
if sendall_recipient != selfdestruct_contract_address:
sendall_final_balances[sendall_recipient] += selfdestruct_contract_current_balance
- # Balance is only kept by the self-destructing contract if we are sending to self and the
- # EIP is activated, otherwise the balance is destroyed
+ # Balance is only kept by the self-destructing contract if we are
+ # sending to self and the EIP is activated, otherwise the balance is
+ # destroyed
if sendall_recipient != selfdestruct_contract_address or not eip_enabled:
selfdestruct_contract_current_balance = 0
@@ -737,8 +758,8 @@ def test_selfdestruct_pre_existing(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Lastly return zero so the entry point contract is created and we can retain the stored
- # values for verification.
+ # Lastly return zero so the entry point contract is created and we can
+ # retain the stored values for verification.
entry_code += Op.RETURN(32, 1)
tx = Transaction(
@@ -787,8 +808,9 @@ def test_selfdestruct_created_same_block_different_tx(
call_times: int,
):
"""
- Test that if an account created in the same block that contains a selfdestruct is
- called, its balance is sent to the send-all address, but the account is not deleted.
+ Test that if an account created in the same block that contains a
+ selfdestruct is called, its balance is sent to the send-all address, but
+ the account is not deleted.
"""
selfdestruct_code = selfdestruct_code_preset(
sendall_recipient_addresses=sendall_recipient_addresses,
@@ -800,11 +822,11 @@ def test_selfdestruct_created_same_block_different_tx(
sendall_amount = selfdestruct_contract_initial_balance
entry_code = Bytecode()
- # Entry code in this case will simply call the pre-existing self-destructing contract,
- # as many times as required
+ # Entry code in this case will simply call the pre-existing self-
+ # destructing contract, as many times as required
- # Call the self-destructing contract multiple times as required, increasing the wei sent each
- # time
+ # Call the self-destructing contract multiple times as required, increasing
+ # the wei sent each time
entry_code_balance = 0
for i in range(call_times):
entry_code += Op.SSTORE(
@@ -838,8 +860,8 @@ def test_selfdestruct_created_same_block_different_tx(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Lastly return zero so the entry point contract is created and we can retain the stored
- # values for verification.
+ # Lastly return zero so the entry point contract is created and we can
+ # retain the stored values for verification.
entry_code += Op.RETURN(32, 1)
post: Dict[Address, Account] = {
@@ -890,15 +912,17 @@ def test_calling_from_new_contract_to_pre_existing_contract(
selfdestruct_contract_initial_balance: int,
):
"""
- Test that if an account created in the current transaction delegate-call a previously created
- account that executes self-destruct, the calling account is deleted.
+ Test that if an account created in the current transaction delegate-call a
+ previously created account that executes self-destruct, the calling account
+ is deleted.
"""
pre_existing_selfdestruct_address = pre.deploy_contract(
selfdestruct_code_preset(
sendall_recipient_addresses=sendall_recipient_addresses,
),
)
- # Our entry point is an initcode that in turn creates a self-destructing contract
+ # Our entry point is an initcode that in turn creates a self-destructing
+ # contract
entry_code_storage = Storage()
sendall_amount = 0
@@ -915,9 +939,11 @@ def test_calling_from_new_contract_to_pre_existing_contract(
# Bytecode used to create the contract, can be CREATE or CREATE2
create_bytecode = create_opcode(size=len(selfdestruct_contract_initcode))
- # Entry code that will be executed, creates the contract and then calls it in the same tx
+ # Entry code that will be executed, creates the contract and then calls it
+ # in the same tx
entry_code = (
- # Initcode is already deployed at `initcode_copy_from_address`, so just copy it
+ # Initcode is already deployed at `initcode_copy_from_address`, so just
+ # copy it
Op.EXTCODECOPY(
initcode_copy_from_address,
0,
@@ -942,8 +968,8 @@ def test_calling_from_new_contract_to_pre_existing_contract(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Call the self-destructing contract multiple times as required, increasing the wei sent each
- # time
+ # Call the self-destructing contract multiple times as required, increasing
+ # the wei sent each time
entry_code_balance = 0
for i in range(call_times):
entry_code += Op.SSTORE(
@@ -977,8 +1003,8 @@ def test_calling_from_new_contract_to_pre_existing_contract(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Lastly return zero so the entry point contract is created and we can retain the stored
- # values for verification.
+ # Lastly return zero so the entry point contract is created and we can
+ # retain the stored values for verification.
entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1)
if selfdestruct_contract_initial_balance > 0:
@@ -1025,9 +1051,9 @@ def test_calling_from_pre_existing_contract_to_new_contract(
pre_existing_contract_initial_balance: int,
):
"""
- Test that if an account created in the current transaction contains a self-destruct and is
- delegate-called by an account created before the current transaction, the calling account
- is not deleted.
+ Test that if an account created in the current transaction contains a
+ self-destruct and is delegate-called by an account created before the
+ current transaction, the calling account is not deleted.
"""
selfdestruct_contract_initcode = Initcode(deploy_code=selfdestruct_code)
initcode_copy_from_address = pre.deploy_contract(
@@ -1051,13 +1077,16 @@ def test_calling_from_pre_existing_contract_to_new_contract(
balance=pre_existing_contract_initial_balance,
)
- # Our entry point is an initcode that in turn creates a self-destructing contract
+ # Our entry point is an initcode that in turn creates a self-destructing
+ # contract
entry_code_storage = Storage()
sendall_amount = pre_existing_contract_initial_balance
- # Entry code that will be executed, creates the contract and then calls it in the same tx
+ # Entry code that will be executed, creates the contract and then calls it
+ # in the same tx
entry_code = (
- # Initcode is already deployed at `initcode_copy_from_address`, so just copy it
+ # Initcode is already deployed at `initcode_copy_from_address`, so just
+ # copy it
Op.EXTCODECOPY(
initcode_copy_from_address,
0,
@@ -1085,8 +1114,9 @@ def test_calling_from_pre_existing_contract_to_new_contract(
Op.EXTCODEHASH(caller_address),
)
- # Now instead of calling the newly created contract directly, we delegate call to it
- # from a pre-existing contract, and the contract must not self-destruct
+ # Now instead of calling the newly created contract directly, we delegate
+ # call to it from a pre-existing contract, and the contract must not self-
+ # destruct
entry_code_balance = selfdestruct_contract_initial_balance
for i in range(call_times):
entry_code += Op.SSTORE(
@@ -1120,8 +1150,8 @@ def test_calling_from_pre_existing_contract_to_new_contract(
Op.EXTCODEHASH(caller_address),
)
- # Lastly return zero so the entry point contract is created and we can retain the stored
- # values for verification.
+ # Lastly return zero so the entry point contract is created and we can
+ # retain the stored values for verification.
entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1)
tx = Transaction(
@@ -1177,8 +1207,9 @@ def test_create_selfdestruct_same_tx_increased_nonce(
selfdestruct_contract_initial_balance: int,
):
"""
- Verify that a contract can self-destruct if it was created in the same transaction, even when
- its nonce has been increased due to contract creation.
+ Verify that a contract can self-destruct if it was created in the same
+ transaction, even when its nonce has been increased due to contract
+ creation.
"""
initcode = Op.RETURN(0, 1)
selfdestruct_pre_bytecode = Op.MSTORE(0, Op.PUSH32(bytes(initcode))) + Op.POP(
@@ -1196,7 +1227,8 @@ def test_create_selfdestruct_same_tx_increased_nonce(
)
if selfdestruct_contract_initial_balance > 0:
pre.fund_address(selfdestruct_contract_address, selfdestruct_contract_initial_balance)
- # Our entry point is an initcode that in turn creates a self-destructing contract
+ # Our entry point is an initcode that in turn creates a self-destructing
+ # contract
entry_code_storage = Storage()
# Create a dict to record the expected final balances
@@ -1208,9 +1240,11 @@ def test_create_selfdestruct_same_tx_increased_nonce(
# Bytecode used to create the contract, can be CREATE or CREATE2
create_bytecode = create_opcode(size=len(selfdestruct_contract_initcode))
- # Entry code that will be executed, creates the contract and then calls it in the same tx
+ # Entry code that will be executed, creates the contract and then calls it
+ # in the same tx
entry_code = (
- # Initcode is already deployed at `initcode_copy_from_address`, so just copy it
+ # Initcode is already deployed at `initcode_copy_from_address`, so just
+ # copy it
Op.EXTCODECOPY(
initcode_copy_from_address,
0,
@@ -1235,8 +1269,8 @@ def test_create_selfdestruct_same_tx_increased_nonce(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Call the self-destructing contract multiple times as required, increasing the wei sent each
- # time
+ # Call the self-destructing contract multiple times as required, increasing
+ # the wei sent each time
entry_code_balance = 0
for i, sendall_recipient in zip(range(call_times), cycle(sendall_recipient_addresses)):
entry_code += Op.MSTORE(0, sendall_recipient)
@@ -1259,8 +1293,9 @@ def test_create_selfdestruct_same_tx_increased_nonce(
if sendall_recipient != selfdestruct_contract_address:
sendall_final_balances[sendall_recipient] += selfdestruct_contract_current_balance
- # Self-destructing contract must always have zero balance after the call because the
- # self-destruct always happens in the same transaction in this test
+ # Self-destructing contract must always have zero balance after the
+ # call because the self-destruct always happens in the same transaction
+ # in this test
selfdestruct_contract_current_balance = 0
entry_code += Op.SSTORE(
@@ -1279,8 +1314,8 @@ def test_create_selfdestruct_same_tx_increased_nonce(
Op.EXTCODEHASH(selfdestruct_contract_address),
)
- # Lastly return zero so the entry point contract is created and we can retain the stored
- # values for verification.
+ # Lastly return zero so the entry point contract is created and we can
+ # retain the stored values for verification.
entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1)
tx = Transaction(
@@ -1307,7 +1342,8 @@ def test_create_selfdestruct_same_tx_increased_nonce(
for address, balance in sendall_final_balances.items():
post[address] = Account(balance=balance, storage={0: 1})
- # Check the new contracts created from the self-destructing contract were correctly created.
+ # Check the new contracts created from the self-destructing contract were
+ # correctly created.
for address in [
compute_create_address(address=selfdestruct_contract_address, nonce=i + 1)
for i in range(call_times)
diff --git a/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py b/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py
index c13dfb8526..e42f98c6d1 100644
--- a/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py
+++ b/tests/eest/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py
@@ -1,4 +1,4 @@
-"""tests for selfdestruct interaction with revert."""
+"""Tests for selfdestruct interaction with revert."""
from typing import Dict
@@ -64,9 +64,10 @@ def recursive_revert_contract_code(
) -> Bytecode:
"""
Contract code that:
- Given selfdestructable contract A, transfer value to A and call A.selfdestruct.
- Then, recurse into a new call which transfers value to A,
- call A.selfdestruct, and reverts.
+ Given selfdestructable contract A, transfer value to A
+ and call A.selfdestruct.
+ Then, recurse into a new call which transfers value to A,
+ call A.selfdestruct, and reverts.
"""
# Common prefix for all three cases:
# case 1: selfdestruct_on_outer_call=1
@@ -244,7 +245,9 @@ def selfdestruct_with_transfer_contract_address(
selfdestruct_with_transfer_contract_code: Bytecode,
same_tx: bool,
) -> Address:
- """Contract address for contract that can selfdestruct and receive value."""
+ """
+ Contract address for contract that can selfdestruct and receive value.
+ """
if same_tx:
return compute_create_address(address=entry_code_address, nonce=1)
# We need to deploy the contract before.
@@ -303,7 +306,9 @@ def selfdestruct_with_transfer_initcode_copy_from_address(
pre: Alloc,
selfdestruct_with_transfer_contract_initcode: Bytecode,
) -> Address:
- """Address of a pre-existing contract we use to simply copy initcode from."""
+ """
+ Address of a pre-existing contract we use to simply copy initcode from.
+ """
addr = pre.deploy_contract(selfdestruct_with_transfer_contract_initcode)
return addr
@@ -340,11 +345,13 @@ def test_selfdestruct_created_in_same_tx_with_revert( # noqa SC200
):
"""
Given:
- Contract A which has methods to receive balance and selfdestruct, and was created in current tx
+ Contract A which has methods to receive balance and selfdestruct,
+ and was created in current tx.
+
Test the following call sequence:
- Transfer value to A and call A.selfdestruct.
- Recurse into a new call from transfers value to A, calls A.selfdestruct, and reverts.
- """ # noqa: E501
+ Transfer value to A and call A.selfdestruct. Recurse into a new call
+ from transfers value to A, calls A.selfdestruct, and reverts.
+ """
entry_code = Op.EXTCODECOPY(
selfdestruct_with_transfer_initcode_copy_from_address,
0,
@@ -357,7 +364,8 @@ def test_selfdestruct_created_in_same_tx_with_revert( # noqa SC200
Op.CREATE(
0,
0,
- len(bytes(selfdestruct_with_transfer_contract_initcode)), # Value # Offset
+ # Value Offset
+ len(bytes(selfdestruct_with_transfer_contract_initcode)),
),
)
@@ -400,7 +408,8 @@ def test_selfdestruct_created_in_same_tx_with_revert( # noqa SC200
code=selfdestruct_with_transfer_contract_code,
storage=Storage(
{
- # 2 value transfers (1 in outer call, 1 in reverted inner call)
+ # 2 value transfers (1 in outer call, 1 in reverted inner
+ # call)
0: 1, # type: ignore
# 1 selfdestruct in reverted inner call
1: 0, # type: ignore
@@ -454,8 +463,8 @@ def test_selfdestruct_not_created_in_same_tx_with_revert(
recursive_revert_contract_code: Bytecode,
):
"""
- Same test as selfdestruct_created_in_same_tx_with_revert except selfdestructable contract
- is pre-existing.
+ Same test as selfdestruct_created_in_same_tx_with_revert except
+ selfdestructable contract is pre-existing.
"""
entry_code = Op.CALL(
Op.GASLIMIT(),
@@ -477,7 +486,8 @@ def test_selfdestruct_not_created_in_same_tx_with_revert(
code=selfdestruct_with_transfer_contract_code,
storage=Storage(
{
- # 2 value transfers: 1 in outer call, 1 in reverted inner call
+ # 2 value transfers: 1 in outer call, 1 in reverted inner
+ # call
0: 1, # type: ignore
# 1 selfdestruct in reverted inner call
1: 1, # type: ignore
@@ -493,9 +503,11 @@ def test_selfdestruct_not_created_in_same_tx_with_revert(
code=selfdestruct_with_transfer_contract_code,
storage=Storage(
{
- # 2 value transfers: 1 in outer call, 1 in reverted inner call
+ # 2 value transfers:
+ # 1 in outer call, 1 in reverted inner call
0: 1, # type: ignore
- # 2 selfdestructs: 1 in outer call, 1 in reverted inner call # noqa SC100
+ # 2 selfdestructs:
+ # 1 in outer call, 1 in reverted inner call
1: 0, # type: ignore
}
),
diff --git a/tests/eest/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py b/tests/eest/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py
index 6f1f170ed8..0080477326 100644
--- a/tests/eest/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py
+++ b/tests/eest/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py
@@ -1,8 +1,8 @@
"""
-abstract: Tests [EIP-7516: BLOBBASEFEE opcode](https://eips.ethereum.org/EIPS/eip-7516)
- Test BLOBGASFEE opcode [EIP-7516: BLOBBASEFEE opcode](https://eips.ethereum.org/EIPS/eip-7516).
+BLOBBASEFEE opcode tests.
-""" # noqa: E501
+Tests for [EIP-7516: BLOBBASEFEE opcode](https://eips.ethereum.org/EIPS/eip-7516).
+"""
from itertools import count
@@ -52,18 +52,24 @@ def caller_code(
callee_address: Address,
) -> Bytecode:
"""Bytecode used to call the bytecode containing the BLOBBASEFEE opcode."""
- return Op.SSTORE(Op.NUMBER, Op.CALL(gas=call_gas, address=callee_address))
+ return Op.SSTORE(Op.SELFBALANCE, Op.CALL(gas=call_gas, address=callee_address))
@pytest.fixture
def caller_pre_storage() -> Storage:
- """Storage of the account containing the bytecode that calls the test contract."""
+ """
+ Storage of the account containing the bytecode that calls the test
+ contract.
+ """
return Storage()
@pytest.fixture
def caller_address(pre: Alloc, caller_code: Bytecode, caller_pre_storage) -> Address:
- """Address of the account containing the bytecode that calls the test contract."""
+ """
+ Address of the account containing the bytecode that calls the test
+ contract.
+ """
return pre.deploy_contract(caller_code)
@@ -77,6 +83,7 @@ def tx(pre: Alloc, caller_address: Address) -> Transaction:
sender=pre.fund_eoa(),
gas_limit=1_000_000,
to=caller_address,
+ value=1,
)
@@ -96,7 +103,10 @@ def test_blobbasefee_stack_overflow(
tx: Transaction,
call_fails: bool,
):
- """Tests that the BLOBBASEFEE opcode produces a stack overflow by using it repeatedly."""
+ """
+ Tests that the BLOBBASEFEE opcode produces a stack overflow by using it
+ repeatedly.
+ """
post = {
caller_address: Account(
storage={1: 0 if call_fails else 1},
@@ -155,7 +165,10 @@ def test_blobbasefee_before_fork(
callee_address: Address,
tx: Transaction,
):
- """Tests that the BLOBBASEFEE opcode results on exception when called before the fork."""
+ """
+ Tests that the BLOBBASEFEE opcode results on exception when called before
+ the fork.
+ """
# Fork happens at timestamp 15_000
timestamp = 7_500
post = {
@@ -193,8 +206,8 @@ def test_blobbasefee_during_fork(
tx: Transaction,
):
"""
- Tests that the BLOBBASEFEE opcode results on exception when called before the fork and
- succeeds when called after the fork.
+ Tests that the BLOBBASEFEE opcode results on exception when called before
+ the fork and succeeds when called after the fork.
"""
code_caller_post_storage = Storage()
diff --git a/tests/eest/constantinople/eip1014_create2/__init__.py b/tests/eest/constantinople/eip1014_create2/__init__.py
index c63c990d8b..724704b181 100644
--- a/tests/eest/constantinople/eip1014_create2/__init__.py
+++ b/tests/eest/constantinople/eip1014_create2/__init__.py
@@ -1,5 +1,3 @@
"""
-abstract: Test [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014).
-
- Tests for [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014).
+Tests for [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014).
"""
diff --git a/tests/eest/constantinople/eip1014_create2/test_create_returndata.py b/tests/eest/constantinople/eip1014_create2/test_create_returndata.py
index 3e64af7dae..94dfcf1069 100644
--- a/tests/eest/constantinople/eip1014_create2/test_create_returndata.py
+++ b/tests/eest/constantinople/eip1014_create2/test_create_returndata.py
@@ -1,7 +1,7 @@
"""
-Return data management around create2
-Port call_outsize_then_create2_successful_then_returndatasizeFiller.json test
-Port call_then_create2_successful_then_returndatasizeFiller.json test.
+Return data management around create2 Port
+call_outsize_then_create2_successful_then_returndatasizeFiller.json test Port
+call_then_create2_successful_then_returndatasizeFiller.json test.
"""
import pytest
@@ -28,6 +28,7 @@
@pytest.mark.parametrize("create_type", [Op.CREATE, Op.CREATE2])
@pytest.mark.parametrize("return_type", [Op.RETURN, Op.REVERT])
@pytest.mark.parametrize("return_type_in_create", [Op.RETURN, Op.REVERT])
+@pytest.mark.slow()
def test_create2_return_data(
call_return_size: int,
create_type: Op,
@@ -36,7 +37,10 @@ def test_create2_return_data(
pre: Alloc,
state_test: StateTestFiller,
):
- """Validate that create2 return data does not interfere with previously existing memory."""
+ """
+ Validate that create2 return data does not interfere with previously
+ existing memory.
+ """
# Storage vars
slot_returndatasize_before_create = 0
slot_returndatasize_after_create = 1
@@ -104,7 +108,8 @@ def test_create2_return_data(
slot_returndatacopy_before_create: expected_returndatacopy,
slot_returndatacopy_before_create_2: 0,
#
- # the actual bytes returned by returndatacopy opcode after create
+ # the actual bytes returned by returndatacopy opcode after
+ # create
slot_returndatacopy_after_create: (
return_data_in_create if return_type_in_create == Op.REVERT else 0
),
@@ -122,7 +127,8 @@ def test_create2_return_data(
else keccak256(int.to_bytes(return_data_in_create, 32, byteorder="big"))
),
#
- # check that create 2 didn't mess up with initial memory space declared for return
+ # check that create 2 didn't mess up with initial memory space
+ # declared for return
slot_begin_memory_after_create: expected_returndatacopy,
} # type: ignore
)
diff --git a/tests/eest/constantinople/eip1014_create2/test_recreate.py b/tests/eest/constantinople/eip1014_create2/test_recreate.py
index 702eca9bb7..116bbeb452 100644
--- a/tests/eest/constantinople/eip1014_create2/test_recreate.py
+++ b/tests/eest/constantinople/eip1014_create2/test_recreate.py
@@ -30,8 +30,8 @@ def test_recreate(
recreate_on_separate_block: bool,
):
"""
- Test that the storage is cleared when a contract is first destructed then re-created using
- CREATE2.
+ Test that the storage is cleared when a contract is first destructed then
+ re-created using CREATE2.
"""
creator_contract_code = Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.CREATE2(
0, 0, Op.CALLDATASIZE, 0
diff --git a/tests/eest/constantinople/eip145_bitwise_shift/__init__.py b/tests/eest/constantinople/eip145_bitwise_shift/__init__.py
index 5fc43725bb..bdca58cbe6 100644
--- a/tests/eest/constantinople/eip145_bitwise_shift/__init__.py
+++ b/tests/eest/constantinople/eip145_bitwise_shift/__init__.py
@@ -1,5 +1,3 @@
"""
-abstract: Test [EIP-145: Bitwise shifting instructions in EVM](https://eips.ethereum.org/EIPS/eip-145).
-
- Tests for [EIP-145: Bitwise shifting instructions in EVM](https://eips.ethereum.org/EIPS/eip-145).
+Test [EIP-145: Bitwise shifting instructions in EVM](https://eips.ethereum.org/EIPS/eip-145).
"""
diff --git a/tests/eest/constantinople/eip145_bitwise_shift/spec.py b/tests/eest/constantinople/eip145_bitwise_shift/spec.py
index 5b272a9e22..b8649ae2ad 100644
--- a/tests/eest/constantinople/eip145_bitwise_shift/spec.py
+++ b/tests/eest/constantinople/eip145_bitwise_shift/spec.py
@@ -21,8 +21,8 @@ class Spec:
https://eips.ethereum.org/EIPS/eip-145.
"""
- # Below are GPT o4-mini-high implementation of shift functions
- # It can contain bugs, treat it with caution and refer to EVM implementations
+ # Below are GPT o4-mini-high implementation of shift functions It can
+ # contain bugs, treat it with caution and refer to EVM implementations
@staticmethod
def sar(shift: int, value: int) -> int:
"""
diff --git a/tests/eest/frontier/create/test_create_one_byte.py b/tests/eest/frontier/create/test_create_one_byte.py
index 0cd90521e1..2c3a1312f4 100644
--- a/tests/eest/frontier/create/test_create_one_byte.py
+++ b/tests/eest/frontier/create/test_create_one_byte.py
@@ -1,6 +1,6 @@
"""
-The test calls CREATE in a loop deploying 1-byte contracts with all possible byte values,
-records in storage the values that failed to deploy.
+The test calls CREATE in a loop deploying 1-byte contracts with all possible
+byte values, records in storage the values that failed to deploy.
"""
import pytest
diff --git a/tests/eest/frontier/create/test_create_suicide_during_init.py b/tests/eest/frontier/create/test_create_suicide_during_init.py
new file mode 100644
index 0000000000..1e5c77c7f4
--- /dev/null
+++ b/tests/eest/frontier/create/test_create_suicide_during_init.py
@@ -0,0 +1,104 @@
+"""Deploy contract that calls selfdestruct in it's initcode."""
+
+from enum import Enum
+
+import pytest
+
+from ethereum_test_forks import Byzantium, Fork
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ Environment,
+ Initcode,
+ StateTestFiller,
+ Transaction,
+ compute_create_address,
+)
+from ethereum_test_tools import Opcodes as Op
+
+
+class Operation(Enum):
+ """Enum for created contract actions."""
+
+ SUICIDE = 1
+ SUICIDE_TO_ITSELF = 2
+
+ def __int__(self):
+ """Convert to int."""
+ return int(self.value)
+
+
+@pytest.mark.ported_from(
+ [
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json",
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json",
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json",
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json",
+ ],
+ pr=["https://github.com/ethereum/execution-spec-tests/pull/1871"],
+ coverage_missed_reason="Tip to coinbase, original test contains empty account.",
+)
+@pytest.mark.valid_from("Frontier")
+@pytest.mark.with_all_create_opcodes
+@pytest.mark.parametrize("transaction_create", [False, True])
+@pytest.mark.parametrize(
+ "operation",
+ [Operation.SUICIDE, Operation.SUICIDE_TO_ITSELF],
+)
+def test_create_suicide_during_transaction_create(
+ state_test: StateTestFiller,
+ fork: Fork,
+ pre: Alloc,
+ create_opcode: Op,
+ operation: Operation,
+ transaction_create: bool,
+):
+ """Contract init code calls suicide then measures different metrics."""
+ if create_opcode != Op.CREATE and transaction_create:
+ pytest.skip(f"Excluded: {create_opcode} with transaction_create=True")
+
+ sender = pre.fund_eoa()
+ contract_deploy = pre.deploy_contract(
+ code=Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE)
+ + create_opcode(size=Op.CALLDATASIZE(), value=Op.CALLVALUE())
+ )
+ contract_success = pre.deploy_contract(code=Op.SSTORE(1, 1))
+ self_destruct_destination = pre.deploy_contract(code=Op.STOP)
+ contract_after_suicide = pre.deploy_contract(code=Op.SSTORE(1, 1))
+
+ contract_initcode = Initcode(
+ initcode_prefix=Op.CALL(address=contract_success, gas=Op.SUB(Op.GAS, 100_000))
+ + Op.SELFDESTRUCT(
+ Op.ADDRESS if operation == Operation.SUICIDE_TO_ITSELF else self_destruct_destination
+ )
+ + Op.CALL(address=contract_after_suicide, gas=Op.SUB(Op.GAS, 100_000)),
+ deploy_code=Op.SSTORE(0, 1),
+ )
+
+ expected_create_address = compute_create_address(
+ address=sender if transaction_create else contract_deploy,
+ nonce=1 if transaction_create else 0,
+ initcode=contract_initcode,
+ opcode=create_opcode,
+ )
+
+ tx_value = 100
+ tx = Transaction(
+ gas_limit=1_000_000,
+ to=None if transaction_create else contract_deploy,
+ data=contract_initcode,
+ value=tx_value,
+ sender=sender,
+ protected=fork >= Byzantium,
+ )
+
+ post = {
+ contract_success: Account(storage={1: 1}),
+ self_destruct_destination: Account(
+ balance=0 if operation == Operation.SUICIDE_TO_ITSELF else tx_value
+ ),
+ contract_deploy: Account(storage={0: 0}),
+ contract_after_suicide: Account(storage={1: 0}), # suicide eats all gas
+ expected_create_address: Account.NONEXISTENT,
+ }
+ state_test(env=Environment(), pre=pre, post=post, tx=tx)
diff --git a/tests/eest/frontier/identity_precompile/common.py b/tests/eest/frontier/identity_precompile/common.py
index 6aef16f982..be7dc17c42 100644
--- a/tests/eest/frontier/identity_precompile/common.py
+++ b/tests/eest/frontier/identity_precompile/common.py
@@ -39,17 +39,18 @@ def generate_identity_call_bytecode(
call_succeeds: bool,
) -> Bytecode:
"""
- Generate bytecode for calling the identity precompile with given memory values.
+ Generate bytecode for calling the identity precompile with given memory
+ values.
Args:
- storage (Storage): The storage object to use for storing values.
- call_type (Op): The type of call opcode (CALL or CALLCODE).
- memory_values (Tuple[int, ...]): Values to store in memory before the call.
- call_args (CallArgs): Arguments for the CALL opcode.
- call_succeeds (bool): Whether the call should succeed or not.
+ storage (Storage): The storage object to use for storing values.
+ call_type (Op): The type of call opcode (CALL or CALLCODE).
+ memory_values(Tuple[int, ...]): Values to store in memory before
+ the call.
+ call_args(CallArgs): Arguments for the CALL opcode.
+ call_succeeds (bool): Whether the call should succeed or not.
- Returns:
- Bytecode: The generated bytecode for the identity precompile call.
+ Returns: Bytecode: The generated bytecode for the identity precompile call.
"""
code = Bytecode()
@@ -65,7 +66,8 @@ def generate_identity_call_bytecode(
if mstore_count > i + 1:
mstore_offset += 0x20
- # Call the identity precompile, then check that the last value in memory has not changed
+ # Call the identity precompile, then check that the last value in memory
+ # has not changed
code += (
Op.SSTORE(
storage.store_next(call_succeeds),
diff --git a/tests/eest/frontier/identity_precompile/test_identity.py b/tests/eest/frontier/identity_precompile/test_identity.py
index dc3222cfaf..653c763564 100644
--- a/tests/eest/frontier/identity_precompile/test_identity.py
+++ b/tests/eest/frontier/identity_precompile/test_identity.py
@@ -1,4 +1,4 @@
-"""abstract: Test identity precompile output size."""
+"""Test identity precompile output size."""
from typing import Tuple
@@ -118,7 +118,10 @@ def test_call_identity_precompile(
tx_gas_limit: int,
contract_balance: int,
):
- """Test identity precompile RETURNDATA is sized correctly based on the input size."""
+ """
+ Test identity precompile RETURNDATA is sized correctly based on the input
+ size.
+ """
env = Environment()
storage = Storage()
diff --git a/tests/eest/frontier/identity_precompile/test_identity_returndatasize.py b/tests/eest/frontier/identity_precompile/test_identity_returndatasize.py
index 45538b0c94..6e352664dc 100644
--- a/tests/eest/frontier/identity_precompile/test_identity_returndatasize.py
+++ b/tests/eest/frontier/identity_precompile/test_identity_returndatasize.py
@@ -1,4 +1,4 @@
-"""abstract: Test identity precompile output size."""
+"""Test identity precompile output size."""
import pytest
@@ -37,7 +37,10 @@ def test_identity_precompile_returndata(
output_size: int,
expected_returndatasize: int,
):
- """Test identity precompile RETURNDATA is sized correctly based on the input size."""
+ """
+ Test identity precompile RETURNDATA is sized correctly based on the input
+ size.
+ """
env = Environment()
storage = Storage()
diff --git a/tests/eest/frontier/opcodes/test_all_opcodes.py b/tests/eest/frontier/opcodes/test_all_opcodes.py
index d8679d252c..1d0301c7ce 100644
--- a/tests/eest/frontier/opcodes/test_all_opcodes.py
+++ b/tests/eest/frontier/opcodes/test_all_opcodes.py
@@ -1,6 +1,6 @@
"""
-Call every possible opcode and test that the subcall is successful
-if the opcode is supported by the fork supports and fails otherwise.
+Call every possible opcode and test that the subcall is successful if the
+opcode is supported by the fork supports and fails otherwise.
"""
from typing import Dict
@@ -17,8 +17,8 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcode, UndefinedOpcodes
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcode, UndefinedOpcodes
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "N/A"
REFERENCE_SPEC_VERSION = "N/A"
@@ -56,9 +56,9 @@ def prepare_suffix(opcode: Opcode) -> Bytecode:
@pytest.mark.valid_from("Frontier")
def test_all_opcodes(state_test: StateTestFiller, pre: Alloc, fork: Fork):
"""
- Test each possible opcode on the fork with a single contract that
- calls each opcode in succession. Check that each subcall passes
- if the opcode is supported and fails otherwise.
+ Test each possible opcode on the fork with a single contract that calls
+ each opcode in succession. Check that each subcall passes if the opcode is
+ supported and fails otherwise.
"""
code_worked = 1000
@@ -75,8 +75,8 @@ def test_all_opcodes(state_test: StateTestFiller, pre: Alloc, fork: Fork):
code=sum(
Op.SSTORE(
Op.PUSH1(opcode.int()),
- # Limit gas to limit the gas consumed by the exceptional aborts in each
- # subcall that uses an undefined opcode.
+ # Limit gas to limit the gas consumed by the exceptional aborts
+ # in each subcall that uses an undefined opcode.
Op.CALL(35_000, opcode_address, 0, 0, 0, 0, 0),
)
for opcode, opcode_address in code_contract.items()
diff --git a/tests/eest/frontier/opcodes/test_blockhash.py b/tests/eest/frontier/opcodes/test_blockhash.py
new file mode 100644
index 0000000000..f213f791b5
--- /dev/null
+++ b/tests/eest/frontier/opcodes/test_blockhash.py
@@ -0,0 +1,74 @@
+"""Tests for BLOCKHASH opcode."""
+
+import pytest
+
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ Block,
+ BlockchainTestFiller,
+ Storage,
+ Transaction,
+)
+from ethereum_test_tools import Opcodes as Op
+
+
+@pytest.mark.valid_from("Frontier")
+def test_genesis_hash_available(blockchain_test: BlockchainTestFiller, pre: Alloc):
+ """
+ Verify BLOCKHASH returns genesis and block 1 hashes.
+
+ Regression test: Blockchain test infrastructure must populate block hashes
+ before execution. Without this, BLOCKHASH returns 0, breaking dynamic
+ address computations like BLOCKHASH(0) | TIMESTAMP.
+
+ Tests both genesis (block 0) and first executed block (block 1) hash
+ insertion by calling the contract in block 2.
+
+ Bug context: revm blockchaintest runner wasn't inserting block_hashes,
+ causing failures in tests with BLOCKHASH-derived addresses.
+ """
+ storage = Storage()
+
+ # Store ISZERO(BLOCKHASH(0)) and ISZERO(BLOCKHASH(1))
+ # Both should be 0 (false) if hashes exist
+ code = Op.SSTORE(storage.store_next(0), Op.ISZERO(Op.BLOCKHASH(0))) + Op.SSTORE(
+ storage.store_next(0), Op.ISZERO(Op.BLOCKHASH(1))
+ )
+
+ contract = pre.deploy_contract(code=code)
+ sender = pre.fund_eoa()
+
+ blocks = [
+ Block(
+ txs=[
+ Transaction(
+ sender=sender,
+ to=contract,
+ gas_limit=100_000,
+ protected=False,
+ )
+ ]
+ ),
+ Block(
+ txs=[
+ Transaction(
+ sender=sender,
+ to=contract,
+ gas_limit=100_000,
+ protected=False,
+ )
+ ]
+ ),
+ ]
+
+ post = {
+ contract: Account(
+ storage={
+ 0: 0, # ISZERO(BLOCKHASH(0)) = 0 (genesis hash exists)
+ 1: 0, # ISZERO(BLOCKHASH(1)) = 0 (block 1 hash exists)
+ }
+ )
+ }
+
+ blockchain_test(pre=pre, post=post, blocks=blocks)
diff --git a/tests/eest/frontier/opcodes/test_call.py b/tests/eest/frontier/opcodes/test_call.py
index ad13a4d73a..e5fead6786 100644
--- a/tests/eest/frontier/opcodes/test_call.py
+++ b/tests/eest/frontier/opcodes/test_call.py
@@ -6,16 +6,17 @@
from ethereum_test_tools import (
Account,
Alloc,
+ CodeGasMeasure,
Environment,
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.code.generators import CodeGasMeasure
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
-# TODO: There's an issue with gas definitions on forks previous to Berlin, remove this when fixed.
-# https://github.com/ethereum/execution-spec-tests/pull/1952#discussion_r2237634275
+# TODO: There's an issue with gas definitions on forks previous to Berlin,
+# remove this when fixed. https://github.com/ethereum/execution-spec-
+# tests/pull/1952#discussion_r2237634275
@pytest.mark.valid_from("Berlin")
def test_call_large_offset_mstore(
state_test: StateTestFiller,
@@ -23,10 +24,11 @@ def test_call_large_offset_mstore(
fork: Fork,
):
"""
- CALL with ret_offset larger than memory size and ret_size zero
- Then do an MSTORE in that offset to see if memory was expanded in CALL.
+ CALL with ret_offset larger than memory size and ret_size zero Then do an
+ MSTORE in that offset to see if memory was expanded in CALL.
- This is for bug in a faulty EVM implementation where memory is expanded when it shouldn't.
+ This is for bug in a faulty EVM implementation where memory is expanded
+ when it shouldn't.
"""
sender = pre.fund_eoa()
@@ -35,14 +37,16 @@ def test_call_large_offset_mstore(
call_measure = CodeGasMeasure(
code=Op.CALL(gas=0, ret_offset=mem_offset, ret_size=0),
- overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), # Cost of pushing CALL args
+ # Cost of pushing CALL args
+ overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs),
extra_stack_items=1, # Because CALL pushes 1 item to the stack
sstore_key=0,
stop=False, # Because it's the first CodeGasMeasure
)
mstore_measure = CodeGasMeasure(
code=Op.MSTORE(offset=mem_offset, value=1),
- overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), # Cost of pushing MSTORE args
+ # Cost of pushing MSTORE args
+ overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs),
extra_stack_items=0,
sstore_key=1,
)
@@ -77,8 +81,9 @@ def test_call_large_offset_mstore(
)
-# TODO: There's an issue with gas definitions on forks previous to Berlin, remove this when fixed.
-# https://github.com/ethereum/execution-spec-tests/pull/1952#discussion_r2237634275
+# TODO: There's an issue with gas definitions on forks previous to Berlin,
+# remove this when fixed. https://github.com/ethereum/execution-spec-
+# tests/pull/1952#discussion_r2237634275
@pytest.mark.valid_from("Berlin")
def test_call_memory_expands_on_early_revert(
state_test: StateTestFiller,
@@ -87,27 +92,33 @@ def test_call_memory_expands_on_early_revert(
):
"""
When CALL reverts early (e.g. because of not enough balance by the sender),
- memory should be expanded anyway.
- We check this with an MSTORE.
+ memory should be expanded anyway. We check this with an MSTORE.
- This is for a bug in an EVM implementation where memory is expanded after executing a CALL, but
- not when an early revert happens.
+ This is for a bug in an EVM implementation where memory is expanded after
+ executing a CALL, but not when an early revert happens.
"""
sender = pre.fund_eoa()
gsc = fork.gas_costs()
- ret_size = 128 # arbitrary number, greater than memory size to trigger an expansion
+ # arbitrary number, greater than memory size to trigger an expansion
+ ret_size = 128
call_measure = CodeGasMeasure(
- code=Op.CALL(gas=0, value=100, ret_size=ret_size), # CALL with value
- overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), # Cost of pushing CALL args
- extra_stack_items=1, # Because CALL pushes 1 item to the stack
+ # CALL with value
+ code=Op.CALL(gas=0, value=100, ret_size=ret_size),
+ # Cost of pushing CALL args
+ overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs),
+ # Because CALL pushes 1 item to the stack
+ extra_stack_items=1,
sstore_key=0,
- stop=False, # Because it's the first CodeGasMeasure
+ # Because it's the first CodeGasMeasure
+ stop=False,
)
mstore_measure = CodeGasMeasure(
- code=Op.MSTORE(offset=ret_size // 2, value=1), # Low offset for not expanding memory
- overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), # Cost of pushing MSTORE args
+ # Low offset for not expanding memory
+ code=Op.MSTORE(offset=ret_size // 2, value=1),
+ # Cost of pushing MSTORE args
+ overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs),
extra_stack_items=0,
sstore_key=1,
)
@@ -123,7 +134,8 @@ def test_call_memory_expands_on_early_revert(
)
memory_expansion_gas_calc = fork.memory_expansion_gas_calculator()
- # call cost: address_access_cost + new_acc_cost + memory_expansion_cost + value - stipend
+ # call cost:
+ # address_access_cost+new_acc_cost+memory_expansion_cost+value-stipend
call_cost = (
gsc.G_COLD_ACCOUNT_ACCESS
+ gsc.G_NEW_ACCOUNT
@@ -132,7 +144,8 @@ def test_call_memory_expands_on_early_revert(
- gsc.G_CALL_STIPEND
)
- # mstore cost: base cost. No memory expansion cost needed, it was expanded on CALL.
+ # mstore cost: base cost. No memory expansion cost needed, it was expanded
+ # on CALL.
mstore_cost = gsc.G_MEMORY
state_test(
env=Environment(),
@@ -149,8 +162,9 @@ def test_call_memory_expands_on_early_revert(
)
-# TODO: There's an issue with gas definitions on forks previous to Berlin, remove this when fixed.
-# https://github.com/ethereum/execution-spec-tests/pull/1952#discussion_r2237634275
+# TODO: There's an issue with gas definitions on forks previous to Berlin,
+# remove this when fixed. https://github.com/ethereum/execution-spec-
+# tests/pull/1952#discussion_r2237634275
@pytest.mark.with_all_call_opcodes
@pytest.mark.valid_from("Berlin")
def test_call_large_args_offset_size_zero(
@@ -170,7 +184,8 @@ def test_call_large_args_offset_size_zero(
call_measure = CodeGasMeasure(
code=call_opcode(gas=0, args_offset=very_large_offset, args_size=0),
- overhead_cost=gsc.G_VERY_LOW * len(call_opcode.kwargs), # Cost of pushing xCALL args
+ # Cost of pushing xCALL args
+ overhead_cost=gsc.G_VERY_LOW * len(call_opcode.kwargs),
extra_stack_items=1, # Because xCALL pushes 1 item to the stack
sstore_key=0,
)
diff --git a/tests/eest/frontier/opcodes/test_call_and_callcode_gas_calculation.py b/tests/eest/frontier/opcodes/test_call_and_callcode_gas_calculation.py
index 73e9c9f3cc..61ac377bac 100644
--- a/tests/eest/frontier/opcodes/test_call_and_callcode_gas_calculation.py
+++ b/tests/eest/frontier/opcodes/test_call_and_callcode_gas_calculation.py
@@ -1,26 +1,33 @@
"""
-abstract: Tests the nested CALL/CALLCODE opcode gas consumption with a positive value transfer.
- This test is designed to investigate an issue identified in EthereumJS, as reported in:
- https://github.com/ethereumjs/ethereumjs-monorepo/issues/3194.
-
- The issue pertains to the incorrect gas calculation for CALL/CALLCODE operations with a
- positive value transfer, due to the pre-addition of the gas stipend (2300) to the currently
- available gas instead of adding it to the new call frame. This bug was specific to the case
- where insufficient gas was provided for the CALL/CALLCODE operation. Due to the pre-addition
- of the stipend to the currently available gas, the case for insufficient gas was not properly
- failing with an out-of-gas error.
-
- Test setup: Given two smart contract accounts, 0x0A (caller) and 0x0B (callee):
- 1) An arbitrary transaction calls into the contract 0x0A.
- 2) Contract 0x0A executes a CALL to contract 0x0B with a specific gas limit (X).
- 3) Contract 0x0B then attempts a CALL/CALLCODE to a non-existent contract 0x0C,
- with a positive value transfer (activating the gas stipend).
- 4) If the gas X provided by contract 0x0A to 0x0B is sufficient, contract 0x0B
- will push 0x01 onto the stack after returning to the call frame in 0x0A. Otherwise, it
- should push 0x00, indicating the insufficiency of gas X (for the bug in EthereumJS, the
- CALL/CALLCODE operation would return 0x01 due to the pre-addition of the gas stipend).
- 5) The resulting stack value is saved into contract 0x0A's storage, allowing us to
- verify whether the provided gas was sufficient or insufficient.
+Tests nested CALL/CALLCODE gas usage with positive value transfer.
+
+This test investigates an issue identified in EthereumJS, as reported in:
+https://github.com/ethereumjs/ethereumjs-monorepo/issues/3194.
+
+The issue pertains to the incorrect gas calculation for CALL/CALLCODE
+operations with a positive value transfer, due to the pre-addition of the
+gas stipend (2300) to the currently available gas instead of adding it to
+the new call frame. This bug was specific to the case where insufficient
+gas was provided for the CALL/CALLCODE operation. Due to the pre-addition
+of the stipend to the currently available gas, the case for insufficient
+gas was not properly failing with an out-of-gas error.
+
+Test setup:
+
+Given two smart contract accounts, 0x0A (caller) and 0x0B (callee):
+1. An arbitrary transaction calls into the contract 0x0A.
+2. Contract 0x0A executes a CALL to contract 0x0B with a specific gas limit
+(X).
+3. Contract 0x0B then attempts a CALL/CALLCODE to a non-existent contract
+0x0C, with a positive value transfer (activating the gas stipend).
+4. If the gas X provided by contract 0x0A to 0x0B is sufficient, contract
+0x0B will push 0x01 onto the stack after returning to the call frame in
+0x0A. Otherwise, it should push 0x00, indicating the insufficiency of
+gas X (for the bug in EthereumJS, the CALL/CALLCODE operation would
+return 0x01 due to the pre-addition of the gas stipend).
+5. The resulting stack value is saved into contract 0x0A's storage,
+allowing us to verify whether the provided gas was sufficient or
+insufficient.
"""
from typing import Dict
@@ -37,17 +44,19 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
"""
PUSH opcode cost is 3, GAS opcode cost is 2.
-We need 6 PUSH's and one GAS to fill the stack for both CALL & CALLCODE, in the callee contract.
+We need 6 PUSH's and one GAS to fill the stack for both CALL & CALLCODE,
+in the callee contract.
"""
CALLEE_INIT_STACK_GAS = 6 * 3 + 2
"""
CALL gas breakdowns: (https://www.evm.codes/#f1)
-memory_exp_cost + code_exec_cost + address_access_cost + positive_value_cost + empty_account_cost
+memory_exp_cost + code_exec_cost + address_access_cost +
+positive_value_cost + empty_account_cost
= 0 + 0 + 2600 + 9000 + 25000 = 36600
"""
CALL_GAS = 36600
@@ -55,8 +64,8 @@
"""
CALLCODE gas breakdowns: (https://www.evm.codes/#f2)
-memory_exp_cost + code_exec_cost + address_access_cost + positive_value_cost
-= 0 + 0 + 2600 + 9000 = 11600
+memory_exp_cost + code_exec_cost + address_access_cost +
+positive_value_cost = 0 + 0 + 2600 + 9000 = 11600
"""
CALLCODE_GAS = 11600
CALLCODE_SUFFICIENT_GAS = CALLCODE_GAS + CALLEE_INIT_STACK_GAS
@@ -66,14 +75,14 @@
def callee_code(pre: Alloc, callee_opcode: Op) -> Bytecode:
"""
Code called by the caller contract:
- PUSH1 0x00 * 4
- PUSH1 0x01 <- for positive value transfer
- PUSH2 Contract.nonexistent
- GAS <- value doesn't matter
- CALL/CALLCODE.
+ PUSH1 0x00 * 4
+ PUSH1 0x01 <- for positive value transfer
+ PUSH2 Contract.nonexistent
+ GAS <- value doesn't matter
+ CALL/CALLCODE.
"""
- # The address needs to be empty and different for each execution of the fixture,
- # otherwise the calculations (empty_account_cost) are incorrect.
+ # The address needs to be empty and different for each execution of the
+ # fixture, otherwise the calculations (empty_account_cost) are incorrect.
return callee_opcode(Op.GAS(), pre.empty_account(), 1, 0, 0, 0, 0)
@@ -93,12 +102,12 @@ def callee_address(pre: Alloc, callee_code: Bytecode) -> Address:
def caller_code(caller_gas_limit: int, callee_address: Address) -> Bytecode:
"""
Code to CALL the callee contract:
- PUSH1 0x00 * 5
- PUSH2 Contract.callee
- PUSH2 caller_gas <- gas limit set for CALL to callee contract
- CALL
- PUSH1 0x00
- SSTORE.
+ PUSH1 0x00 * 5
+ PUSH2 Contract.callee
+ PUSH2 caller_gas <- gas limit set for CALL to callee contract
+ CALL
+ PUSH1 0x00
+ SSTORE.
"""
return Op.SSTORE(0, Op.CALL(caller_gas_limit, callee_address, 0, 0, 0, 0, 0))
@@ -107,12 +116,12 @@ def caller_code(caller_gas_limit: int, callee_address: Address) -> Bytecode:
def caller_address(pre: Alloc, caller_code: Bytecode) -> Address:
"""
Code to CALL the callee contract:
- PUSH1 0x00 * 5
- PUSH2 Contract.callee
- PUSH2 caller_gas <- gas limit set for CALL to callee contract
- CALL
- PUSH1 0x00
- SSTORE.
+ PUSH1 0x00 * 5
+ PUSH2 Contract.callee
+ PUSH2 caller_gas <- gas limit set for CALL to callee contract
+ CALL
+ PUSH1 0x00
+ SSTORE.
"""
return pre.deploy_contract(caller_code, balance=0x03)
@@ -151,5 +160,8 @@ def test_value_transfer_gas_calculation(
caller_tx: Transaction,
post: Dict[str, Account],
):
- """Tests the nested CALL/CALLCODE opcode gas consumption with a positive value transfer."""
+ """
+ Tests the nested CALL/CALLCODE opcode gas consumption with a positive value
+ transfer.
+ """
state_test(env=Environment(), pre=pre, post=post, tx=caller_tx)
diff --git a/tests/eest/frontier/opcodes/test_calldatacopy.py b/tests/eest/frontier/opcodes/test_calldatacopy.py
index 44ab406a45..90bd3c68ce 100644
--- a/tests/eest/frontier/opcodes/test_calldatacopy.py
+++ b/tests/eest/frontier/opcodes/test_calldatacopy.py
@@ -4,7 +4,7 @@
from ethereum_test_forks import Byzantium, Fork
from ethereum_test_tools import Account, Alloc, Bytecode, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
@pytest.mark.ported_from(
diff --git a/tests/eest/frontier/opcodes/test_calldataload.py b/tests/eest/frontier/opcodes/test_calldataload.py
index ca135e51a0..9776e66e05 100644
--- a/tests/eest/frontier/opcodes/test_calldataload.py
+++ b/tests/eest/frontier/opcodes/test_calldataload.py
@@ -5,7 +5,7 @@
from ethereum_test_forks import Byzantium, Fork
from ethereum_test_tools import Account, Alloc, StateTestFiller, Transaction
from ethereum_test_tools import Macros as Om
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
@pytest.mark.ported_from(
@@ -53,10 +53,15 @@ def test_calldataload(
Test `CALLDATALOAD` opcode.
Tests two scenarios:
- - calldata_source is "contract": CALLDATALOAD reads from calldata passed by another contract
- - calldata_source is "tx": CALLDATALOAD reads directly from transaction calldata
+ - calldata_source is "contract": CALLDATALOAD reads from calldata
+ passed by another contract
+ - calldata_source is "tx": CALLDATALOAD reads directly from
+ transaction calldata
- Based on https://github.com/ethereum/tests/blob/ae4791077e8fcf716136e70fe8392f1a1f1495fb/src/GeneralStateTestsFiller/VMTests/vmTests/calldatacopyFiller.yml
+ Based on
+ https://github.com/ethereum/tests/blob/
+ ae4791077e8fcf716136e70fe8392f1a1f1495fb/src/
+ GeneralStateTestsFiller/VMTests/vmTests/calldatacopyFiller.yml
"""
contract_address = pre.deploy_contract(
Op.SSTORE(0, Op.CALLDATALOAD(offset=calldata_offset)) + Op.STOP,
diff --git a/tests/eest/frontier/opcodes/test_calldatasize.py b/tests/eest/frontier/opcodes/test_calldatasize.py
index 38a2f9415a..9eae9de863 100644
--- a/tests/eest/frontier/opcodes/test_calldatasize.py
+++ b/tests/eest/frontier/opcodes/test_calldatasize.py
@@ -5,7 +5,7 @@
from ethereum_test_forks import Byzantium, Fork
from ethereum_test_tools import Account, Alloc, StateTestFiller, Transaction
from ethereum_test_tools import Macros as Om
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
@pytest.mark.ported_from(
@@ -19,6 +19,7 @@
[0, 2, 16, 33, 257],
)
@pytest.mark.parametrize("calldata_source", ["contract", "tx"])
+@pytest.mark.slow()
def test_calldatasize(
state_test: StateTestFiller,
fork: Fork,
@@ -30,10 +31,15 @@ def test_calldatasize(
Test `CALLDATASIZE` opcode.
Tests two scenarios:
- - calldata_source is "contract": CALLDATASIZE reads from calldata passed by another contract
- - calldata_source is "tx": CALLDATASIZE reads directly from transaction calldata
+ - calldata_source is "contract": CALLDATASIZE reads from calldata
+ passed by another contract
+ - calldata_source is "tx": CALLDATASIZE reads directly from
+ transaction calldata
- Based on https://github.com/ethereum/tests/blob/81862e4848585a438d64f911a19b3825f0f4cd95/src/GeneralStateTestsFiller/VMTests/vmTests/calldatasizeFiller.yml
+ Based on
+ https://github.com/ethereum/tests/blob/
+ 81862e4848585a438d64f911a19b3825f0f4cd95/src/
+ GeneralStateTestsFiller/VMTests/vmTests/calldatasizeFiller.yml
"""
contract_address = pre.deploy_contract(Op.SSTORE(key=0x0, value=Op.CALLDATASIZE))
calldata = b"\x01" * args_size
diff --git a/tests/eest/frontier/opcodes/test_dup.py b/tests/eest/frontier/opcodes/test_dup.py
index a4d3d3e85f..ee8cbd3c14 100644
--- a/tests/eest/frontier/opcodes/test_dup.py
+++ b/tests/eest/frontier/opcodes/test_dup.py
@@ -1,8 +1,4 @@
-"""
-abstract: Test DUP
- Test the DUP opcodes.
-
-"""
+"""Test DUP Test the DUP opcodes."""
import pytest
@@ -43,9 +39,13 @@ def test_dup(
"""
Test the DUP1-DUP16 opcodes.
- Note: Test case ported from [ethereum/tests](https://github.com/ethereum/tests)
- Test ported from [ethereum/tests/GeneralStateTests/VMTests/vmTests/dup.json](https://github.com/ethereum/tests/blob/v14.0/GeneralStateTests/VMTests/vmTests/dup.json) by Ori Pomerantz.
- """ # noqa: E501
+ Note: Test case ported from
+ [ethereum/tests](https://github.com/ethereum/tests).
+
+ Test ported from [ethereum/tests/GeneralStateTests/VMTests/
+ vmTests/dup.json](https://github.com/ethereum/tests/blob/
+ v14.0/GeneralStateTests/VMTests/vmTests/dup.json) by Ori Pomerantz.
+ """
env = Environment()
sender = pre.fund_eoa()
post = {}
diff --git a/tests/eest/frontier/opcodes/test_push.py b/tests/eest/frontier/opcodes/test_push.py
index 65cb213d6d..516c6f8091 100644
--- a/tests/eest/frontier/opcodes/test_push.py
+++ b/tests/eest/frontier/opcodes/test_push.py
@@ -1,14 +1,18 @@
"""
A State test for the set of `PUSH*` opcodes.
-Ported from: https://github.com/ethereum/tests/blob/4f65a0a7cbecf4442415c226c65e089acaaf6a8b/src/GeneralStateTestsFiller/VMTests/vmTests/pushFiller.yml.
-""" # noqa: E501
+
+Ported from:
+https://github.com/ethereum/tests/blob/
+4f65a0a7cbecf4442415c226c65e089acaaf6a8b/src/
+GeneralStateTestsFiller/VMTests/vmTests/pushFiller.yml.
+"""
import pytest
from ethereum_test_forks import Fork, Frontier, Homestead
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
from ethereum_test_tools import Opcodes as Op
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
def get_input_for_push_opcode(opcode: Op) -> bytes:
@@ -30,7 +34,8 @@ def get_input_for_push_opcode(opcode: Op) -> bytes:
)
@pytest.mark.parametrize(
"push_opcode",
- [getattr(Op, f"PUSH{i}") for i in range(1, 33)], # Dynamically parametrize PUSH opcodes
+ # Dynamically parametrize PUSH opcodes
+ [getattr(Op, f"PUSH{i}") for i in range(1, 33)],
ids=lambda op: str(op),
)
@pytest.mark.valid_from("Frontier")
@@ -38,9 +43,8 @@ def test_push(state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode:
"""
The set of `PUSH*` opcodes pushes data onto the stack.
- In this test, we ensure that the set of `PUSH*` opcodes writes
- a portion of an excerpt from the Ethereum yellow paper to
- storage.
+ In this test, we ensure that the set of `PUSH*` opcodes writes a portion of
+ an excerpt from the Ethereum yellow paper to storage.
"""
# Input used to test the `PUSH*` opcode.
excerpt = get_input_for_push_opcode(push_opcode)
@@ -87,22 +91,28 @@ def test_push(state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode:
)
@pytest.mark.parametrize("stack_height", range(1024, 1026))
@pytest.mark.valid_from("Frontier")
+@pytest.mark.slow()
def test_stack_overflow(
state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode: Op, stack_height: int
):
- """A test to ensure that the stack overflows when the stack limit of 1024 is exceeded."""
+ """
+ A test the stack overflows when the stack limit of 1024 is exceeded.
+ """
env = Environment()
# Input used to test the `PUSH*` opcode.
excerpt = get_input_for_push_opcode(push_opcode)
"""
- Essentially write a n-byte message to storage by pushing [1024,1025] times to stack. This
- simulates a "jump" over the stack limit of 1024.
- The message is UTF-8 encoding of excerpt (say 0x45 for PUSH1). Within the stack limit,
- the message is written to the to the storage at the same offset (0x45 for PUSH1).
- The last iteration will overflow the stack and the storage slot will be empty.
+
+ Essentially write a n-byte message to storage by pushing [1024,1025] times
+ to stack. This simulates a "jump" over the stack limit of 1024.
+
+ The message is UTF-8 encoding of excerpt (say 0x45 for PUSH1). Within the
+ stack limit, the message is written to the to the storage at the same
+ offset (0x45 for PUSH1). The last iteration will overflow the stack and the
+ storage slot will be empty.
** Bytecode explanation **
+---------------------------------------------------+
@@ -115,7 +125,8 @@ def test_stack_overflow(
"""
contract_code: Bytecode = Bytecode()
for _ in range(stack_height - 2):
- contract_code += Op.PUSH1(0) # mostly push 0 to avoid contract size limit exceeded
+ # mostly push 0 to avoid contract size limit exceeded
+ contract_code += Op.PUSH1(0)
contract_code += push_opcode(excerpt) * 2 + Op.SSTORE
contract = pre.deploy_contract(contract_code)
diff --git a/tests/eest/frontier/opcodes/test_selfdestruct.py b/tests/eest/frontier/opcodes/test_selfdestruct.py
index e165684a0d..bedddbf679 100644
--- a/tests/eest/frontier/opcodes/test_selfdestruct.py
+++ b/tests/eest/frontier/opcodes/test_selfdestruct.py
@@ -10,9 +10,9 @@
@pytest.mark.valid_until("Homestead")
def test_double_kill(blockchain_test: BlockchainTestFiller, pre: Alloc):
"""
- Test that when two transactions attempt to destruct a contract,
- the second transaction actually resurrects the contract as an empty account (prior to Spurious
- Dragon).
+ Test that when two transactions attempt to destruct a contract, the second
+ transaction actually resurrects the contract as an empty account (prior to
+ Spurious Dragon).
"""
sender = pre.fund_eoa()
diff --git a/tests/eest/frontier/opcodes/test_swap.py b/tests/eest/frontier/opcodes/test_swap.py
new file mode 100644
index 0000000000..c6bde78a5d
--- /dev/null
+++ b/tests/eest/frontier/opcodes/test_swap.py
@@ -0,0 +1,147 @@
+"""
+A State test for the set of `SWAP*` opcodes.
+Ported from: https://github.com/ethereum/tests/
+blob/develop/src/GeneralStateTestsFiller/VMTests/vmTests/swapFiller.yml.
+"""
+
+import pytest # noqa: I001
+
+from ethereum_test_forks import Fork, Frontier, Homestead
+from ethereum_test_tools import Account, Alloc, Bytecode, Environment
+from ethereum_test_tools import Opcodes as Op
+from ethereum_test_tools import StateTestFiller, Storage, Transaction
+
+
+@pytest.mark.ported_from(
+ [
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/VMTests/vmTests/swapFiller.yml"
+ ],
+ pr=["https://github.com/ethereum/execution-spec-tests/pull/1163"],
+ coverage_missed_reason=(
+ "Test isolation (1 contract per execution) reduces evmone state "
+ "comparisons vs old dispatcher pattern (16 contracts per execution)"
+ ),
+)
+@pytest.mark.parametrize(
+ "swap_opcode",
+ [getattr(Op, f"SWAP{i}") for i in range(1, 17)],
+ ids=lambda op: str(op),
+)
+@pytest.mark.valid_from("Frontier")
+def test_swap(state_test: StateTestFiller, fork: Fork, pre: Alloc, swap_opcode: Op):
+ """
+ The set of `SWAP*` opcodes swaps the top of the stack with a specific
+ element.
+
+ In this test, we ensure that the set of `SWAP*` opcodes correctly swaps
+ the top element with the nth element and stores the result in storage.
+ """
+ env = Environment()
+
+ # Calculate which position we're swapping with (1-based index)
+ swap_pos = swap_opcode.int() - 0x90 + 1
+
+ # Generate stack values
+ stack_values = list(range(swap_pos + 16))
+
+ # Push the stack values onto the stack (in reverse order).
+ contract_code = Bytecode()
+ for value in reversed(stack_values):
+ contract_code += Op.PUSH1(value)
+
+ # Perform the SWAP operation.
+ contract_code += swap_opcode
+
+ # Store multiple values to storage.
+ for slot in range(16):
+ contract_code += Op.PUSH1(slot) + Op.SSTORE
+
+ # Deploy the contract with the generated bytecode.
+ contract_address = pre.deploy_contract(contract_code)
+
+ # Create a transaction to execute the contract.
+ tx = Transaction(
+ sender=pre.fund_eoa(),
+ to=contract_address,
+ gas_limit=500_000,
+ protected=False if fork in [Frontier, Homestead] else True,
+ )
+
+ # Calculate expected storage values after SWAP and storage operations
+ # Initial stack (after pushes, before swap): [0, 1, 2, ..., swap_pos+15]
+ # (top is index 0)
+ # After SWAP at position swap_pos: top and position swap_pos are swapped
+ # Then we do: PUSH1(slot) SSTORE 16 times, which pops values from stack
+
+ # Build the stack state after SWAP
+ stack_after_swap = stack_values.copy()
+ stack_after_swap[0], stack_after_swap[swap_pos] = (
+ stack_after_swap[swap_pos],
+ stack_after_swap[0],
+ )
+
+ # Store the first 16 values from the post-swap stack
+ storage = Storage()
+ for value in stack_after_swap[:16]:
+ storage.store_next(value)
+
+ post = {contract_address: Account(storage=storage)}
+
+ # Run the state test.
+ state_test(env=env, pre=pre, post=post, tx=tx)
+
+
+@pytest.mark.parametrize(
+ "swap_opcode",
+ [getattr(Op, f"SWAP{i}") for i in range(1, 17)],
+ ids=lambda op: str(op),
+)
+@pytest.mark.valid_from("Frontier")
+def test_stack_underflow(
+ state_test: StateTestFiller,
+ fork: Fork,
+ pre: Alloc,
+ swap_opcode: Op,
+):
+ """
+ A test to ensure that the stack underflow when there are not enough
+ elements for the `SWAP*` opcode to operate.
+
+ For each SWAPn operation, we push exactly (n-1) elements to cause an
+ underflow when trying to swap with the nth element.
+ """
+ env = Environment()
+
+ # Calculate which position we're swapping with (1-based index)
+ swap_pos = swap_opcode.int() - 0x90 + 1
+
+ # Push exactly (n-1) elements for SWAPn to cause underflow
+ contract_code = Bytecode()
+ for i in range(swap_pos - 1):
+ contract_code += Op.PUSH1(i % 256)
+
+ # Attempt to perform the SWAP operation
+ contract_code += swap_opcode
+
+ # Store the top of the stack in storage slot 0
+ contract_code += Op.PUSH1(0) + Op.SSTORE
+
+ # Deploy the contract with the generated bytecode.
+ contract = pre.deploy_contract(contract_code)
+
+ # Create a transaction to execute the contract.
+ tx = Transaction(
+ sender=pre.fund_eoa(),
+ to=contract,
+ gas_limit=500_000,
+ protected=False if fork in [Frontier, Homestead] else True,
+ )
+
+ # Define the expected post-state.
+ post = {}
+ storage = Storage()
+ storage.store_next(0, f"SWAP{swap_pos} failed due to stack underflow")
+ post[contract] = Account(storage=storage)
+
+ # Run the state test.
+ state_test(env=env, pre=pre, post=post, tx=tx)
diff --git a/tests/eest/frontier/precompiles/test_precompile_absence.py b/tests/eest/frontier/precompiles/test_precompile_absence.py
index 1982ad2f21..46b9dd44ec 100644
--- a/tests/eest/frontier/precompiles/test_precompile_absence.py
+++ b/tests/eest/frontier/precompiles/test_precompile_absence.py
@@ -1,4 +1,4 @@
-"""abstract: Test Calling Precompile Range (close to zero)."""
+"""Test Calling Precompile Range (close to zero)."""
import pytest
@@ -33,7 +33,10 @@ def test_precompile_absence(
fork: Fork,
calldata_size: int,
):
- """Test that addresses close to zero are not precompiles unless active in the fork."""
+ """
+ Test that addresses close to zero are not precompiles unless active in the
+ fork.
+ """
active_precompiles = fork.precompiles()
storage = Storage()
call_code = Bytecode()
diff --git a/tests/eest/frontier/precompiles/test_precompiles.py b/tests/eest/frontier/precompiles/test_precompiles.py
index 280b732353..b7ba6b9142 100644
--- a/tests/eest/frontier/precompiles/test_precompiles.py
+++ b/tests/eest/frontier/precompiles/test_precompiles.py
@@ -13,19 +13,21 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
def precompile_addresses(fork: Fork) -> Iterator[Tuple[Address, bool]]:
"""
- Yield the addresses of precompiled contracts and their support status for a given fork.
+ Yield the addresses of precompiled contracts and their support status for a
+ given fork.
Args:
- fork (Fork): The fork instance containing precompiled contract information.
+ 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.
+ 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()
@@ -60,17 +62,19 @@ def test_precompiles(
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.
+ 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()
diff --git a/tests/eest/frontier/scenarios/common.py b/tests/eest/frontier/scenarios/common.py
index ce9170c035..cb17f44cf1 100644
--- a/tests/eest/frontier/scenarios/common.py
+++ b/tests/eest/frontier/scenarios/common.py
@@ -5,8 +5,8 @@
from enum import Enum
from ethereum_test_forks import Fork, Frontier
-from ethereum_test_tools import Address, Alloc, Bytecode, Conditional
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_tools import Address, Alloc, Bytecode, Conditional, MemoryVariable
+from ethereum_test_vm import Opcodes as Op
class ScenarioExpectOpcode(Enum):
@@ -30,9 +30,9 @@ class ScenarioExpectOpcode(Enum):
@dataclass
class ScenarioEnvironment:
"""
- Scenario evm environment
- Each scenario must define an environment on which program is executed
- This is so post state verification could check results of evm opcodes.
+ Scenario evm environment Each scenario must define an environment on which
+ program is executed This is so post state verification could check results
+ of evm opcodes.
"""
code_address: Address # Op.ADDRESS, address scope for program
@@ -63,9 +63,10 @@ class ProgramResult:
Describe expected result of a program.
Attributes:
- result (int | ScenarioExpectOpcode): The result of the program
- from_fork (Fork): The result is only valid from this fork (default: Frontier)
- static_support (bool): Can be verified in static context (default: True)
+ result (int | ScenarioExpectOpcode): The result of the program
+ from_fork (Fork): The result is only valid from this fork
+ (default: Frontier)
+ static_support (bool): Can be verified in static context (default: True)
"""
@@ -79,8 +80,8 @@ def translate_result(
self, env: ScenarioEnvironment, exec_env: ExecutionEnvironment
) -> int | Address:
"""
- Translate expected program result code into concrete value,
- given the scenario evm environment and test execution environment.
+ Translate expected program result code into concrete value, given the
+ scenario evm environment and test execution environment.
"""
if exec_env.fork < self.from_fork:
return 0
@@ -154,10 +155,10 @@ class ScenarioGeneratorInput:
Parameters for the scenario generator function.
Attributes:
- fork (Fork): Fork for which we ask to generate scenarios
- pre (Alloc): Access to the state to be able to deploy contracts into pre
- operation (Bytecode): Evm bytecode program that will be tested
- external_address (Address): Static external address for ext opcodes
+ fork (Fork): Fork for which we ask to generate scenarios
+ pre(Alloc): Access to the state to be able to deploy contracts into pre
+ operation (Bytecode): Evm bytecode program that will be tested
+ external_address (Address): Static external address for ext opcodes
"""
@@ -172,11 +173,12 @@ class Scenario:
Describe test scenario that will be run in test for each program.
Attributes:
- category (str): Scenario category name
- name (str): Scenario name for the test vector
- code (Address): Address that is an entry point for scenario code
- env (ScenarioEnvironment): Evm values for ScenarioExpectAddress map
- reverting (bool): If scenario reverts program execution, making result 0 (default: False)
+ category (str): Scenario category name
+ name (str): Scenario name for the test vector
+ code (Address): Address that is an entry point for scenario code
+ env (ScenarioEnvironment): Evm values for ScenarioExpectAddress map
+ reverting (bool): If scenario reverts program execution,
+ making result 0 (default: False)
"""
@@ -189,25 +191,46 @@ class Scenario:
def make_gas_hash_contract(pre: Alloc) -> Address:
"""
- Contract that spends unique amount of gas based on input
- Used for the values we can't predict, can be gas consuming on high values
- So that if we can't check exact value in expect section,
- we at least could spend unique gas amount.
+ Contract that spends unique amount of gas based on input.
+ Used for the values we can't predict, can be gas consuming on high values.
+ So that if we can't check exact value in expect section, we at least
+ could spend unique gas amount.
"""
+ # EVM memory variables
+ byte_offset = MemoryVariable(0)
+ current_byte = MemoryVariable(32)
+
+ # Code for memory initialization
+ initialize_code = byte_offset.set(0)
+ calldata_copy = Op.JUMPDEST + Op.CALLDATACOPY(
+ dest_offset=current_byte.offset + 32 - 1,
+ offset=byte_offset,
+ size=1,
+ )
+
+ # Code offsets
+ offset_calldata_copy = len(initialize_code)
+ offset_conditional = offset_calldata_copy + len(calldata_copy)
+
+ # Deploy contract
gas_hash_address = pre.deploy_contract(
- code=Op.MSTORE(0, 0)
- + Op.JUMPDEST
- + Op.CALLDATACOPY(63, Op.MLOAD(0), 1)
- + Op.JUMPDEST
+ code=initialize_code
+ + calldata_copy # offset_calldata_copy
+ + Op.JUMPDEST # offset_conditional
+ Conditional(
- condition=Op.ISZERO(Op.MLOAD(32)),
- if_true=Op.MSTORE(0, Op.ADD(1, Op.MLOAD(0)))
- + Conditional(
- condition=Op.GT(Op.MLOAD(0), 32),
- if_true=Op.RETURN(0, 0),
- if_false=Op.JUMP(5),
+ condition=Op.ISZERO(current_byte),
+ if_true=(
+ # Increase the calldata byte offset, and if it's greater than
+ # the calldata size, return, otherwise jump to the calldata
+ # copy code and read the next byte.
+ byte_offset.add(1)
+ + Conditional(
+ condition=Op.GT(byte_offset, Op.CALLDATASIZE()),
+ if_true=Op.RETURN(offset=0, size=0),
+ if_false=Op.JUMP(offset_calldata_copy),
+ )
),
- if_false=Op.MSTORE(32, Op.SUB(Op.MLOAD(32), 1)) + Op.JUMP(14),
+ if_false=(current_byte.sub(1) + Op.JUMP(offset_conditional)),
)
)
return gas_hash_address
@@ -215,8 +238,9 @@ def make_gas_hash_contract(pre: Alloc) -> Address:
def make_invalid_opcode_contract(pre: Alloc, fork: Fork) -> Address:
"""
- Deploy a contract that will execute any asked byte as an opcode from calldataload
- Deploy 20 empty stack elements. Jump to opcode instruction. if worked, return 0.
+ Deploy a contract that will execute any asked byte as an opcode from
+ calldataload Deploy 20 empty stack elements. Jump to opcode instruction. if
+ worked, return 0.
"""
invalid_opcode_caller = pre.deploy_contract(
code=Op.PUSH1(0) * 20
@@ -238,19 +262,25 @@ def make_invalid_opcode_contract(pre: Alloc, fork: Fork) -> Address:
if op not in valid_opcode_values:
invalid_opcodes.append(op)
+ results_sum = MemoryVariable(0)
+ current_opcode = MemoryVariable(32)
+
code = Bytecode(
sum(
- Op.MSTORE(64, opcode)
- + Op.MSTORE(
- 32,
- Op.CALL(gas=50000, address=invalid_opcode_caller, args_offset=64, args_size=32),
+ current_opcode.set(opcode)
+ + results_sum.add(
+ Op.CALL(
+ gas=50000,
+ address=invalid_opcode_caller,
+ args_offset=current_opcode.offset,
+ args_size=32,
+ ),
)
- + Op.MSTORE(0, Op.ADD(Op.MLOAD(0), Op.MLOAD(32)))
for opcode in invalid_opcodes
)
# If any of invalid instructions works, mstore[0] will be > 1
- + Op.MSTORE(0, Op.ADD(Op.MLOAD(0), 1))
- + Op.RETURN(0, 32)
+ + results_sum.add(1)
+ + results_sum.return_value()
)
return pre.deploy_contract(code=code)
diff --git a/tests/eest/frontier/scenarios/programs/all_frontier_opcodes.py b/tests/eest/frontier/scenarios/programs/all_frontier_opcodes.py
index 1120fbf4da..72d8fa459a 100644
--- a/tests/eest/frontier/scenarios/programs/all_frontier_opcodes.py
+++ b/tests/eest/frontier/scenarios/programs/all_frontier_opcodes.py
@@ -1,10 +1,13 @@
-"""Define a program for scenario test that executes all frontier opcodes and entangles it's result.""" # noqa: E501
+"""
+Define a program for scenario test that executes all frontier opcodes and
+entangles it's result.
+"""
from functools import cached_property
from ethereum_test_forks import Fork
from ethereum_test_tools import Alloc, Bytecode, Conditional
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from ..common import ProgramResult, ScenarioTestProgram
@@ -15,7 +18,9 @@
def make_all_opcode_program() -> Bytecode:
- """Make a program that call each Frontier opcode and verifies it's result."""
+ """
+ Make a program that call each Frontier opcode and verifies it's result.
+ """
code: Bytecode = (
# Test opcode 01 - ADD
Conditional(
diff --git a/tests/eest/frontier/scenarios/programs/context_calls.py b/tests/eest/frontier/scenarios/programs/context_calls.py
index bcf0a1ba4f..7a44035c9e 100644
--- a/tests/eest/frontier/scenarios/programs/context_calls.py
+++ b/tests/eest/frontier/scenarios/programs/context_calls.py
@@ -4,7 +4,8 @@
from ethereum_test_forks import Byzantium, Cancun, Constantinople, Fork, Istanbul, London, Shanghai
from ethereum_test_tools import Alloc, Bytecode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_types import ChainConfigDefaults
+from ethereum_test_vm import Opcodes as Op
from ..common import (
ProgramResult,
@@ -15,7 +16,9 @@
class ProgramAddress(ScenarioTestProgram):
- """Check that ADDRESS is really the code execution address in all scenarios."""
+ """
+ Check that ADDRESS is really the code execution address in all scenarios.
+ """
def make_test_code(self, pre: Alloc, fork: Fork) -> Bytecode:
"""Test code."""
@@ -427,7 +430,10 @@ def id(self) -> str:
def result(self) -> ProgramResult:
"""Test result."""
- return ProgramResult(result=1, from_fork=Istanbul)
+ # TODO: use `chain_config` fixture instead.
+ chain_id = ChainConfigDefaults.chain_id
+
+ return ProgramResult(result=chain_id, from_fork=Istanbul)
class ProgramSelfbalance(ScenarioTestProgram):
diff --git a/tests/eest/frontier/scenarios/programs/invalid_opcodes.py b/tests/eest/frontier/scenarios/programs/invalid_opcodes.py
index 82c396ff58..0157dba7b2 100644
--- a/tests/eest/frontier/scenarios/programs/invalid_opcodes.py
+++ b/tests/eest/frontier/scenarios/programs/invalid_opcodes.py
@@ -4,7 +4,7 @@
from ethereum_test_forks import Fork
from ethereum_test_tools import Alloc, Bytecode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from ..common import ProgramResult, ScenarioTestProgram, make_invalid_opcode_contract
diff --git a/tests/eest/frontier/scenarios/programs/static_violation.py b/tests/eest/frontier/scenarios/programs/static_violation.py
index 950eed293e..42146f2c4b 100644
--- a/tests/eest/frontier/scenarios/programs/static_violation.py
+++ b/tests/eest/frontier/scenarios/programs/static_violation.py
@@ -4,7 +4,7 @@
from ethereum_test_forks import Cancun, Fork
from ethereum_test_tools import Alloc, Bytecode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from ..common import ProgramResult, ScenarioTestProgram
diff --git a/tests/eest/frontier/scenarios/scenarios/call_combinations.py b/tests/eest/frontier/scenarios/scenarios/call_combinations.py
index 1049218f27..318c48d08e 100644
--- a/tests/eest/frontier/scenarios/scenarios/call_combinations.py
+++ b/tests/eest/frontier/scenarios/scenarios/call_combinations.py
@@ -4,9 +4,8 @@
from typing import List
from ethereum_test_tools import Address, Alloc
-from ethereum_test_tools.vm.opcode import Opcode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
-from ethereum_test_vm import EVMCodeType
+from ethereum_test_vm import EVMCodeType, Opcode
+from ethereum_test_vm import Opcodes as Op
from ..common import Scenario, ScenarioEnvironment, ScenarioGeneratorInput
@@ -56,15 +55,17 @@ def __init__(self, scenario_input: ScenarioGeneratorInput):
def generate(self) -> List[Scenario]:
"""
- Generate Scenarios for call combinations
- We take code that we want to test at scenario_input.operation_contract
- and put it in the context of call combinations.
+ Generate Scenarios for call combinations We take code that we want to
+ test at scenario_input.operation_contract and put it in the context of
+ call combinations.
Example:
- root_contract -> call -> scenario_contract -> first_call -> sub_contract
- sub_contact -> second_call -> code
- We assume that code always returns it's result
- That we pass as return value in scenario_contract for the post state verification
+ root_contract -> call -> scenario_contract -> first_call ->
+ sub_contract sub_contact -> second_call -> code
+
+ We assume that code always returns its result.
+ That we pass as return value in scenario_contract for the
+ post state verification.
"""
scenarios_list: List[Scenario] = []
@@ -81,8 +82,8 @@ def generate(self) -> List[Scenario]:
def _generate_one_call_scenario(self, first_call: Opcode) -> Scenario:
"""
- Generate scenario for only one call
- root_contract -(CALL)-> scenario_contract -(first_call)-> operation_contract.
+ Generate scenario for only one call root_contract -(CALL)->
+ scenario_contract -(first_call)-> operation_contract.
"""
scenario_input: ScenarioGeneratorInput = self.scenario_input
pre: Alloc = scenario_input.pre
@@ -163,15 +164,16 @@ def _generate_one_call_scenario(self, first_call: Opcode) -> Scenario:
def _generate_two_call_scenario(self, first_call: Opcode, second_call: Opcode) -> Scenario:
"""
- Generate scenario for two types of calls combination
- root_contract -(CALL)-> scenario_contract -(first_call)-> sub_contract
- sub_contract -(second_call) -> operation_contract.
+ Generate scenario for two types of calls combination root_contract
+ -(CALL)-> scenario_contract -(first_call)-> sub_contract sub_contract
+ -(second_call) -> operation_contract.
"""
def _compute_code_caller() -> Address:
"""
- Calculate who is the code caller in program_contract's code in given sequence
- root -CALL-> scenario_contract -(first_call)-> sub_contract -(second_call)-> program.
+ Calculate who is the code caller in program_contract's code in
+ given sequence root -CALL-> scenario_contract -(first_call)
+ -> sub_contract -(second_call)-> program.
"""
code_caller: Address = root_contract
if first_call == Op.DELEGATECALL:
@@ -189,8 +191,9 @@ def _compute_code_caller() -> Address:
def _compute_selfbalance() -> int:
"""
- Calculate the result of Op.SELFBALANCE in program scope in given sequence
- root -CALL-> scenario_contract -(first_call)-> sub_contract -(second_call)-> program.
+ Calculate the result of Op.SELFBALANCE in program scope in given
+ sequence root -CALL-> scenario_contract -(first_call)->
+ sub_contract -(second_call)-> program.
"""
selfbalance: int = 0
if second_call in [Op.CALL]:
@@ -215,7 +218,8 @@ def _compute_selfbalance() -> int:
def _compute_callvalue() -> int:
"""
Calculate the expected callvalue in program scope given sequence:
- root -CALL-> scenario_contract -(first_call)-> sub_contract -(second_call)-> program.
+ root -CALL-> scenario_contract -(first_call)-> sub_contract
+ -(second_call)-> program.
"""
if second_call == Op.STATICCALL:
return 0
diff --git a/tests/eest/frontier/scenarios/scenarios/create_combinations.py b/tests/eest/frontier/scenarios/scenarios/create_combinations.py
index 8c43dcb88c..0a5040a873 100644
--- a/tests/eest/frontier/scenarios/scenarios/create_combinations.py
+++ b/tests/eest/frontier/scenarios/scenarios/create_combinations.py
@@ -4,11 +4,10 @@
from typing import List
from ethereum_test_tools import Alloc, Bytecode
-from ethereum_test_tools.vm.opcode import Macros as Om
-from ethereum_test_tools.vm.opcode import Opcode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types import compute_create_address
-from ethereum_test_vm import EVMCodeType
+from ethereum_test_vm import EVMCodeType, Opcode
+from ethereum_test_vm import Macros as Om
+from ethereum_test_vm import Opcodes as Op
from ..common import Scenario, ScenarioEnvironment, ScenarioGeneratorInput
@@ -28,7 +27,10 @@ def scenarios_create_combinations(scenario_input: ScenarioGeneratorInput) -> Lis
"""Generate Scenarios for create combinations."""
def _compute_selfbalance() -> int:
- """Compute selfbalance opcode for root -> call -> scenario -> create | [call*] -> program.""" # noqa: E501
+ """
+ Compute selfbalance opcode for root -> call -> scenario ->
+ create | [call*] -> program.
+ """
if call in [Op.DELEGATECALL, Op.CALLCODE]:
return (
balance.scenario_contract_balance + balance.root_call_value - balance.create_value
@@ -52,7 +54,8 @@ def _compute_selfbalance() -> int:
salt = [0] if create == Op.CREATE2 else []
operation_contract = scenario_input.pre.deploy_contract(code=scenario_input.operation_code)
- # the code result in init code will be actually code of a deployed contract
+ # the code result in init code will be actually code of a deployed
+ # contract
scenario_contract = scenario_input.pre.deploy_contract(
balance=3,
code=Op.EXTCODECOPY(operation_contract, 0, 0, Op.EXTCODESIZE(operation_contract))
diff --git a/tests/eest/frontier/scenarios/scenarios/revert_combinations.py b/tests/eest/frontier/scenarios/scenarios/revert_combinations.py
index 1734428523..668fe83455 100644
--- a/tests/eest/frontier/scenarios/scenarios/revert_combinations.py
+++ b/tests/eest/frontier/scenarios/scenarios/revert_combinations.py
@@ -2,9 +2,9 @@
from typing import List
-from ethereum_test_tools.vm.opcode import Macro, Opcode
-from ethereum_test_tools.vm.opcode import Macros as Om
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Macro, Opcode
+from ethereum_test_vm import Macros as Om
+from ethereum_test_vm import Opcodes as Op
from ..common import Scenario, ScenarioEnvironment, ScenarioGeneratorInput
diff --git a/tests/eest/frontier/scenarios/test_scenarios.py b/tests/eest/frontier/scenarios/test_scenarios.py
index 4fd73509ce..263e8fa71d 100644
--- a/tests/eest/frontier/scenarios/test_scenarios.py
+++ b/tests/eest/frontier/scenarios/test_scenarios.py
@@ -1,6 +1,6 @@
"""
-Call every possible opcode and test that the subcall is successful
-if the opcode is supported by the fork and fails otherwise.
+Call every possible opcode and test that the subcall is successful if the
+opcode is supported by the fork and fails otherwise.
"""
from typing import List
@@ -18,7 +18,7 @@
Storage,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .common import (
ExecutionEnvironment,
@@ -76,7 +76,10 @@
@pytest.fixture
def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List[Scenario]:
- """Define fixture vectors of all possible scenarios, given the current pre state input."""
+ """
+ Define fixture vectors of all possible scenarios, given the current pre
+ state input.
+ """
scenarios_list: List[Scenario] = []
scenario_input = ScenarioGeneratorInput(
@@ -117,10 +120,14 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List
)
@pytest.mark.valid_from("Frontier")
@pytest.mark.parametrize(
- # select program to debug ("program_id", "scenario_name")
- # program="" select all programs
- # scenario_name="" select all scenarios
- # Example: [ScenarioDebug(program_id=ProgramSstoreSload().id, scenario_name="scenario_CALL_CALL")], # noqa: E501
+ # select program to debug ("program_id","scenario_name")
+ # program=""
+ # select all programs scenario_name=""
+ # select all scenarios
+ #
+ # Example:
+ # [ScenarioDebug(program_id=ProgramSstoreSload().id,
+ # scenario_name="scenario_CALL_CALL")]
"debug",
[
ScenarioDebug(
@@ -137,7 +144,7 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List
ProgramTstoreTload(),
ProgramLogs(),
ProgramSuicide(),
- pytest.param(ProgramInvalidOpcode(), marks=[pytest.mark.slow()]),
+ ProgramInvalidOpcode(),
ProgramAddress(),
ProgramBalance(),
ProgramOrigin(),
@@ -152,7 +159,7 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List
ProgramReturnDataSize(),
ProgramReturnDataCopy(),
ProgramExtCodehash(),
- pytest.param(ProgramBlockhash(), marks=[pytest.mark.slow()]),
+ ProgramBlockhash(),
ProgramCoinbase(),
ProgramTimestamp(),
ProgramNumber(),
@@ -169,6 +176,7 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List
ProgramAllFrontierOpcodes(),
],
)
+@pytest.mark.slow()
def test_scenarios(
blockchain_test: BlockchainTestFiller,
fork: Fork,
@@ -178,13 +186,13 @@ def test_scenarios(
scenarios,
):
"""
- Test given operation in different scenarios
- Verify that it's return value equal to expected result on every scenario,
- that is valid for the given fork.
+ Test given operation in different scenarios Verify that it's return value
+ equal to expected result on every scenario, that is valid for the given
+ fork.
- Note: Don't use pytest parametrize for scenario production, because scenarios will be complex
- Generate one test file for [each operation] * [each scenario] to save space
- As well as operations will be complex too
+ Note: Don't use pytest parametrize for scenario production, because
+ scenarios will be complex Generate one test file for [each operation] *
+ [each scenario] to save space As well as operations will be complex too
"""
tx_env = Environment()
tx_origin: Address = pre.fund_eoa()
@@ -213,7 +221,8 @@ def test_scenarios(
fork=fork,
origin=tx_origin,
gasprice=tx_gasprice,
- timestamp=tx_env.timestamp, # we can't know timestamp before head, use gas hash
+ timestamp=tx_env.timestamp, # we can't know timestamp before head,
+ # use gas hash
number=len(blocks) + 1,
gaslimit=tx_env.gas_limit,
coinbase=tx_env.fee_recipient,
diff --git a/tests/eest/homestead/coverage/test_coverage.py b/tests/eest/homestead/coverage/test_coverage.py
index b7240c38a3..5274307642 100644
--- a/tests/eest/homestead/coverage/test_coverage.py
+++ b/tests/eest/homestead/coverage/test_coverage.py
@@ -1,10 +1,13 @@
-"""Tests that address coverage gaps that result from updating `ethereum/tests` into EEST tests."""
+"""
+Tests that address coverage gaps that result from updating `ethereum/tests`
+into EEST tests.
+"""
import pytest
from ethereum_test_forks import Cancun, Fork
from ethereum_test_tools import Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "N/A"
REFERENCE_SPEC_VERSION = "N/A"
@@ -17,11 +20,11 @@ def test_coverage(
fork: Fork,
):
"""
- Cover gaps that result from transforming Yul code into
- `ethereum_test_tools.vm.opcode.Opcodes` bytecode.
+ Cover gaps that result from transforming Yul code into our Python opcode
+ wrapper bytecode.
- E.g. Yul tends to optimize stack items by using `SWAP1` and `DUP1` opcodes, which are not
- regularly used in python code.
+ E.g. Yul tends to optimize stack items by using `SWAP1` and `DUP1` opcodes,
+ which are not regularly used in python code.
Modify this test to cover more Yul code if required in the future.
"""
diff --git a/tests/eest/homestead/identity_precompile/__init__.py b/tests/eest/homestead/identity_precompile/__init__.py
new file mode 100644
index 0000000000..786785884f
--- /dev/null
+++ b/tests/eest/homestead/identity_precompile/__init__.py
@@ -0,0 +1 @@
+"""abstract: EIP-2: Homestead Precompile Identity Test Cases."""
diff --git a/tests/eest/homestead/identity_precompile/test_identity.py b/tests/eest/homestead/identity_precompile/test_identity.py
new file mode 100644
index 0000000000..b818079738
--- /dev/null
+++ b/tests/eest/homestead/identity_precompile/test_identity.py
@@ -0,0 +1,103 @@
+"""abstract: EIP-2: Homestead Identity Precompile Test Cases."""
+
+import pytest
+
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ Environment,
+ StateTestFiller,
+ Transaction,
+ keccak256,
+)
+from ethereum_test_tools import Opcodes as Op
+
+
+@pytest.mark.with_all_call_opcodes()
+@pytest.mark.valid_from("Byzantium")
+def test_identity_return_overwrite(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ call_opcode: Op,
+):
+ """
+ Test the return data of the identity precompile overwriting its input.
+ """
+ code = (
+ sum(Op.MSTORE8(offset=i, value=(i + 1)) for i in range(4)) # memory = [1, 2, 3, 4]
+ + call_opcode(
+ address=4,
+ args_offset=0,
+ args_size=4, # args = [1, 2, 3, 4]
+ ret_offset=1,
+ ret_size=4,
+ ) # memory = [1, 1, 2, 3, 4]
+ + Op.RETURNDATACOPY(
+ dest_offset=0, offset=0, size=Op.RETURNDATASIZE()
+ ) # memory correct = [1, 2, 3, 4, 4], corrupt = [1, 1, 2, 3, 4]
+ + Op.SSTORE(1, Op.SHA3(offset=0, size=Op.MSIZE))
+ )
+ contract_address = pre.deploy_contract(
+ code=code,
+ )
+ tx = Transaction(
+ sender=pre.fund_eoa(),
+ to=contract_address,
+ gas_limit=100_000,
+ )
+
+ post = {
+ contract_address: Account(
+ storage={
+ 1: keccak256(bytes([1, 2, 3, 4, 4]).ljust(32, b"\0")),
+ },
+ ),
+ }
+
+ state_test(pre=pre, post=post, tx=tx)
+
+
+@pytest.mark.with_all_call_opcodes()
+@pytest.mark.valid_from("Byzantium")
+def test_identity_return_buffer_modify(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ call_opcode: Op,
+):
+ """
+ Test the modification of the input range to attempt to modify the return
+ buffer.
+ """
+ env = Environment()
+ code = (
+ sum(Op.MSTORE8(offset=i, value=(i + 1)) for i in range(4)) # memory = [1, 2, 3, 4]
+ + call_opcode(
+ address=4,
+ args_offset=0,
+ args_size=4, # args = [1, 2, 3, 4]
+ ) # memory = [1, 2, 3, 4]
+ + Op.MSTORE8(offset=0, value=5) # memory = [5, 2, 3, 4]
+ + Op.MSTORE8(offset=4, value=5) # memory = [5, 2, 3, 4, 5]
+ + Op.RETURNDATACOPY(
+ dest_offset=0, offset=0, size=Op.RETURNDATASIZE()
+ ) # memory correct = [1, 2, 3, 4, 5], corrupt = [5, 2, 3, 4, 5]
+ + Op.SSTORE(1, Op.SHA3(offset=0, size=Op.MSIZE))
+ )
+ contract_address = pre.deploy_contract(
+ code=code,
+ )
+ tx = Transaction(
+ sender=pre.fund_eoa(),
+ to=contract_address,
+ gas_limit=100_000,
+ )
+
+ post = {
+ contract_address: Account(
+ storage={
+ 1: keccak256(bytes([1, 2, 3, 4, 5]).ljust(32, b"\0")),
+ },
+ ),
+ }
+
+ state_test(env=env, pre=pre, post=post, tx=tx)
diff --git a/tests/eest/istanbul/eip1344_chainid/__init__.py b/tests/eest/istanbul/eip1344_chainid/__init__.py
index bb41fcd2e7..3669063cbe 100644
--- a/tests/eest/istanbul/eip1344_chainid/__init__.py
+++ b/tests/eest/istanbul/eip1344_chainid/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-1344: ChainID Opcode](https://eips.ethereum.org/EIPS/eip-1344)
- Test cases for [EIP-1344: ChainID Opcode](https://eips.ethereum.org/EIPS/eip-1344).
+Tests for [EIP-1344: ChainID Opcode](https://eips.ethereum.org/EIPS/eip-1344).
"""
diff --git a/tests/eest/istanbul/eip1344_chainid/test_chainid.py b/tests/eest/istanbul/eip1344_chainid/test_chainid.py
index 0fb3b7fbaf..da878691b2 100644
--- a/tests/eest/istanbul/eip1344_chainid/test_chainid.py
+++ b/tests/eest/istanbul/eip1344_chainid/test_chainid.py
@@ -1,12 +1,11 @@
"""
-abstract: Tests [EIP-1344: CHAINID opcode](https://eips.ethereum.org/EIPS/eip-1344)
- Test cases for [EIP-1344: CHAINID opcode](https://eips.ethereum.org/EIPS/eip-1344).
+Tests [EIP-1344: CHAINID opcode](https://eips.ethereum.org/EIPS/eip-1344).
"""
import pytest
from ethereum_test_tools import Account, Alloc, ChainConfig, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1344.md"
REFERENCE_SPEC_VERSION = "02e46aebc80e6e5006ab4d2daa41876139f9a9e2"
diff --git a/tests/eest/istanbul/eip152_blake2/__init__.py b/tests/eest/istanbul/eip152_blake2/__init__.py
index 1f034e456f..040419e930 100644
--- a/tests/eest/istanbul/eip152_blake2/__init__.py
+++ b/tests/eest/istanbul/eip152_blake2/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-152: BLAKE2 compression precompile](https://eips.ethereum.org/EIPS/eip-152)
- Test cases for [EIP-152: BLAKE2 compression precompile](https://eips.ethereum.org/EIPS/eip-152).
+Tests [EIP-152: BLAKE2 compression precompile](https://eips.ethereum.org/EIPS/eip-152).
"""
diff --git a/tests/eest/istanbul/eip152_blake2/common.py b/tests/eest/istanbul/eip152_blake2/common.py
index 7081a31a2e..2f0ab7ba7c 100644
--- a/tests/eest/istanbul/eip152_blake2/common.py
+++ b/tests/eest/istanbul/eip152_blake2/common.py
@@ -14,15 +14,19 @@ class Blake2bInput(TestParameterGroup):
call data from them. Returns all inputs encoded as bytes.
Attributes:
- rounds_length (int): An optional integer representing the bytes length
- for the number of rounds. Defaults to the expected length of 4.
- rounds (int | str): A hex string or integer value representing the number of rounds.
- h (str): A hex string that represents the state vector.
- m (str): A hex string that represents the message block vector.
- t_0 (int | str): A hex string or integer value that represents the first offset counter.
- t_1 (int | str): A hex string or integer value that represents the second offset counter.
- f (bool): An optional boolean that represents the final block indicator flag.
- Defaults to True.
+ rounds_length (int): An optional integer representing the bytes
+ length for the number of rounds.
+ Defaults to the expected length of 4.
+ rounds (int | str): A hex string or integer value representing the number
+ of rounds.
+ h (str): A hex string that represents the state vector.
+ m (str): A hex string that represents the message block vector.
+ t_0 (int | str): A hex string or integer value that represents
+ the first offset counter.
+ t_1(int | str): A hex string or integer value that represents the second
+ offset counter.
+ f (bool): An optional boolean that represents the final block indicator
+ flag. Defaults to True.
"""
@@ -58,10 +62,10 @@ class ExpectedOutput(TestParameterGroup):
Expected test result.
Attributes:
- call_succeeds (str | bool): A hex string or boolean to indicate whether the call was
- successful or not.
- data_1 (str): String value of the first updated state vector.
- data_2 (str): String value of the second updated state vector.
+ call_succeeds (str | bool): A hex string or boolean to indicate
+ whether the call was successful or not.
+ data_1 (str): String value of the first updated state vector.
+ data_2 (str): String value of the second updated state vector.
"""
diff --git a/tests/eest/istanbul/eip152_blake2/conftest.py b/tests/eest/istanbul/eip152_blake2/conftest.py
index c21a352ced..a6fbc26be1 100644
--- a/tests/eest/istanbul/eip152_blake2/conftest.py
+++ b/tests/eest/istanbul/eip152_blake2/conftest.py
@@ -2,8 +2,8 @@
import pytest
-from ethereum_test_tools.vm.opcode import Opcodes as Op
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .spec import Spec
@@ -11,8 +11,8 @@
@pytest.fixture
def blake2b_contract_bytecode(call_opcode: Op) -> Bytecode:
"""
- Contract code that performs the provided opcode (CALL or CALLCODE) to the BLAKE2b precompile
- and stores the result.
+ Contract code that performs the provided opcode (CALL or CALLCODE) to the
+ BLAKE2b precompile and stores the result.
"""
return (
Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
diff --git a/tests/eest/istanbul/eip152_blake2/spec.py b/tests/eest/istanbul/eip152_blake2/spec.py
index 38413b7189..021c94a28d 100644
--- a/tests/eest/istanbul/eip152_blake2/spec.py
+++ b/tests/eest/istanbul/eip152_blake2/spec.py
@@ -35,7 +35,8 @@ class Spec:
BLAKE2_PRECOMPILE_T_1_LENGTH = 8
BLAKE2_PRECOMPILE_F_LENGTH = 1
- # Constants for BLAKE2b and BLAKE2s spec defined at https://datatracker.ietf.org/doc/html/rfc7693#section-3.2
+ # Constants for BLAKE2b and BLAKE2s spec defined at
+ # https://datatracker.ietf.org/doc/html/rfc7693#section-3.2
BLAKE2B_PRECOMPILE_ROUNDS = 12
BLAKE2B_PRECOMPILE_H_LENGTH = 64
@@ -47,8 +48,19 @@ class SpecTestVectors:
"""Defines common test parameters for the BLAKE2b precompile."""
# The following constants are used to define common test parameters
- # Origin of vectors defined at https://datatracker.ietf.org/doc/html/rfc7693.html#appendix-A
- BLAKE2_STATE_VECTOR = "48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b" # noqa:E501
- BLAKE2_MESSAGE_BLOCK_VECTOR = "6162630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" # noqa:E501
+ # Origin of vectors defined at
+ # https://datatracker.ietf.org/doc/html/rfc7693.html#appendix-A
+ BLAKE2_STATE_VECTOR = (
+ "48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1"
+ "361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f"
+ "79217e1319cde05b"
+ )
+ BLAKE2_MESSAGE_BLOCK_VECTOR = (
+ "616263000000000000000000000000000000000"
+ "00000000000000000000000000000000000000000000000000000000000000000"
+ "00000000000000000000000000000000000000000000000000000000000000000"
+ "00000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000"
+ )
BLAKE2_OFFSET_COUNTER_0 = 3
BLAKE2_OFFSET_COUNTER_1 = 0
diff --git a/tests/eest/istanbul/eip152_blake2/test_blake2.py b/tests/eest/istanbul/eip152_blake2/test_blake2.py
index 0fb8660781..f22b4ef3ef 100644
--- a/tests/eest/istanbul/eip152_blake2/test_blake2.py
+++ b/tests/eest/istanbul/eip152_blake2/test_blake2.py
@@ -1,6 +1,5 @@
"""
-abstract: Tests [EIP-152: BLAKE2b compression precompile](https://eips.ethereum.org/EIPS/eip-152)
- Test cases for [EIP-152: BLAKE2b compression precompile](https://eips.ethereum.org/EIPS/eip-152).
+Tests [EIP-152: BLAKE2b compression precompile](https://eips.ethereum.org/EIPS/eip-152).
"""
from typing import List
@@ -16,7 +15,7 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .common import Blake2bInput, ExpectedOutput
from .spec import SpecTestVectors, ref_spec_152
@@ -390,6 +389,7 @@
),
],
)
+@pytest.mark.slow()
def test_blake2b(
state_test: StateTestFiller,
pre: Alloc,
diff --git a/tests/eest/istanbul/eip152_blake2/test_blake2_delegatecall.py b/tests/eest/istanbul/eip152_blake2/test_blake2_delegatecall.py
index b7ed40ba4a..79ecfb664b 100644
--- a/tests/eest/istanbul/eip152_blake2/test_blake2_delegatecall.py
+++ b/tests/eest/istanbul/eip152_blake2/test_blake2_delegatecall.py
@@ -1,4 +1,6 @@
-"""abstract: Test delegatecall to Blake2B Precompile before and after it was added."""
+"""
+Test delegatecall to Blake2B Precompile before and after added.
+"""
import pytest
@@ -21,7 +23,10 @@
@pytest.mark.valid_from("ConstantinopleFix")
def test_blake2_precompile_delegatecall(state_test: StateTestFiller, pre: Alloc, fork: Fork):
- """Test delegatecall consumes specified gas for the Blake2B precompile when it exists."""
+ """
+ Test delegatecall consumes specified gas for the Blake2B precompile when it
+ exists.
+ """
env = Environment()
account = pre.deploy_contract(
@@ -43,7 +48,8 @@ def test_blake2_precompile_delegatecall(state_test: StateTestFiller, pre: Alloc,
protected=True,
)
- # If precompile exists, DELEGATECALL will fail, otherwise DELEGATECALL will succeed
+ # If precompile exists, DELEGATECALL will fail, otherwise DELEGATECALL will
+ # succeed
post = {
account: Account(
storage={
diff --git a/tests/eest/osaka/__init__.py b/tests/eest/osaka/__init__.py
index 5eceac229b..81fc13f353 100644
--- a/tests/eest/osaka/__init__.py
+++ b/tests/eest/osaka/__init__.py
@@ -1 +1,4 @@
-"""Test cases for EVM functionality introduced in Osaka, [EIP-7607: Hardfork Meta - Fusaka](https://eip.directory/eips/eip-7607).""" # noqa: E501
+"""
+Test cases for EVM functionality introduced in Osaka, [EIP-7607: Hardfork Meta
+- Fusaka](https://eip.directory/eips/eip-7607).
+"""
diff --git a/tests/eest/osaka/eip7594_peerdas/__init__.py b/tests/eest/osaka/eip7594_peerdas/__init__.py
index 3b5d044978..43cd5354b7 100644
--- a/tests/eest/osaka/eip7594_peerdas/__init__.py
+++ b/tests/eest/osaka/eip7594_peerdas/__init__.py
@@ -1,4 +1,5 @@
"""
Test suite for
-[EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594).
+[EIP-7594: PeerDAS - Peer Data Availability
+Sampling](https://eips.ethereum.org/EIPS/eip-7594).
"""
diff --git a/tests/eest/osaka/eip7594_peerdas/test_get_blobs.py b/tests/eest/osaka/eip7594_peerdas/test_get_blobs.py
index 5e8e9a350f..a38fcf36c5 100644
--- a/tests/eest/osaka/eip7594_peerdas/test_get_blobs.py
+++ b/tests/eest/osaka/eip7594_peerdas/test_get_blobs.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests get blobs engine endpoint for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594)
- Test get blobs engine endpoint for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594).
-""" # noqa: E501
+Get blobs engine endpoint tests.
+
+Tests for get blobs engine endpoint in [EIP-7594: PeerDAS - Peer Data
+Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594).
+"""
from hashlib import sha256
from typing import List, Optional
@@ -19,7 +21,7 @@
Transaction,
TransactionException,
)
-from pytest_plugins.logging import get_logger
+from pytest_plugins.custom_logging import get_logger
from .spec import ref_spec_7594
@@ -92,7 +94,8 @@ def excess_blob_gas(
block_base_fee_per_gas: int,
) -> int | None:
"""
- Calculate the excess blob gas of the block under test from the parent block.
+ Calculate the excess blob gas of the block under test from the parent
+ block.
Value can be overloaded by a test case to provide a custom excess blob gas.
"""
@@ -148,10 +151,10 @@ def tx_max_fee_per_blob_gas( # noqa: D103
@pytest.fixture
def tx_error() -> Optional[TransactionException]:
"""
- Even though the final block we are producing in each of these tests is invalid, and some of the
- transactions will be invalid due to the format in the final block, none of the transactions
- should be rejected by the transition tool because they are being sent to it with the correct
- format.
+ Even though the final block we are producing in each of these tests is
+ invalid, and some of the transactions will be invalid due to the format in
+ the final block, none of the transactions should be rejected by the
+ transition tool because they are being sent to it with the correct format.
"""
return None
@@ -319,8 +322,8 @@ def test_get_blobs(
txs: List[NetworkWrappedTransaction | Transaction],
):
"""
- Test valid blob combinations where one or more txs in the block
- serialized version contain a full blob (network version) tx.
+ Test valid blob combinations where one or more txs in the block serialized
+ version contain a full blob (network version) tx.
"""
blobs_test(pre=pre, txs=txs)
@@ -336,6 +339,9 @@ def test_get_blobs_nonexisting(
pre: Alloc,
txs: List[NetworkWrappedTransaction | Transaction],
):
- """Test that ensures clients respond with 'null' when at least one requested blob is not available.""" # noqa: E501
+ """
+ Test that ensures clients respond with 'null' when at least one requested
+ blob is not available.
+ """
nonexisting_blob_hashes = [Hash(sha256(str(i).encode()).digest()) for i in range(5)]
blobs_test(pre=pre, txs=txs, nonexisting_blob_hashes=nonexisting_blob_hashes)
diff --git a/tests/eest/osaka/eip7594_peerdas/test_max_blob_per_tx.py b/tests/eest/osaka/eip7594_peerdas/test_max_blob_per_tx.py
index 52c6eb2fde..4dcf4ce205 100644
--- a/tests/eest/osaka/eip7594_peerdas/test_max_blob_per_tx.py
+++ b/tests/eest/osaka/eip7594_peerdas/test_max_blob_per_tx.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests `MAX_BLOBS_PER_TX` limit for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594)
- Tests `MAX_BLOBS_PER_TX` limit for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594).
-""" # noqa: E501
+MAX_BLOBS_PER_TX limit tests.
+
+Tests for `MAX_BLOBS_PER_TX` limit in [EIP-7594: PeerDAS - Peer Data
+Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594).
+"""
import pytest
@@ -88,9 +90,9 @@ def test_valid_max_blobs_per_tx(
tx: Transaction,
):
"""
- Test that transactions with blob count from 1 to MAX_BLOBS_PER_TX are accepted.
- Verifies that individual transactions can contain up to the maximum allowed
- number of blobs per transaction.
+ Test that transactions with blob count from 1 to MAX_BLOBS_PER_TX are
+ accepted. Verifies that individual transactions can contain up to the
+ maximum allowed number of blobs per transaction.
"""
state_test(
env=env,
@@ -120,10 +122,10 @@ def test_invalid_max_blobs_per_tx(
blob_count: int,
):
"""
- Test that transactions exceeding MAX_BLOBS_PER_TX are rejected.
- Verifies that individual transactions cannot contain more than the maximum
- allowed number of blobs per transaction, even if the total would be within
- the block limit.
+ Test that transactions exceeding MAX_BLOBS_PER_TX are rejected. Verifies
+ that individual transactions cannot contain more than the maximum allowed
+ number of blobs per transaction, even if the total would be within the
+ block limit.
"""
state_test(
env=env,
@@ -177,7 +179,7 @@ def test_max_blobs_per_tx_fork_transition(
exception=[expected_exception],
)
post_fork_block = Block(
- txs=[tx.with_nonce(2).with_error(expected_exception)],
+ txs=[tx.with_nonce(1).with_error(expected_exception)],
timestamp=FORK_TIMESTAMP + 1,
exception=[expected_exception],
)
diff --git a/tests/eest/osaka/eip7823_modexp_upper_bounds/__init__.py b/tests/eest/osaka/eip7823_modexp_upper_bounds/__init__.py
index 20ebfaec01..b41a84cc6c 100644
--- a/tests/eest/osaka/eip7823_modexp_upper_bounds/__init__.py
+++ b/tests/eest/osaka/eip7823_modexp_upper_bounds/__init__.py
@@ -1,4 +1,5 @@
"""
-abstract: Tests [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823)
- Test cases for [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823).
+Tests [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823).
+
+Test cases for EIP-7823: Set upper bounds for MODEXP.
"""
diff --git a/tests/eest/osaka/eip7823_modexp_upper_bounds/conftest.py b/tests/eest/osaka/eip7823_modexp_upper_bounds/conftest.py
new file mode 100644
index 0000000000..663cd5456d
--- /dev/null
+++ b/tests/eest/osaka/eip7823_modexp_upper_bounds/conftest.py
@@ -0,0 +1,194 @@
+"""Conftest for EIP-7823 tests."""
+
+from typing import Dict
+
+import pytest
+
+from ethereum_test_forks import Fork, Osaka
+from ethereum_test_tools import Account, Address, Alloc, Storage, Transaction, keccak256
+from ethereum_test_types import Environment
+from ethereum_test_vm import Opcodes as Op
+
+from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput
+from ..eip7883_modexp_gas_increase.spec import Spec, Spec7883
+
+
+@pytest.fixture
+def call_contract_post_storage() -> Storage:
+ """
+ Storage of the test contract after the transaction is executed. Note:
+ Fixture `call_contract_code` fills the actual expected storage values.
+ """
+ return Storage()
+
+
+@pytest.fixture
+def call_succeeds(
+ total_gas_used: int, fork: Fork, env: Environment, modexp_input: ModExpInput
+) -> bool:
+ """
+ By default, depending on the expected output, we can deduce if the call is
+ expected to succeed or fail.
+ """
+ # Transaction gas limit exceeded
+ tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit
+ if total_gas_used > tx_gas_limit_cap:
+ return False
+
+ # Input length exceeded
+ base_length, exp_length, mod_length = modexp_input.get_declared_lengths()
+ if (
+ base_length > Spec.MAX_LENGTH_BYTES
+ or exp_length > Spec.MAX_LENGTH_BYTES
+ or mod_length > Spec.MAX_LENGTH_BYTES
+ ) and fork >= Osaka:
+ return False
+
+ return True
+
+
+@pytest.fixture
+def gas_measure_contract(
+ pre: Alloc,
+ fork: Fork,
+ modexp_expected: bytes,
+ precompile_gas: int,
+ call_contract_post_storage: Storage,
+ call_succeeds: bool,
+) -> Address:
+ """
+ Deploys a contract that measures ModExp gas consumption and execution
+ result.
+
+ Always stored:
+ storage[0]: precompile call success
+ storage[1]: return data length from precompile
+ Only if the precompile call succeeds:
+ storage[2]: gas consumed by precompile
+ storage[3]: hash of return data from precompile
+ """
+ call_code = Op.CALL(
+ precompile_gas,
+ Spec.MODEXP_ADDRESS,
+ 0,
+ 0,
+ Op.CALLDATASIZE(),
+ 0,
+ 0,
+ )
+
+ gas_costs = fork.gas_costs()
+ extra_gas = (
+ gas_costs.G_WARM_ACCOUNT_ACCESS
+ + (gas_costs.G_VERY_LOW * (len(Op.CALL.kwargs) - 1)) # type: ignore
+ + gas_costs.G_BASE # CALLDATASIZE
+ + gas_costs.G_BASE # GAS
+ )
+
+ # Build the gas measurement contract code
+ # Stack operations:
+ # [gas_start]
+ # [gas_start, call_result]
+ # [gas_start, call_result, gas_end]
+ # [gas_start, gas_end, call_result]
+ call_result_measurement = Op.GAS + call_code + Op.GAS + Op.SWAP1
+
+ # Calculate gas consumed: gas_start - (gas_end + extra_gas)
+ # Stack Operation:
+ # [gas_start, gas_end]
+ # [gas_start, gas_end, extra_gas]
+ # [gas_start, gas_end + extra_gas]
+ # [gas_end + extra_gas, gas_start]
+ # [gas_consumed]
+ gas_calculation = Op.PUSH2[extra_gas] + Op.ADD + Op.SWAP1 + Op.SUB
+
+ code = (
+ Op.CALLDATACOPY(dest_offset=0, offset=0, size=Op.CALLDATASIZE)
+ + Op.SSTORE(call_contract_post_storage.store_next(call_succeeds), call_result_measurement)
+ + Op.SSTORE(
+ call_contract_post_storage.store_next(len(modexp_expected) if call_succeeds else 0),
+ Op.RETURNDATASIZE(),
+ )
+ )
+
+ if call_succeeds:
+ code += Op.SSTORE(call_contract_post_storage.store_next(precompile_gas), gas_calculation)
+ code += Op.RETURNDATACOPY(dest_offset=0, offset=0, size=Op.RETURNDATASIZE())
+ code += Op.SSTORE(
+ call_contract_post_storage.store_next(keccak256(bytes(modexp_expected))),
+ Op.SHA3(0, Op.RETURNDATASIZE()),
+ )
+ return pre.deploy_contract(code)
+
+
+@pytest.fixture
+def precompile_gas(fork: Fork, modexp_input: ModExpInput) -> int:
+ """
+ Calculate gas cost for the ModExp precompile and verify it matches expected
+ gas.
+ """
+ spec = Spec if fork < Osaka else Spec7883
+ try:
+ calculated_gas = spec.calculate_gas_cost(modexp_input)
+ return calculated_gas
+ except Exception:
+ # Used for `test_modexp_invalid_inputs` we expect the call to not
+ # succeed. Return is for completeness.
+ return 500 if fork >= Osaka else 200
+
+
+@pytest.fixture
+def tx(
+ pre: Alloc,
+ gas_measure_contract: Address,
+ modexp_input: ModExpInput,
+ tx_gas_limit: int,
+) -> Transaction:
+ """Transaction to measure gas consumption of the ModExp precompile."""
+ return Transaction(
+ sender=pre.fund_eoa(),
+ to=gas_measure_contract,
+ data=bytes(modexp_input),
+ gas_limit=tx_gas_limit,
+ )
+
+
+@pytest.fixture
+def total_gas_used(
+ fork: Fork, modexp_expected: bytes, modexp_input: ModExpInput, precompile_gas: int
+) -> int:
+ """
+ Transaction gas limit used for the test (Can be overridden in the test).
+ """
+ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
+ memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
+ extra_gas = 500_000
+
+ total_gas = (
+ extra_gas
+ + intrinsic_gas_cost_calculator(calldata=bytes(modexp_input))
+ + memory_expansion_gas_calculator(new_bytes=len(bytes(modexp_input)))
+ + precompile_gas
+ )
+
+ return total_gas
+
+
+@pytest.fixture
+def tx_gas_limit(total_gas_used: int, fork: Fork, env: Environment) -> int:
+ """
+ Transaction gas limit used for the test (Can be overridden in the test).
+ """
+ tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit
+ return min(tx_gas_limit_cap, total_gas_used)
+
+
+@pytest.fixture
+def post(
+ gas_measure_contract: Address,
+ call_contract_post_storage: Storage,
+) -> Dict[Address, Account]:
+ """Return expected post state with gas consumption check."""
+ return {
+ gas_measure_contract: Account(storage=call_contract_post_storage),
+ }
diff --git a/tests/eest/osaka/eip7823_modexp_upper_bounds/eip_checklist_external_coverage.txt b/tests/eest/osaka/eip7823_modexp_upper_bounds/eip_checklist_external_coverage.txt
new file mode 100644
index 0000000000..213471321d
--- /dev/null
+++ b/tests/eest/osaka/eip7823_modexp_upper_bounds/eip_checklist_external_coverage.txt
@@ -0,0 +1,27 @@
+precompile/test/call_contexts/set_code = Covered in EIP-7702 cases
+precompile/test/call_contexts/normal = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/call_contexts/delegate = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/call_contexts/static = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/call_contexts/callcode = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/call_contexts/tx_entry = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/call_contexts/initcode/CREATE = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/call_contexts/initcode/tx = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/call_contexts/set_code = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/inputs/valid = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/inputs/valid/boundary = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/inputs/all_zeros = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/inputs/invalid = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/inputs/invalid/crypto = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/inputs/invalid/corrupted = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/value_transfer/no_fee = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/out_of_bounds/max_plus_one = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/input_lengths/zero = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/input_lengths/dynamic/valid = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/input_lengths/dynamic/too_long = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/gas_usage/dynamic/exact = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/gas_usage/dynamic/oog = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/excessive_gas_usage = Covered in osaka/eip7883_modexp_gas_increase
+precompile/test/fork_transition/after/warm = Covered in osaka/eip7883_modexp_gas_increase
+gas_cost_changes/test/gas_updates_measurement = Covered in osaka/eip7883_modexp_gas_increase
+gas_cost_changes/test/fork_transition/before = Covered in osaka/eip7883_modexp_gas_increase
+gas_cost_changes/test/fork_transition/after = Covered in osaka/eip7883_modexp_gas_increase
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7823_modexp_upper_bounds/eip_checklist_not_applicable.txt b/tests/eest/osaka/eip7823_modexp_upper_bounds/eip_checklist_not_applicable.txt
new file mode 100644
index 0000000000..2fe9ebdfdc
--- /dev/null
+++ b/tests/eest/osaka/eip7823_modexp_upper_bounds/eip_checklist_not_applicable.txt
@@ -0,0 +1,24 @@
+precompile/test/value_transfer/fee/under = No value is required
+precompile/test/value_transfer/fee/exact = No value is required
+precompile/test/value_transfer/fee/over = No value is required
+precompile/test/input_lengths/static/correct = The Modexp input length is not static
+precompile/test/input_lengths/static/too_short = The Modexp input length is not static
+precompile/test/input_lengths/static/too_long = The Modexp input length is not static
+precompile/test/input_lengths/dynamic/too_short = there would be no padding for precompile
+precompile/test/gas_usage/constant/oog = The Modexp gas cost is dynamic
+precompile/test/gas_usage/constant/exact = The Modexp gas cost is dynamic
+precompile/test/fork_transition/before/invalid_input = Modexp is not new precompile, it is still valid befork fork activation
+precompile/test/fork_transition/before/zero_gas = Modexp is not new precompile, it is still valid befork fork activation
+precompile/test/fork_transition/before/cold = Modexp is not new precompile, it is still valid befork fork activation
+gas_cost_changes/test/out_of_gas = No Out-of-gas scenario in Modexp
+system_contract = EIP does not include a new system contract
+opcode = EIP does not introduce a new opcode
+removed_precompile = EIP does not remove a precompile
+transaction_type = EIP does not introduce a new transaction type
+block_header_field = EIP does not add any new block header fields
+gas_refunds_changes = EIP does not introduce any gas refund changes
+blob_count_changes = EIP does not introduce any blob count changes
+execution_layer_request = EIP does not introduce an execution layer request
+new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint
+modified_transaction_validity_constraint = EIP does not introduce a modified transaction validity constraint
+block_body_field = EIP does not add any new block body fields
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7823_modexp_upper_bounds/spec.py b/tests/eest/osaka/eip7823_modexp_upper_bounds/spec.py
new file mode 100644
index 0000000000..88fddca02a
--- /dev/null
+++ b/tests/eest/osaka/eip7823_modexp_upper_bounds/spec.py
@@ -0,0 +1,14 @@
+"""Defines EIP-7823 specification constants and functions."""
+
+from dataclasses import dataclass
+
+
+@dataclass(frozen=True)
+class ReferenceSpec:
+ """Defines the reference spec version and git path."""
+
+ git_path: str
+ version: str
+
+
+ref_spec_7823 = ReferenceSpec("EIPS/eip-7823.md", "c8321494fdfbfda52ad46c3515a7ca5dc86b857c")
diff --git a/tests/eest/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py b/tests/eest/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py
index 6ac1a74270..d91c4d3c71 100644
--- a/tests/eest/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py
+++ b/tests/eest/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py
@@ -1,123 +1,147 @@
"""
-abstract: Test [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823)
- Tests upper bounds of the MODEXP precompile.
+Test [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823).
"""
-import pytest
-
-from ethereum_test_forks import Fork, Osaka
-from ethereum_test_tools import Account, Alloc, Bytes, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
-
-from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput, ModExpOutput
-from ..eip7883_modexp_gas_increase.spec import Spec, Spec7883
+from typing import Dict
-REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7823.md"
-REFERENCE_SPEC_VERSION = "c8321494fdfbfda52ad46c3515a7ca5dc86b857c"
+import pytest
-MAX_LENGTH_BYTES = 1024
-TX_GAS_LIMIT = 2**24
+from ethereum_test_checklists import EIPChecklist
+from ethereum_test_forks import Fork
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ Block,
+ BlockchainTestFiller,
+ Bytes,
+ StateTestFiller,
+ Transaction,
+ keccak256,
+)
+from ethereum_test_vm import Opcodes as Op
+from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput
+from ..eip7883_modexp_gas_increase.spec import Spec
+from .spec import ref_spec_7823
-@pytest.fixture
-def precompile_gas(fork: Fork, mod_exp_input: ModExpInput) -> int:
- """Calculate gas cost for the ModExp precompile and verify it matches expected gas."""
- spec = Spec if fork < Osaka else Spec7883
- calculated_gas = spec.calculate_gas_cost(mod_exp_input)
- return calculated_gas
+REFERENCE_SPEC_GIT_PATH = ref_spec_7823.git_path
+REFERENCE_SPEC_VERSION = ref_spec_7823.version
-@pytest.mark.valid_from("Prague")
+@pytest.mark.valid_from("Osaka")
@pytest.mark.parametrize(
- "mod_exp_input",
+ "modexp_input,modexp_expected,call_succeeds",
[
pytest.param(
ModExpInput(
- base=b"\0" * (MAX_LENGTH_BYTES + 1),
+ base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
exponent=b"\0",
modulus=b"\2",
),
+ Spec.modexp_error,
+ False,
id="excess_length_base",
),
pytest.param(
ModExpInput(
base=b"\0",
- exponent=b"\0" * (MAX_LENGTH_BYTES + 1),
+ exponent=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
modulus=b"\2",
),
+ Spec.modexp_error,
+ False,
id="excess_length_exponent",
),
pytest.param(
ModExpInput(
base=b"\0",
exponent=b"\0",
- modulus=b"\0" * (MAX_LENGTH_BYTES) + b"\2",
+ modulus=b"\0" * (Spec.MAX_LENGTH_BYTES) + b"\2",
),
+ Spec.modexp_error,
+ False,
id="excess_length_modulus",
),
pytest.param(
ModExpInput(
base=b"",
- exponent=b"\0" * (MAX_LENGTH_BYTES + 1),
+ exponent=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
modulus=b"",
),
+ Spec.modexp_error,
+ False,
id="exp_1025_base_0_mod_0",
),
pytest.param(
ModExpInput(
base=b"",
- # Non-zero exponent is cancelled with zero multiplication complexity pre EIP-7823.
- exponent=b"\xff" * (MAX_LENGTH_BYTES + 1),
+ # Non-zero exponent is cancelled with zero multiplication
+ # complexity pre EIP-7823.
+ exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
modulus=b"",
),
+ Spec.modexp_error,
+ False,
id="expFF_1025_base_0_mod_0",
),
pytest.param(
ModExpInput(
- base=b"\0" * MAX_LENGTH_BYTES,
- exponent=b"\xff" * (MAX_LENGTH_BYTES + 1),
+ base=b"\0" * Spec.MAX_LENGTH_BYTES,
+ exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
modulus=b"",
),
+ Spec.modexp_error,
+ False,
id="expFF_1025_base_1024_mod_0",
),
pytest.param(
ModExpInput(
- base=b"\0" * (MAX_LENGTH_BYTES + 1),
- exponent=b"\xff" * (MAX_LENGTH_BYTES + 1),
+ base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
+ exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
modulus=b"",
),
+ Spec.modexp_error,
+ False,
id="expFF_1025_base_1025_mod_0",
),
pytest.param(
ModExpInput(
- base=b"\0" * (MAX_LENGTH_BYTES + 1),
+ base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
exponent=b"",
modulus=b"",
),
+ Spec.modexp_error,
+ False,
id="exp_0_base_1025_mod_0",
),
pytest.param(
ModExpInput(
- base=b"\0" * (MAX_LENGTH_BYTES + 1),
+ base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
exponent=b"",
modulus=b"\2",
),
+ Spec.modexp_error,
+ False,
id="exp_0_base_1025_mod_1",
),
pytest.param(
ModExpInput(
base=b"",
exponent=b"",
- modulus=b"\0" * (MAX_LENGTH_BYTES + 1),
+ modulus=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
),
+ Spec.modexp_error,
+ False,
id="exp_0_base_0_mod_1025",
),
pytest.param(
ModExpInput(
base=b"\1",
exponent=b"",
- modulus=b"\0" * (MAX_LENGTH_BYTES + 1),
+ modulus=b"\0" * (Spec.MAX_LENGTH_BYTES + 1),
),
+ Spec.modexp_error,
+ False,
id="exp_0_base_1_mod_1025",
),
pytest.param(
@@ -127,32 +151,40 @@ def precompile_gas(fork: Fork, mod_exp_input: ModExpInput) -> int:
modulus=b"",
declared_exponent_length=2**64,
),
+ Spec.modexp_error,
+ False,
id="exp_2_pow_64_base_0_mod_0",
),
# Implementation coverage tests
pytest.param(
ModExpInput(
- base=b"\xff" * (MAX_LENGTH_BYTES + 1),
- exponent=b"\xff" * (MAX_LENGTH_BYTES + 1),
- modulus=b"\xff" * (MAX_LENGTH_BYTES + 1),
+ base=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
+ exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
+ modulus=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
),
+ Spec.modexp_error,
+ False,
id="all_exceed_check_ordering",
),
pytest.param(
ModExpInput(
- base=b"\x00" * MAX_LENGTH_BYTES,
- exponent=b"\xff" * (MAX_LENGTH_BYTES + 1),
- modulus=b"\xff" * (MAX_LENGTH_BYTES + 1),
+ base=b"\x00" * Spec.MAX_LENGTH_BYTES,
+ exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
+ modulus=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1),
),
+ Spec.modexp_error,
+ False,
id="exp_mod_exceed_base_ok",
),
pytest.param(
ModExpInput(
# Bitwise pattern for Nethermind optimization
- base=b"\xaa" * (MAX_LENGTH_BYTES + 1),
- exponent=b"\x55" * MAX_LENGTH_BYTES,
- modulus=b"\xff" * MAX_LENGTH_BYTES,
+ base=b"\xaa" * (Spec.MAX_LENGTH_BYTES + 1),
+ exponent=b"\x55" * Spec.MAX_LENGTH_BYTES,
+ modulus=b"\xff" * Spec.MAX_LENGTH_BYTES,
),
+ Spec.modexp_error,
+ False,
id="bitwise_pattern_base_exceed",
),
pytest.param(
@@ -165,76 +197,158 @@ def precompile_gas(fork: Fork, mod_exp_input: ModExpInput) -> int:
declared_exponent_length=1,
declared_modulus_length=1,
),
+ Spec.modexp_error,
+ False,
id="near_uint64_max_base",
),
pytest.param(
ModExpInput(
- base=b"\x01" * MAX_LENGTH_BYTES,
+ base=b"\x01" * Spec.MAX_LENGTH_BYTES,
exponent=b"",
- modulus=b"\x02" * (MAX_LENGTH_BYTES + 1),
+ modulus=b"\x02" * (Spec.MAX_LENGTH_BYTES + 1),
declared_exponent_length=0,
),
+ Spec.modexp_error,
+ False,
id="zero_exp_mod_exceed",
),
+ pytest.param(
+ ModExpInput(
+ base=b"\x01" * Spec.MAX_LENGTH_BYTES,
+ exponent=b"\x00",
+ modulus=b"\x02",
+ ),
+ b"\x01",
+ True,
+ id="base_boundary",
+ ),
+ pytest.param(
+ ModExpInput(
+ base=b"\x01",
+ exponent=b"\x00" * Spec.MAX_LENGTH_BYTES,
+ modulus=b"\x02",
+ ),
+ b"\x01",
+ True,
+ id="exp_boundary",
+ ),
+ pytest.param(
+ ModExpInput(
+ base=b"\x01",
+ exponent=b"\x00",
+ modulus=b"\x02" * Spec.MAX_LENGTH_BYTES,
+ ),
+ b"\x01".rjust(Spec.MAX_LENGTH_BYTES, b"\x00"),
+ True,
+ id="mod_boundary",
+ ),
+ pytest.param(
+ ModExpInput(
+ base=b"\x01" * Spec.MAX_LENGTH_BYTES,
+ exponent=b"\x00",
+ modulus=b"\x02" * Spec.MAX_LENGTH_BYTES,
+ ),
+ b"\x01".rjust(Spec.MAX_LENGTH_BYTES, b"\x00"),
+ True,
+ id="base_mod_boundary",
+ ),
],
)
+@EIPChecklist.Precompile.Test.Inputs.MaxValues
+@EIPChecklist.Precompile.Test.OutOfBounds.Max
def test_modexp_upper_bounds(
state_test: StateTestFiller,
- mod_exp_input: ModExpInput,
+ modexp_input: ModExpInput,
+ modexp_expected: bytes,
precompile_gas: int,
fork: Fork,
+ tx: Transaction,
+ post: Dict,
pre: Alloc,
):
- """Test the MODEXP precompile."""
- sender = pre.fund_eoa()
+ """Test the MODEXP precompile input bounds."""
+ state_test(pre=pre, tx=tx, post=post)
- account = pre.deploy_contract(
- # Store all CALLDATA into memory (offset 0)
- Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
- # Store the returned CALL status (success = 1, fail = 0) into slot 0:
- + Op.SSTORE(
- 0,
- # Setup stack to CALL into ModExp with the CALLDATA and CALL into it (+ pop value)
- Op.CALL(
- gas=precompile_gas,
- address=0x05,
- value=0,
- args_offset=0,
- args_size=Op.CALLDATASIZE(),
+
+@pytest.mark.parametrize(
+ "modexp_input,modexp_expected",
+ [
+ pytest.param(
+ ModExpInput(
+ base=b"\1" * (Spec.MAX_LENGTH_BYTES + 1),
+ exponent=b"\0",
+ modulus=b"\2",
),
- )
- # STOP (handy for tracing)
- + Op.STOP(),
+ b"\1",
+ id="base_1_exp_0_mod_2",
+ ),
+ ],
+)
+@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True)
+def test_modexp_upper_bounds_fork_transition(
+ blockchain_test: BlockchainTestFiller,
+ pre: Alloc,
+ fork: Fork,
+ precompile_gas: int,
+ modexp_input: ModExpInput,
+ modexp_expected: bytes,
+):
+ """
+ Test MODEXP upper bounds enforcement transition from before to after Osaka
+ hard fork.
+ """
+ call_code = Op.CALL(
+ address=Spec.MODEXP_ADDRESS,
+ args_size=Op.CALLDATASIZE,
)
- intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
- intrinsic_gas_cost = intrinsic_gas_cost_calc(calldata=mod_exp_input)
- memory_expansion_gas_calc = fork.memory_expansion_gas_calculator()
- memory_expansion_gas = memory_expansion_gas_calc(new_bytes=len(bytes(mod_exp_input)))
+ code = (
+ Op.CALLDATACOPY(size=Op.CALLDATASIZE)
+ + Op.SSTORE(
+ Op.TIMESTAMP,
+ call_code,
+ )
+ + Op.RETURNDATACOPY(size=Op.RETURNDATASIZE())
+ + Op.SSTORE(
+ Op.AND(Op.TIMESTAMP, 0xFF),
+ Op.SHA3(0, Op.RETURNDATASIZE()),
+ )
+ )
- gas_limit = intrinsic_gas_cost + (precompile_gas * 64 // 63) + memory_expansion_gas + 100_000
- expensive = gas_limit > TX_GAS_LIMIT
- gas_limit = TX_GAS_LIMIT if expensive else gas_limit
- env = Environment(gas_limit=gas_limit)
+ senders = [pre.fund_eoa() for _ in range(3)]
+ contracts = [pre.deploy_contract(code) for _ in range(3)]
+ timestamps = [14_999, 15_000, 15_001] # Before, at, and after transition
+ expected_results = [True, False, False]
- tx = Transaction(
- ty=0x0,
- to=account,
- data=mod_exp_input,
- gas_limit=gas_limit,
- protected=True,
- sender=sender,
- )
- base_length, exp_length, mod_length = mod_exp_input.get_declared_lengths()
- if (
- base_length <= MAX_LENGTH_BYTES
- and exp_length <= MAX_LENGTH_BYTES
- and mod_length <= MAX_LENGTH_BYTES
- ) or (fork < Osaka and not expensive):
- output = ModExpOutput(call_success=True, returned_data="0x01")
- else:
- output = ModExpOutput(call_success=False, returned_data="0x")
+ blocks = [
+ Block(
+ timestamp=ts,
+ txs=[
+ Transaction(
+ to=contract,
+ data=bytes(modexp_input),
+ sender=sender,
+ gas_limit=6_000_000,
+ )
+ ],
+ )
+ for ts, contract, sender in zip(timestamps, contracts, senders, strict=False)
+ ]
- post = {account: Account(storage={0: output.call_success})}
+ post = {
+ contract: Account(
+ storage={
+ ts: expected,
+ ts & 0xFF: keccak256(modexp_expected)
+ if expected
+ else keccak256(Spec.modexp_error),
+ }
+ )
+ for contract, ts, expected in zip(contracts, timestamps, expected_results, strict=False)
+ }
- state_test(env=env, pre=pre, post=post, tx=tx)
+ blockchain_test(
+ pre=pre,
+ blocks=blocks,
+ post=post,
+ )
diff --git a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/__init__.py b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/__init__.py
index ecc57bb22b..6ad1209d93 100644
--- a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/__init__.py
+++ b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-7825: Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825).
- Test cases for [EIP-7825: Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825).
+Tests [EIP-7825: Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825).
"""
diff --git a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_external_coverage.txt b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_external_coverage.txt
new file mode 100644
index 0000000000..f0b87011f0
--- /dev/null
+++ b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_external_coverage.txt
@@ -0,0 +1,2 @@
+general/code_coverage/eels = Please check https://app.codecov.io/gh/ethereum/execution-specs/pull/1388/blob/src/ethereum/osaka/vm/instructions/bitwise.py#L243 for relevant test coverage
+general/code_coverage/test_coverage = Please run the test with `--cov` flag for final coverage
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_not_applicable.txt b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_not_applicable.txt
new file mode 100644
index 0000000000..8f1d2d066c
--- /dev/null
+++ b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_not_applicable.txt
@@ -0,0 +1,12 @@
+system_contract = EIP does not introduce a new system contract
+opcode = EIP does not introduce a new opcode
+precompile = EIP does not introduce a new precompile
+removed_precompile = EIP does not remove a precompile
+transaction_type = EIP does not introduce a new transaction type
+block_header_field = EIP does not add any new block header fields
+block_body_field = EIP does not add any new block body fields
+gas_cost_changes = EIP does not modify existing gas costs, only introduces new opcode with fixed cost
+gas_refunds_changes = EIP does not introduce any gas refund changes
+blob_count_changes = EIP does not introduce any blob count changes
+execution_layer_request = EIP does not introduce an execution layer request
+new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint
diff --git a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/spec.py b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/spec.py
index 05f459f1bc..319c70e398 100644
--- a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/spec.py
+++ b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/spec.py
@@ -12,12 +12,14 @@ class ReferenceSpec:
# EIP-7825 reference specification
-ref_spec_7825 = ReferenceSpec("EIPS/eip-7825.md", "47cbfed315988c0bd4d10002c110ae402504cd94")
+ref_spec_7825 = ReferenceSpec("EIPS/eip-7825.md", "1ed95cbac750539c2aac67c8cbbcc2d77974231c")
@dataclass(frozen=True)
class Spec:
- """Constants and helpers for the EIP-7825 Transaction Gas Limit Cap tests."""
+ """
+ Constants and helpers for the EIP-7825 Transaction Gas Limit Cap tests.
+ """
# Gas limit constants
tx_gas_limit_cap = 2**24 # 16,777,216
diff --git a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py
index c20efa7a3a..5c23a5571b 100644
--- a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py
+++ b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py
@@ -1,6 +1,8 @@
"""
-abstract: Tests [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825)
- Test cases for [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825)].
+Transaction gas limit cap tests.
+
+Tests for transaction gas limit cap in [EIP-7825: Transaction Gas Limit
+Cap](https://eips.ethereum.org/EIPS/eip-7825).
"""
from typing import List
@@ -16,6 +18,7 @@
AuthorizationTuple,
Block,
BlockchainTestFiller,
+ Bytecode,
Environment,
Hash,
StateTestFiller,
@@ -25,7 +28,7 @@
add_kzg_version,
)
from ethereum_test_tools.utility.pytest import ParameterSet
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .spec import Spec, ref_spec_7825
@@ -36,12 +39,13 @@
def tx_gas_limit_cap_tests(fork: Fork) -> List[ParameterSet]:
"""
- Return a list of tests for transaction gas limit cap parametrized for each different
- fork.
+ Return a list of tests for transaction gas limit cap parametrized for each
+ different fork.
"""
fork_tx_gas_limit_cap = fork.transaction_gas_limit_cap()
if fork_tx_gas_limit_cap is None:
- # Use a default value for forks that don't have a transaction gas limit cap
+ # Use a default value for forks that don't have a transaction gas limit
+ # cap
return [
pytest.param(Spec.tx_gas_limit_cap + 1, None, id="tx_gas_limit_cap_none"),
]
@@ -53,7 +57,7 @@ def tx_gas_limit_cap_tests(fork: Fork) -> List[ParameterSet]:
id="tx_gas_limit_cap_exceeds_maximum",
marks=pytest.mark.exception_test,
),
- pytest.param(fork_tx_gas_limit_cap, None, id="tx_gas_limit_cap_none"),
+ pytest.param(fork_tx_gas_limit_cap, None, id="tx_gas_limit_cap_over"),
]
@@ -68,7 +72,9 @@ def test_transaction_gas_limit_cap(
error: TransactionException | None,
tx_type: int,
):
- """Test the transaction gas limit cap behavior for all transaction types."""
+ """
+ Test the transaction gas limit cap behavior for all transaction types.
+ """
env = Environment()
sender = pre.fund_eoa()
@@ -178,7 +184,9 @@ def test_tx_gas_larger_than_block_gas_limit(
fork: Fork,
exceed_block_gas_limit: bool,
):
- """Test multiple transactions with total gas larger than the block gas limit."""
+ """
+ Test multiple transactions with total gas larger than the block gas limit.
+ """
tx_gas_limit_cap = fork.transaction_gas_limit_cap()
assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap"
@@ -201,6 +209,68 @@ def test_tx_gas_larger_than_block_gas_limit(
blockchain_test(pre=pre, post={}, blocks=[block])
+@pytest.mark.parametrize(
+ "exceed_gas_refund_limit",
+ [
+ pytest.param(True),
+ pytest.param(False),
+ ],
+)
+@pytest.mark.valid_from("Osaka")
+def test_maximum_gas_refund(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ fork: Fork,
+ exceed_gas_refund_limit: bool,
+):
+ """Test the maximum gas refund behavior according to EIP-3529."""
+ gas_costs = fork.gas_costs()
+ tx_gas_limit_cap = fork.transaction_gas_limit_cap()
+ assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap"
+ max_refund_quotient = fork.max_refund_quotient()
+
+ storage = Storage()
+
+ # Base Operation: SSTORE(slot, 0)
+ iteration_cost = gas_costs.G_STORAGE_RESET + gas_costs.G_BASE + gas_costs.G_VERY_LOW
+ gas_refund = gas_costs.R_STORAGE_CLEAR
+
+ # EIP-3529: Reduction in refunds
+ storage_count = tx_gas_limit_cap // iteration_cost
+ gas_used = storage_count * iteration_cost
+
+ maximum_gas_refund = gas_used // max_refund_quotient
+ gas_refund_count = maximum_gas_refund // gas_refund
+
+ # Base case: operations that fit within the refund limit
+ iteration_count = min(storage_count, gas_refund_count + int(exceed_gas_refund_limit))
+
+ assert iteration_cost * iteration_count <= tx_gas_limit_cap, (
+ "Iteration cost exceeds tx gas limit cap"
+ )
+
+ opcode = sum(
+ (Op.SSTORE(storage.store_next(0), Op.PUSH0) for _ in range(iteration_count)),
+ Bytecode(),
+ )
+ assert len(opcode) <= fork.max_code_size(), "code size exceeds max code size"
+
+ contract = pre.deploy_contract(
+ code=opcode,
+ storage={Hash(i): Hash(1) for i in range(iteration_count)},
+ )
+
+ tx = Transaction(
+ to=contract,
+ sender=pre.fund_eoa(),
+ gas_limit=tx_gas_limit_cap,
+ )
+
+ post = {contract: Account(storage=storage)}
+
+ state_test(pre=pre, post=post, tx=tx)
+
+
@pytest.fixture
def total_cost_floor_per_token(fork: Fork):
"""Total cost floor per token."""
@@ -208,6 +278,7 @@ def total_cost_floor_per_token(fork: Fork):
return gas_costs.G_TX_DATA_FLOOR_TOKEN_COST
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"exceed_tx_gas_limit,correct_intrinsic_cost_in_transaction_gas_limit",
[
@@ -238,7 +309,8 @@ def test_tx_gas_limit_cap_full_calldata(
num_of_bytes += int(exceed_tx_gas_limit)
- # Gas cost calculation based on EIP-7623: (https://eips.ethereum.org/EIPS/eip-7623)
+ # Gas cost calculation based on EIP-7623:
+ # (https://eips.ethereum.org/EIPS/eip-7623)
#
# Simplified in this test case:
# - No execution gas used (no opcodes are executed)
@@ -313,12 +385,12 @@ def test_tx_gas_limit_cap_contract_creation(
code = Op.JUMPDEST * num_of_bytes
- # Craft a contract creation transaction that exceeds the transaction gas limit cap
+ # Craft a contract creation transaction that exceeds the transaction gas
+ # limit cap
#
# Total cost =
# intrinsic cost (base tx cost + contract creation cost)
- # + calldata cost
- # + init code execution cost
+ # + calldata cost + init code execution cost
#
# The contract body is filled with JUMPDEST instructions, so:
# total cost = intrinsic cost + calldata cost + (num_of_jumpdest * 1 gas)
@@ -360,7 +432,10 @@ def test_tx_gas_limit_cap_access_list_with_diff_keys(
pre: Alloc,
fork: Fork,
):
- """Test the transaction gas limit cap behavior for access list with different storage keys."""
+ """
+ Test the transaction gas limit cap behavior for access list with different
+ storage keys.
+ """
intrinsic_cost = fork.transaction_intrinsic_cost_calculator()
tx_gas_limit_cap = fork.transaction_gas_limit_cap()
assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap"
@@ -436,7 +511,10 @@ def test_tx_gas_limit_cap_access_list_with_diff_addr(
exceed_tx_gas_limit: bool,
correct_intrinsic_cost_in_transaction_gas_limit: bool,
):
- """Test the transaction gas limit cap behavior for access list with different addresses."""
+ """
+ Test the transaction gas limit cap behavior for access list with different
+ addresses.
+ """
intrinsic_cost = fork.transaction_intrinsic_cost_calculator()
tx_gas_limit_cap = fork.transaction_gas_limit_cap()
assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap"
@@ -524,14 +602,13 @@ def test_tx_gas_limit_cap_authorized_tx(
)
# EIP-7702 authorization transaction cost:
+ # 21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 *
+ # access list storage key count + 2400 * access list address count +
+ # PER_EMPTY_ACCOUNT_COST * authorization list length
#
- # 21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes
- # + 1900 * access list storage key count
- # + 2400 * access list address count
- # + PER_EMPTY_ACCOUNT_COST * authorization list length
+ # There is no calldata and no storage keys in this test case and the access
+ # address list count is equal to the authorization list length
#
- # There is no calldata and no storage keys in this test case
- # and the access address list count is equal to the authorization list length
# total cost = 21000 + (2400 + 25_000) * auth_list_length
auth_address = pre.deploy_contract(code=Op.STOP)
diff --git a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py
index 6519014695..c28cd62dbc 100644
--- a/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py
+++ b/tests/eest/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py
@@ -1,10 +1,13 @@
"""
-abstract: Tests [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825)
- Test cases for [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825)].
+Transaction gas limit cap fork transition tests.
+
+Tests for fork transition behavior in [EIP-7825: Transaction Gas Limit
+Cap](https://eips.ethereum.org/EIPS/eip-7825).
"""
import pytest
+from ethereum_test_checklists import EIPChecklist
from ethereum_test_forks import Fork
from ethereum_test_tools import (
Account,
@@ -14,7 +17,7 @@
Transaction,
TransactionException,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .spec import ref_spec_7825
@@ -22,73 +25,87 @@
REFERENCE_SPEC_VERSION = ref_spec_7825.version
+@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.AcceptedBeforeFork()
+@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedBeforeFork()
+@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.AcceptedAfterFork()
+@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedAfterFork()
@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True)
-@pytest.mark.exception_test
+@pytest.mark.parametrize(
+ "transaction_at_cap",
+ [
+ pytest.param(True, id="at_cap"),
+ pytest.param(False, marks=pytest.mark.exception_test, id="above_cap"),
+ ],
+)
def test_transaction_gas_limit_cap_at_transition(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
fork: Fork,
+ transaction_at_cap: bool,
):
"""
Test transaction gas limit cap behavior at the Osaka transition.
- Before timestamp 15000: No gas limit cap (transactions with gas > 2^24 are valid)
- At/after timestamp 15000: Gas limit cap of 2^24 is enforced
+ Before timestamp 15000: No gas limit cap (transactions with gas > 2^24 are
+ valid) At/after timestamp 15000: Gas limit cap of 2^24 is enforced
"""
- sender = pre.fund_eoa()
contract_address = pre.deploy_contract(
- code=Op.SSTORE(0, Op.ADD(Op.SLOAD(0), 1)) + Op.STOP,
+ code=Op.SSTORE(Op.TIMESTAMP, Op.ADD(Op.SLOAD(Op.TIMESTAMP), 1)) + Op.STOP,
)
- pre_cap = fork.transaction_gas_limit_cap()
- post_cap = fork.transaction_gas_limit_cap(timestamp=15_000)
- assert post_cap is not None, "Post cap should not be None"
+ # Get the gas limit cap at fork activation
+ tx_gas_cap = fork.transaction_gas_limit_cap(timestamp=15_000)
+ assert tx_gas_cap is not None, "Gas limit cap should not be None after fork activation"
- pre_cap = pre_cap if pre_cap else post_cap + 1
+ # Test boundary: cap + 1 should fail after fork activation
+ above_cap = tx_gas_cap + 1
- assert post_cap <= pre_cap, (
- "Post cap should be less than or equal to pre cap, test needs update"
+ # Before fork activation: both cap and above_cap transactions should
+ # succeed
+ at_cap_tx_before_fork = Transaction(
+ ty=0, # Legacy transaction
+ to=contract_address,
+ gas_limit=tx_gas_cap,
+ sender=pre.fund_eoa(),
)
- # Transaction with gas limit above the cap before transition
- high_gas_tx = Transaction(
+ above_cap_tx_before_fork = Transaction(
ty=0, # Legacy transaction
to=contract_address,
- gas_limit=pre_cap,
- data=b"",
- value=0,
- sender=sender,
+ gas_limit=above_cap,
+ sender=pre.fund_eoa(),
)
post_cap_tx_error = TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM
- # Transaction with gas limit at the cap
- cap_gas_tx = Transaction(
+ # After fork activation: test at cap vs above cap
+ transition_tx = Transaction(
ty=0, # Legacy transaction
to=contract_address,
- gas_limit=post_cap + 1,
- data=b"",
- value=0,
- sender=sender,
- error=post_cap_tx_error,
+ gas_limit=tx_gas_cap if transaction_at_cap else above_cap,
+ sender=pre.fund_eoa(),
+ error=None if transaction_at_cap else post_cap_tx_error,
)
blocks = []
- # Before transition (timestamp < 15000): high gas transaction should succeed
+ # Before transition (timestamp < 15000): both cap and above_cap
+ # transactions should succeed
blocks.append(
Block(
timestamp=14_999,
- txs=[high_gas_tx],
+ txs=[above_cap_tx_before_fork, at_cap_tx_before_fork],
)
)
- # At transition (timestamp = 15000): high gas transaction should fail
+ # At transition (timestamp = 15000):
+ # - transaction at cap should succeed
+ # - transaction above cap (cap + 1) should fail
blocks.append(
Block(
timestamp=15_000,
- txs=[cap_gas_tx], # Only transaction at the cap succeeds
- exception=post_cap_tx_error,
+ txs=[transition_tx],
+ exception=post_cap_tx_error if not transaction_at_cap else None,
)
)
@@ -96,7 +113,12 @@ def test_transaction_gas_limit_cap_at_transition(
post = {
contract_address: Account(
storage={
- 0: 1, # Set by first transaction (before transition)
+ # Set by both transactions in first block (before transition):
+ 14_999: 2,
+ # After transition:
+ # - Set by transaction at cap (should succeed)
+ # - Not set by transaction above cap (should fail)
+ 15_000: 1 if transaction_at_cap else 0,
}
)
}
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/__init__.py b/tests/eest/osaka/eip7883_modexp_gas_increase/__init__.py
index 4b43f2c9ed..7987a367c2 100644
--- a/tests/eest/osaka/eip7883_modexp_gas_increase/__init__.py
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883)
- Test cases for [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883).
+Tests for [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883).
"""
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/conftest.py b/tests/eest/osaka/eip7883_modexp_gas_increase/conftest.py
index 2d75c80d99..2740800c66 100644
--- a/tests/eest/osaka/eip7883_modexp_gas_increase/conftest.py
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/conftest.py
@@ -15,7 +15,7 @@
Transaction,
keccak256,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput
from .spec import Spec, Spec7883
@@ -42,8 +42,8 @@ def call_opcode() -> Op:
@pytest.fixture
def call_contract_post_storage() -> Storage:
"""
- Storage of the test contract after the transaction is executed.
- Note: Fixture `call_contract_code` fills the actual expected storage values.
+ Storage of the test contract after the transaction is executed. Note:
+ Fixture `call_contract_code` fills the actual expected storage values.
"""
return Storage()
@@ -83,9 +83,10 @@ def expected_tx_cap_fail() -> bool:
@pytest.fixture
def call_succeeds(exceeds_tx_gas_cap: bool, expected_tx_cap_fail: bool) -> bool:
"""
- Determine whether the ModExp precompile call should succeed or fail.
- By default, depending on the expected output, we assume it succeeds.
- Under EIP-7825, transactions requiring more gas than the cap should fail only if unexpected.
+ Determine whether the ModExp precompile call should succeed or fail. By
+ default, depending on the expected output, we assume it succeeds. Under
+ EIP-7825, transactions requiring more gas than the cap should fail only if
+ unexpected.
"""
if exceeds_tx_gas_cap and not expected_tx_cap_fail:
pytest.fail(
@@ -107,20 +108,28 @@ def gas_measure_contract(
call_succeeds: bool,
) -> Address:
"""
- Deploys a contract that measures ModExp gas consumption and execution result.
+ Deploys a contract that measures ModExp gas consumption and execution
+ result.
Always stored:
- storage[0]: precompile call success
- storage[1]: return data length from precompile
+ storage[0]: precompile call success
+ storage[1]: return data length from precompile
+
Only if the precompile call succeeds:
- storage[2]: gas consumed by precompile
- storage[3]: hash of return data from precompile
+ storage[2]: gas consumed by precompile
+ storage[3]: hash of return data from precompile
"""
assert call_opcode in [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]
value = [0] if call_opcode in [Op.CALL, Op.CALLCODE] else []
+ gas_used = (
+ precompile_gas + precompile_gas_modifier
+ if precompile_gas_modifier != float("inf")
+ else Environment().gas_limit
+ )
+
call_code = call_opcode(
- precompile_gas + precompile_gas_modifier,
+ gas_used,
Spec.MODEXP_ADDRESS,
*value,
0,
@@ -177,7 +186,10 @@ def gas_measure_contract(
def precompile_gas(
fork: Fork, modexp_input: ModExpInput, gas_old: int | None, gas_new: int | None
) -> int:
- """Calculate gas cost for the ModExp precompile and verify it matches expected gas."""
+ """
+ Calculate gas cost for the ModExp precompile and verify it matches expected
+ gas.
+ """
spec = Spec if fork < Osaka else Spec7883
try:
calculated_gas = spec.calculate_gas_cost(modexp_input)
@@ -193,8 +205,8 @@ def precompile_gas(
)
return calculated_gas
except Exception:
- # Used for `test_modexp_invalid_inputs` we expect the call to not succeed.
- # Return is for completeness.
+ # Used for `test_modexp_invalid_inputs` we expect the call to not
+ # succeed. Return is for completeness.
return 500 if fork >= Osaka else 200
@@ -222,7 +234,9 @@ def tx(
@pytest.fixture
def tx_gas_limit(total_tx_gas_needed: int, fork: Fork, env: Environment) -> int:
- """Transaction gas limit used for the test (Can be overridden in the test)."""
+ """
+ Transaction gas limit used for the test (Can be overridden in the test).
+ """
tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit
return min(tx_gas_limit_cap, total_tx_gas_needed)
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/eip_checklist_external_coverage.txt b/tests/eest/osaka/eip7883_modexp_gas_increase/eip_checklist_external_coverage.txt
new file mode 100644
index 0000000000..b2d3db4ab8
--- /dev/null
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/eip_checklist_external_coverage.txt
@@ -0,0 +1,3 @@
+precompile/test/call_contexts/set_code = Covered in EIP-7702 cases
+precompile/test/inputs/max_values = Covered in osaka/eip7823_modexp_upper_bounds
+precompile/test/out_of_bounds/max = Covered in osaka/eip7823_modexp_upper_bounds
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/eip_checklist_not_applicable.txt b/tests/eest/osaka/eip7883_modexp_gas_increase/eip_checklist_not_applicable.txt
new file mode 100644
index 0000000000..63a41d5689
--- /dev/null
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/eip_checklist_not_applicable.txt
@@ -0,0 +1,24 @@
+precompile/test/value_transfer/fee/under = No value is required
+precompile/test/value_transfer/fee/exact = No value is required
+precompile/test/value_transfer/fee/over = No value is required
+precompile/test/input_lengths/static/correct = The Modexp input length is not static
+precompile/test/input_lengths/static/too_short = The Modexp input length is not static
+precompile/test/input_lengths/static/too_long = The Modexp input length is not static
+precompile/test/input_lengths/dynamic/too_short = there would be no padding for precompile
+precompile/test/gas_usage/constant/oog = The Modexp gas cost is dynamic
+precompile/test/gas_usage/constant/exact = The Modexp gas cost is dynamic
+precompile/test/fork_transition/before/invalid_input = Modexp is not new precompile, it is still valid befork fork activation
+precompile/test/fork_transition/before/zero_gas = Modexp is not new precompile, it is still valid befork fork activation
+precompile/test/fork_transition/before/cold = Modexp is not new precompile, it is still valid befork fork activation
+gas_cost_changes/test/out_of_gas = No Out-of-gas scenario in Modexp
+system_contract = EIP does not include a new system contract
+opcode = EIP does not introduce a new opcode
+removed_precompile = EIP does not remove a precompile
+transaction_type = EIP does not introduce a new transaction type
+block_header_field = EIP does not add any new block header fields
+gas_refunds_changes = EIP does not introduce any gas refund changes
+blob_count_changes = EIP does not introduce any blob count changes
+execution_layer_request = EIP does not introduce an execution layer request
+new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint
+modified_transaction_validity_constraint = EIP does not introduce a modified transaction validity constraint
+block_body_field = EIP does not add any new block body fields
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/helpers.py b/tests/eest/osaka/eip7883_modexp_gas_increase/helpers.py
index 62819fea4b..dc1e05536f 100644
--- a/tests/eest/osaka/eip7883_modexp_gas_increase/helpers.py
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/helpers.py
@@ -31,7 +31,10 @@ class Vector(BaseModel):
model_config = ConfigDict(alias_generator=to_pascal)
def to_pytest_param(self):
- """Convert the test vector to a tuple that can be used as a parameter in a pytest test."""
+ """
+ Convert the test vector to a tuple that can be used as a parameter in a
+ pytest test.
+ """
return pytest.param(
self.modexp_input, self.modexp_expected, self.gas_old, self.gas_new, id=self.name
)
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/spec.py b/tests/eest/osaka/eip7883_modexp_gas_increase/spec.py
index 74908e60b9..bd399595af 100644
--- a/tests/eest/osaka/eip7883_modexp_gas_increase/spec.py
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/spec.py
@@ -18,8 +18,8 @@ class ReferenceSpec:
def ceiling_division(a: int, b: int) -> int:
"""
- Calculate the ceil without using floating point.
- Used by many of the EVM's formulas.
+ Calculate the ceil without using floating point. Used by many of the EVM's
+ formulas.
"""
return -(a // -b)
@@ -63,9 +63,9 @@ def calculate_multiplication_complexity(cls, base_length: int, modulus_length: i
@classmethod
def calculate_iteration_count(cls, modexp_input: ModExpInput) -> int:
"""
- Calculate the iteration count of the ModExp precompile.
- This handles length mismatch cases by using declared lengths from the raw input
- and only the first 32 bytes of exponent data for iteration calculation.
+ Calculate the iteration count of the ModExp precompile. This handles
+ length mismatch cases by using declared lengths from the raw input and
+ only the first 32 bytes of exponent data for iteration calculation.
"""
_, exponent_length, _ = modexp_input.get_declared_lengths()
exponent_head = modexp_input.get_exponent_head()
@@ -83,8 +83,9 @@ def calculate_iteration_count(cls, modexp_input: ModExpInput) -> int:
@classmethod
def calculate_gas_cost(cls, modexp_input: ModExpInput) -> int:
"""
- Calculate the ModExp gas cost according to EIP-2565 specification, overridden by the
- constants within `Spec7883` when calculating for the EIP-7883 specification.
+ Calculate the ModExp gas cost according to EIP-2565 specification,
+ overridden by the constants within `Spec7883` when calculating for the
+ EIP-7883 specification.
"""
base_length, _, modulus_length = modexp_input.get_declared_lengths()
multiplication_complexity = cls.calculate_multiplication_complexity(
@@ -97,8 +98,8 @@ def calculate_gas_cost(cls, modexp_input: ModExpInput) -> int:
@dataclass(frozen=True)
class Spec7883(Spec):
"""
- Constants and helpers for the ModExp gas cost increase EIP.
- These override the original Spec class variables for EIP-7883.
+ Constants and helpers for the ModExp gas cost increase EIP. These override
+ the original Spec class variables for EIP-7883.
"""
MODEXP_ADDRESS = 0x05
@@ -110,7 +111,10 @@ class Spec7883(Spec):
@classmethod
def calculate_multiplication_complexity(cls, base_length: int, modulus_length: int) -> int:
- """Calculate the multiplication complexity of the ModExp precompile for EIP-7883."""
+ """
+ Calculate the multiplication complexity of the ModExp precompile for
+ EIP-7883.
+ """
max_length = max(base_length, modulus_length)
words = ceiling_division(max_length, cls.WORD_SIZE)
complexity = 16
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py b/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py
index 4b12e98c51..f397b7c110 100644
--- a/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py
@@ -1,6 +1,8 @@
"""
-abstract: Tests [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883)
- Test cases for [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883).
+EIP-7883 ModExp gas cost increase tests.
+
+Tests for ModExp gas cost increase in
+[EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883).
"""
from typing import Dict
@@ -8,8 +10,17 @@
import pytest
from ethereum_test_checklists import EIPChecklist
-from ethereum_test_tools import Alloc, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_forks import Fork, Osaka
+from ethereum_test_tools import (
+ Alloc,
+ Environment,
+ StateTestFiller,
+ Storage,
+ Transaction,
+ keccak256,
+)
+from ethereum_test_types.helpers import compute_create_address
+from ethereum_test_vm import Opcodes as Op
from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput
from .helpers import vectors_from_file
@@ -24,7 +35,11 @@
vectors_from_file("vectors.json"),
ids=lambda v: v.name,
)
+@EIPChecklist.Precompile.Test.Inputs.Valid()
+@EIPChecklist.Precompile.Test.InputLengths.Dynamic.Valid()
+@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement()
@pytest.mark.valid_from("Berlin")
+@pytest.mark.slow()
def test_vectors_from_eip(
state_test: StateTestFiller,
pre: Alloc,
@@ -44,6 +59,7 @@ def test_vectors_from_eip(
vectors_from_file("legacy.json"),
ids=lambda v: v.name,
)
+@EIPChecklist.Precompile.Test.Inputs.Invalid()
@pytest.mark.valid_from("Berlin")
def test_vectors_from_legacy_tests(
state_test: StateTestFiller,
@@ -62,8 +78,8 @@ def test_vectors_from_legacy_tests(
@pytest.mark.parametrize(
"modexp_input,",
[
- # These invalid inputs are from EIP-7823.
- # Ref: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7823.md#analysis
+ # These invalid inputs are from EIP-7823. Ref:
+ # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7823.md#analysis
pytest.param(
bytes.fromhex("9e5faafc"),
id="invalid-case-1",
@@ -83,6 +99,7 @@ def test_vectors_from_legacy_tests(
[
pytest.param(bytes(), False),
],
+ ids=[""],
)
@EIPChecklist.Precompile.Test.Inputs.AllZeros
@pytest.mark.valid_from("Berlin")
@@ -145,6 +162,10 @@ def test_modexp_invalid_inputs(
),
],
)
+@EIPChecklist.Precompile.Test.OutOfBounds.MaxPlusOne()
+@EIPChecklist.Precompile.Test.Inputs.Invalid.Corrupted()
+@EIPChecklist.Precompile.Test.Inputs.Invalid()
+@EIPChecklist.Precompile.Test.InputLengths.Dynamic.TooLong()
@pytest.mark.valid_from("Osaka")
def test_modexp_boundary_inputs(
state_test: StateTestFiller,
@@ -175,10 +196,10 @@ def test_modexp_boundary_inputs(
pytest.param(Spec.modexp_input, Spec.modexp_expected, id="base-heavy"),
],
)
-@EIPChecklist.Precompile.Test.CallContexts.Static
-@EIPChecklist.Precompile.Test.CallContexts.Delegate
-@EIPChecklist.Precompile.Test.CallContexts.Callcode
-@EIPChecklist.Precompile.Test.CallContexts.Normal
+@EIPChecklist.Precompile.Test.CallContexts.Static()
+@EIPChecklist.Precompile.Test.CallContexts.Delegate()
+@EIPChecklist.Precompile.Test.CallContexts.Callcode()
+@EIPChecklist.Precompile.Test.CallContexts.Normal()
@pytest.mark.valid_from("Berlin")
def test_modexp_call_operations(
state_test: StateTestFiller,
@@ -218,11 +239,17 @@ def test_modexp_call_operations(
False,
id="insufficient_gas",
),
+ pytest.param(
+ Spec.modexp_input,
+ Spec.modexp_expected,
+ float("inf"),
+ True,
+ id="excessive_gas",
+ ),
],
)
-@EIPChecklist.Precompile.Test.ValueTransfer.Fee.Over
-@EIPChecklist.Precompile.Test.ValueTransfer.Fee.Exact
-@EIPChecklist.Precompile.Test.ValueTransfer.Fee.Under
+@EIPChecklist.Precompile.Test.GasUsage.Dynamic()
+@EIPChecklist.Precompile.Test.ExcessiveGasUsage()
@pytest.mark.valid_from("Berlin")
def test_modexp_gas_usage_contract_wrapper(
state_test: StateTestFiller,
@@ -230,17 +257,21 @@ def test_modexp_gas_usage_contract_wrapper(
tx: Transaction,
post: Dict,
):
- """Test ModExp gas cost with different gas modifiers using contract wrapper calls."""
+ """
+ Test ModExp gas cost with different gas modifiers using contract wrapper
+ calls.
+ """
state_test(pre=pre, tx=tx, post=post)
@pytest.mark.parametrize(
- "modexp_input,modexp_expected,precompile_gas_modifier,call_succeeds",
+ "modexp_input,modexp_expected,precompile_gas_modifier,call_values,call_succeeds",
[
pytest.param(
Spec.modexp_input,
Spec.modexp_expected,
1,
+ 0,
True,
id="extra_gas",
),
@@ -248,18 +279,30 @@ def test_modexp_gas_usage_contract_wrapper(
Spec.modexp_input,
Spec.modexp_expected,
0,
+ 0,
True,
id="exact_gas",
),
+ pytest.param(
+ Spec.modexp_input,
+ Spec.modexp_expected,
+ 0,
+ 1000,
+ True,
+ id="extra_value",
+ ),
pytest.param(
Spec.modexp_input,
Spec.modexp_error,
-1,
+ 0,
False,
id="insufficient_gas",
),
],
)
+@EIPChecklist.Precompile.Test.CallContexts.TxEntry()
+@EIPChecklist.Precompile.Test.ValueTransfer.NoFee()
@pytest.mark.valid_from("Berlin")
def test_modexp_used_in_transaction_entry_points(
state_test: StateTestFiller,
@@ -267,108 +310,253 @@ def test_modexp_used_in_transaction_entry_points(
tx: Transaction,
modexp_input: bytes,
tx_gas_limit: int,
+ call_values: int,
):
- """Test ModExp using in transaction entry points with different precompile gas modifiers."""
+ """
+ Test ModExp using in transaction entry points with different precompile gas
+ modifiers.
+ """
tx = Transaction(
to=Spec.MODEXP_ADDRESS,
sender=pre.fund_eoa(),
data=bytes(modexp_input),
gas_limit=tx_gas_limit,
+ value=call_values,
)
state_test(pre=pre, tx=tx, post={})
+@pytest.mark.parametrize(
+ "modexp_input,modexp_expected",
+ [
+ pytest.param(
+ Spec.modexp_input,
+ Spec.modexp_expected,
+ id="valid_input",
+ )
+ ],
+)
+@EIPChecklist.Precompile.Test.CallContexts.Initcode()
+@pytest.mark.valid_from("Berlin")
+def test_contract_creation_transaction(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ post: dict,
+ tx: Transaction,
+ modexp_input: bytes,
+ modexp_expected: bytes,
+):
+ """Test the contract creation for the ModExp precompile."""
+ sender = pre.fund_eoa()
+
+ storage = Storage()
+
+ contract_address = compute_create_address(address=sender, nonce=0)
+ contract_bytecode = (
+ Op.CODECOPY(0, Op.SUB(Op.CODESIZE, len(bytes(modexp_input))), len(bytes(modexp_input)))
+ + Op.CALL(
+ gas=1_000_000,
+ address=Spec.MODEXP_ADDRESS,
+ value=0,
+ args_offset=0,
+ args_size=len(bytes(modexp_input)),
+ ret_offset=0,
+ ret_size=len(bytes(modexp_expected)),
+ )
+ + Op.SSTORE(storage.store_next(True), Op.DUP1())
+ + Op.SSTORE(
+ storage.store_next(keccak256(bytes(modexp_expected))), Op.SHA3(0, Op.RETURNDATASIZE())
+ )
+ + Op.SSTORE(storage.store_next(len(bytes(modexp_expected))), Op.RETURNDATASIZE())
+ + Op.STOP
+ )
+
+ tx = Transaction(
+ sender=sender,
+ gas_limit=1_000_000,
+ to=None,
+ value=0,
+ data=contract_bytecode + bytes(modexp_input),
+ )
+
+ post = {
+ contract_address: {
+ "storage": storage,
+ }
+ }
+
+ state_test(env=Environment(), pre=pre, post=post, tx=tx)
+
+
+@pytest.mark.parametrize(
+ "modexp_input,modexp_expected",
+ [
+ pytest.param(
+ Spec.modexp_input,
+ Spec.modexp_expected,
+ id="valid_input",
+ ),
+ ],
+)
+@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2])
+@EIPChecklist.Precompile.Test.CallContexts.Initcode.CREATE()
+@pytest.mark.valid_from("Berlin")
+def test_contract_initcode(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ post: dict,
+ tx: Transaction,
+ modexp_input: bytes,
+ modexp_expected: bytes,
+ opcode: Op,
+):
+ """Test ModExp behavior from contract creation."""
+ sender = pre.fund_eoa()
+
+ storage = Storage()
+
+ call_modexp_bytecode = (
+ Op.CODECOPY(0, Op.SUB(Op.CODESIZE, len(bytes(modexp_input))), len(bytes(modexp_input)))
+ + Op.CALL(
+ gas=200_000,
+ address=Spec.MODEXP_ADDRESS,
+ value=0,
+ args_offset=0,
+ args_size=len(bytes(modexp_input)),
+ ret_offset=0,
+ ret_size=len(bytes(modexp_expected)),
+ )
+ + Op.SSTORE(storage.store_next(True), Op.DUP1())
+ + Op.SSTORE(
+ storage.store_next(keccak256(bytes(modexp_expected))), Op.SHA3(0, Op.RETURNDATASIZE())
+ )
+ + Op.SSTORE(storage.store_next(len(bytes(modexp_expected))), Op.RETURNDATASIZE())
+ + Op.STOP
+ )
+ full_initcode = call_modexp_bytecode + bytes(modexp_input)
+ total_bytecode_length = len(call_modexp_bytecode) + len(bytes(modexp_input))
+
+ create_contract = (
+ Op.CALLDATACOPY(offset=0, size=total_bytecode_length)
+ + opcode(offset=0, size=total_bytecode_length)
+ + Op.STOP
+ )
+
+ factory_contract_address = pre.deploy_contract(code=create_contract)
+ contract_address = compute_create_address(
+ address=factory_contract_address, nonce=1, initcode=full_initcode, opcode=opcode
+ )
+
+ tx = Transaction(
+ sender=sender,
+ gas_limit=200_000,
+ to=factory_contract_address,
+ value=0,
+ data=call_modexp_bytecode + bytes(modexp_input),
+ )
+
+ post = {
+ contract_address: {
+ "storage": storage,
+ }
+ }
+
+ state_test(env=Environment(), pre=pre, post=post, tx=tx)
+
+
def create_modexp_variable_gas_test_cases():
"""
Create test cases for ModExp variable gas cost testing.
- Returns:
- List of pytest.param objects for the test cases
-
+ Returns: List of pytest.param objects for the test cases
"""
- # Test case definitions: (base, exponent, modulus, expected_result, test_id)
+ # Test case definitions: (base, exponent, modulus, expected_result,
+ # gas_usage, test_id)
test_cases = [
- ("", "", "", "", "Z0"),
- ("01" * 32, "00" * 32, "", "", "Z1"),
- ("01" * 1024, "00" * 32, "", "", "Z2"),
- ("01" * 32, "00" * 1024, "", "", "Z3"),
- ("01" * 32, "00" * 1023 + "01", "", "", "Z4"),
- ("", "", "01" * 32, "00" * 31 + "01", "Z5"),
- ("", "01" * 32, "01" * 32, "00" * 32, "Z6"),
- ("", "00" * 31 + "01", "01" * 1024, "00" * 1024, "Z7"),
- ("01" * 16, "00" * 16, "02" * 16, "00" * 15 + "01", "S0"),
- ("01" * 16, "00" * 15 + "03", "02" * 16, "01" * 16, "S1"),
- ("01" * 32, "FF" * 32, "02" * 32, "01" * 32, "S2"),
- ("01" * 16, "00" * 40, "02" * 16, "00" * 15 + "01", "S3"),
- ("01" * 16, "00" * 39 + "01", "02" * 16, "01" * 16, "S4"),
- ("01" * 24, "00", "02" * 8, "00" * 7 + "01", "S5"),
- ("01" * 8, "01", "02" * 24, "00" * 16 + "01" * 8, "S6"),
- ("01" * 40, "00" * 16, "02" * 40, "00" * 39 + "01", "L0"),
- ("01" * 40, "FF" * 32, "02" * 40, "01" * 40, "L1"),
- ("01" * 40, "00" * 40, "02" * 40, "00" * 39 + "01", "L2"),
- ("01" * 40, "00" * 39 + "01", "02" * 40, "01" * 40, "L3"),
- ("01" * 48, "01", "02" * 16, "01" * 16, "L4"),
- ("01" * 16, "00" * 40, "02" * 48, "00" * 47 + "01", "L5"),
+ ("", "", "", "", 500, "Z0"),
+ ("01" * 32, "00" * 32, "", "", 500, "Z1"),
+ ("01" * 1024, "00" * 32, "", "", 32768, "Z2"),
+ ("01" * 32, "00" * 1024, "", "", 253952, "Z3"),
+ ("01" * 32, "00" * 1023 + "01", "", "", 253952, "Z4"),
+ ("", "", "01" * 32, "00" * 31 + "01", 500, "Z5"),
+ ("", "01" * 32, "01" * 32, "00" * 32, 3968, "Z6"),
+ ("", "00" * 31 + "01", "01" * 1024, "00" * 1024, 32768, "Z7"),
+ ("01" * 16, "00" * 16, "02" * 16, "00" * 15 + "01", 500, "S0"),
+ ("01" * 16, "00" * 15 + "03", "02" * 16, "01" * 16, 500, "S1"),
+ ("01" * 32, "FF" * 32, "02" * 32, "01" * 32, 4080, "S2"),
+ ("01" * 16, "00" * 40, "02" * 16, "00" * 15 + "01", 2048, "S3"),
+ ("01" * 16, "00" * 39 + "01", "02" * 16, "01" * 16, 2048, "S4"),
+ ("01" * 24, "00", "02" * 8, "00" * 7 + "01", 500, "S5"),
+ ("01" * 8, "01", "02" * 24, "00" * 16 + "01" * 8, 500, "S6"),
+ ("01" * 40, "00" * 16, "02" * 40, "00" * 39 + "01", 500, "L0"),
+ ("01" * 40, "FF" * 32, "02" * 40, "01" * 40, 12750, "L1"),
+ ("01" * 40, "00" * 40, "02" * 40, "00" * 39 + "01", 6400, "L2"),
+ ("01" * 40, "00" * 39 + "01", "02" * 40, "01" * 40, 6400, "L3"),
+ ("01" * 48, "01", "02" * 16, "01" * 16, 500, "L4"),
+ ("01" * 16, "00" * 40, "02" * 48, "00" * 47 + "01", 9216, "L5"),
# Critical 32-byte boundary cases
- ("01" * 31, "01", "02" * 33, "00" * 2 + "01" * 31, "B1"),
- ("01" * 33, "01", "02" * 31, "00" * 29 + "01" * 2, "B2"),
- ("01" * 33, "01", "02" * 33, "01" * 33, "B4"),
+ ("01" * 31, "01", "02" * 33, "00" * 2 + "01" * 31, 500, "B1"),
+ ("01" * 33, "01", "02" * 31, "00" * 29 + "01" * 2, 500, "B2"),
+ ("01" * 33, "01", "02" * 33, "01" * 33, 500, "B4"),
# Zero value edge cases
- ("00" * 32, "00" * 32, "01" * 32, "00" * 31 + "01", "Z8"),
- ("01" * 32, "00" * 32, "00" * 32, "00" * 32, "Z9"),
- ("00" * 32, "01" * 32, "02" * 32, "00" * 32, "Z10"),
- ("00" * 32, "00" * 33, "01" * 32, "00" * 31 + "01", "Z11"),
- ("00" * 32, "00" * 1024, "01" * 32, "00" * 31 + "01", "Z12"),
- ("00" * 1024, "00" * 32, "01" * 32, "00" * 31 + "01", "Z13"),
- ("01" * 32, "00" * 1024, "00" * 32, "00" * 32, "Z14"),
- ("01" * 32, "00" * 31 + "01", "00" * 1024, "00" * 1024, "Z15"),
+ ("00" * 32, "00" * 32, "01" * 32, "00" * 31 + "01", 500, "Z8"),
+ ("01" * 32, "00" * 32, "00" * 32, "00" * 32, 500, "Z9"),
+ ("00" * 32, "01" * 32, "02" * 32, "00" * 32, 3968, "Z10"),
+ ("00" * 32, "00" * 33, "01" * 32, "00" * 31 + "01", 500, "Z11"),
+ ("00" * 32, "00" * 1024, "01" * 32, "00" * 31 + "01", 253952, "Z12"),
+ ("00" * 1024, "00" * 32, "01" * 32, "00" * 31 + "01", 32768, "Z13"),
+ ("01" * 32, "00" * 1024, "00" * 32, "00" * 32, 253952, "Z14"),
+ ("01" * 32, "00" * 31 + "01", "00" * 1024, "00" * 1024, 32768, "Z15"),
# Maximum value stress tests
- ("FF" * 64, "FF" * 64, "FF" * 64, "00" * 64, "M1"),
- ("FF" * 32, "01", "FF" * 32, "00" * 32, "M2"),
- ("01", "FF" * 64, "FF" * 64, "00" * 63 + "01", "M3"),
+ ("FF" * 64, "FF" * 64, "FF" * 64, "00" * 64, 98176, "M1"),
+ ("FF" * 32, "01", "FF" * 32, "00" * 32, 500, "M2"),
+ ("01", "FF" * 64, "FF" * 64, "00" * 63 + "01", 98176, "M3"),
# Tiny maximum values
- ("FF", "FE", "FD", "47", "T2"),
+ ("FF", "FE", "FD", "47", 500, "T2"),
# Bit pattern cases
- ("01" * 32, "80" * 32, "02" * 32, "01" * 32, "P2"),
- ("01" * 33, "00" * 31 + "80" + "00", "02" * 33, "01" * 33, "P3"),
+ ("01" * 32, "80" * 32, "02" * 32, "01" * 32, 4080, "P2"),
+ ("01" * 33, "00" * 31 + "80" + "00", "02" * 33, "01" * 33, 1150, "P3"),
# Asymmetric length cases
- ("01", "00" * 64, "02" * 64, "00" * 63 + "01", "A1"),
- ("01" * 64, "01", "02", "01", "A2"),
- ("01" * 64, "00" * 64, "02", "01", "A3"),
+ ("01", "00" * 64, "02" * 64, "00" * 63 + "01", 65536, "A1"),
+ ("01" * 64, "01", "02", "01", 500, "A2"),
+ ("01" * 64, "00" * 64, "02", "01", 65536, "A3"),
# Word boundary case
- ("01" * 8, "01", "02" * 8, "0101010101010101", "W2"),
+ ("01" * 8, "01", "02" * 8, "0101010101010101", 500, "W2"),
# Exponent edge cases
- ("01" * 16, "00" * 32 + "01", "02" * 16, "01" * 16, "E1"),
- ("01" * 16, "80" + "00" * 31, "02" * 16, "01" * 16, "E2"),
- ("01" * 16, "00" * 31 + "80", "02" * 16, "01" * 16, "E3"),
- ("01" * 16, "7F" + "FF" * 31, "02" * 16, "01" * 16, "E4"),
+ ("01" * 16, "00" * 32 + "01", "02" * 16, "01" * 16, 500, "E1"),
+ ("01" * 16, "80" + "00" * 31, "02" * 16, "01" * 16, 4080, "E2"),
+ ("01" * 16, "00" * 31 + "80", "02" * 16, "01" * 16, 500, "E3"),
+ ("01" * 16, "7F" + "FF" * 31, "02" * 16, "01" * 16, 4064, "E4"),
# Implementation coverage cases
# IC1: Bit shift vs multiplication at 33-byte boundary
- ("FF" * 33, "01", "FF" * 33, "00" * 33, "IC1"),
+ ("FF" * 33, "01", "FF" * 33, "00" * 33, 500, "IC1"),
# IC3: Ceiling division at 7 bytes
- ("01" * 7, "01", "02" * 7, "01" * 7, "IC3"),
+ ("01" * 7, "01", "02" * 7, "01" * 7, 500, "IC3"),
# IC4: Ceiling division at 9 bytes
- ("01" * 9, "01", "02" * 9, "01" * 9, "IC4"),
+ ("01" * 9, "01", "02" * 9, "01" * 9, 500, "IC4"),
# IC5: Bit counting in middle of exponent
- ("01", "00" * 15 + "80" + "00" * 16, "02", "01", "IC5"),
+ ("01", "00" * 15 + "80" + "00" * 16, "02", "01", 2160, "IC5"),
# IC6: Native library even byte optimization
- ("01" * 31 + "00", "01", "01" * 31 + "00", "00" * 32, "IC6"),
+ ("01" * 31 + "00", "01", "01" * 31 + "00", "00" * 32, 500, "IC6"),
# IC7: Vector optimization 128-bit boundary
- ("00" * 15 + "01" * 17, "01", "00" * 15 + "01" * 17, "00" * 32, "IC7"),
+ ("00" * 15 + "01" * 17, "01", "00" * 15 + "01" * 17, "00" * 32, 500, "IC7"),
# IC9: Zero modulus with large inputs
- ("FF" * 32, "FF" * 32, "", "", "IC9"),
+ ("FF" * 32, "FF" * 32, "", "", None, "IC9"), # N/A case
# IC10: Power-of-2 boundary with high bit
- ("01" * 32, "80" + "00" * 31, "02" * 32, "01" * 32, "IC10"),
+ ("01" * 32, "80" + "00" * 31, "02" * 32, "01" * 32, 4080, "IC10"),
]
# Gas calculation parameters:
#
- # Please refer to EIP-7883 for details of each function in the gas calculation.
+ # Please refer to EIP-7883 for details of each function in the gas
+ # calculation.
# Link: https://eips.ethereum.org/EIPS/eip-7883
#
# - calculate_multiplication_complexity:
- # - Comp: if max_length <= 32 bytes, it is Small (S), otherwise it is Large (L)
- # - Rel (Length Relation): base < modulus (<), base = modulus (=), base > modulus (>)
+ # - Comp: if max_length <= 32 bytes, it is Small (S), otherwise it is
+ # Large (L)
+ # - Rel (Length Relation): base < modulus (<), base = modulus (=),
+ # base > modulus (>)
#
# - calculate_iteration_count
# - Iter (Iteration Case):
@@ -378,88 +566,100 @@ def create_modexp_variable_gas_test_cases():
# - D: exp>32 and low256≠0
#
# - calculate_gas_cost
- # - Clamp: True if raw gas < 500 (clamped to 500), False if raw gas ≥ 500 (no clamping)
-
- # Test case coverage table:
- # ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐
- # │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │
- # ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤
- # │ Z0 │ - │ - │ - │ - │ 500 │ Zero case – empty inputs │
- # │ Z1 │ S │ - │ A │ True │ 500 │ Non-zero base, zero exp, empty modulus │
- # │ Z2 │ L │ - │ A │ False │ 32768 │ Large base (1024B), zero exp, empty modulus │
- # │ Z3 │ S │ - │ C │ False │253936 │ Base, large zero exp (1024B), empty modulus │
- # │ Z4 │ S │ - │ D │ False │253952 │ Base, large exp (last byte=1), empty modulus │
- # │ Z5 │ S │ < │ A │ True │ 500 │ Empty base/exp, non-zero modulus only │
- # │ Z6 │ S │ < │ B │ False │ 3968 │ Empty base, non-zero exp and modulus │
- # │ Z7 │ L │ < │ B │ False │ 32768 │ Empty base, small exp, large modulus │
- # │ S0 │ S │ = │ A │ True │ 500 │ Small, equal, zero exp, clamped │
- # │ S1 │ S │ = │ B │ True │ 500 │ Small, equal, small exp, clamped │
- # │ S2 │ S │ = │ B │ False │ 4080 │ Small, equal, large exp, unclamped │
- # │ S3 │ S │ = │ C │ False │ 2048 │ Small, equal, large exp + zero low256 │
- # │ S4 │ S │ = │ D │ False │ 2048 │ Small, equal, large exp + non-zero low256 │
- # │ S5 │ S │ > │ A │ True │ 500 │ Small, base > mod, zero exp, clamped │
- # │ S6 │ S │ < │ B │ True │ 500 │ Small, base < mod, small exp, clamped │
- # │ L0 │ L │ = │ A │ True │ 500 │ Large, equal, zero exp, clamped │
- # │ L1 │ L │ = │ B │ False │ 12750 │ Large, equal, large exp, unclamped │
- # │ L2 │ L │ = │ C │ False │ 6400 │ Large, equal, large exp + zero low256 │
- # │ L3 │ L │ = │ D │ False │ 6400 │ Large, equal, large exp + non-zero low256 │
- # │ L4 │ L │ > │ B │ True │ 500 │ Large, base > mod, small exp, clamped │
- # │ L5 │ L │ < │ C │ False │ 9216 │ Large, base < mod, large exp + zero low256 │
- # │ B1 │ L │ < │ B │ True │ 500 │ Cross 32-byte boundary (31/33) │
- # │ B2 │ L │ > │ B │ True │ 500 │ Cross 32-byte boundary (33/31) │
- # │ B4 │ L │ = │ B │ True │ 500 │ Just over 32-byte boundary │
- # │ Z8 │ S │ = │ A │ True │ 500 │ All zeros except modulus │
- # │ Z9 │ S │ = │ A │ True │ 500 │ Zero modulus special case │
- # │ Z10 │ S │ = │ B │ False │ 3968 │ Zero base, large exponent │
- # │ Z11 │ S │ = │ C │ True │ 500 │ Zero base, 33B zero exp, non-zero modulus │
- # │ Z12 │ S │ = │ C │ False │253936 │ Zero base, large zero exp, non-zero modulus │
- # │ Z13 │ L │ > │ A │ False │ 32768 │ Large zero base, zero exp, non-zero modulus │
- # │ Z14 │ S │ = │ C │ False │253936 │ Base, large zero exp, zero modulus │
- # │ Z15 │ L │ < │ B │ False │ 32768 │ Base, small exp, large zero modulus │
- # │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) |
- # │ M1 │ L │ = │ D │ False │ 98176 │ Maximum values stress test │
- # │ M2 │ S │ = │ B │ True │ 500 │ Max base/mod, small exponent │
- # │ M3 │ L │ < │ D │ False │ 98176 │ Small base, max exponent/mod │
- # │ T2 │ S │ = │ B │ True │ 500 │ Tiny maximum values │
- # │ P2 │ S │ = │ B │ False │ 4080 │ High bit in exponent │
- # │ P3 │ L │ = │ D │ False │ 1150 │ Specific bit pattern in large exponent │
- # │ A1 │ L │ < │ C │ False │ 65536 │ Asymmetric: tiny base, large exp/mod │
- # │ A2 │ L │ > │ B │ True │ 500 │ Asymmetric: large base, tiny exp/mod │
- # │ A3 │ L │ > │ C │ False │ 65536 │ Asymmetric: large base/exp, tiny modulus │
- # │ W2 │ S │ = │ B │ True │ 500 │ Exactly 8-byte words │
- # │ E1 │ S │ = │ D │ True │ 500 │ Exponent exactly 33 bytes │
- # │ E2 │ S │ = │ B │ False │ 4080 │ High bit in exponent first byte │
- # │ E3 │ S │ = │ B │ True │ 500 │ High bit in exponent last byte │
- # │ E4 │ S │ = │ B │ False │ 4064 │ Maximum 32-byte exponent │
- # │ IC1 │ L │ = │ B │ True │ 500 │ Bit shift vs multiplication @ 33 bytes │
- # │ IC3 │ S │ = │ B │ True │ 500 │ Ceiling division at 7 bytes │
- # │ IC4 │ S │ = │ B │ True │ 500 │ Ceiling division at 9 bytes │
- # │ IC5 │ S │ = │ B │ False │ 2160 │ Bit counting in middle of exponent │
- # │ IC6 │ L │ = │ B │ True │ 500 │ Native library even byte optimization │
- # │ IC7 │ L │ = │ B │ True │ 500 │ Vector optimization 128-bit boundary │
- # │ IC9 │ S │ = │ B │ N/A │ N/A │ Zero modulus handling │
- # │ IC10│ S │ = │ B │ False │ 4080 │ Power-of-2 boundary with high bit │
- # └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘
- for base, exponent, modulus, expected_result, test_id in test_cases:
+ # - Clamp: True if raw gas < 500 (clamped to 500), False if raw gas ≥ 500
+ # (no clamping)
+
+ """
+ Test case coverage table:
+
+ ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐
+ │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │
+ ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤
+ │ Z0 │ - │ - │ - │ - │ 500 │ Zero case – empty inputs │
+ │ Z1 │ S │ - │ A │ True │ 500 │ Non-zero base, zero exp, empty modulus │
+ │ Z2 │ L │ - │ A │ False │ 32768 │ Large base (1024B), zero exp, empty modulus │
+ │ Z3 │ S │ - │ C │ False |253952 │ Base, large zero exp (1024B), empty modulus │
+ │ Z4 │ S │ - │ D │ False │253952 │ Base, large exp (last byte=1), empty modulus │
+ │ Z5 │ S │ < │ A │ True │ 500 │ Empty base/exp, non-zero modulus only │
+ │ Z6 │ S │ < │ B │ False │ 3968 │ Empty base, non-zero exp and modulus │
+ │ Z7 │ L │ < │ B │ False │ 32768 │ Empty base, small exp, large modulus │
+ │ S0 │ S │ = │ A │ True │ 500 │ Small, equal, zero exp, clamped │
+ │ S1 │ S │ = │ B │ True │ 500 │ Small, equal, small exp, clamped │
+ │ S2 │ S │ = │ B │ False │ 4080 │ Small, equal, large exp, unclamped │
+ │ S3 │ S │ = │ C │ False │ 2048 │ Small, equal, large exp + zero low256 │
+ │ S4 │ S │ = │ D │ False │ 2048 │ Small, equal, large exp + non-zero low256 │
+ │ S5 │ S │ > │ A │ True │ 500 │ Small, base > mod, zero exp, clamped │
+ │ S6 │ S │ < │ B │ True │ 500 │ Small, base < mod, small exp, clamped │
+ │ L0 │ L │ = │ A │ True │ 500 │ Large, equal, zero exp, clamped │
+ │ L1 │ L │ = │ B │ False │ 12750 │ Large, equal, large exp, unclamped │
+ │ L2 │ L │ = │ C │ False │ 6400 │ Large, equal, large exp + zero low256 │
+ │ L3 │ L │ = │ D │ False │ 6400 │ Large, equal, large exp + non-zero low256 │
+ │ L4 │ L │ > │ B │ True │ 500 │ Large, base > mod, small exp, clamped │
+ │ L5 │ L │ < │ C │ False │ 9216 │ Large, base < mod, large exp + zero low256 │
+ │ B1 │ L │ < │ B │ True │ 500 │ Cross 32-byte boundary (31/33) │
+ │ B2 │ L │ > │ B │ True │ 500 │ Cross 32-byte boundary (33/31) │
+ │ B4 │ L │ = │ B │ True │ 500 │ Just over 32-byte boundary │
+ │ Z8 │ S │ = │ A │ True │ 500 │ All zeros except modulus │
+ │ Z9 │ S │ = │ A │ True │ 500 │ Zero modulus special case │
+ │ Z10 │ S │ = │ B │ False │ 3968 │ Zero base, large exponent │
+ │ Z11 │ S │ = │ C │ True │ 500 │ Zero base, 33B zero exp, non-zero modulus │
+ │ Z12 │ S │ = │ C │ False |253952 │ Zero base, large zero exp, non-zero modulus │
+ │ Z13 │ L │ > │ A │ False │ 32768 │ Large zero base, zero exp, non-zero modulus │
+ │ Z14 │ S │ = │ C │ False |253952 │ Base, large zero exp, zero modulus │
+ │ Z15 │ L │ < │ B │ False │ 32768 │ Base, small exp, large zero modulus │
+ │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) |
+ │ M1 │ L │ = │ D │ False │ 98176 │ Maximum values stress test │
+ │ M2 │ S │ = │ B │ True │ 500 │ Max base/mod, small exponent │
+ │ M3 │ L │ < │ D │ False │ 98176 │ Small base, max exponent/mod │
+ │ T2 │ S │ = │ B │ True │ 500 │ Tiny maximum values │
+ │ P2 │ S │ = │ B │ False │ 4080 │ High bit in exponent │
+ │ P3 │ L │ = │ D │ False │ 1150 │ Specific bit pattern in large exponent │
+ │ A1 │ L │ < │ C │ False │ 65536 │ Asymmetric: tiny base, large exp/mod │
+ │ A2 │ L │ > │ B │ True │ 500 │ Asymmetric: large base, tiny exp/mod │
+ │ A3 │ L │ > │ C │ False │ 65536 │ Asymmetric: large base/exp, tiny modulus │
+ │ W2 │ S │ = │ B │ True │ 500 │ Exactly 8-byte words │
+ │ E1 │ S │ = │ D │ True │ 500 │ Exponent exactly 33 bytes │
+ │ E2 │ S │ = │ B │ False │ 4080 │ High bit in exponent first byte │
+ │ E3 │ S │ = │ B │ True │ 500 │ High bit in exponent last byte │
+ │ E4 │ S │ = │ B │ False │ 4064 │ Maximum 32-byte exponent │
+ │ IC1 │ L │ = │ B │ True │ 500 │ Bit shift vs multiplication @ 33 bytes │
+ │ IC3 │ S │ = │ B │ True │ 500 │ Ceiling division at 7 bytes │
+ │ IC4 │ S │ = │ B │ True │ 500 │ Ceiling division at 9 bytes │
+ │ IC5 │ S │ = │ B │ False │ 2160 │ Bit counting in middle of exponent │
+ │ IC6 │ L │ = │ B │ True │ 500 │ Native library even byte optimization │
+ │ IC7 │ L │ = │ B │ True │ 500 │ Vector optimization 128-bit boundary │
+ │ IC9 │ S │ = │ B │ N/A │ N/A │ Zero modulus handling │
+ │ IC10│ S │ = │ B │ False │ 4080 │ Power-of-2 boundary with high bit │
+ └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘
+ """ # noqa: W505
+ for base, exponent, modulus, expected_result, gas_usage, test_id in test_cases:
yield pytest.param(
ModExpInput(base=base, exponent=exponent, modulus=modulus),
bytes.fromhex(expected_result),
+ gas_usage,
id=test_id,
)
@pytest.mark.parametrize(
- "modexp_input,modexp_expected",
+ "modexp_input,modexp_expected,gas_usage",
create_modexp_variable_gas_test_cases(),
)
+@EIPChecklist.Precompile.Test.InputLengths.Zero()
+@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement()
@pytest.mark.valid_from("Berlin")
def test_modexp_variable_gas_cost(
state_test: StateTestFiller,
+ precompile_gas: int,
+ gas_usage: int,
pre: Alloc,
tx: Transaction,
+ fork: Fork,
post: Dict,
):
"""Test ModExp variable gas cost."""
+ if fork >= Osaka: # Check that gas used defined in table is accurate
+ assert (gas_usage is None) or (precompile_gas >= gas_usage), "inconsistent gas usage"
state_test(pre=pre, tx=tx, post=post)
@@ -477,13 +677,14 @@ def test_modexp_variable_gas_cost(
@pytest.mark.valid_from("Berlin")
def test_modexp_variable_gas_cost_exceed_tx_gas_cap(state_test, pre, tx, post):
"""
- Test ModExp variable gas cost.
- Inputs with an expected gas cost over the EIP-7825 tx gas cap.
- """
- # Test case coverage table (gas cap):
- # ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐
- # │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │
- # ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤
- # │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) |
- # └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘
+ Test ModExp variable gas cost. Inputs with an expected gas cost over the
+ EIP-7825 tx gas cap.
+
+ Test case coverage table (gas cap):
+ ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐
+ │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │
+ ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤
+ │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) |
+ └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘
+ """ # noqa: W505
state_test(pre=pre, tx=tx, post=post)
diff --git a/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py b/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py
index a5a10c866a..5d779ae627 100644
--- a/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py
+++ b/tests/eest/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py
@@ -1,10 +1,13 @@
-"""Test ModExp gas cost transition from EIP-7883 before and after the Osaka hard fork."""
+"""
+Test ModExp gas cost transition from EIP-7883 before & after the Osaka fork.
+"""
import pytest
+from ethereum_test_checklists import EIPChecklist
from ethereum_test_forks import Fork
-from ethereum_test_tools import Account, Alloc, Block, BlockchainTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_tools import Account, Alloc, Block, BlockchainTestFiller, Transaction, keccak256
+from ethereum_test_vm import Opcodes as Op
from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput
from .spec import Spec, ref_spec_7883
@@ -20,7 +23,13 @@
[
pytest.param(Spec.modexp_input, Spec.modexp_expected, 200, 1200),
],
+ ids=[""],
)
+@EIPChecklist.GasCostChanges.Test.ForkTransition.Before()
+@EIPChecklist.GasCostChanges.Test.ForkTransition.After()
+@EIPChecklist.Precompile.Test.ForkTransition.After.Warm()
+@EIPChecklist.GasCostChanges.Test.ForkTransition.Before()
+@EIPChecklist.GasCostChanges.Test.ForkTransition.After()
def test_modexp_fork_transition(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
@@ -29,8 +38,12 @@ def test_modexp_fork_transition(
gas_new: int,
tx_gas_limit: int,
modexp_input: ModExpInput,
+ modexp_expected: bytes,
):
- """Test ModExp gas cost transition from EIP-7883 before and after the Osaka hard fork."""
+ """
+ Test ModExp gas cost transition from EIP-7883 before and after the Osaka
+ hard fork.
+ """
call_code = Op.CALL(
address=Spec.MODEXP_ADDRESS,
args_size=Op.CALLDATASIZE,
@@ -57,6 +70,12 @@ def test_modexp_fork_transition(
+ Op.SSTORE # []
)
+ # Verification the precompile call result
+ code += Op.RETURNDATACOPY(dest_offset=0, offset=0, size=Op.RETURNDATASIZE()) + Op.SSTORE(
+ Op.AND(Op.TIMESTAMP, 0xFF),
+ Op.SHA3(0, Op.RETURNDATASIZE()),
+ )
+
senders = [pre.fund_eoa() for _ in range(3)]
contracts = [pre.deploy_contract(code) for _ in range(3)]
timestamps = [14_999, 15_000, 15_001]
@@ -78,7 +97,7 @@ def test_modexp_fork_transition(
]
post = {
- contract: Account(storage={ts: gas})
+ contract: Account(storage={ts: gas, ts & 0xFF: keccak256(bytes(modexp_expected))})
for contract, ts, gas in zip(contracts, timestamps, gas_values, strict=False)
}
diff --git a/tests/eest/osaka/eip7918_blob_reserve_price/conftest.py b/tests/eest/osaka/eip7918_blob_reserve_price/conftest.py
index 027cf97134..4f5f9d81bd 100644
--- a/tests/eest/osaka/eip7918_blob_reserve_price/conftest.py
+++ b/tests/eest/osaka/eip7918_blob_reserve_price/conftest.py
@@ -56,7 +56,9 @@ def parent_excess_blob_gas(
parent_excess_blobs: int | None,
blob_gas_per_blob: int,
) -> int | None:
- """Calculate the excess blob gas of the parent block from the excess blobs."""
+ """
+ Calculate the excess blob gas of the parent block from the excess blobs.
+ """
if parent_excess_blobs is None:
return None
assert parent_excess_blobs >= 0
@@ -68,7 +70,8 @@ def blobs_per_tx() -> int:
"""
Total number of blobs per transaction.
- Can be overloaded by a test case to provide a custom blobs per transaction count.
+ Can be overloaded by a test case to provide a custom blobs per transaction
+ count.
"""
return 1
@@ -85,7 +88,10 @@ def block_base_fee_per_gas(
parent_excess_blobs: int | None,
block_base_fee_per_gas_delta: int,
) -> int:
- """Block base fee per gas. Default is 7 unless a delta is provided or overloaded."""
+ """
+ Block base fee per gas. Default is 7 unless a delta is provided or
+ overloaded.
+ """
if block_base_fee_per_gas_delta != 0:
if parent_excess_blobs is None:
blob_base_fee = 1
@@ -106,7 +112,8 @@ def excess_blob_gas(
block_base_fee_per_gas: int,
) -> int | None:
"""
- Calculate the excess blob gas of the block under test from the parent block.
+ Calculate the excess blob gas of the block under test from the parent
+ block.
Value can be overloaded by a test case to provide a custom excess blob gas.
"""
@@ -127,7 +134,8 @@ def correct_excess_blob_gas(
block_base_fee_per_gas: int,
) -> int:
"""
- Calculate the correct excess blob gas of the block under test from the parent block.
+ Calculate the correct excess blob gas of the block under test from the
+ parent block.
Should not be overloaded by a test case.
"""
@@ -193,7 +201,9 @@ def env(
block_base_fee_per_gas: int,
genesis_excess_blob_gas: int,
) -> Environment:
- """Prepare the environment of the genesis block for all blockchain tests."""
+ """
+ Prepare the environment of the genesis block for all blockchain tests.
+ """
return Environment(
excess_blob_gas=genesis_excess_blob_gas,
blob_gas_used=0,
diff --git a/tests/eest/osaka/eip7918_blob_reserve_price/spec.py b/tests/eest/osaka/eip7918_blob_reserve_price/spec.py
index 32c162bb45..60d480da5a 100644
--- a/tests/eest/osaka/eip7918_blob_reserve_price/spec.py
+++ b/tests/eest/osaka/eip7918_blob_reserve_price/spec.py
@@ -20,8 +20,8 @@ class ReferenceSpec:
@dataclass(frozen=True)
class Spec(EIP4844Spec):
"""
- Parameters from the EIP-7918 specifications.
- Extends EIP-4844 spec with the new reserve price constant and functionality.
+ Parameters from the EIP-7918 specifications. Extends EIP-4844 spec with the
+ new reserve price constant and functionality.
"""
BLOB_BASE_COST = 2**13
@@ -50,6 +50,8 @@ def calc_effective_blob_base_fee(
base_fee_per_gas: int,
blob_base_fee: int,
) -> int:
- """Calculate the effective blob base fee considering the reserve price."""
+ """
+ Calculate the effective blob base fee considering the reserve price.
+ """
reserve_price = cls.get_reserve_price(base_fee_per_gas)
return max(reserve_price, blob_base_fee)
diff --git a/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py b/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py
index 1b1d902b31..820f19b54a 100644
--- a/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py
+++ b/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py
@@ -1,8 +1,9 @@
"""
-abstract: [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918)
- Test the blob base fee reserve price mechanism for [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918).
+ [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918).
-""" # noqa: E501
+Test the blob base fee reserve price mechanism for
+[EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918).
+"""
from typing import Dict, List
@@ -145,7 +146,10 @@ def test_reserve_price_various_base_fee_scenarios(
block: Block,
post: Dict[Address, Account],
):
- """Test reserve price mechanism across various block base fee and excess blob gas scenarios."""
+ """
+ Test reserve price mechanism across various block base fee and excess blob
+ gas scenarios.
+ """
blockchain_test(
pre=pre,
post=post,
@@ -156,7 +160,8 @@ def test_reserve_price_various_base_fee_scenarios(
@pytest.mark.parametrize_by_fork(
"parent_excess_blobs",
- # Keep max assuming this will be greater than 20 in the future, to test a blob fee of > 1 :)
+ # Keep max assuming this will be greater than 20 in the future, to test a
+ # blob fee of > 1 :)
lambda fork: [0, 3, fork.target_blobs_per_block(), fork.max_blobs_per_block()],
)
@pytest.mark.parametrize("block_base_fee_per_gas_delta", [-2, -1, 0, 1, 10, 100])
@@ -168,17 +173,30 @@ def test_reserve_price_boundary(
post: Dict[Address, Account],
):
"""
- Tests the reserve price boundary mechanism. Note the default block base fee per gas is 7 (delta is 0).
- With a non zero delta the block base fee per gas is set to (boundary * blob base fee) + delta.
-
- Example scenarios from parametrization, assume parent_excess_blobs = 3:
- delta=-2: blob_base_fee=1, boundary=8, block_base_fee_per_gas=8+(-2)=6, 6 < 8, reserve inactive, effective_fee=1
- delta=0: blob_base_fee=1, boundary=8, block_base_fee_per_gas=7, 7 < 8, reserve inactive, effective_fee=1
- delta=100: blob_base_fee=1, boundary=8, block_base_fee_per_gas=8+100=108, 108 > 8, reserve active, effective_fee=max(108/8, 1)=13
-
- All values give a blob base_ fee of 1 because we need a much higher excess blob gas
- to increase the blob fee. This only increases to 2 at 20 excess blobs.
- """ # noqa: E501
+ Tests the reserve price boundary mechanism. Note the default block base fee
+ per gas is 7 (delta is 0). With a non zero delta the block base fee per gas
+ is set to (boundary * blob base fee) + delta.
+
+ Example scenarios from parametrization:
+ Assume
+ parent_excess_blobs = 3:
+ delta=-2:
+ blob_base_fee=1,
+ boundary=8,
+ block_base_fee_per_gas=8+(-2)=6, 6 < 8,
+ reserve inactive,
+ effective_fee=1 delta=0:
+ blob_base_fee=1, boundary=8,
+ block_base_fee_per_gas=7, 7 < 8,
+ reserve inactive, effective_fee=1
+ delta=100: blob_base_fee=1,
+ boundary=8, block_base_fee_per_gas=8+100=108, 108 > 8,
+ reserve active, effective_fee=max(108/8, 1)=13
+
+ All values give a blob base_ fee of 1 because we need a much higher excess
+ blob gas to increase the blob fee. This only increases to 2 at 20 excess
+ blobs.
+ """
blockchain_test(
genesis_environment=env,
pre=pre,
diff --git a/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py b/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py
index 07e1d69711..b52dce2943 100644
--- a/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py
+++ b/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py
@@ -1,8 +1,7 @@
"""
-abstract: [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918)
- Test the blob base fee reserve price mechanism for [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918).
-
-""" # noqa: E501
+ [EIP-7918: Blob base fee bounded by execution
+cost](https://eips.ethereum.org/EIPS/eip-7918).
+"""
import pytest
diff --git a/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py b/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py
index 7bf2883b26..b41b9eb298 100644
--- a/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py
+++ b/tests/eest/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py
@@ -99,8 +99,8 @@ def genesis_base_fee_per_gas(
parent_base_fee_per_gas: int,
) -> int:
"""Genesis base fee per gas."""
- # Base fee always drops from genesis to block 1 because the genesis block never uses
- # any tx gas.
+ # Base fee always drops from genesis to block 1 because the genesis block
+ # never uses any tx gas.
return (parent_base_fee_per_gas * fork.base_fee_max_change_denominator()) // 7
@@ -151,10 +151,12 @@ def env(
) -> Environment:
"""Environment for the test."""
return Environment(
- # Excess blob gas always drops from genesis to block 1 because genesis uses no blob gas.
+ # Excess blob gas always drops from genesis to block 1 because genesis
+ # uses no blob gas.
excess_blob_gas=genesis_excess_blob_gas,
base_fee_per_gas=genesis_base_fee_per_gas,
- gas_limit=16_000_000, # To make it easier to reach the requirement with a single tx
+ gas_limit=16_000_000, # To make it easier to reach the requirement
+ # with a single tx
)
@@ -234,8 +236,8 @@ def parent_block_txs(
"""
Transactions included in the block prior to the fork transition fork.
- Includes blob transactions to raise the `parent_blob_gas_used` and normal transactions
- to raise/lower the base fee per gas.
+ Includes blob transactions to raise the `parent_blob_gas_used` and normal
+ transactions to raise/lower the base fee per gas.
"""
parent_block_blob_txs = get_blob_transactions(
blob_count=parent_blob_count,
@@ -386,8 +388,8 @@ def target_blob_gas_per_block(self) -> int:
def calculate_excess_blob_gas(self, parent_header: ParentHeader) -> int:
"""
- Calculate the excess blob gas for the current block based
- on the gas used in the parent block.
+ Calculate the excess blob gas for the current block based on the gas
+ used in the parent block.
"""
excess_blob_gas_calculator = self.fork.excess_blob_gas_calculator(timestamp=self.timestamp)
return excess_blob_gas_calculator(
@@ -400,8 +402,8 @@ def execution_base_fee_threshold_from_excess_blob_gas(
self, excess_blob_gas: int
) -> int | None:
"""
- Return the minimum base fee required to trigger the reserve mechanism, or None
- for blob schedules that don't have a reserve price mechanism.
+ Return the minimum base fee required to trigger the reserve mechanism,
+ or None for blob schedules that don't have a reserve price mechanism.
"""
if self.blob_base_cost is None:
return None
@@ -414,8 +416,8 @@ def execution_base_fee_threshold_from_excess_blob_gas(
def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]:
"""
- Return the list of scenarios at the fork boundary depending on the source fork and
- transition fork properties.
+ Return the list of scenarios at the fork boundary depending on the source
+ fork and transition fork properties.
"""
source_blob_schedule = BlobSchedule(fork=fork, timestamp=0)
transition_blob_schedule = BlobSchedule(fork=fork, timestamp=15_000)
@@ -439,16 +441,16 @@ def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]:
source_execution_threshold != transition_execution_threshold
and transition_execution_threshold is not None
):
- # The source base fee reserve threshold is different from the transition one
- # given the excess blob gas.
- # We can verify that the BPO is activated correctly by using the a setup block
- # with transition_execution_threshold to trigger the reserve.
+ # The source base fee reserve threshold is different from the
+ # transition one given the excess blob gas. We can verify that the
+ # BPO is activated correctly by using the a setup block with
+ # transition_execution_threshold to trigger the reserve.
for source_blob_count in [0, source_blob_schedule.target, source_blob_schedule.max]:
- # Scenario 1: Parent base fee per gas is below the threshold at the
- # parent of the transition block, so even though the base fee increases on
- # the transition block to reach the value required to activate the reserve,
- # since the base fee per gas of the parent is used, the reserve must not be
- # activated.
+ # Scenario 1: Parent base fee per gas is below the threshold at
+ # the parent of the transition block, so even though the base
+ # fee increases on the transition block to reach the value
+ # required to activate the reserve, since the base fee per gas
+ # of the parent is used, the reserve must not be activated.
parent_base_fee = transition_execution_threshold - 1
transition_base_fee = transition_execution_threshold
parent_header = ParentHeader(
@@ -477,9 +479,9 @@ def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]:
),
)
- # Scenario 2: Parent base fee per gas is at the threshold, so the reserve
- # is activated even though the base fee per gas decreases below the
- # threshold on the transition block.
+ # Scenario 2: Parent base fee per gas is at the threshold, so
+ # the reserve is activated even though the base fee per gas
+ # decreases below the threshold on the transition block.
parent_base_fee = transition_execution_threshold
transition_base_fee = transition_execution_threshold - 1
parent_header = ParentHeader(
@@ -509,7 +511,8 @@ def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]:
)
if fork == BPO2ToBPO3AtTime15k:
- # Explicitly add the exact scenario that triggered the Fusaka Devnet-4 fork.
+ # Explicitly add the exact scenario that triggered the Fusaka Devnet-4
+ # fork.
yield pytest.param(
0x32,
0x125BF5F,
@@ -541,7 +544,10 @@ def test_reserve_price_at_transition(
transition_block: Block,
env: Environment,
):
- """Test reserve price mechanism across various block base fee and excess blob gas scenarios."""
+ """
+ Test reserve price mechanism across various block base fee and excess blob
+ gas scenarios.
+ """
blockchain_test(
pre=pre,
post={},
diff --git a/tests/eest/osaka/eip7934_block_rlp_limit/__init__.py b/tests/eest/osaka/eip7934_block_rlp_limit/__init__.py
index 5c84ada870..f2bdbe0226 100644
--- a/tests/eest/osaka/eip7934_block_rlp_limit/__init__.py
+++ b/tests/eest/osaka/eip7934_block_rlp_limit/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934)
- Test cases for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934).
+Tests for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934).
"""
diff --git a/tests/eest/osaka/eip7934_block_rlp_limit/conftest.py b/tests/eest/osaka/eip7934_block_rlp_limit/conftest.py
index 651ae98488..c3ee0fccd8 100644
--- a/tests/eest/osaka/eip7934_block_rlp_limit/conftest.py
+++ b/tests/eest/osaka/eip7934_block_rlp_limit/conftest.py
@@ -6,8 +6,8 @@
Address,
Alloc,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types import Environment
+from ethereum_test_vm import Opcodes as Op
@pytest.fixture
diff --git a/tests/eest/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py b/tests/eest/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py
index fc90e59bde..8fb3550b71 100644
--- a/tests/eest/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py
+++ b/tests/eest/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py
@@ -1,6 +1,5 @@
"""
-abstract: Test [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934)
- Tests for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934).
+Tests for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934).
"""
from functools import lru_cache
@@ -59,7 +58,9 @@ def block_size_limit(fork: Fork) -> int:
@pytest.fixture
def block_errors() -> List[BlockException]:
- """Block exceptions expected for blocks that exceed the `MAX_RLP_BLOCK_SIZE`."""
+ """
+ Block exceptions expected for blocks that exceed the `MAX_RLP_BLOCK_SIZE`.
+ """
return [BlockException.RLP_BLOCK_LIMIT_EXCEEDED]
@@ -121,8 +122,8 @@ def exact_size_transactions(
"""
Generate transactions that fill a block to exactly the RLP size limit.
- The calculation uses caching to avoid recalculating the same block rlp for each
- fork. Calculate the block and fill with real sender for testing.
+ The calculation uses caching to avoid recalculating the same block rlp for
+ each fork. Calculate the block and fill with real sender for testing.
Args:
sender: The sender account
@@ -131,7 +132,8 @@ def exact_size_transactions(
pre: Required if emit_logs is True, used to deploy the log contract
gas_limit: The gas limit for the block
emit_logs: If True, transactions will call a contract that emits logs
- specific_transaction_to_include: If provided, this transaction will be included
+ specific_transaction_to_include: If provided, this transaction will
+ be included
"""
log_contract = None
@@ -190,8 +192,8 @@ def _exact_size_transactions_cached(
emit_logs_contract: Address | None = None,
) -> Tuple[List[Transaction], int]:
"""
- Generate transactions that fill a block to exactly the RLP size limit. Abstracted
- with hashable arguments for caching block calculations.
+ Generate transactions that fill a block to exactly the RLP size limit.
+ Abstracted with hashable arguments for caching block calculations.
"""
return _exact_size_transactions_impl(
block_size_limit,
@@ -212,8 +214,8 @@ def _exact_size_transactions_impl(
emit_logs_contract: Address | None = None,
) -> Tuple[List[Transaction], int]:
"""
- Calculate the exact size of transactions to be included. Shared by both cached and
- non-cached paths.
+ Calculate the exact size of transactions to be included. Shared by both
+ cached and non-cached paths.
"""
transactions = []
nonce = 0
@@ -224,9 +226,10 @@ def _exact_size_transactions_impl(
data_large = Bytes(b"\x00" * 500_000)
gas_limit_large = calculator(calldata=data_large)
- # block with 16 transactions + large calldata remains safely below the limit
- # add 15 generic transactions to fill the block and one typed transaction
- # if tx_type is specified, otherwise just add 16 generic transactions
+ # block with 16 transactions + large calldata remains safely below the
+ # limit add 15 generic transactions to fill the block and one typed
+ # transaction if tx_type is specified, otherwise just add 16 generic
+ # transactions
not_all_generic_txs = any(
kwarg is not None for kwarg in [specific_transaction_to_include, emit_logs_contract]
)
@@ -381,6 +384,7 @@ def _exact_size_transactions_impl(
return transactions, final_gas
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"delta",
[
@@ -440,6 +444,7 @@ def test_block_at_rlp_size_limit_boundary(
)
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.with_all_typed_transactions
@pytest.mark.verify_sync
def test_block_rlp_size_at_limit_with_all_typed_transactions(
@@ -479,6 +484,7 @@ def test_block_rlp_size_at_limit_with_all_typed_transactions(
)
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.verify_sync
def test_block_at_rlp_limit_with_logs(
blockchain_test: BlockchainTestFiller,
@@ -489,7 +495,10 @@ def test_block_at_rlp_limit_with_logs(
fork: Fork,
block_size_limit: int,
):
- """Test that a block at the RLP size limit is valid even when transactions emit logs."""
+ """
+ Test that a block at the RLP size limit is valid even when transactions
+ emit logs.
+ """
transactions, gas_used = exact_size_transactions(
sender,
block_size_limit,
diff --git a/tests/eest/osaka/eip7939_count_leading_zeros/__init__.py b/tests/eest/osaka/eip7939_count_leading_zeros/__init__.py
index 23769774cf..1e9f1a4156 100644
--- a/tests/eest/osaka/eip7939_count_leading_zeros/__init__.py
+++ b/tests/eest/osaka/eip7939_count_leading_zeros/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939)
- Test cases for [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939).
+Tests [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939).
"""
diff --git a/tests/eest/osaka/eip7939_count_leading_zeros/eip_checklist_external_coverage.txt b/tests/eest/osaka/eip7939_count_leading_zeros/eip_checklist_external_coverage.txt
new file mode 100644
index 0000000000..f0b87011f0
--- /dev/null
+++ b/tests/eest/osaka/eip7939_count_leading_zeros/eip_checklist_external_coverage.txt
@@ -0,0 +1,2 @@
+general/code_coverage/eels = Please check https://app.codecov.io/gh/ethereum/execution-specs/pull/1388/blob/src/ethereum/osaka/vm/instructions/bitwise.py#L243 for relevant test coverage
+general/code_coverage/test_coverage = Please run the test with `--cov` flag for final coverage
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7939_count_leading_zeros/eip_checklist_not_applicable.txt b/tests/eest/osaka/eip7939_count_leading_zeros/eip_checklist_not_applicable.txt
new file mode 100644
index 0000000000..f8a1d0e744
--- /dev/null
+++ b/tests/eest/osaka/eip7939_count_leading_zeros/eip_checklist_not_applicable.txt
@@ -0,0 +1,29 @@
+system_contract = EIP does not introduce a new system contract
+precompile = EIP does not introduce a new precompile
+removed_precompile = EIP does not remove a precompile
+transaction_type = EIP does not introduce a new transaction type
+block_header_field = EIP does not add any new block header fields
+block_body_field = EIP does not add any new block body fields
+gas_cost_changes = EIP does not modify existing gas costs, only introduces new opcode with fixed cost
+gas_refunds_changes = EIP does not introduce any gas refund changes
+blob_count_changes = EIP does not introduce any blob count changes
+execution_layer_request = EIP does not introduce an execution layer request
+new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint
+modified_transaction_validity_constraint = EIP does not introduce a modified transaction validity constraint
+opcode/test/mem_exp = CLZ does not read/write to memory component
+opcode/test/stack_overflow = CLZ takes one args and pushes one args to stack, not increasing stack element, hence no overflow issue
+opcode/test/stack_complex_operations/data_portion_variables = there is no data portion for CLZ
+opcode/test/execution_context/delegatecall/code = CLZ does not modify code
+opcode/test/execution_context/tx_context = CLZ does not change behavior depending on transaction property
+opcode/test/execution_context/block_context = CLZ does not change behavior depending on block property
+opcode/test/execution_context/initcode/reentry = CLZ is not a stateful opcode
+opcode/test/gas_usage/memory_expansion = no memory read/write for CLZ
+opcode/test/gas_usage/out_of_gas_memory = no memory read/write for CLZ
+opcode/test/gas_usage/order_of_operations = the order will not affect result of CLZ
+opcode/test/return_data = although we could verify the return buffer is not affected, but it is more like testing memory write operation, as CLZ does not write to memory directly
+opcode/test/terminating = not such opcode
+opcode/test/terminating/rollback = CLZ is not a terminating opcode, so no rollback behavior
+opcode/test/out_of_bounds = takes one element from stack, no specific boundary
+opcode/test/exceptional_abort = underflow is the only exceptional abort scenario and it is included already
+opcode/test/data_portion = no data portion
+opcode/test/contract_creation = no contract created in execution
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py b/tests/eest/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py
index 4f9c0efa52..f2592a8189 100644
--- a/tests/eest/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py
+++ b/tests/eest/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py
@@ -1,11 +1,11 @@
"""
-abstract: Tests [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939)
- Test cases for [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939).
+Tests [EIP-7939: Count leading zeros (CLZ)](https://eips.ethereum.org/EIPS/eip-7939).
"""
import pytest
from ethereum_test_base_types import Storage
+from ethereum_test_checklists import EIPChecklist
from ethereum_test_forks import Fork
from ethereum_test_tools import (
Account,
@@ -20,7 +20,7 @@
Transaction,
compute_create_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from ...prague.eip7702_set_code_tx.spec import Spec as Spec7702
from .spec import Spec, ref_spec_7939
@@ -96,7 +96,8 @@ def test_clz_opcode_scenarios(
Test CLZ opcode functionality.
Cases:
- - Format 0xb000...111: leading zeros followed by ones (2**256 - 1 >> bits)
+ - Format 0xb000...111: leading zeros followed by ones
+ (2**256 - 1 >> bits)
- Format 0xb010...000: single bit set at position (1 << bits)
Test coverage:
@@ -144,6 +145,9 @@ def test_clz_gas_cost(state_test: StateTestFiller, pre: Alloc, fork: Fork):
state_test(pre=pre, post=post, tx=tx)
+@EIPChecklist.Opcode.Test.GasUsage.Normal()
+@EIPChecklist.Opcode.Test.GasUsage.OutOfGasExecution()
+@EIPChecklist.Opcode.Test.GasUsage.ExtraGas()
@pytest.mark.valid_from("Osaka")
@pytest.mark.parametrize("bits", [0, 64, 128, 255])
@pytest.mark.parametrize("gas_cost_delta", [-2, -1, 0, 1, 2])
@@ -178,9 +182,13 @@ def test_clz_gas_cost_boundary(
state_test(pre=pre, post=post, tx=tx)
+@EIPChecklist.Opcode.Test.StackUnderflow()
+@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Zero()
@pytest.mark.valid_from("Osaka")
def test_clz_stack_underflow(state_test: StateTestFiller, pre: Alloc):
- """Test CLZ opcode with empty stack (should revert due to stack underflow)."""
+ """
+ Test CLZ opcode with empty stack (should revert due to stack underflow).
+ """
sender = pre.fund_eoa()
callee_address = pre.deploy_contract(
code=Op.CLZ + Op.STOP, # No stack items, should underflow
@@ -202,6 +210,8 @@ def test_clz_stack_underflow(state_test: StateTestFiller, pre: Alloc):
state_test(pre=pre, post=post, tx=tx)
+@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Odd()
+@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Even()
@pytest.mark.valid_from("Osaka")
def test_clz_stack_not_overflow(state_test: StateTestFiller, pre: Alloc, fork: Fork):
"""Test CLZ opcode never causes stack overflow."""
@@ -260,6 +270,8 @@ def test_clz_push_operation_same_value(state_test: StateTestFiller, pre: Alloc):
state_test(pre=pre, post=post, tx=tx)
+@EIPChecklist.Opcode.Test.ForkTransition.Invalid()
+@EIPChecklist.Opcode.Test.ForkTransition.At()
@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True)
def test_clz_fork_transition(blockchain_test: BlockchainTestFiller, pre: Alloc):
"""Test CLZ opcode behavior at fork transition."""
@@ -320,9 +332,12 @@ def test_clz_fork_transition(blockchain_test: BlockchainTestFiller, pre: Alloc):
),
callee_address: Account(
storage={
- 14_999: "0xdeadbeef", # CLZ not valid before fork, storage unchanged
- 15_000: 155, # CLZ valid on transition block, CLZ(1 << 100) = 155
- 15_001: 155, # CLZ continues to be valid after transition
+ # CLZ not valid before fork, storage unchanged
+ 14_999: "0xdeadbeef",
+ # CLZ valid on transition block, CLZ(1 << 100) = 155
+ 15_000: 155,
+ # CLZ continues to be valid after transition
+ 15_001: 155,
}
),
},
@@ -386,6 +401,7 @@ def test_clz_jump_operation(
auth_account_start_balance = 0
+@EIPChecklist.Opcode.Test.ExecutionContext.SetCode()
@pytest.mark.valid_from("Osaka")
def test_clz_from_set_code(
state_test: StateTestFiller,
@@ -457,7 +473,8 @@ def test_clz_code_copy_operation(state_test: StateTestFiller, pre: Alloc, bits:
address=target_address, dest_offset=0, offset=clz_code_offset, size=1
)
)
- + Op.SSTORE(storage.store_next(mload_value), Op.MLOAD(0)) # Store loaded CLZ byte
+ # Store loaded CLZ byte
+ + Op.SSTORE(storage.store_next(mload_value), Op.MLOAD(0))
),
storage={"0x00": "0xdeadbeef"},
)
@@ -494,8 +511,9 @@ def test_clz_with_memory_operation(state_test: StateTestFiller, pre: Alloc, bits
# MSTORE
#
# This sequence stores a 32-byte value in memory.
- # Later, we copy the immediate value from the PUSH32 instruction into memory
- # using CODECOPY or EXTCODECOPY, and then load it with MLOAD for the CLZ test.
+ # Later, we copy the immediate value from the PUSH32 instruction into
+ # memory using CODECOPY or EXTCODECOPY, and then load it with MLOAD for
+ # the CLZ test.
target_code = Op.PUSH32(1 << bits)
offset = 1
@@ -530,6 +548,7 @@ def test_clz_with_memory_operation(state_test: StateTestFiller, pre: Alloc, bits
state_test(pre=pre, post=post, tx=tx)
+@EIPChecklist.Opcode.Test.ExecutionContext.Initcode.Behavior.Tx()
@pytest.mark.valid_from("Osaka")
def test_clz_initcode_context(state_test: StateTestFiller, pre: Alloc):
"""Test CLZ opcode behavior when creating a contract."""
@@ -559,6 +578,7 @@ def test_clz_initcode_context(state_test: StateTestFiller, pre: Alloc):
state_test(pre=pre, post=post, tx=tx)
+@EIPChecklist.Opcode.Test.ExecutionContext.Initcode.Behavior.Opcode()
@pytest.mark.valid_from("Osaka")
@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2])
def test_clz_initcode_create(state_test: StateTestFiller, pre: Alloc, opcode: Op):
@@ -609,6 +629,10 @@ class CallingContext:
no_context = 3 # STATICCALL
+@EIPChecklist.Opcode.Test.ExecutionContext.Call()
+@EIPChecklist.Opcode.Test.ExecutionContext.Delegatecall()
+@EIPChecklist.Opcode.Test.ExecutionContext.Callcode()
+@EIPChecklist.Opcode.Test.ExecutionContext.Staticcall()
@pytest.mark.valid_from("Osaka")
@pytest.mark.parametrize(
"opcode,context",
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/__init__.py b/tests/eest/osaka/eip7951_p256verify_precompiles/__init__.py
index dc20209ead..a5fa2c7cfc 100644
--- a/tests/eest/osaka/eip7951_p256verify_precompiles/__init__.py
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)
- Test cases for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)].
+Tests [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951).
"""
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/conftest.py b/tests/eest/osaka/eip7951_p256verify_precompiles/conftest.py
index 17833d4408..179eebd87c 100644
--- a/tests/eest/osaka/eip7951_p256verify_precompiles/conftest.py
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/conftest.py
@@ -16,9 +16,11 @@ def vector_gas_value() -> int | None:
"""
Gas value from the test vector if any.
- If `None` it means that the test scenario did not come from a file, so no comparison is needed.
+ If `None` it means that the test scenario did not come from a file, so no
+ comparison is needed.
- The `vectors_from_file` function reads the gas value from the file and overwrites this fixture.
+ The `vectors_from_file` function reads the gas value from the file and
+ overwrites this fixture.
"""
return None
@@ -38,9 +40,10 @@ def precompile_gas_modifier() -> int:
"""
Modify the gas passed to the precompile, for testing purposes.
- By default the call is made with the exact gas amount required for the given opcode,
- but when this fixture is overridden, the gas amount can be modified to, e.g., test
- a lower amount and test if the precompile call fails.
+ By default the call is made with the exact gas amount required for the
+ given opcode, but when this fixture is overridden, the gas amount can be
+ modified to, e.g., test a lower amount and test if the precompile call
+ fails.
"""
return 0
@@ -59,7 +62,10 @@ def call_opcode() -> Op:
def call_contract_post_storage() -> Storage:
"""
Storage of the test contract after the transaction is executed.
- Note: Fixture `call_contract_code` fills the actual expected storage values.
+
+ Note:
+ Fixture `call_contract_code` fills the actual expected storage values.
+
"""
return Storage()
@@ -67,8 +73,8 @@ def call_contract_post_storage() -> Storage:
@pytest.fixture
def call_succeeds() -> bool:
"""
- By default, depending on the expected output, we can deduce if the call is expected to succeed
- or fail.
+ By default, depending on the expected output, we can deduce if the call is
+ expected to succeed or fail.
"""
return True
@@ -130,7 +136,9 @@ def post(call_contract_address: Address, call_contract_post_storage: Storage):
@pytest.fixture
def tx_gas_limit(fork: Fork, input_data: bytes, precompile_gas: int) -> int:
- """Transaction gas limit used for the test (Can be overridden in the test)."""
+ """
+ Transaction gas limit used for the test (Can be overridden in the test).
+ """
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
extra_gas = 100_000
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/helpers.py b/tests/eest/osaka/eip7951_p256verify_precompiles/helpers.py
index c220f0e517..320f04e4e3 100644
--- a/tests/eest/osaka/eip7951_p256verify_precompiles/helpers.py
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/helpers.py
@@ -9,7 +9,10 @@
def current_python_script_directory(*args: str) -> str:
- """Get the current Python script directory, optionally appending additional path components."""
+ """
+ Get the current Python script directory, optionally appending additional
+ path components.
+ """
return os.path.join(os.path.dirname(os.path.realpath(__file__)), *args)
@@ -24,7 +27,10 @@ class Vector(BaseModel):
model_config = ConfigDict(alias_generator=to_pascal)
def to_pytest_param(self):
- """Convert the test vector to a tuple that can be used as a parameter in a pytest test."""
+ """
+ Convert the test vector to a tuple that can be used as a parameter in a
+ pytest test.
+ """
return pytest.param(self.input, self.expected, self.gas, id=self.name)
@@ -38,7 +44,10 @@ class FailVector(BaseModel):
model_config = ConfigDict(alias_generator=to_pascal)
def to_pytest_param(self):
- """Convert the test vector to a tuple that can be used as a parameter in a pytest test."""
+ """
+ Convert the test vector to a tuple that can be used as a parameter in a
+ pytest test.
+ """
return pytest.param(self.input, id=self.name)
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/scripts/find_low_p256_points.sage b/tests/eest/osaka/eip7951_p256verify_precompiles/scripts/find_low_p256_points.sage
new file mode 100644
index 0000000000..d785afa721
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/scripts/find_low_p256_points.sage
@@ -0,0 +1,54 @@
+# Find points on P256 with low x or y coordinates by solving the curve equation
+# independently for range of low x and y values.
+#
+# Can be executed online: https://sagecell.sagemath.org/?q=pmqnkn
+#
+# Test cases generated:
+#
+# x_0_y_positive:
+# (0x0000000000000000000000000000000000000000000000000000000000000000, 0x66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4)
+# x_0_y_negative:
+# (0x0000000000000000000000000000000000000000000000000000000000000000, 0x99b7a386f1d07c29dbcc42a27b5f9449abe3d50de25178e8d7407a95e8b06c0b)
+# x_5_y_positive:
+# x_P_plus_5_y_positive:
+# (0x0000000000000000000000000000000000000000000000000000000000000005, 0x459243b9aa581806fe913bce99817ade11ca503c64d9a3c533415c083248fbcc)
+# x_5_y_negative:
+# x_P_plus_5_y_negative:
+# (0x0000000000000000000000000000000000000000000000000000000000000005, 0xba6dbc4555a7e7fa016ec431667e8521ee35afc49b265c3accbea3f7cdb70433)
+# y_1:
+# y_P_plus_1:
+# (0x09e78d4ef60d05f750f6636209092bc43cbdd6b47e11a9de20a9feb2a50bb96c, 0x0000000000000000000000000000000000000000000000000000000000000001)
+
+
+p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
+a = -3
+b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
+
+F = GF(p)
+aF = F(a)
+bF = F(b)
+
+M = 11
+
+for x_int in range(0, M):
+ print(f"x = {x_int}:")
+ xF = F(x_int)
+ rhs = xF**3 + aF*xF + bF
+
+ if rhs.is_square():
+ y = rhs.sqrt()
+ for yF in [y, -y]:
+ print(f" (0x{int(xF):064x}, 0x{int(yF):064x})")
+
+R. = PolynomialRing(F)
+for y_int in range(0, M):
+ yF = F(y_int)
+ # Solve x^3 + a*x + (b - y^2) == 0 over F_p
+ c = bF - yF * yF
+ f = x^3 + aF * x + c
+
+ roots = [r for (r, mult) in f.roots()] # distinct roots over F_p
+
+ print(f"y = {y_int}:")
+ for xF in sorted(roots):
+ print(f" (0x{int(xF):064x}, 0x{y_int:064x})")
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/spec.py b/tests/eest/osaka/eip7951_p256verify_precompiles/spec.py
index 84532af2e8..277897f0ca 100644
--- a/tests/eest/osaka/eip7951_p256verify_precompiles/spec.py
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/spec.py
@@ -99,18 +99,31 @@ class Spec:
B = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B ## Curve Coefficient
N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 ## Subgroup Order
+ Gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296 ## Generator Point X
+ Gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 ## Generator Point Y
+
# Other constants
SUCCESS_RETURN_VALUE = b"\x01".rjust(32, b"\x00")
INVALID_RETURN_VALUE = b""
DELEGATION_DESIGNATION = Bytes("ef0100")
- # Test constants (from https://github.com/C2SP/wycheproof/blob/4a6c2bf5dc4c0b67c770233ad33961ee653996a0/testvectors/ecdsa_secp256r1_sha256_test.json#L35)
+ # Test constants, from:
+ # https://github.com/C2SP/wycheproof/blob/4a6c2bf5dc4c0b67c770233ad33961ee653996a0/testvectors/ecdsa_secp256r1_sha256_test.json#L35
H0 = H(0xBB5A52F42F9C9261ED4361F59422A1E30036E7C32B270C8807A419FECA605023)
R0 = R(0x2BA3A8BE6B94D5EC80A6D9D1190A436EFFE50D85A1EEE859B8CC6AF9BD5C2E18)
S0 = S(0x4CD60B855D442F5B3C7B11EB6C4E0AE7525FE710FAB9AA7C77A67F79E6FADD76)
X0 = X(0x2927B10512BAE3EDDCFE467828128BAD2903269919F7086069C8C4DF6C732838)
Y0 = Y(0xC7787964EAAC00E5921FB1498A60F4606766B3D9685001558D1A974E7341513E)
+ # Test constants from:
+ # https://github.com/C2SP/wycheproof/blob/4a6c2bf5dc4c0b67c770233ad33961ee653996a0/testvectors/ecdsa_webcrypto_test.json#L1064
+ # k*G has a large x-coordinate which also gives very small r.
+ H1 = H(0x532EAABD9574880DBF76B9B8CC00832C20A6EC113D682299550D7A6E0F345E25)
+ R1 = R(0x000000000000000000000000000000004319055358E8617B0C46353D039CDAAB)
+ S1 = S(0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E)
+ X1 = X(0xD705D16F80987E2D9B1A6957D29CE22FEBF7D10FA515153182415C8361BAACA4)
+ Y1 = Y(0xB1FC105EE5CE80D514EC1238BEAE2037A6F83625593620D460819E8682160926)
+
@staticmethod
def delegation_designation(address: Address) -> Bytes:
"""Return delegation designation for the given address."""
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify.py
index 8c4f1cd5ef..68ad5779cc 100644
--- a/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify.py
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify.py
@@ -1,6 +1,5 @@
"""
-abstract: Tests [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)
- Test cases for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)].
+Tests for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951).
"""
import pytest
@@ -30,16 +29,190 @@
@pytest.mark.parametrize(
"input_data,expected_output,vector_gas_value",
- vectors_from_file("secp256r1_test.json"),
- # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite
- # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json
+ vectors_from_file("secp256r1_signature_specific.json")
+ + vectors_from_file("secp256r1_shamir_multiplication.json")
+ + vectors_from_file("secp256r1_special_case_hash.json")
+ + vectors_from_file("secp256r1_u1_u2.json")
+ + vectors_from_file("secp256r1_k_and_s.json")
+ + vectors_from_file("secp256r1_public_key.json"),
+ # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test
+ # suite, valid cases are from this source:
+ # https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json
)
@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""])
@EIPChecklist.Precompile.Test.CallContexts.Normal()
@EIPChecklist.Precompile.Test.Inputs.Valid()
@EIPChecklist.Precompile.Test.Inputs.MaxValues()
+def test_wycheproof_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction):
+ """Test P256Verify precompile with Wycheproof test suite (valid cases)."""
+ state_test(env=Environment(), pre=pre, post=post, tx=tx)
+
+
+@pytest.mark.parametrize(
+ "input_data,expected_output,vector_gas_value",
+ vectors_from_file("secp256r1_special_case_r_s.json")
+ + vectors_from_file("secp256r1_modified_r_s.json"),
+ # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256
+ # test suite, invalid cases
+ # Source: https://github.com/C2SP/wycheproof/blob/main/
+ # testvectors/ecdsa_secp256r1_sha256_test.json
+)
+@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""])
+@EIPChecklist.Precompile.Test.CallContexts.Normal()
+@EIPChecklist.Precompile.Test.Inputs.Invalid()
+@EIPChecklist.Precompile.Test.Inputs.MaxValues()
+def test_wycheproof_invalid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction):
+ """
+ Test P256Verify precompile with Wycheproof test suite
+ (invalid cases).
+ """
+ state_test(env=Environment(), pre=pre, post=post, tx=tx)
+
+
+@pytest.mark.parametrize(
+ "input_data,expected_output,vector_gas_value",
+ vectors_from_file("secp256r1_small_large_r_s.json")
+ + vectors_from_file("secp256r1_special_points.json"),
+ # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256
+ # test suite, valid/invalid cases
+ # Source: https://github.com/C2SP/wycheproof/blob/main/
+ # testvectors/ecdsa_secp256r1_sha256_test.json
+)
+@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""])
+@EIPChecklist.Precompile.Test.CallContexts.Normal()
+@EIPChecklist.Precompile.Test.Inputs.MaxValues()
+def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction):
+ """
+ Test P256Verify precompile with Wycheproof test suite
+ (mixed valid/invalid cases).
+ """
+ state_test(env=Environment(), pre=pre, post=post, tx=tx)
+
+
+@pytest.mark.parametrize(
+ "input_data",
+ [
+ pytest.param(
+ H(0) + R(Spec.Gx) + S(Spec.Gx) + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_0",
+ ),
+ pytest.param(
+ H(Spec.N - 1) + R(Spec.Gx) + S(Spec.Gx - 1) + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_N_minus_1",
+ ),
+ pytest.param(
+ H(Spec.N) + R(Spec.Gx) + S(Spec.Gx) + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_N",
+ ),
+ pytest.param(
+ H(Spec.P - 1)
+ + R(Spec.Gx)
+ + S(Spec.Gx + Spec.P - 1 - Spec.N)
+ + X(Spec.Gx)
+ + Y(Spec.Gy),
+ id="hash_P_minus_1",
+ ),
+ pytest.param(
+ H(Spec.P) + R(Spec.Gx) + S(Spec.Gx + Spec.P - Spec.N) + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_P",
+ ),
+ pytest.param(
+ H(2**256 - 1)
+ + R(Spec.Gx)
+ + S(Spec.Gx + 2**256 - 1 - Spec.N)
+ + X(Spec.Gx)
+ + Y(Spec.Gy),
+ id="hash_max",
+ ),
+ pytest.param(
+ H(Spec.N + 1 - Spec.Gx) + R(Spec.Gx) + S(1) + X(Spec.Gx) + Y(Spec.Gy),
+ id="s_1",
+ ),
+ pytest.param(
+ H(Spec.N - 1 - Spec.Gx) + R(Spec.Gx) + S(Spec.N - 1) + X(Spec.Gx) + Y(Spec.Gy),
+ id="s_N_minus_1",
+ ),
+ pytest.param(
+ H(((2**256 - 1) % Spec.N) - Spec.Gx + Spec.N)
+ + R(Spec.Gx)
+ + S((2**256 - 1) % Spec.N)
+ + X(Spec.Gx)
+ + Y(Spec.Gy),
+ id="s_max_mod_N",
+ ),
+ pytest.param(
+ H(0xC3D3BE9EB3577F217AE0AB360529A30B18ADC751AEC886328593D7D6FE042809)
+ + R(0x3A4E97B44CBF88B90E6205A45BA957E520F63F3C6072B53C244653278A1819D8)
+ + S(0x6A184AA037688A5EBD25081FD2C0B10BB64FA558B671BD81955CA86E09D9D722)
+ + X(0)
+ + Y(0x66485C780E2F83D72433BD5D84A06BB6541C2AF31DAE871728BF856A174F93F4),
+ id="x_0_y_positive",
+ ),
+ pytest.param(
+ H(0xF98A88895CB0866C5BAD58CF03000DDF9D21CB9407892FF54D637E6A046AFBB3)
+ + R(0x81DC074973D3222F3930981AD98D022517C91063FFB83CFD620E29B86DC30A8F)
+ + S(0x365E4CD085617A265765062A2D9954ED86309DFA33CF5AE1464FE119419FC34A)
+ + X(0)
+ + Y(0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B),
+ id="x_0_y_negative",
+ ),
+ pytest.param(
+ H(0x5F95DCD6E41662D1E0AEFCCDB7877877C1FD88C9E67FC3CDA0D1D520FA8A3AC2)
+ + R(0xAF5DFDDB7EDC789D7C9C42A44AFBBF13C8F1D77D576B6EE5F11FEA4F33E2CB39)
+ + S(0xA28F8C5625AD622950F2FCE9672784B287EF9E032ADE8C23BA218413A1CF6522)
+ + X(5)
+ + Y(0x459243B9AA581806FE913BCE99817ADE11CA503C64D9A3C533415C083248FBCC),
+ id="x_5_y_positive",
+ ),
+ pytest.param(
+ H(0x31CE0B00FA8DD61EF28C7DC5F839C78CF70D60E625E0670BF9C9FCE25E89D99F)
+ + R(0x0FA19CBE154513BA348F2DB951AFB6E135BAC5BD8891282781A032103C3F1289)
+ + S(0xD9ABF5C4E61098A6E653F265770BDBA36ECC8073CEF99548D89FE2C39A7AFA9B)
+ + X(5)
+ + Y(0xBA6DBC4555A7E7FA016EC431667E8521EE35AFC49B265C3ACCBEA3F7CDB70433),
+ id="x_5_y_negative",
+ ),
+ pytest.param(
+ H(0x65B0E03E7A27E6F9F4989C72486FCAF0A3ECF3EF60D14F1C11FB5BF071A8FD1B)
+ + R(0x0B0CC9E314E4180FE18D205010DD1C4410632D472CC4E7AB56CBC04091ABE006)
+ + S(0x8D12C4F19AC41D7877705453A247AB96394E7C093F57EC073A9D150CDE6B68C6)
+ + X(0x09E78D4EF60D05F750F6636209092BC43CBDD6B47E11A9DE20A9FEB2A50BB96C)
+ + Y(1),
+ id="y_1",
+ ),
+ pytest.param(
+ H(0x744084AD41EE67ED1802A6868ACE7815FD6FC0585A3479FF68E69ADB8DD2B420)
+ + R(0xB481C7650CBE85BCD15565811966DA2DA4E4E2931F0892D911520B6A06C340D8)
+ + S(0xE4C2D9FB9A4E3E29B7414F0408B2EBC4421D5BC8ADDCCF864AFF9E7E10DA31BB)
+ + X(0x09E78D4EF60D05F750F6636209092BC43CBDD6B47E11A9DE20A9FEB2A50BB96C)
+ + Y(Spec.P - 1),
+ id="y_P_minus_1",
+ ),
+ # Test case for u1==u2 and Q==G.
+ # This test case is important because u1*G + u2*Q is point doubling.
+ pytest.param(
+ H(0x7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978)
+ + R(0x7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978)
+ + S(0x830D84E672FCB08275ADC7FCFB4AE53BFC5D90CB2F25834F4DAE81C6B4FC8BD9)
+ + X(Spec.Gx)
+ + Y(Spec.Gy),
+ id="u1_eq_u2_and_Q_eq_G",
+ ),
+ # Test case for u1==u2 and Q!=G.
+ pytest.param(
+ H(0x65FB4407BCB2A33AE2E486366BAA79B3A8A17A83DDE0FED6F09014A8AC6F78A1)
+ + R(0x65FB4407BCB2A33AE2E486366BAA79B3A8A17A83DDE0FED6F09014A8AC6F78A1)
+ + S(0x65FB4407BCB2A33AE2E486366BAA79B3A8A17A83DDE0FED6F09014A8AC6F78A1)
+ + Spec.X0
+ + Spec.Y0,
+ id="u1_eq_u2_and_Q_ne_G",
+ ),
+ ],
+)
+@pytest.mark.parametrize("expected_output", [Spec.SUCCESS_RETURN_VALUE], ids=[""])
+@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""])
def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction):
- """Test P256Verify precompile."""
+ """Positive tests for the P256VERIFY precompile."""
state_test(env=Environment(), pre=pre, post=post, tx=tx)
@@ -59,6 +232,30 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
H(0) + R(0) + S(0) + X(0) + Y(0),
id="input_all_zeros",
),
+ pytest.param(
+ H(0) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0,
+ id="hash_0",
+ ),
+ pytest.param(
+ H(Spec.N - 1) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0,
+ id="hash_N_minus_1",
+ ),
+ pytest.param(
+ H(Spec.N) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0,
+ id="hash_N",
+ ),
+ pytest.param(
+ H(Spec.P - 1) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0,
+ id="hash_P_minus_1",
+ ),
+ pytest.param(
+ H(Spec.P) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0,
+ id="hash_P",
+ ),
+ pytest.param(
+ H(2**256 - 1) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0,
+ id="hash_max",
+ ),
pytest.param(
Spec.H0 + R(0) + Spec.S0 + Spec.X0 + Spec.Y0,
id="r_eq_to_zero",
@@ -67,6 +264,14 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
Spec.H0 + R(Spec.N) + Spec.S0 + Spec.X0 + Spec.Y0,
id="r_eq_to_n",
),
+ pytest.param(
+ Spec.H1 + R(Spec.R1.value + Spec.N) + Spec.S1 + Spec.X1 + Spec.Y1,
+ id="r_above_n",
+ ),
+ pytest.param(
+ Spec.H0 + R(2**256 - 1) + Spec.S0 + Spec.X0 + Spec.Y0,
+ id="r_max",
+ ),
pytest.param(
Spec.H0 + Spec.R0 + S(0) + Spec.X0 + Spec.Y0,
id="s_eq_to_zero",
@@ -75,6 +280,60 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
Spec.H0 + Spec.R0 + S(Spec.N) + Spec.X0 + Spec.Y0,
id="s_eq_to_n",
),
+ # If checks for r, s, and point-at-infinity are missing, the s=0 zeros
+ # both u1 and u2, so the computed R is the point at infinity,
+ # and the signature may be considered valid in such implementation.
+ pytest.param(
+ Spec.H0 + R(0) + S(0) + X(Spec.Gx) + Y(Spec.Gy),
+ id="r_0_s_0",
+ ),
+ pytest.param(
+ Spec.H0 + R(0) + S(Spec.N) + X(Spec.Gx) + Y(Spec.Gy),
+ id="r_0_s_N",
+ ),
+ pytest.param(
+ Spec.H0 + R(Spec.N) + S(0) + X(Spec.Gx) + Y(Spec.Gy),
+ id="r_N_s_0",
+ ),
+ pytest.param(
+ Spec.H0 + R(Spec.N) + S(Spec.N) + X(Spec.Gx) + Y(Spec.Gy),
+ id="r_N_s_N",
+ ),
+ # If checks for r and point-at-infinity are missing, the h=0 and r=0
+ # zero both u1 and u2, so the computed R is the point at infinity,
+ # and the signature may be considered valid in such implementation.
+ pytest.param(
+ H(0) + R(0) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_0_r_0",
+ ),
+ pytest.param(
+ H(0) + R(Spec.N) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_0_r_N",
+ ),
+ pytest.param(
+ H(Spec.N) + R(0) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_N_r_0",
+ ),
+ pytest.param(
+ H(Spec.N) + R(Spec.N) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy),
+ id="hash_N_r_N",
+ ),
+ pytest.param(
+ Spec.H0 + R(Spec.Gx) + S((2**256 - 1) % Spec.N) + X(Spec.Gx) + Y(Spec.Gy),
+ id="s_max_mod_N",
+ ),
+ pytest.param(
+ H(Spec.N + 1 - Spec.Gx) + R(Spec.Gx) + S(Spec.N + 1) + X(Spec.Gx) + Y(Spec.Gy),
+ id="s_N_plus_1",
+ ),
+ pytest.param(
+ H(((2**256 - 1) % Spec.N) - Spec.Gx + Spec.N)
+ + R(Spec.Gx)
+ + S(2**256 - 1)
+ + X(Spec.Gx)
+ + Y(Spec.Gy),
+ id="s_max",
+ ),
pytest.param(
Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.P) + Spec.Y0,
id="x_eq_to_p",
@@ -85,7 +344,17 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
),
pytest.param(
Spec.H0 + Spec.R0 + Spec.S0 + X(0) + Y(0),
- id="point_on_infinity",
+ id="point_at_infinity",
+ ),
+ # Test case with Q at infinity. If the implementation misses the check
+ # that Q is not the point at infinity, the signature should verify.
+ pytest.param(
+ Spec.H0
+ + R(0x2DD5CBB0E37BAEC8D1460909B206CA2C87E50CA43B8F31E46168027A7F0AEEC6)
+ + Spec.S0
+ + X(0)
+ + Y(0),
+ id="point_at_infinity_v2",
),
pytest.param(
Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.X0.value + 1) + Spec.Y0,
@@ -107,6 +376,56 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.P + 1) + Spec.Y0,
id="x_greater_than_p",
),
+ pytest.param(
+ H(0xC3D3BE9EB3577F217AE0AB360529A30B18ADC751AEC886328593D7D6FE042809)
+ + R(0x3A4E97B44CBF88B90E6205A45BA957E520F63F3C6072B53C244653278A1819D8)
+ + S(0x6A184AA037688A5EBD25081FD2C0B10BB64FA558B671BD81955CA86E09D9D722)
+ + X(Spec.P) # Valid for X(0)
+ + Y(0x66485C780E2F83D72433BD5D84A06BB6541C2AF31DAE871728BF856A174F93F4),
+ id="x_P_y_positive",
+ ),
+ pytest.param(
+ H(0xF98A88895CB0866C5BAD58CF03000DDF9D21CB9407892FF54D637E6A046AFBB3)
+ + R(0x81DC074973D3222F3930981AD98D022517C91063FFB83CFD620E29B86DC30A8F)
+ + S(0x365E4CD085617A265765062A2D9954ED86309DFA33CF5AE1464FE119419FC34A)
+ + X(Spec.P) # Valid for X(0)
+ + Y(0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B),
+ id="x_P_y_negative",
+ ),
+ pytest.param(
+ H(0x5F95DCD6E41662D1E0AEFCCDB7877877C1FD88C9E67FC3CDA0D1D520FA8A3AC2)
+ + R(0xAF5DFDDB7EDC789D7C9C42A44AFBBF13C8F1D77D576B6EE5F11FEA4F33E2CB39)
+ + S(0xA28F8C5625AD622950F2FCE9672784B287EF9E032ADE8C23BA218413A1CF6522)
+ + X(Spec.P + 5) # Valid for X(5)
+ + Y(0x459243B9AA581806FE913BCE99817ADE11CA503C64D9A3C533415C083248FBCC),
+ id="x_P_plus_5_y_positive",
+ ),
+ pytest.param(
+ H(0x31CE0B00FA8DD61EF28C7DC5F839C78CF70D60E625E0670BF9C9FCE25E89D99F)
+ + R(0x0FA19CBE154513BA348F2DB951AFB6E135BAC5BD8891282781A032103C3F1289)
+ + S(0xD9ABF5C4E61098A6E653F265770BDBA36ECC8073CEF99548D89FE2C39A7AFA9B)
+ + X(Spec.P + 5) # Valid for X(5)
+ + Y(0xBA6DBC4555A7E7FA016EC431667E8521EE35AFC49B265C3ACCBEA3F7CDB70433),
+ id="x_P_plus_5_y_negative",
+ ),
+ pytest.param(
+ H(0x65B0E03E7A27E6F9F4989C72486FCAF0A3ECF3EF60D14F1C11FB5BF071A8FD1B)
+ + R(0x0B0CC9E314E4180FE18D205010DD1C4410632D472CC4E7AB56CBC04091ABE006)
+ + S(0x8D12C4F19AC41D7877705453A247AB96394E7C093F57EC073A9D150CDE6B68C6)
+ + X(0x09E78D4EF60D05F750F6636209092BC43CBDD6B47E11A9DE20A9FEB2A50BB96C)
+ + Y(Spec.P + 1), # Valid for Y(1)
+ id="y_P_plus_1",
+ ),
+ # Test case produces the point R at infinity: (R0/S0)*G + (R0/S0)*(-G).
+ pytest.param(
+ H(Spec.R0.value) + Spec.R0 + Spec.S0 + X(Spec.Gx) + Y(Spec.P - Spec.Gy),
+ id="R_at_infinity_v1",
+ ),
+ # Test case produces the point R at infinity: (1/1)*G + (1/1)*(-G).
+ pytest.param(
+ H(1) + R(1) + S(1) + X(Spec.Gx) + Y(Spec.P - Spec.Gy),
+ id="R_at_infinity_v2",
+ ),
pytest.param(
Spec.H0
+ R(0x813EF79CCEFA9A56F7BA805F0E478584FE5F0DD5F567BC09B5123CCBC9832365)
@@ -132,11 +451,14 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
id="near_field_boundary_p_minus_3",
),
pytest.param(
- # Invalid curve attack: This point satisfies y² = x³ - 3x + 1 (mod p)
- # instead of the correct P-256 equation y² = x³ - 3x + b where
- # b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
- # This tests that the implementation properly validates the curve equation
- # and rejects points on different curves (CVE-2020-0601 class vulnerability)
+ # Invalid curve attack: This point satisfies y² = x³ - 3x + 1 (mod
+ # p) instead of the correct P-256 equation y² = x³ - 3x + b where
+ # b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53...
+ # ...B0F63BCE3C3E27D2604B
+ #
+ # This tests that the implementation properly validates the curve
+ # equation and rejects points on different curves (CVE-2020-0601
+ # class vulnerability)
Spec.H0
+ Spec.R0
+ Spec.S0
@@ -146,9 +468,12 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
),
pytest.param(
# Invalid curve attack: Singular curve with b = 0
- # Point satisfies y² = x³ - 3x (mod p) - a singular/degenerate curve
- # Singular curves have discriminant = 0 and provide no security guarantees
- # This tests rejection of points on curves with catastrophic security failures
+ # Point satisfies y² = x³ - 3x (mod p) - a singular/degenerate
+ # curve
+ # Singular curves have discriminant = 0 and provide no security
+ # guarantees.
+ # This tests rejection of points on curves with catastrophic
+ # security failures
Spec.H0
+ Spec.R0
+ Spec.S0
@@ -159,8 +484,11 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
pytest.param(
# Invalid curve attack: Boundary value b = p-1
# Point satisfies y² = x³ - 3x + (p-1) (mod p)
- # Tests proper parameter validation at modular arithmetic boundaries
- # Ensures implementations handle field arithmetic edge cases correctly
+ #
+ # Tests proper parameter validation at
+ # modular arithmetic boundaries.
+ # Ensures implementations handle field arithmetic edge cases
+ # correctly.
Spec.H0
+ Spec.R0
+ Spec.S0
@@ -171,8 +499,11 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
pytest.param(
# Invalid curve attack: Small discriminant curve with b = 2
# Point satisfies y² = x³ - 3x + 2 (mod p)
- # Curves with small discriminants are vulnerable to specialized attacks
- # Tests rejection of cryptographically weak curve parameters
+ #
+ # Curves with small discriminants are vulnerable to specialized
+ # attacks.
+ #
+ # Tests rejection of cryptographically weak curve parameters.
Spec.H0 + Spec.R0 + Spec.S0 + X(0x1) + Y(0x0),
id="invalid_curve_attack_small_discriminant",
),
@@ -188,6 +519,151 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact
+ Y(0x85EC5A4AF40176B63189069AEFFCB229C96D3E046E0283ED2F9DAC21B15AD3C),
id="invalid_curve_attack_composite_order",
),
+ pytest.param(
+ # Invalid curve attack: Composite order curve with b = -Spec.B
+ # Random point which satisfies y² = x³ - 3x - Spec.B (mod p)
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0xC223E1538C4D7B5BBD3EF932736826FD64F4E8B5C80250D9E07A728689D13C38)
+ + R(0x0C7CB59EF6BE7539397CC979AD9A87A3B73A0DD268BBA4990A3378C6391512D5)
+ + S(0xF8C943685BCFE7864C0F8485CACD732D3A9F167531CAF26B67A3CB10B641F92C)
+ + X(0xF1F2ADE681DB5699741B1F9FF080E9A08DCFF48F48A5048C4D90EC89440C3EFB)
+ + Y(0xBFFE372E7BBDBD60E4DF885E17A37878461AE13B6491E7863020305962F2C6B6),
+ id="invalid_curve_attack_bneg_1",
+ ),
+ pytest.param(
+ # Invalid curve attack: Composite order curve with b = -Spec.B
+ # Random point which satisfies y² = x³ - 3x - Spec.B (mod p)
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0x982D25BF8E0E81FF41AC3C8033604C78ED5EF17C6EDDA977072EAB6821A7AD0A)
+ + R(0x7C1996FA0EC911E4739AE7340B5345823272F494DFA32034A4FE5642C3DB91F2)
+ + S(0x1E4D6CCF1AFB675D18BD27274770C8B84028D272D1D2641E70B30E1DF17AF3DC)
+ + X(0xC9124B6AB12F08790A2712AEC74A1B71FA997CA7DE1E9117BC18D07DCBFE7C91)
+ + Y(0xADD1E9DF40A47ADD6B2191C05D0C1B4AF1BAEEAA0C0A97E7B3D06FFAE543D096),
+ id="invalid_curve_attack_bneg_2",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0)
+ + R(0xD21697149F598FEAE9A750DCA86AE6D5EFA654680BA748D2DF7053115101C129)
+ + S(0xEF3FD943AD1F126B3EBA1A5900D79886755DB6DAFCB6B0117D86364340CE36CC)
+ + X(0x687216395BD2F58E5A6D91964AE67E766DF2A2FB8E623795A5852507927C70C2)
+ + Y(0xF40E19B93BEB5C0678EDE25AB3654E08C0C6EF6A143CEC9865F3A447C6EB84E3),
+ id="invalid_curve_attack_h0_random1",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0)
+ + R(0x52E47C5D6AAB66AB6A18A694359EB86FDD40F10E79EF5493C5469EC88BA03334)
+ + S(0x7584C5BF3CA2869C7E383B1603A935EEB79D990B7F7152E055EC562E87FD715E)
+ + X(0x0000000000000002000000000000000000000000000000000000000000000000)
+ + Y(0x000000000000000000000000000000000000000000000000FE00000000000000),
+ id="invalid_curve_attack_h0_random2",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0)
+ + R(0x81333B13B13F362253BD536D17563A72EB575F1993F55ED40E633E503F60B864)
+ + S(0xE2208C4045F5241ECCF08F825399224C4B78595A10433EC33799DCAD7B0E1F4A)
+ + X(0xCE9C1088B4BCC71223A187410BB05819A6D32D2F1A1024B83557E51833AB23DC)
+ + Y(0x00FB64209538D1143A88E8B91D2DA46095AF852D7DD494BE6AF26C29D545F856),
+ id="invalid_curve_attack_h0_random3",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0)
+ + R(0x3C593B5857D1D0EB83923D73E76A7A53EF191BB210267D8C0BE17A4E34AB2E73)
+ + S(0xD022359310067882F713AFBECECE71CB80E4857368F46AB0346362DB033ED298)
+ + X(0x358DF65C0D732CCAB431D4CAB7F98E9F9279BD71D64635FAB21EA87EF254C5D1)
+ + Y(0x82909FF2E230433D000000000000000000000000000000000000000000000000),
+ id="invalid_curve_attack_h0_random4",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0)
+ + R(0x425CFFCA652791CABFC81B1E4B7712DBA196599FABCE16978E06E6AF486B1FEC)
+ + S(0x58B864B5A41CD17524E4773EC353C9590D792F601DA075AD9B3F40E8E7070E8A)
+ + X(0x00000000000000000000000000000000000000000000000000007FFFFFFFFFFF)
+ + Y(0xFFFF000000000000000000000000000000000000000000000000000000000000),
+ id="invalid_curve_attack_h0_random5",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0x2DA0A74BE3122AEAEF5704D0EB27881FBFB918B4A5252B660935263D0569BA92)
+ + R(0x5543729CBCFD99EE6C3B422D7F245903E7177B3A6A4E3C20C0DC5F5E109795AE)
+ + S(0x96403D5BB253EBD7DEF44BCBC062FCD4EA5E358B19B67C13E625EFDF6B977597)
+ + X(0x996CADC001622FB5E363B421A08854096569397B3BDCB8C3DEC907392F7CC59B)
+ + Y(0xD34A4E0F08C6FC549F7FAFFBCAF610D7F6C467B7B27072720E81079FB6595B52),
+ id="invalid_curve_attack_random6",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0x1F9D9B26DB42380C85F075174DDAF158F9DE4CD10C3104190D7AF96938DD8ECD)
+ + R(0x159946DBC4F1DE68CD4096862A5B10E5986ACB32229D6E68884DC83DAB70A307)
+ + S(0x63D80724A4074421F7DD255630794E3AEBE635B756D72B24652AAC07D01B289C)
+ + X(0x9CA2F39CC3536861000000000000000000000000000000000000000000000000)
+ + Y(0x000000000000B100000000000000000000000000000000000000000000000000),
+ id="invalid_curve_attack_random7",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0xD380DA9251F1FB809ED48C70DC8F81E91C471F0E81BC95E7611C653278A5B6B4)
+ + R(0xFF197EB72A9E531B17B872525247E6564B786CC014ED28B6849CE7D8C976BDF2)
+ + S(0x7B0B2EFF9BB5409052B35FD3FF81DCE77D95A1F75C46989817045120DA5C3C9C)
+ + X(0xBA7695481956A6269DD646ADDD4AFE6D9763637D76AD780299E51201384A8403)
+ + Y(0xA62443DD4AFE6D9763637D76AD780299E51201384AE4FEDD3CDAC9F461600D53),
+ id="invalid_curve_attack_random8",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0x4B082B60497ED87FFE570612D521E73A2CD6C832744EF8E4E2E329E30D3D5879)
+ + R(0x6665A88CB3FF30D339A1975FD46CF5EF480A68A093AB778550073D3528C3B609)
+ + S(0xAEAADDB235E4AC6097356DB96161E27849EA8EDF1E971F74EB51E19A1CC950A1)
+ + X(0x0000000000000002000000000000000000000000000000000000000000000000)
+ + Y(0x000000000000000000000000000000000000000000000000FE00000000000000),
+ id="invalid_curve_attack_random9",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0x6CC2B605CFBDB22B9E7B55EFE8C1DA0F1C5A0EC1AA8D82EEDFB5EA70E9846E88)
+ + R(0x3C593B5857D1D0EB83923D73E76A7A53EF191BB210267D8C0BE17A4E34AB2E73)
+ + S(0xD022359310067882F713AFBECECE71CB80E4857368F46AB0346362DB033ED298)
+ + X(0x358DF65C0D732CCAB431D4CAB7F98E9F9279BD71D64635FAB21EA87EF254C5D1)
+ + Y(0x82909FF2E230433D000000000000000000000000000000000000000000000000),
+ id="invalid_curve_attack_random10",
+ ),
+ pytest.param(
+ # Invalid curve attack: random point bytes.
+ # Without the curve check in the implementation,
+ # the signature checks out.
+ H(0x810C1D53EA96A700C93F6AF1C183197B040EA6FEAE10564877A1C78EC6074FF1)
+ + R(0x34D0F0C8E14D39002B5DEA00808957963E849503DDFD626323433047D696C7C4)
+ + S(0x6A7FE39C046304317F799FB900877073F2AE3C798DD4414795551A833ABCBA85)
+ + X(0x0000000000F90000000067923073C067015B601D94F262F0E82B9DA2D33A6A32)
+ + Y(0xFC3D71CB490CF346ED31DC37405FB0069F4A7ED188381DC049ABAB66E9F80080),
+ id="invalid_curve_attack_random_11",
+ ),
],
)
@pytest.mark.parametrize("expected_output", [Spec.INVALID_RETURN_VALUE], ids=[""])
@@ -361,14 +837,34 @@ def test_precompile_will_return_success_with_tx_value(
# This tests the modular comparison: r' ≡ r (mod N)
pytest.param(
Spec.H0
- # R: A value that when used in ECDSA verification produces an x-coordinate > N
+ # R: A value that when used in ECDSA verification produces an
+ # x-coordinate > N
+ R(0x000000000000000000000000000000004319055358E8617B0C46353D039CDAAB)
+ S(0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E)
- # X, Y: Public key coordinates that will produce x-coordinate > N during verification
+ # X, Y: Public key coordinates that will produce x-coordinate > N
+ # during verification
+ X(0x0AD99500288D466940031D72A9F5445A4D43784640855BF0A69874D2DE5FE103)
+ Y(0xC5011E6EF2C42DCD50D5D3D29F99AE6EBA2C80C9244F4C5422F0979FF0C3BA5E),
Spec.SUCCESS_RETURN_VALUE,
- id="modular_comparison_x_coordinate_exceeds_n",
+ id="x_coordinate_exceeds_n",
+ ),
+ pytest.param(
+ Spec.H1 + Spec.R1 + Spec.S1 + Spec.X1 + Spec.Y1,
+ Spec.SUCCESS_RETURN_VALUE,
+ id="x_coordinate_exceeds_n_v2",
+ ),
+ # Test cases where compute x-coordinate exceeds curve order N,
+ # but the signature is invalid.
+ # This is a modification of the above test by taking -h, -r, -s
+ # what gives the same u1 and u2 and in the result the same point R.
+ pytest.param(
+ H(Spec.N - Spec.H1.value)
+ + R(Spec.N - Spec.R1.value)
+ + S(Spec.N - Spec.S1.value)
+ + Spec.X1
+ + Spec.Y1,
+ Spec.INVALID_RETURN_VALUE,
+ id="invalid_x_coordinate_exceeds_n",
),
pytest.param(
Spec.H0
@@ -376,7 +872,8 @@ def test_precompile_will_return_success_with_tx_value(
+ Spec.S0
+ Spec.X0
+ Spec.Y0,
- Spec.INVALID_RETURN_VALUE, # Should fail because R = 1 is not a valid signature
+ Spec.INVALID_RETURN_VALUE, # Should fail because R = 1 is not a
+ # valid signature
id="r_equals_n_plus_one",
),
pytest.param(
@@ -385,7 +882,8 @@ def test_precompile_will_return_success_with_tx_value(
+ Spec.S0
+ Spec.X0
+ Spec.Y0,
- Spec.INVALID_RETURN_VALUE, # Should fail because R = 2 is not a valid signature
+ Spec.INVALID_RETURN_VALUE, # Should fail because R = 2 is not a
+ # valid signature
id="r_equals_n_plus_two",
),
],
@@ -397,9 +895,9 @@ def test_modular_comparison(state_test: StateTestFiller, pre: Alloc, post: dict,
"""
Test the modular comparison condition for secp256r1 precompile.
- This tests that when the x-coordinate of R' exceeds the curve order N,
- the verification should use modular arithmetic:
- r' ≡ r (mod N) instead of direct equality r' == r.
+ This tests that when the x-coordinate of R' exceeds the curve order N, the
+ verification should use modular arithmetic: r' ≡ r (mod N) instead of
+ direct equality r' == r.
"""
state_test(env=Environment(), pre=pre, post=post, tx=tx)
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py b/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py
index b331b55c36..9f8f692ad3 100644
--- a/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py
@@ -1,7 +1,11 @@
"""
-abstract: Tests P256VERIFY precompiles of [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)
- Tests P256VERIFY precompiles of [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)
- before the Osaka hard fork is active.
+Tests P256VERIFY precompiles of [EIP-7951: Precompile for secp256r1
+Curve Support](https://eips.ethereum.org/EIPS/eip-7951).
+
+Tests P256VERIFY
+precompiles of [EIP-7951: Precompile for secp256r1 Curve
+Support](https://eips.ethereum.org/EIPS/eip-7951) before the Osaka hard fork is
+active.
"""
import pytest
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_k_and_s.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_k_and_s.json
new file mode 100644
index 0000000000..ed4f0bedf9
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_k_and_s.json
@@ -0,0 +1,170 @@
+[
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c704fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #176: extreme value for k and edgecase s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63ccc6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #177: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #178: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaf6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #179: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #180: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #181: extreme value for k",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c705e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #182: extreme value for k and edgecase s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #183: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #184: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #185: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #186: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb8d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #187: extreme value for k",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c70961691a5e960d07a301dbbad4d86247ec27d7089faeb3ddd1add395efff1e0fe7254622cc371866cdf990d2c5377790e37d1f1519817f09a231bd260a9e78aeb",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #694: extreme value for k and edgecase s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc5d283e13ce8ca60da868e3b0fb33e6b4f1074793274e2928250e71e2aca63e9c214dc74fa25371fb4d9e506d418ed9a1bfd6d0c8bb6591d3e0f44505a84886ce",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #695: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa70fc351da038ae0803bd1d86514ae0462f9f8216551d9315aa9d297f792eef6a341c74eed786f2d33da35360ca7aa925e753f00d6077a1e9e5fc339d634019c73",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #696: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaa1e34c8f16d138673fee55c080547c2bfd4de7550065f638322bba9430ce4b60662be9bb512663aa4d7df8ab3f3b4181c5d44a7bdf42436620b7d8a6b81ac936",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #697: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c1857e1a8a8338d7fd8cf41d322a302d2078a87a23c7186150ed7cda6e52817c1bdfd0a9135a89d21ce821e29014b2898349254d748272b2d4eb8d59ee34c615377f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #698: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb5c19fe227a61abc65c61ee7a018cc9571b2c6f663ea33583f76a686f64be078b7b4a0d734940f613d52bc48673b457c2cf78492490a5cc5606c0541d17b24ddb",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #699: extreme value for k",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c70db02d1f3421d600e9d9ef9e47419dba3208eed08c2d4189a5db63abeb2739666e0ed26967b9ada9ed7ffe480827f90a0d210d5fd8ec628e31715e6b24125512a",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #700: extreme value for k and edgecase s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc6222d1962655501893c29e441395b6c05711bd3ed5a0ef72cfab338b88229c4baaae079cb44a1af070362aaa520ee24cac2626423b0bf81af1c54311d8e2fd23",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #701: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa74ccfa24c67f3def7fa81bc99c70bb0419c0952ba599f4c03361da184b04cdca5db76b797f7f41d9c729a2219478a7e629728df870800be8cf6ca7a0a82153bfa",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #702: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaea1c72c91034036bac71402b6e9ecc4af3dbde7a99dc574061e99fefff9d84dab7dd057e75b78ac6f56e34eb048f0a9d29d5d055408c90d02bc2ea918c18cb63",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #703: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185c2879a66d86cb20b820b7795da2da62b38924f7817d1cd350d936988e90e79bc5431a7268ff6931c7a759de024eff90bcb0177216db6fd1f3aaaa11fa3b6a083",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #704: extreme value for k and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bbab1c0f273f74abc2b848c75006f2ef3c54c26df27711b06558f455079aee0ba3df510f2ecef6d9a05997c776f14ad6456c179f0a13af1771e4d6c37fa48b47f2",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #705: extreme value for k",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_modified_r_s.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_modified_r_s.json
new file mode 100644
index 0000000000..e49fac0054
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_modified_r_s.json
@@ -0,0 +1,93 @@
+[
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #3: Modified r or s, e.g. by adding or subtracting the order of the group",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #5: Modified r or s, e.g. by adding or subtracting the order of the group",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #8: Modified r or s, e.g. by adding or subtracting the order of the group",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502329a3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #118: modify first byte of integer",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e98b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #120: modify last byte of integer",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568475b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #121: modify last byte of integer",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1800b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568472927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #124: truncated integer",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f47aa2bbd0a4c384ee1493b1f518ada018ef05465583885980861905228a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #139: Modified r or s, e.g. by adding or subtracting the order of the group",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #636: r too large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e3cd8d2f81d6953b0844c09d7b560d527cd2ef67056893eadafa52c8501387d59ee41fdb4d10402ce7a0c5e3b747adfa3a490b62a6b7719068903485c0bb6dc2d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #637: r,s are large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd48240cd81edd91cb6936133508c3915100e81f332c4545d41189b481196851378e05b06e72d4a1bff80ea5db514aa2f93ea6dd6d9c0ae27b7837dc432f9ce89d9",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #638: r and s^-1 have a large Hamming weight",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5b062947356748b0fc17f1704c65aa1dca6e1bfe6779756fa616d91eaad13df2c0b38c17f3d0672e7409cfc5992a99fff12b84a4f8432293b431113f1b2fb579d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #639: r and s^-1 have a large Hamming weight",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c707a736d8e326a9ca62bbe25a34ea4e3633b499a96afa7aaa3fcf3fd88f8e07edeb3e45879d8622b93e818443a686e869eeda7bf9ae46aa3eafcc48a5934864627",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #651: r and s^-1 are close to n",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_public_key.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_public_key.json
new file mode 100644
index 0000000000..9ec469d523
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_public_key.json
@@ -0,0 +1,191 @@
+[
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #196: x-coordinate of the public key has many trailing 0's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #197: x-coordinate of the public key has many trailing 0's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #198: x-coordinate of the public key has many trailing 0's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #199: y-coordinate of the public key has many trailing 0's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #200: y-coordinate of the public key has many trailing 0's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #201: y-coordinate of the public key has many trailing 0's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #202: y-coordinate of the public key has many trailing 1's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #203: y-coordinate of the public key has many trailing 1's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #204: y-coordinate of the public key has many trailing 1's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #205: x-coordinate of the public key has many trailing 1's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #206: x-coordinate of the public key has many trailing 1's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #207: x-coordinate of the public key has many trailing 1's",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #208: x-coordinate of the public key is large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #209: x-coordinate of the public key is large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #210: x-coordinate of the public key is large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #211: x-coordinate of the public key is small",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #212: x-coordinate of the public key is small",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #213: x-coordinate of the public key is small",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #214: y-coordinate of the public key is small",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #215: y-coordinate of the public key is small",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #216: y-coordinate of the public key is small",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #217: y-coordinate of the public key is large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #218: y-coordinate of the public key is large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #219: y-coordinate of the public key is large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c7038a084ffccc4ae2f8204be2abca9fb8ad4ab283b2aa50f13b6bb2347adabc69ca699799b77b1cc6dad271e88b899c12931986e958e1f5cf5653dddf7389365e2",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a90000000000000000000000000000000000000000000000000000000000000000fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "invalid public key x param errors",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af0150000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "invalid public key y param errors",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_shamir_multiplication.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_shamir_multiplication.json
new file mode 100644
index 0000000000..052e2e9658
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_shamir_multiplication.json
@@ -0,0 +1,9 @@
+[
+ {
+ "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #58: Edge case for Shamir multiplication",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_signature_specific.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_signature_specific.json
new file mode 100644
index 0000000000..f1145f76ef
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_signature_specific.json
@@ -0,0 +1,72 @@
+[
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #1: signature malleability",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #137: edge case for signature malleability",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a968ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #138: edge case for signature malleability",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #192: pseudorandom signature",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "dc1921946f4af96a2856e7be399007c9e807bdf4c5332f19f59ec9dd1bb8c7b3530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e904aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #193: pseudorandom signature",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #194: pseudorandom signature",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #195: pseudorandom signature",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a878d844dc7f16b73b1f2a39730da5d8cd99fe2e70a18482384e37dcd2bfea02e1ed6572e01eb7a8d113d02c666c45ef22d3b9a6a6dea99aa43a8183c26e75d336",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #655: edge case for signature malleability",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9dec6c8257dde94110eacc8c09d2e5789cc5beb81a958b02b4d62da9599a7401466fae1614174be63970b83f6524421067b06dd6f4e9c56baca4e344fdd690f1d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #656: edge case for signature malleability",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2530e782f964b2e2ff065a051bc7adc20615d8c43a1365713c88268822c253bcce5b16df652aa1ecb2dc8b46c515f9604e2e84cacfa7c6eec30428d2d3f4e08ed504aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1211: pseudorandom signature",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_small_large_r_s.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_small_large_r_s.json
new file mode 100644
index 0000000000..9dced484a5
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_small_large_r_s.json
@@ -0,0 +1,233 @@
+[
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #114: r too large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254eab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #115: r,s are large",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #116: r and s^-1 have a large Hamming weight",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a54201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #117: r and s^-1 have a large Hamming weight",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #118: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000036627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #120: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000055a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #122: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #124: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325560000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea88d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7a4838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4d7393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b5ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b1d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c70083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #133: r and s^-1 are close to n",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000018aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #134: s == 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000008aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #135: s == 0",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000014a03ef9f92eb268cafa601072489a56380fa0dc43171d7712813b3a19a1eb5e53e213e28a608ce9a2f4a17fd830c6654018a79b3e0263d91a8ba90622df6f2f0",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #118: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003091194c1cba17f34e286b4833701606a41cef26177ada8850b601ea1f859e70127242fcec708828758403ce2fe501983a7984e6209f4d6b95db9ad77767f55eb",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #120: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005103c6ecceff59e71ea8f56fee3a4b2b148e81c2bdbdd39c195812c96dcfb41a72303a193dc591be150b883d770ec51ebb4ebce8b09042c2ecb16c448d8e57bf5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #122: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #124: small r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255600000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84ff2f6c24e4a33cd71c09fdcbc74a6233961b874b8c8e0eb94582092cbc50c3084fa9547afda5c66335f3f937d4c79afa120486b534139d59ae82d61ead26420",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea8884b959080bb30859cd53c2fb973cf14d60cdaa8ee00587889b5bc657ac588175a02ce5c1e53cb196113c78b4cb8dc7d360e5ea7850b0f6650b0c45af2c3cd7ca",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7adf4083bd6ecbda5a77ae578e5d835fa7f74a07ebb91e0570e1ff32a563354e9925af80b09a167d9ef647df28e2d9acd0d4bc4f2deec5723818edaf9071e311f8",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4dc2569a3c9bf8c1838ca821f7ba6f000cc8679d278f3736b414a34a7c956a03770387ea85bc4f28804b4a91c9b7d65bc6434c975806795ab7d441a4e9683aeb09",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b4a9f7da2a6c359a16540c271774a6bf1c586357c978256f44a6496d80670968ac496e73a44563f8d56fbd7bb9e4e3ae304c86f2c508eb777b03924755beb40d4",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b874146432b3cd2c9e26204c0a34136996067d466dde4917a8ff23a8e95ca106b709b3d50976ef8b385a813bc35f3a20710bdc6edd465e6f43ac4866703a6608c",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000001e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #134: s == 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000000e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #135: s == 0",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_hash.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_hash.json
new file mode 100644
index 0000000000..dd8bd2c603
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_hash.json
@@ -0,0 +1,380 @@
+[
+ {
+ "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #59: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #60: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #61: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #62: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #63: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #64: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #65: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #66: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #67: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #68: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #69: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #70: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #71: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #72: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #73: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #74: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #75: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #76: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #77: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #78: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #79: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #80: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #81: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #82: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #83: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #84: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #85: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #86: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #87: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #88: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #89: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #90: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #91: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #92: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #93: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #94: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #95: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #96: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #97: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #98: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #99: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #100: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #101: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #102: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #103: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #104: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #105: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #106: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #107: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #108: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #109: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #110: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #111: special case hash",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #112: special case hash",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_r_s.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_r_s.json
new file mode 100644
index 0000000000..05e809bf92
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_r_s.json
@@ -0,0 +1,345 @@
+[
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #9: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #10: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #11: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #12: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #13: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #14: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #15: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #16: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #17: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #18: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #19: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #20: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #21: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #22: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #23: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #24: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #25: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #26: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #27: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #28: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #29: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #30: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #31: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #32: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #33: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #34: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #35: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #36: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #37: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #38: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #39: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #40: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #41: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #42: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #43: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #44: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #45: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #46: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #47: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #48: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #49: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #50: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #51: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #52: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #53: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #54: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #55: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #56: Signature with special case values for r and s",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #57: Signature with special case values for r and s",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_points.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_points.json
new file mode 100644
index 0000000000..65cbd0ae22
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_points.json
@@ -0,0 +1,135 @@
+[
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #3: valid",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c70b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #136: point at infinity during verify",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #171: point duplication during verification",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #172: duplication bug",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c706adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #175: comparison with point at infinity ",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #188: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #189: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #190: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #191: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c700203736fcb198b15d8d7a0c80f66dddd15259240aa78d08aae67c467de04503434383438d5041ea9a387ee8e4d4e84b4471b160c6bcf2568b072f8f20e87a996",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #654: point at infinity during verify",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237e2a964fc00d377a8592b8b61aafa7a4aaa7c7b9fd2b41d6e0e17bd1ba5677edcd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #689: point duplication during verification",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237ed569b03ef2c8857b6d4749e550585b5558384603d4be291f1e842e45a9881232",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #690: duplication bug",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9664ce273320d918d8bdb2e61201b4549b36b7cdc54e33b84adb6f2c10aac831e49e68831f18bda2973ac3d76bfbc8c5ee1cceed2dd862e2dc7c915c736cef1f4",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #693: comparison with point at infinity ",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #706: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #707: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #708: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #709: testing point duplication",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "",
+ "Gas": 6900,
+ "Name": "reference point errors",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_test.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_test.json
deleted file mode 100644
index 5a87452136..0000000000
--- a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_test.json
+++ /dev/null
@@ -1,2060 +0,0 @@
-[
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #1: signature malleability",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #3: Modified r or s, e.g. by adding or subtracting the order of the group",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #5: Modified r or s, e.g. by adding or subtracting the order of the group",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #8: Modified r or s, e.g. by adding or subtracting the order of the group",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #9: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #10: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #11: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #12: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #13: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #14: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #15: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #16: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #17: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #18: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #19: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #20: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #21: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #22: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #23: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #24: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #25: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #26: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #27: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #28: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #29: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #30: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #31: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #32: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #33: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #34: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #35: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #36: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #37: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #38: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #39: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #40: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #41: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #42: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #43: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #44: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #45: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #46: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #47: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #48: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #49: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #50: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #51: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #52: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #53: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #54: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #55: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #56: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #57: Signature with special case values for r and s",
- "NoBenchmark": false
- },
- {
- "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #58: Edge case for Shamir multiplication",
- "NoBenchmark": false
- },
- {
- "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #59: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #60: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #61: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #62: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #63: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #64: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #65: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #66: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #67: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #68: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #69: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #70: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #71: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #72: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #73: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #74: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #75: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #76: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #77: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #78: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #79: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #80: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #81: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #82: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #83: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #84: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #85: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #86: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #87: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #88: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #89: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #90: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #91: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #92: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #93: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #94: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #95: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #96: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #97: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #98: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #99: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #100: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #101: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #102: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #103: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #104: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #105: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #106: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #107: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #108: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #109: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #110: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #111: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #112: special case hash",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #114: r too large",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254eab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #115: r,s are large",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #116: r and s^-1 have a large Hamming weight",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a54201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #117: r and s^-1 have a large Hamming weight",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #118: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000036627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #120: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000055a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #122: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #124: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325560000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea88d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7a4838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4d7393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b5ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b1d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c70083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #133: r and s^-1 are close to n",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000018aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #134: s == 1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000008aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #135: s == 0",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c70b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #136: point at infinity during verify",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #137: edge case for signature malleability",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a968ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #138: edge case for signature malleability",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502369da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #139: u1 == 1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52ed8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #140: u1 == n - 1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c703623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #141: u2 == 1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #142: u2 == n - 1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #143: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #144: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #145: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #146: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #147: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f915eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #148: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #149: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #150: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d63fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #151: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd29798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d89cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #152: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dda3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #153: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd16e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1baf19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #154: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a9783a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #155: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd81ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #156: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #157: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f22eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #158: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e84db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #159: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf291b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #160: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #161: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #162: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86000a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #163: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #164: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #165: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b0992f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #166: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #167: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e378651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #168: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #169: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #170: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #171: point duplication during verification",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #172: duplication bug",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c706adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #175: comparison with point at infinity ",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c704fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #176: extreme value for k and edgecase s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63ccc6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #177: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #178: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaf6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #179: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #180: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #181: extreme value for k",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c705e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #182: extreme value for k and edgecase s",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #183: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #184: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #185: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #186: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb8d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #187: extreme value for k",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #188: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #189: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #190: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #191: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #192: pseudorandom signature",
- "NoBenchmark": false
- },
- {
- "Input": "dc1921946f4af96a2856e7be399007c9e807bdf4c5332f19f59ec9dd1bb8c7b3530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e904aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #193: pseudorandom signature",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #194: pseudorandom signature",
- "NoBenchmark": false
- },
- {
- "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #195: pseudorandom signature",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #196: x-coordinate of the public key has many trailing 0's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #197: x-coordinate of the public key has many trailing 0's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #198: x-coordinate of the public key has many trailing 0's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #199: y-coordinate of the public key has many trailing 0's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #200: y-coordinate of the public key has many trailing 0's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #201: y-coordinate of the public key has many trailing 0's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #202: y-coordinate of the public key has many trailing 1's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #203: y-coordinate of the public key has many trailing 1's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #204: y-coordinate of the public key has many trailing 1's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #205: x-coordinate of the public key has many trailing 1's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #206: x-coordinate of the public key has many trailing 1's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #207: x-coordinate of the public key has many trailing 1's",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #208: x-coordinate of the public key is large",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #209: x-coordinate of the public key is large",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #210: x-coordinate of the public key is large",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #211: x-coordinate of the public key is small",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #212: x-coordinate of the public key is small",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #213: x-coordinate of the public key is small",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #214: y-coordinate of the public key is small",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #215: y-coordinate of the public key is small",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #216: y-coordinate of the public key is small",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #217: y-coordinate of the public key is large",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #218: y-coordinate of the public key is large",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #219: y-coordinate of the public key is large",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #3: valid",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502329a3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #118: modify first byte of integer",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e98b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #120: modify last byte of integer",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568475b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #121: modify last byte of integer",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1800b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568472927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #124: truncated integer",
- "NoBenchmark": false
- },
- {
- "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f47aa2bbd0a4c384ee1493b1f518ada018ef05465583885980861905228a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #139: Modified r or s, e.g. by adding or subtracting the order of the group",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #636: r too large",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e3cd8d2f81d6953b0844c09d7b560d527cd2ef67056893eadafa52c8501387d59ee41fdb4d10402ce7a0c5e3b747adfa3a490b62a6b7719068903485c0bb6dc2d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #637: r,s are large",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd48240cd81edd91cb6936133508c3915100e81f332c4545d41189b481196851378e05b06e72d4a1bff80ea5db514aa2f93ea6dd6d9c0ae27b7837dc432f9ce89d9",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #638: r and s^-1 have a large Hamming weight",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5b062947356748b0fc17f1704c65aa1dca6e1bfe6779756fa616d91eaad13df2c0b38c17f3d0672e7409cfc5992a99fff12b84a4f8432293b431113f1b2fb579d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #639: r and s^-1 have a large Hamming weight",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c707a736d8e326a9ca62bbe25a34ea4e3633b499a96afa7aaa3fcf3fd88f8e07edeb3e45879d8622b93e818443a686e869eeda7bf9ae46aa3eafcc48a5934864627",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #651: r and s^-1 are close to n",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c700203736fcb198b15d8d7a0c80f66dddd15259240aa78d08aae67c467de04503434383438d5041ea9a387ee8e4d4e84b4471b160c6bcf2568b072f8f20e87a996",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #654: point at infinity during verify",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a878d844dc7f16b73b1f2a39730da5d8cd99fe2e70a18482384e37dcd2bfea02e1ed6572e01eb7a8d113d02c666c45ef22d3b9a6a6dea99aa43a8183c26e75d336",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #655: edge case for signature malleability",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9dec6c8257dde94110eacc8c09d2e5789cc5beb81a958b02b4d62da9599a7401466fae1614174be63970b83f6524421067b06dd6f4e9c56baca4e344fdd690f1d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #656: edge case for signature malleability",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25a17f5b75a35ed64623ca5cbf1f91951292db0c23f0c2ea24c3d0cad0988cabc083a7a618625c228940730b4fa3ee64faecbb2fc20fdde7c58b3a3f6300424dc6",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #657: u1 == 1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c04ba0cba291a37db13f33bf90dab628c04ec8393a0200419e9eaa1ebcc9fb5c31f3a0a0e6823a49b625ad57b12a32d4047970fc3428f0f0049ecf4265dc12f62",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #658: u1 == n - 1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c70692b6c828e0feed63d8aeaa2b7322f9ccbe8723a1ed39f229f204a434b8900efa1f6f6abcb38ea3b8fde38b98c7c271f274af56a8c5628dc3329069ae4dd5716",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #659: u2 == 1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e100cefd9162d13e64cb93687a9cd8f9755ebb5a3ef7632f800f84871874ccef09543ecbeaf7e8044ef721be2fb5f549e4b8480d2587404ebf7dbbef2c54bc0cb1",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #660: u2 == n - 1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd710f8e3edc7c2d5a3fd23de844002bb949d9f794f6d5405f6d97c1bb03dd2bd2b975183b42551cf52f291d5c1921fd5e12f50c8c85a4beb9de03efa3f0f244862243018e6866df922dc313612020311ff21e242ce3fb15bc78c406b25ab43091",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #661: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdedffbc270f722c243069a7e5f40335a61a58525c7b4db2e7a8e269274ffe4e1bc25f1d166f3e211cdf042a26f8abf6094d48b8d17191d74ed71714927446699965d06dd6a88abfa49e8b4c5da6bb922851969adf9604b5accfb52a114e77ccdb",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #662: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffda25adcae105ed7ff4f95d2344e24ee523314c3e178525d007904b68919ba4d538fe5e88243a76e41a004236218a3c3a2d6eee398a23c3a0b008d7f0164cbc0ca98a20d1bdcf573513c7cfd9b83c63e3a82d40127c897697c86b8cb387af7f240",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #663: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2e4348c645707dce6760d773de3f3e87346924b2f64bd3dd0297e766b5805ebb02148256b530fbc470c7b341970b38243ecee6d5a840a37beca2efb37e8dff2cc0adbea0882482a7489ca703a399864ba987eeb6ddb738af53a83573473cb30d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #664: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd348c673b07dce3920d773de3f3e87408869e916dbcf797d8f9684fb67753d1dca34db012ce6eda1e9c7375c5fcf3e54ed698e19615124273b3a621d021c76f8e777458d6f55a364c221e39e1205d5510bb4fbb7ddf08d8d8fdde13d1d6df7f14",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #665: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6918ce760fb9c7241aee7bc7e7d0e8110d3d22db79ef2fb1f2d09f6ceea7a3b8b97af3fe78be15f2912b6271dd8a43badb6dd2a1b315b2ce7ae37b4e7778041d930d71ee1992d2466495c42102d08e81154c305307d1dcd52d0fa4c479b278e7",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #666: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd73b3c694391d8eadde3f3e874089464715ac20e4c126bbf6d864d648969f5b5a81e7198a3c3f23901cedc7a1d6eff6e9bf81108e6c35cd8559139af3135dbcbb9ef1568530291a8061b90c9f4285eefcba990d4570a4e3b7b737525b5d580034",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #667: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb07ac7a86948c2c2989a16db1930ef1b89ce112595197656877e53c41457f28ab4d792ca121d1dba39cb9de645149c2ab573e8becc6ddff3cc9960f188ddf737f90ba23664153e93262ff73355415195858d7be1315a69456386de68285a3c8",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #668: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27e4d82cb6c061dd9337c69bf9332ed3d198662d6f2299443f62c861187db648518412b69af43aae084476a68d59bbde51fbfa9e5be80563f587c9c2652f88ef2d3b90d25baa6bdb7b0c55e5240a3a98fbc24afed8523edec1c70503fc10f233",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #669: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde7c5cf3aac2e88923b77850515fff6a12d13b356dfe9ec275c3dd81ae94609a4a08f14a644b9a935dffea4761ebaf592d1f66fe6cd373aa7f5d370af34f8352da54b5bc4025cf335900a914c2934ec2fec7a396d0a7affcad732a5741c7aaaf5",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #670: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc77838df91c1e953e016e10bddffea2317f9fee32bacfe553cede9e57a748f68ccf2296a6a89b62b90739d38af4ae3a20e9f45715b90044639241061e33f8f8caace0046491eeaa1c6e9a472b96d88f4af83e7ff1bb84438c7e058034412ae08",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #671: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8ef071c02383d2a6c02dc217bbffd446730d0318b0425e2586220907f885f97f94b0fc1525bcabf82b1f34895e5819a06c02b23e04002276e165f962c86e3927be7c2ab4d0b25303204fb32a1f8292902792225e16a6d2dbfb29fbc89a9c3376",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #672: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5668aaa0b545bbf9a044a32399ffbe69ce20074e34d7bdf5cf56282a769763965351f37e1de0c88c508527d89882d183ccdcf2efca407edb0627cadfd16de6ec44b4b57cdf960d32ebcc4c97847eed218425853b5b675eb781b766a1a1300349",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #673: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd12d6e56882f6c0027cae91a27127728f7fddf478fb4fdc2b65f40a60b0eb952748bbafc320e6735cb64019710a269c6c2b5d147bdc831325cb2fb276ac971a69d655e9a755bc9d800ad21ee3fd4d980d93a7a49a8c5ccd37005177578f51163",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #674: edge case for u1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a14b3bbd75c5e1c0c36535a934d4ab85112410b3b90fa97a31c33038964fd85cc112f7d837f8f9c36b460d636c965a5f818f2b50c5d00fb3f9705561dd6631883",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #675: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2d823533c04cd8edc6d6f950a8e08ade04a9bafa2f14a590356935671ae9305bf43178d1f88b6a57a96924c265f0ddb75b58312907b195acb59d7797303123775",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #676: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851edb2b3408b3167d91030624c6328e8ce3ec108c105575c2f3d209b92e654bab69c34318139c50b0802c6e612f0fd3189d800df7c996d5d7b7c3d6be82836fa258",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #677: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf209179ce7c59225392216453b2ac1e9d178c24837dfae26bc1dd7ab60638527425556b42e330289f3b826b2db7a86d19d45c2860a59f2be1ddcc3b691f95a9255",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #678: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb366901959fb8deda56e5467b7e4b214ea4c2d0c2fb29d70ff19b6b1eccebd6568d7ed9dbd77a918297fd970bff01e1343f6925167db5a14d098a211c39cc3a413398",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #679: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2567f1fdc387e5350c852b4e8f8ba9d6d947e1c5dd7ccc61a5938245dd6bcab3a9960bebaf919514f9535c22eaaf0b5812857970e26662267b1f3eb1011130a11",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #680: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86003499f974ff4ca6bbb2f51682fd5f51762f9dd6dd2855262660b36d46d3e4bec2f498fae2487807e220119152f0122476c64d4fa46ddce85c4546630f0d5c5e81",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #681: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad32c5c01662cf00c1929596257db13b26ecf30d0f3ec4b9f0351b0f27094473426e986a086060d086eee822ddd2fc744247a0154b57f7a69c51d9fdafa484e4ac7",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #682: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f491d4cba813a04d86dbae94c23be6f52c15774183be7ba5b2d9f3cf010b160501900b8adfea6491019a9ac080d516025a541bf4b952b0ad7be4b1874b02fd544a",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #683: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09ef7fd0a3a36386638330ecad41e1a3b302af36960831d0210c614b948e8aa124ef0d6d800e4047d6d3c1be0fdeaf11fcd8cab5ab59c730eb34116e35a8c7d098",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #684: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4a521dab13cc9152d8ca77035a607fea06c55cc3ca5dbeb868cea92eafe93df2a7bfb9b28531996635e6a5ccaa2826a406ce1111bdb9c2e0ca36500418a2f43de",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #685: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37474d58a4eec16e0d565f2187fe11d4e8e7a2683a12f38b4fc01d1237a81a10976e55f73bb7cdda46bdb67ef77f6fd2969df2b67920fb5945fde3a517a6ded4cd",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #686: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa692da5cd4309d9a6e5cb525c37da8fa0879f7b57208cdabbf47d223a5b23a62140e0daa78cfdd207a7389aaed61738b17fc5fc3e6a5ed3397d2902e9125e6ab4",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #687: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f85689b3e0775c7718a90279f14a8082cfcd4d1f1679274f4e9b8805c570a0670167fcc5ca734552e09afa3640f4a034e15b9b7ca661ec7ff70d3f240ebe705b1",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #688: edge case for u2",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237e2a964fc00d377a8592b8b61aafa7a4aaa7c7b9fd2b41d6e0e17bd1ba5677edcd",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #689: point duplication during verification",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237ed569b03ef2c8857b6d4749e550585b5558384603d4be291f1e842e45a9881232",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #690: duplication bug",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9664ce273320d918d8bdb2e61201b4549b36b7cdc54e33b84adb6f2c10aac831e49e68831f18bda2973ac3d76bfbc8c5ee1cceed2dd862e2dc7c915c736cef1f4",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #693: comparison with point at infinity ",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c70961691a5e960d07a301dbbad4d86247ec27d7089faeb3ddd1add395efff1e0fe7254622cc371866cdf990d2c5377790e37d1f1519817f09a231bd260a9e78aeb",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #694: extreme value for k and edgecase s",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc5d283e13ce8ca60da868e3b0fb33e6b4f1074793274e2928250e71e2aca63e9c214dc74fa25371fb4d9e506d418ed9a1bfd6d0c8bb6591d3e0f44505a84886ce",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #695: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa70fc351da038ae0803bd1d86514ae0462f9f8216551d9315aa9d297f792eef6a341c74eed786f2d33da35360ca7aa925e753f00d6077a1e9e5fc339d634019c73",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #696: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaa1e34c8f16d138673fee55c080547c2bfd4de7550065f638322bba9430ce4b60662be9bb512663aa4d7df8ab3f3b4181c5d44a7bdf42436620b7d8a6b81ac936",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #697: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c1857e1a8a8338d7fd8cf41d322a302d2078a87a23c7186150ed7cda6e52817c1bdfd0a9135a89d21ce821e29014b2898349254d748272b2d4eb8d59ee34c615377f",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #698: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb5c19fe227a61abc65c61ee7a018cc9571b2c6f663ea33583f76a686f64be078b7b4a0d734940f613d52bc48673b457c2cf78492490a5cc5606c0541d17b24ddb",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #699: extreme value for k",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c70db02d1f3421d600e9d9ef9e47419dba3208eed08c2d4189a5db63abeb2739666e0ed26967b9ada9ed7ffe480827f90a0d210d5fd8ec628e31715e6b24125512a",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #700: extreme value for k and edgecase s",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc6222d1962655501893c29e441395b6c05711bd3ed5a0ef72cfab338b88229c4baaae079cb44a1af070362aaa520ee24cac2626423b0bf81af1c54311d8e2fd23",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #701: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa74ccfa24c67f3def7fa81bc99c70bb0419c0952ba599f4c03361da184b04cdca5db76b797f7f41d9c729a2219478a7e629728df870800be8cf6ca7a0a82153bfa",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #702: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaea1c72c91034036bac71402b6e9ecc4af3dbde7a99dc574061e99fefff9d84dab7dd057e75b78ac6f56e34eb048f0a9d29d5d055408c90d02bc2ea918c18cb63",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #703: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185c2879a66d86cb20b820b7795da2da62b38924f7817d1cd350d936988e90e79bc5431a7268ff6931c7a759de024eff90bcb0177216db6fd1f3aaaa11fa3b6a083",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #704: extreme value for k and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bbab1c0f273f74abc2b848c75006f2ef3c54c26df27711b06558f455079aee0ba3df510f2ecef6d9a05997c776f14ad6456c179f0a13af1771e4d6c37fa48b47f2",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #705: extreme value for k",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #706: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #707: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #708: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #709: testing point duplication",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2530e782f964b2e2ff065a051bc7adc20615d8c43a1365713c88268822c253bcce5b16df652aa1ecb2dc8b46c515f9604e2e84cacfa7c6eec30428d2d3f4e08ed504aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1211: pseudorandom signature",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000014a03ef9f92eb268cafa601072489a56380fa0dc43171d7712813b3a19a1eb5e53e213e28a608ce9a2f4a17fd830c6654018a79b3e0263d91a8ba90622df6f2f0",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #118: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003091194c1cba17f34e286b4833701606a41cef26177ada8850b601ea1f859e70127242fcec708828758403ce2fe501983a7984e6209f4d6b95db9ad77767f55eb",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #120: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005103c6ecceff59e71ea8f56fee3a4b2b148e81c2bdbdd39c195812c96dcfb41a72303a193dc591be150b883d770ec51ebb4ebce8b09042c2ecb16c448d8e57bf5",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #122: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #124: small r and s",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255600000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84ff2f6c24e4a33cd71c09fdcbc74a6233961b874b8c8e0eb94582092cbc50c3084fa9547afda5c66335f3f937d4c79afa120486b534139d59ae82d61ead26420",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea8884b959080bb30859cd53c2fb973cf14d60cdaa8ee00587889b5bc657ac588175a02ce5c1e53cb196113c78b4cb8dc7d360e5ea7850b0f6650b0c45af2c3cd7ca",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7adf4083bd6ecbda5a77ae578e5d835fa7f74a07ebb91e0570e1ff32a563354e9925af80b09a167d9ef647df28e2d9acd0d4bc4f2deec5723818edaf9071e311f8",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4dc2569a3c9bf8c1838ca821f7ba6f000cc8679d278f3736b414a34a7c956a03770387ea85bc4f28804b4a91c9b7d65bc6434c975806795ab7d441a4e9683aeb09",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b4a9f7da2a6c359a16540c271774a6bf1c586357c978256f44a6496d80670968ac496e73a44563f8d56fbd7bb9e4e3ae304c86f2c508eb777b03924755beb40d4",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b874146432b3cd2c9e26204c0a34136996067d466dde4917a8ff23a8e95ca106b709b3d50976ef8b385a813bc35f3a20710bdc6edd465e6f43ac4866703a6608c",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000001e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4",
- "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #134: s == 1",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000000e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #135: s == 0",
- "NoBenchmark": false
- },
- {
- "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c7038a084ffccc4ae2f8204be2abca9fb8ad4ab283b2aa50f13b6bb2347adabc69ca699799b77b1cc6dad271e88b899c12931986e958e1f5cf5653dddf7389365e2",
- "Expected": "",
- "Gas": 6900,
- "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a90000000000000000000000000000000000000000000000000000000000000000fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
- "Expected": "",
- "Gas": 6900,
- "Name": "invalid public key x param errors",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af0150000000000000000000000000000000000000000000000000000000000000000",
- "Expected": "",
- "Gas": 6900,
- "Name": "invalid public key y param errors",
- "NoBenchmark": false
- },
- {
- "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "Expected": "",
- "Gas": 6900,
- "Name": "reference point errors",
- "NoBenchmark": false
- }
-]
\ No newline at end of file
diff --git a/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_u1_u2.json b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_u1_u2.json
new file mode 100644
index 0000000000..e7e135da1a
--- /dev/null
+++ b/tests/eest/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_u1_u2.json
@@ -0,0 +1,450 @@
+[
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502369da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #139: u1 == 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52ed8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #140: u1 == n - 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c703623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #141: u2 == 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #142: u2 == n - 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #143: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #144: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #145: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #146: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #147: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f915eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #148: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #149: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #150: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d63fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #151: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd29798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d89cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #152: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dda3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #153: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd16e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1baf19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #154: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a9783a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #155: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd81ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #156: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #157: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f22eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #158: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e84db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #159: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf291b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #160: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #161: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #162: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86000a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #163: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #164: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #165: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b0992f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #166: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #167: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e378651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #168: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #169: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #170: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25a17f5b75a35ed64623ca5cbf1f91951292db0c23f0c2ea24c3d0cad0988cabc083a7a618625c228940730b4fa3ee64faecbb2fc20fdde7c58b3a3f6300424dc6",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #657: u1 == 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c04ba0cba291a37db13f33bf90dab628c04ec8393a0200419e9eaa1ebcc9fb5c31f3a0a0e6823a49b625ad57b12a32d4047970fc3428f0f0049ecf4265dc12f62",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #658: u1 == n - 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c70692b6c828e0feed63d8aeaa2b7322f9ccbe8723a1ed39f229f204a434b8900efa1f6f6abcb38ea3b8fde38b98c7c271f274af56a8c5628dc3329069ae4dd5716",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #659: u2 == 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e100cefd9162d13e64cb93687a9cd8f9755ebb5a3ef7632f800f84871874ccef09543ecbeaf7e8044ef721be2fb5f549e4b8480d2587404ebf7dbbef2c54bc0cb1",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #660: u2 == n - 1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd710f8e3edc7c2d5a3fd23de844002bb949d9f794f6d5405f6d97c1bb03dd2bd2b975183b42551cf52f291d5c1921fd5e12f50c8c85a4beb9de03efa3f0f244862243018e6866df922dc313612020311ff21e242ce3fb15bc78c406b25ab43091",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #661: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdedffbc270f722c243069a7e5f40335a61a58525c7b4db2e7a8e269274ffe4e1bc25f1d166f3e211cdf042a26f8abf6094d48b8d17191d74ed71714927446699965d06dd6a88abfa49e8b4c5da6bb922851969adf9604b5accfb52a114e77ccdb",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #662: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffda25adcae105ed7ff4f95d2344e24ee523314c3e178525d007904b68919ba4d538fe5e88243a76e41a004236218a3c3a2d6eee398a23c3a0b008d7f0164cbc0ca98a20d1bdcf573513c7cfd9b83c63e3a82d40127c897697c86b8cb387af7f240",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #663: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2e4348c645707dce6760d773de3f3e87346924b2f64bd3dd0297e766b5805ebb02148256b530fbc470c7b341970b38243ecee6d5a840a37beca2efb37e8dff2cc0adbea0882482a7489ca703a399864ba987eeb6ddb738af53a83573473cb30d",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #664: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd348c673b07dce3920d773de3f3e87408869e916dbcf797d8f9684fb67753d1dca34db012ce6eda1e9c7375c5fcf3e54ed698e19615124273b3a621d021c76f8e777458d6f55a364c221e39e1205d5510bb4fbb7ddf08d8d8fdde13d1d6df7f14",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #665: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6918ce760fb9c7241aee7bc7e7d0e8110d3d22db79ef2fb1f2d09f6ceea7a3b8b97af3fe78be15f2912b6271dd8a43badb6dd2a1b315b2ce7ae37b4e7778041d930d71ee1992d2466495c42102d08e81154c305307d1dcd52d0fa4c479b278e7",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #666: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd73b3c694391d8eadde3f3e874089464715ac20e4c126bbf6d864d648969f5b5a81e7198a3c3f23901cedc7a1d6eff6e9bf81108e6c35cd8559139af3135dbcbb9ef1568530291a8061b90c9f4285eefcba990d4570a4e3b7b737525b5d580034",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #667: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb07ac7a86948c2c2989a16db1930ef1b89ce112595197656877e53c41457f28ab4d792ca121d1dba39cb9de645149c2ab573e8becc6ddff3cc9960f188ddf737f90ba23664153e93262ff73355415195858d7be1315a69456386de68285a3c8",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #668: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27e4d82cb6c061dd9337c69bf9332ed3d198662d6f2299443f62c861187db648518412b69af43aae084476a68d59bbde51fbfa9e5be80563f587c9c2652f88ef2d3b90d25baa6bdb7b0c55e5240a3a98fbc24afed8523edec1c70503fc10f233",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #669: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde7c5cf3aac2e88923b77850515fff6a12d13b356dfe9ec275c3dd81ae94609a4a08f14a644b9a935dffea4761ebaf592d1f66fe6cd373aa7f5d370af34f8352da54b5bc4025cf335900a914c2934ec2fec7a396d0a7affcad732a5741c7aaaf5",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #670: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc77838df91c1e953e016e10bddffea2317f9fee32bacfe553cede9e57a748f68ccf2296a6a89b62b90739d38af4ae3a20e9f45715b90044639241061e33f8f8caace0046491eeaa1c6e9a472b96d88f4af83e7ff1bb84438c7e058034412ae08",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #671: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8ef071c02383d2a6c02dc217bbffd446730d0318b0425e2586220907f885f97f94b0fc1525bcabf82b1f34895e5819a06c02b23e04002276e165f962c86e3927be7c2ab4d0b25303204fb32a1f8292902792225e16a6d2dbfb29fbc89a9c3376",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #672: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5668aaa0b545bbf9a044a32399ffbe69ce20074e34d7bdf5cf56282a769763965351f37e1de0c88c508527d89882d183ccdcf2efca407edb0627cadfd16de6ec44b4b57cdf960d32ebcc4c97847eed218425853b5b675eb781b766a1a1300349",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #673: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd12d6e56882f6c0027cae91a27127728f7fddf478fb4fdc2b65f40a60b0eb952748bbafc320e6735cb64019710a269c6c2b5d147bdc831325cb2fb276ac971a69d655e9a755bc9d800ad21ee3fd4d980d93a7a49a8c5ccd37005177578f51163",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #674: edge case for u1",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a14b3bbd75c5e1c0c36535a934d4ab85112410b3b90fa97a31c33038964fd85cc112f7d837f8f9c36b460d636c965a5f818f2b50c5d00fb3f9705561dd6631883",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #675: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2d823533c04cd8edc6d6f950a8e08ade04a9bafa2f14a590356935671ae9305bf43178d1f88b6a57a96924c265f0ddb75b58312907b195acb59d7797303123775",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #676: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851edb2b3408b3167d91030624c6328e8ce3ec108c105575c2f3d209b92e654bab69c34318139c50b0802c6e612f0fd3189d800df7c996d5d7b7c3d6be82836fa258",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #677: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf209179ce7c59225392216453b2ac1e9d178c24837dfae26bc1dd7ab60638527425556b42e330289f3b826b2db7a86d19d45c2860a59f2be1ddcc3b691f95a9255",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #678: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb366901959fb8deda56e5467b7e4b214ea4c2d0c2fb29d70ff19b6b1eccebd6568d7ed9dbd77a918297fd970bff01e1343f6925167db5a14d098a211c39cc3a413398",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #679: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2567f1fdc387e5350c852b4e8f8ba9d6d947e1c5dd7ccc61a5938245dd6bcab3a9960bebaf919514f9535c22eaaf0b5812857970e26662267b1f3eb1011130a11",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #680: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86003499f974ff4ca6bbb2f51682fd5f51762f9dd6dd2855262660b36d46d3e4bec2f498fae2487807e220119152f0122476c64d4fa46ddce85c4546630f0d5c5e81",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #681: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad32c5c01662cf00c1929596257db13b26ecf30d0f3ec4b9f0351b0f27094473426e986a086060d086eee822ddd2fc744247a0154b57f7a69c51d9fdafa484e4ac7",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #682: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f491d4cba813a04d86dbae94c23be6f52c15774183be7ba5b2d9f3cf010b160501900b8adfea6491019a9ac080d516025a541bf4b952b0ad7be4b1874b02fd544a",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #683: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09ef7fd0a3a36386638330ecad41e1a3b302af36960831d0210c614b948e8aa124ef0d6d800e4047d6d3c1be0fdeaf11fcd8cab5ab59c730eb34116e35a8c7d098",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #684: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4a521dab13cc9152d8ca77035a607fea06c55cc3ca5dbeb868cea92eafe93df2a7bfb9b28531996635e6a5ccaa2826a406ce1111bdb9c2e0ca36500418a2f43de",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #685: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37474d58a4eec16e0d565f2187fe11d4e8e7a2683a12f38b4fc01d1237a81a10976e55f73bb7cdda46bdb67ef77f6fd2969df2b67920fb5945fde3a517a6ded4cd",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #686: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa692da5cd4309d9a6e5cb525c37da8fa0879f7b57208cdabbf47d223a5b23a62140e0daa78cfdd207a7389aaed61738b17fc5fc3e6a5ed3397d2902e9125e6ab4",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #687: edge case for u2",
+ "NoBenchmark": false
+ },
+ {
+ "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f85689b3e0775c7718a90279f14a8082cfcd4d1f1679274f4e9b8805c570a0670167fcc5ca734552e09afa3640f4a034e15b9b7ca661ec7ff70d3f240ebe705b1",
+ "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
+ "Gas": 6900,
+ "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #688: edge case for u2",
+ "NoBenchmark": false
+ }
+]
\ No newline at end of file
diff --git a/tests/eest/paris/eip7610_create_collision/__init__.py b/tests/eest/paris/eip7610_create_collision/__init__.py
new file mode 100644
index 0000000000..6a0e54c5fd
--- /dev/null
+++ b/tests/eest/paris/eip7610_create_collision/__init__.py
@@ -0,0 +1 @@
+"""Cross-client Create Collision Tests."""
diff --git a/tests/eest/paris/eip7610_create_collision/test_initcollision.py b/tests/eest/paris/eip7610_create_collision/test_initcollision.py
new file mode 100644
index 0000000000..683bf816b9
--- /dev/null
+++ b/tests/eest/paris/eip7610_create_collision/test_initcollision.py
@@ -0,0 +1,156 @@
+"""
+Test collision in CREATE/CREATE2 account creation, where the existing account
+only has a non-zero storage slot set.
+"""
+
+import pytest
+
+from ethereum_test_tools import (
+ Account,
+ Alloc,
+ Bytecode,
+ Initcode,
+ StateTestFiller,
+ Transaction,
+ compute_create_address,
+)
+from ethereum_test_tools import Opcodes as Op
+
+REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7610.md"
+REFERENCE_SPEC_VERSION = "80ef48d0bbb5a4939ade51caaaac57b5df6acd4e"
+
+pytestmark = [
+ pytest.mark.valid_from("Paris"),
+ pytest.mark.ported_from(
+ [
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stSStoreTest/InitCollisionFiller.json",
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stSStoreTest/InitCollisionNonZeroNonceFiller.json",
+ "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stSStoreTest/InitCollisionParisFiller.json",
+ ],
+ pr=["https://github.com/ethereum/execution-spec-tests/pull/636"],
+ ),
+ pytest.mark.parametrize(
+ "collision_nonce,collision_balance,collision_code",
+ [
+ pytest.param(0, 0, b"\0", id="non-empty-code"),
+ pytest.param(0, 1, b"", id="non-empty-balance"),
+ pytest.param(1, 0, b"", id="non-empty-nonce"),
+ ],
+ ),
+ pytest.mark.parametrize(
+ "initcode",
+ [
+ pytest.param(
+ Initcode(
+ deploy_code=Op.STOP,
+ initcode_prefix=Op.SSTORE(0, 1) + Op.SSTORE(1, 0),
+ ),
+ id="correct-initcode",
+ ),
+ pytest.param(Op.REVERT(0, 0), id="revert-initcode"),
+ pytest.param(Op.MSTORE(0xFFFFFFFFFFFFFFFFFFFFFFFFFFF, 1), id="oog-initcode"),
+ ],
+ ),
+ pytest.mark.pre_alloc_modify, # We need to modify the pre-alloc to include the collision
+]
+
+
+@pytest.mark.with_all_contract_creating_tx_types
+def test_init_collision_create_tx(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ tx_type: int,
+ collision_nonce: int,
+ collision_balance: int,
+ collision_code: bytes,
+ initcode: Bytecode,
+):
+ """
+ Test that a contract creation transaction exceptionally aborts when
+ the target address has a non-empty storage, balance, nonce, or code.
+ """
+ tx = Transaction(
+ sender=pre.fund_eoa(),
+ type=tx_type,
+ to=None,
+ data=initcode,
+ gas_limit=200_000,
+ )
+
+ created_contract_address = tx.created_contract
+
+ # This is the collision
+ pre[created_contract_address] = Account(
+ storage={0x01: 0x01},
+ nonce=collision_nonce,
+ balance=collision_balance,
+ code=collision_code,
+ )
+
+ state_test(
+ pre=pre,
+ post={
+ created_contract_address: Account(
+ storage={0x01: 0x01},
+ ),
+ },
+ tx=tx,
+ )
+
+
+@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2])
+def test_init_collision_create_opcode(
+ state_test: StateTestFiller,
+ pre: Alloc,
+ opcode: Op,
+ collision_nonce: int,
+ collision_balance: int,
+ collision_code: bytes,
+ initcode: Bytecode,
+):
+ """
+ Test that a contract creation opcode exceptionally aborts when the target
+ address has a non-empty storage, balance, nonce, or code.
+ """
+ assert len(initcode) <= 32
+ contract_creator_code = (
+ Op.MSTORE(0, Op.PUSH32(bytes(initcode).ljust(32, b"\0")))
+ + Op.SSTORE(0x01, opcode(value=0, offset=0, size=len(initcode)))
+ + Op.STOP
+ )
+ contract_creator_address = pre.deploy_contract(
+ contract_creator_code,
+ storage={0x01: 0x01},
+ )
+ created_contract_address = compute_create_address(
+ address=contract_creator_address,
+ nonce=1,
+ salt=0,
+ initcode=initcode,
+ opcode=opcode,
+ )
+
+ tx = Transaction(
+ sender=pre.fund_eoa(),
+ to=contract_creator_address,
+ data=initcode,
+ gas_limit=2_000_000,
+ )
+
+ pre[created_contract_address] = Account(
+ storage={0x01: 0x01},
+ nonce=collision_nonce,
+ balance=collision_balance,
+ code=collision_code,
+ )
+
+ state_test(
+ pre=pre,
+ post={
+ created_contract_address: Account(
+ storage={0x01: 0x01},
+ ),
+ contract_creator_address: Account(storage={0x01: 0x00}),
+ },
+ tx=tx,
+ )
diff --git a/tests/eest/paris/security/test_selfdestruct_balance_bug.py b/tests/eest/paris/security/test_selfdestruct_balance_bug.py
index 9df539ac8e..99bed4248a 100644
--- a/tests/eest/paris/security/test_selfdestruct_balance_bug.py
+++ b/tests/eest/paris/security/test_selfdestruct_balance_bug.py
@@ -1,13 +1,15 @@
"""
-bug: Tests the Consensus Flaw During Block Processing related to SELFDESTRUCT
- Tests the consensus-vulnerability reported in
- [go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4).
+Tests the Consensus Flaw During Block Processing related to SELFDESTRUCT.
+
+Tests the consensus-vulnerability reported in
+[go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4](https://github.com/ethere
+um/go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4).
To reproduce the issue with this test case:
1. Fill the test with the most recent geth evm version.
-2. Run the fixture output within a vulnerable geth version: v1.9.20 > geth >=
- v1.9.4.
+2. Run the fixture output within a vulnerable geth version:
+ v1.9.20 > geth >= v1.9.4.
"""
import pytest
@@ -23,7 +25,7 @@
Transaction,
compute_create_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
@pytest.mark.valid_from("Constantinople")
@@ -33,18 +35,18 @@ def test_tx_selfdestruct_balance_bug(blockchain_test: BlockchainTestFiller, pre:
`0xaa` contract after executing specific transactions.
1. Start with contract `0xaa` which has initial balance of 3 wei.
- `0xaa` contract code simply performs a self-destruct to itself.
+ `0xaa` contract code simply performs a self-destruct to itself.
- 2. Send a transaction (tx 1) to invoke caller contract `0xcc` (which
- has a balance of 1 wei), which in turn invokes `0xaa` with a 1 wei call.
+ 2. Send a transaction (tx 1) to invoke caller contract `0xcc` (which has a
+ balance of 1 wei), which in turn invokes `0xaa` with a 1 wei call.
- 3. Store the balance of `0xaa` after the first transaction
- is processed. `0xaa` self-destructed. Expected outcome: 0 wei.
+ 3. Store the balance of `0xaa` after the first transaction is processed.
+ `0xaa` self-destructed. Expected outcome: 0 wei.
4. Send another transaction (tx 2) to call 0xaa with 5 wei.
- 5. Store the balance of `0xaa` after the second transaction
- is processed. No self-destruct. Expected outcome: 5 wei.
+ 5. Store the balance of `0xaa` after the second transaction is processed.
+ No self-destruct. Expected outcome: 5 wei.
6. Verify that:
- Call within tx 1 is successful, i.e `0xaa` self-destructed.
diff --git a/tests/eest/prague/__init__.py b/tests/eest/prague/__init__.py
index 9a0cd1ac6c..7a26fa5de3 100644
--- a/tests/eest/prague/__init__.py
+++ b/tests/eest/prague/__init__.py
@@ -1,5 +1,6 @@
"""
-Test cases for EVM functionality introduced in Prague, [EIP-7600: Hardfork Meta - Pectra](https://eip.directory/eips/eip-7600).
+Test cases for EVM functionality introduced in Prague, [EIP-7600: Hardfork Meta
+- Pectra](https://eip.directory/eips/eip-7600).
Devnet Specifications:
@@ -8,4 +9,4 @@
- [ethpandaops/pectra-devnet-3](https://notes.ethereum.org/@ethpandaops/pectra-devnet-3).
- [ethpandaops/pectra-devnet-2](https://notes.ethereum.org/@ethpandaops/pectra-devnet-2).
- [ethpandaops/pectra-devnet-1](https://notes.ethereum.org/@ethpandaops/pectra-devnet-1).
-""" # noqa: E501
+"""
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/__init__.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/__init__.py
index 2cede19405..bc90dfa975 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/__init__.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests for [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Tests [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
+"""
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/conftest.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/conftest.py
index a4780065df..8ae554bff0 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/conftest.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/conftest.py
@@ -17,9 +17,11 @@ def vector_gas_value() -> int | None:
"""
Gas value from the test vector if any.
- If `None` it means that the test scenario did not come from a file, so no comparison is needed.
+ If `None` it means that the test scenario did not come from a file, so no
+ comparison is needed.
- The `vectors_from_file` function reads the gas value from the file and overwrites this fixture.
+ The `vectors_from_file` function reads the gas value from the file and
+ overwrites this fixture.
"""
return None
@@ -42,9 +44,10 @@ def precompile_gas_modifier() -> int:
"""
Modify the gas passed to the precompile, for testing purposes.
- By default the call is made with the exact gas amount required for the given opcode,
- but when this fixture is overridden, the gas amount can be modified to, e.g., test
- a lower amount and test if the precompile call fails.
+ By default the call is made with the exact gas amount required for the
+ given opcode, but when this fixture is overridden, the gas amount can be
+ modified to, e.g., test a lower amount and test if the precompile call
+ fails.
"""
return 0
@@ -63,7 +66,10 @@ def call_opcode() -> Op:
def call_contract_post_storage() -> Storage:
"""
Storage of the test contract after the transaction is executed.
- Note: Fixture `call_contract_code` fills the actual expected storage values.
+
+ Note:
+ Fixture `call_contract_code` fills the actual expected storage values.
+
"""
return Storage()
@@ -73,8 +79,8 @@ def call_succeeds(
expected_output: bytes | SupportsBytes,
) -> bool:
"""
- By default, depending on the expected output, we can deduce if the call is expected to succeed
- or fail.
+ By default, depending on the expected output, we can deduce if the call is
+ expected to succeed or fail.
"""
return len(bytes(expected_output)) > 0
@@ -93,24 +99,23 @@ def call_contract_code(
Code of the test contract.
Args:
- precompile_address:
- Address of the precompile to call.
- precompile_gas:
- Gas cost for the precompile, which is automatically calculated by the `precompile_gas`
- fixture, but can be overridden in the test.
- precompile_gas_modifier:
- Gas cost modifier for the precompile, which is automatically set to zero by the
- `precompile_gas_modifier` fixture, but can be overridden in the test.
- expected_output:
- Expected output of the precompile call. This value is used to determine if the call is
- expected to succeed or fail.
- call_succeeds:
- Boolean that indicates if the call is expected to succeed or fail.
- call_opcode:
- Type of call used to call the precompile (Op.CALL, Op.CALLCODE, Op.DELEGATECALL,
- Op.STATICCALL).
- call_contract_post_storage:
- Storage of the test contract after the transaction is executed.
+ precompile_address: Address of the precompile to call.
+ precompile_gas: Gas cost for the precompile, which is automatically
+ calculated by the `precompile_gas` fixture, but can
+ be overridden in the test.
+ precompile_gas_modifier: Gas cost modifier for the precompile, which
+ is automatically set to zero by the
+ `precompile_gas_modifier` fixture, but
+ can be overridden in the test.
+ expected_output: Expected output of the precompile call.
+ This value is used to determine if the call is
+ expected to succeed or fail.
+ call_succeeds: Boolean that indicates if the call is expected to
+ succeed or fail.
+ call_opcode: Type of call used to call the precompile (Op.CALL,
+ Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL).
+ call_contract_post_storage: Storage of the test contract after the
+ transaction is executed.
"""
expected_output = bytes(expected_output)
@@ -177,7 +182,9 @@ def post(call_contract_address: Address, call_contract_post_storage: Storage):
@pytest.fixture
def tx_gas_limit(fork: Fork, input_data: bytes, precompile_gas: int) -> int:
- """Transaction gas limit used for the test (Can be overridden in the test)."""
+ """
+ Transaction gas limit used for the test (Can be overridden in the test).
+ """
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
extra_gas = 100_000
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/helpers.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/helpers.py
index afadc8bb60..0fe1547152 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/helpers.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/helpers.py
@@ -14,7 +14,10 @@
def current_python_script_directory(*args: str) -> str:
- """Get the current Python script directory, optionally appending additional path components."""
+ """
+ Get the current Python script directory, optionally appending additional
+ path components.
+ """
return os.path.join(os.path.dirname(os.path.realpath(__file__)), *args)
@@ -29,7 +32,10 @@ class Vector(BaseModel):
model_config = ConfigDict(alias_generator=to_pascal)
def to_pytest_param(self):
- """Convert the test vector to a tuple that can be used as a parameter in a pytest test."""
+ """
+ Convert the test vector to a tuple that can be used as a parameter in a
+ pytest test.
+ """
return pytest.param(self.input, self.expected, self.gas, id=self.name)
@@ -43,7 +49,10 @@ class FailVector(BaseModel):
model_config = ConfigDict(alias_generator=to_pascal)
def to_pytest_param(self):
- """Convert the test vector to a tuple that can be used as a parameter in a pytest test."""
+ """
+ Convert the test vector to a tuple that can be used as a parameter in a
+ pytest test.
+ """
return pytest.param(self.input, id=self.name)
@@ -71,6 +80,7 @@ def vectors_from_file(filename: str) -> List:
def add_points_g1(point_a: PointG1, point_b: PointG1) -> PointG1:
"""
Add two points in G1 using standard formulas.
+
For points P = (x, y) and Q = (u, v), compute R = P + Q.
"""
if point_a.x == 0 and point_a.y == 0:
@@ -88,7 +98,9 @@ def add_points_g1(point_a: PointG1, point_b: PointG1) -> PointG1:
def add_points_g2(point_a: PointG2, point_b: PointG2) -> PointG2:
"""
Add two points in G2 using standard formulas.
- For points P = ((x_0, x_1), (y_0, y_1)) and Q = ((u_0, u_1), (v_0, v_1)), compute R = P + Q.
+
+ For points P = ((x_0, x_1), (y_0, y_1)) and
+ Q = ((u_0, u_1), (v_0, v_1)), compute R = P + Q.
"""
if point_a.x == (0, 0) and point_a.y == (0, 0):
return point_b
@@ -112,10 +124,11 @@ class BLSPointGenerator:
- on the standard curve
- in the correct r-order subgroup or not
- on the curve or not
- - on an isomorphic curve (not standard curve) but in the correct r-order subgroup
+ - on an isomorphic curve (not standard curve) but in the correct
+ r-order subgroup
Additional resource that helped the class implementation:
- https://hackmd.io/@benjaminion/bls12-381
+ https://hackmd.io/@benjaminion/bls12-381
"""
# Constants for G1 curve equations
@@ -125,7 +138,8 @@ class BLSPointGenerator:
# This is a known parameter of the BLS12-381 curve specification
STANDARD_B_G1 = Spec.B_COEFFICIENT
- # Isomorphic G1 curve uses b=24 (can be any b value for an isomorphic curve)
+ # Isomorphic G1 curve uses b=24 (can be any b value for an isomorphic
+ # curve)
ISOMORPHIC_B_G1 = 24 # Isomorphic curve: y^2 = x^3 + 24
# Constants for G2 curve equations
@@ -192,8 +206,8 @@ def check_in_g2_subgroup(point: PointG2) -> bool:
@staticmethod
def sqrt_fq(a: FQ) -> Optional[FQ]:
"""
- Compute smallest square root of FQ element (if it exists). Used when finding valid
- y-coordinates for a given x-coordinate on the G1 curve.
+ Compute smallest square root of FQ element (if it exists). Used when
+ finding valid y-coordinates for a given x-coordinate on the G1 curve.
"""
assert field_modulus % 4 == 3, "This sqrt method requires p % 4 == 3"
candidate = a ** ((field_modulus + 1) // 4)
@@ -206,8 +220,8 @@ def sqrt_fq(a: FQ) -> Optional[FQ]:
@staticmethod
def sqrt_fq2(a: FQ2) -> Optional[FQ2]:
"""
- Compute square root of FQ2 element (if it exists). Used when finding valid
- y-coordinates for a given x-coordinate on the G2 curve.
+ Compute square root of FQ2 element (if it exists). Used when finding
+ valid y-coordinates for a given x-coordinate on the G2 curve.
"""
if a == FQ2([0, 0]):
return FQ2([0, 0])
@@ -222,8 +236,9 @@ def sqrt_fq2(a: FQ2) -> Optional[FQ2]:
@classmethod
def multiply_by_cofactor(cls, point: Any, is_g2: bool = False):
"""
- Multiply a point by the cofactor to ensure it's in the correct r-order subgroup.
- Used for creating points in the correct r-order subgroup when using isomorphic curves.
+ Multiply a point by the cofactor to ensure it's in the correct r-order
+ subgroup. Used for creating points in the correct r-order subgroup when
+ using isomorphic curves.
"""
cofactor = cls.G2_COFACTOR if is_g2 else cls.G1_COFACTOR
try:
@@ -251,8 +266,8 @@ def multiply_by_cofactor(cls, point: Any, is_g2: bool = False):
@memory.cache
def find_g1_point_by_x(cls, x_value: int, in_subgroup: bool, on_curve: bool = True) -> PointG1:
"""
- Find a G1 point with x-coordinate at or near the given value,
- with the specified subgroup membership and curve membership.
+ Find a G1 point with x-coordinate at or near the given value, with the
+ specified subgroup membership and curve membership.
"""
max_offset = 5000
isomorphic_b = cls.ISOMORPHIC_B_G1
@@ -267,7 +282,8 @@ def find_g1_point_by_x(cls, x_value: int, in_subgroup: bool, on_curve: bool = Tr
try:
x = FQ(try_x)
- # Calculate y² = x³ + b (standard curve or isomorphic curve)
+ # Calculate y² = x³ + b (standard curve or isomorphic
+ # curve)
b_value = cls.STANDARD_B_G1 if on_curve else isomorphic_b
y_squared = x**3 + FQ(b_value)
@@ -280,7 +296,8 @@ def find_g1_point_by_x(cls, x_value: int, in_subgroup: bool, on_curve: bool = Tr
raw_point = (int(x), int(y))
raw_point2 = (int(x), Spec.P - int(y))
- # For isomorphic curve points in subgroup, apply cofactor multiplication
+ # For isomorphic curve points in subgroup, apply cofactor
+ # multiplication
if not on_curve and in_subgroup:
try:
subgroup_point = cls.multiply_by_cofactor(raw_point, is_g2=False)
@@ -327,8 +344,8 @@ def find_g2_point_by_x(
cls, x_value: tuple, in_subgroup: bool, on_curve: bool = True
) -> PointG2:
"""
- Find a G2 point with x-coordinate at or near the given value,
- with the specified subgroup membership and curve membership.
+ Find a G2 point with x-coordinate at or near the given value, with the
+ specified subgroup membership and curve membership.
"""
max_offset = 5000
isomorphic_b = cls.ISOMORPHIC_B_G2
@@ -344,7 +361,8 @@ def find_g2_point_by_x(
try:
x = FQ2(try_x)
- # Calculate y² = x³ + b (standard curve or isomorphic curve)
+ # Calculate y² = x³ + b (standard curve or isomorphic
+ # curve)
b_value = cls.STANDARD_B_G2 if on_curve else isomorphic_b
y_squared = x**3 + FQ2(b_value)
@@ -363,7 +381,8 @@ def find_g2_point_by_x(
(Spec.P - int(y.coeffs[0]), Spec.P - int(y.coeffs[1])),
)
- # For isomorphic curve points in subgroup, apply cofactor multiplication
+ # For isomorphic curve points in subgroup, apply cofactor
+ # multiplication
if not on_curve and in_subgroup:
try:
subgroup_point = cls.multiply_by_cofactor(raw_point, is_g2=True)
@@ -413,26 +432,36 @@ def find_g2_point_by_x(
# G1 points by x coordinate (near or on the x value)
@classmethod
def generate_g1_point_in_subgroup_by_x(cls, x_value: int) -> PointG1:
- """G1 point that is in the r-order subgroup with x-coordinate by/on the given value."""
+ """
+ G1 point that is in the r-order subgroup with x-coordinate by/on the
+ given value.
+ """
return cls.find_g1_point_by_x(x_value, in_subgroup=True, on_curve=True)
@classmethod
def generate_g1_point_not_in_subgroup_by_x(cls, x_value: int) -> PointG1:
- """G1 point that is NOT in the r-order subgroup with x-coordinate by/on the given value."""
+ """
+ G1 point that is NOT in the r-order subgroup with x-coordinate by/on
+ the given value.
+ """
return cls.find_g1_point_by_x(x_value, in_subgroup=False, on_curve=True)
@classmethod
def generate_g1_point_not_on_curve_by_x(cls, x_value: int) -> PointG1:
- """G1 point that is NOT on the curve with x-coordinate by/on the given value."""
+ """
+ G1 point that is NOT on the curve with x-coordinate by/on the given
+ value.
+ """
return cls.find_g1_point_by_x(x_value, in_subgroup=False, on_curve=False)
@classmethod
def generate_g1_point_on_isomorphic_curve_by_x(cls, x_value: int) -> PointG1:
"""
- G1 point that is on an isomorphic curve (not standard curve)
- but in the r-order subgroup with x-coordinate by/on the given value.
+ G1 point that is on an isomorphic curve (not standard curve) but in the
+ r-order subgroup with x-coordinate by/on the given value.
- Uses cofactor multiplication to ensure the point is in the correct subgroup.
+ Uses cofactor multiplication to ensure the point is in the correct
+ subgroup.
"""
return cls.find_g1_point_by_x(x_value, in_subgroup=True, on_curve=False)
@@ -464,10 +493,11 @@ def generate_random_g1_point_not_on_curve(cls, seed: int) -> PointG1:
@classmethod
def generate_random_g1_point_on_isomorphic_curve(cls, seed: int) -> PointG1:
"""
- Generate a random G1 point that is on an isomorphic curve (not standard curve)
- but in the r-order subgroup.
+ Generate a random G1 point that is on an isomorphic curve (not standard
+ curve) but in the r-order subgroup.
- Uses cofactor multiplication to ensure the point is in the correct subgroup.
+ Uses cofactor multiplication to ensure the point is in the correct
+ subgroup.
"""
seed_bytes = seed.to_bytes(32, "big")
hash_output = hashlib.sha384(seed_bytes + b"on_isomorphic_curve").digest()
@@ -477,26 +507,36 @@ def generate_random_g1_point_on_isomorphic_curve(cls, seed: int) -> PointG1:
# G2 point generators - by x coordinate (near or on the x value)
@classmethod
def generate_g2_point_in_subgroup_by_x(cls, x_value: tuple) -> PointG2:
- """G2 point that is in the r-order subgroup with x-coordinate by/on the given value."""
+ """
+ G2 point that is in the r-order subgroup with x-coordinate by/on the
+ given value.
+ """
return cls.find_g2_point_by_x(x_value, in_subgroup=True, on_curve=True)
@classmethod
def generate_g2_point_not_in_subgroup_by_x(cls, x_value: tuple) -> PointG2:
- """G2 point that is NOT in the r-order subgroup with x-coordinate by/on the given value."""
+ """
+ G2 point that is NOT in the r-order subgroup with x-coordinate by/on
+ the given value.
+ """
return cls.find_g2_point_by_x(x_value, in_subgroup=False, on_curve=True)
@classmethod
def generate_g2_point_not_on_curve_by_x(cls, x_value: tuple) -> PointG2:
- """G2 point that is NOT on the curve with x-coordinate by/on the given value."""
+ """
+ G2 point that is NOT on the curve with x-coordinate by/on the given
+ value.
+ """
return cls.find_g2_point_by_x(x_value, in_subgroup=False, on_curve=False)
@classmethod
def generate_g2_point_on_isomorphic_curve_by_x(cls, x_value: tuple) -> PointG2:
"""
- G2 point that is on an isomorphic curve (not standard curve)
- but in the r-order subgroup with x-coordinate near the given value.
+ G2 point that is on an isomorphic curve (not standard curve) but in the
+ r-order subgroup with x-coordinate near the given value.
- Uses cofactor multiplication to ensure the point is in the correct subgroup.
+ Uses cofactor multiplication to ensure the point is in the correct
+ subgroup.
"""
return cls.find_g2_point_by_x(x_value, in_subgroup=True, on_curve=False)
@@ -537,9 +577,9 @@ def generate_random_g2_point_not_on_curve(cls, seed: int) -> PointG2:
@classmethod
def generate_random_g2_point_on_isomorphic_curve(cls, seed: int) -> PointG2:
"""
- Generate a random G2 point that is on an isomorphic curve (not standard curve)
- but in the r-order subgroup.
- Uses cofactor multiplication to ensure the point is in the correct subgroup.
+ Generate a random G2 point that is on an isomorphic curve (not standard
+ curve) but in the r-order subgroup. Uses cofactor multiplication to
+ ensure the point is in the correct subgroup.
"""
seed_bytes = seed.to_bytes(32, "big")
hash_output = hashlib.sha384(seed_bytes + b"g2_on_isomorphic_curve").digest()
@@ -553,81 +593,127 @@ def generate_random_g2_point_on_isomorphic_curve(cls, seed: int) -> PointG2:
@classmethod
def generate_g1_map_isogeny_kernel_points(cls) -> List[FP]:
"""
- Return precomputed kernel points for the BLS12-381 G1 map to curve function. These map to
- the G1 identity point `Spec.INF_G1`. They are generated using sage math externally with the
- following script as its significantly faster than using `py_ecc` (200-1000x faster).
-
- For reference we can imagine the map to curve function as a simple 2 step process, where an
- input t value is mapped to a point on the auxiliary curve via a SWU map, and then that
- point is mapped to the BLS curve via an 11-isogeny. For reference:
- - https://eips.ethereum.org/assets/eip-2537/field_to_curve
+ Return precomputed kernel points for the BLS12-381 G1 map to curve
+ function. These map to the G1 identity point `Spec.INF_G1`. They are
+ generated using sage math externally with the following script as its
+ significantly faster than using `py_ecc` (200-1000x faster).
+
+ For reference we can imagine the map to curve function as a simple 2
+ step process, where an input t value is mapped to a point on the
+ auxiliary curve via a SWU map, and then that point is mapped to the BLS
+ curve via an 11-isogeny. For reference:
+ https://eips.ethereum.org/assets/eip-2537/field_to_curve
+
+ Note we cannot use sage math directly within EEST as it is not a pure
+ python library and requires an external dependency to be installed on
+ the system machine.
+
+ Thanks to @petertdavies (Peter Miller) for the sage math script to
+ generate these points: ```sage
+ q = 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F3
+ 8512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB
- Note we cannot use sage math directly within EEST as it is not a pure python library and
- requires an external dependency to be installed on the system machine.
-
- Thanks to @petertdavies (Peter Miller) for the sage math script to generate these points:
- ```sage
- q = 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB
Fq = GF(q)
E1 = EllipticCurve(Fq, (0, 4)) # BLS12-381 curve
- ISO_11_A = Fq(0x144698A3B8E9433D693A02C96D4982B0EA985383EE66A8D8E8981AEFD881AC98936F8DA0E0F97F5CF428082D584C1D)
- ISO_11_B = Fq(0x12E2908D11688030018B12E8753EEE3B2016C1F0F24F4070A0B9C14FCEF35EF55A23215A316CEAA5D1CC48E98E172BE0)
+
+ ISO_11_A = Fq(0x144698A3B8E9433D693A02C96D4982B0EA985383EE66A8D8E
+ 8981AEFD881AC98936F8DA0E0F97F5CF428082D584C1D)
+
+ ISO_11_B = Fq(0x12E2908D11688030018B12E8753EEE3B2016C1F0F24F4070A0B
+ 9C14FCEF35EF55A23215A316CEAA5D1CC48E98E172BE0)
+
ISO_11_Z = Fq(11)
+
Ei = EllipticCurve(Fq, (ISO_11_A, ISO_11_B))
- iso = EllipticCurveIsogeny(E=E1, kernel=None, codomain=Ei, degree=11).dual()
+
+ iso = EllipticCurveIsogeny(
+ E=E1,
+ kernel=None,
+ codomain=Ei,
+ degree=11).dual()
+
for (x, _) in iso.kernel_polynomial().roots():
discriminant = 1 - 4 / (ISO_11_A / ISO_11_B * x + 1)
if not discriminant.is_square():
continue
+
for sign in [1, -1]:
zt2 = (-1 + sign * discriminant.sqrt()) / 2
+
t2 = zt2 / ISO_11_Z
+
if t2.is_square():
t = t2.sqrt()
- assert x == -ISO_11_B / ISO_11_A * (1 + 1 / (ISO_11_Z**2 * t**4 + ISO_11_Z * t**2))
+ assert x == -ISO_11_B / ISO_11_A * (1 + 1 / (ISO_11_Z**2 *
+ t**4 + ISO_11_Z * t**2))
+
print(t)
```
- To reproduce, add the script contents to a file called `points.sage`, then run `sage points.sage`!
+ To reproduce, add the script contents to a file called `points.sage`,
+ then run `sage points.sage`!
- Please see the sage math installation guide to replicate:
- - https://doc.sagemath.org/html/en/installation/index.html
+ Please see the sage math installation guide to replicate: -
+ https://doc.sagemath.org/html/en/installation/index.html
- As G1 uses an 11-degree isogeny, its kernel contains exactly 11 points on the auxiliary
- curve that maps to the point at infinity on the BLS curve. This includes the point at
- infinity (doesn't concern us as the initial SWU map can never output infinity from any int
- t) and 10 other unique kernel points.
+ As G1 uses an 11-degree isogeny, its kernel contains exactly 11 points
+ on the auxiliary curve that maps to the point at infinity on the BLS
+ curve. This includes the point at infinity (doesn't concern us as the
+ initial SWU map can never output infinity from any int t) and 10 other
+ unique kernel points.
- These 10 other kernel points correspond to 5 x-coords on the curve (since each x-coord
- yields two points with y and -y). However, not all of these kernel points can be reached by
- the SWU map, which is why we only have 4 unique t values below.
+ These 10 other kernel points correspond to 5 x-coords on the curve
+ (since each x-coord yields two points with y and -y). However, not all
+ of these kernel points can be reached by the SWU map, which is why we
+ only have 4 unique t values below.
- The kernel polynomial has 5 roots (x-coords), and each root can potentially yield two
- t values that map to kernel points via the SWU function. Analysis shows that only 2 of
- these roots yield valid t values because the other 3 roots fail either the discriminant
- square check or the t^2 square check in the SWU inverse calculation. From these 2 valid
- roots, we get the 4 unique t values listed below.
+ The kernel polynomial has 5 roots (x-coords), and each root can
+ potentially yield two t values that map to kernel points via the SWU
+ function. Analysis shows that only 2 of these roots yield valid t
+ values because the other 3 roots fail either the discriminant square
+ check or the t^2 square check in the SWU inverse calculation. From
+ these 2 valid roots, we get the 4 unique t values listed below.
The roots and their properties are as follows:
- - Root 1 (x=3447232547282837364692125741875673748077489238391001187748258124039623697289612052402753422028380156396811587142615):
- Fails because its discriminant is not a square.
- - Root 2 (x=3086251397349454634226049654186198282625136597600255705376316455943570106637401671127489553534256598630507009270951):
- Fails because its discriminant is not a square.
- - Root 3 (x=2512099095366387796245759085729510986367032014959769672734622752070562589059815523018960565849753051338812932816014):
- Has a square discriminant, but both sign options yield t^2 values that are not squares.
- - Root 4 (x=2077344747421819657086473418925078480898358265217674456436079722467637536216749299440611432676849905020722484031356):
- Yields two valid t values:
- - 1731081574565817469321317449275278355306982786154072576198758675751495027640363897075486577327802192163339186341827
- - 861410691052762088300790587394810074303505896628048305535645284922135116676755956131724844456716837983264353875219
- - Root 5 (x=162902306530757011687648381458039960905879760854007434532151803806422383239905014872915974221245198317567396330740):
- Yields two valid t values:
- - 1006044755431560595281793557931171729984964515682961911911398807521437683216171091013202870577238485832047490326971
- - 1562001338336877267717400325455189014780228097985596277514975439801739125527323838522116502949589758528550231396418
-
- Additionally we also have the additive inverses of these t values, which are also valid
- kernel (non-unique) points. These are generated using the relationship:
- `(-t) mod p === (p - t) mod p`
- """ # noqa: E501
+ - Root 1
+ (x=3447232547282837364692125741875673748077489238391001187748258
+ 124039623697289612052402753422028380156396811587142615):
+ Fails because its discriminant is not a square.
+
+ - Root 2
+ (x=3086251397349454634226049654186198282625136597600255705376316
+ 455943570106637401671127489553534256598630507009270951):
+ Fails because its discriminant is not a square.
+
+ - Root 3
+ (x=2512099095366387796245759085729510986367032014959769672734622
+ 752070562589059815523018960565849753051338812932816014):
+ Has a square discriminant, but both sign options yield t^2 values
+ that are not squares.
+
+ - Root 4
+ (x=2077344747421819657086473418925078480898358265217674456436079
+ 722467637536216749299440611432676849905020722484031356):
+ Yields two valid t values:
+ - 173108157456581746932131744927527835530698278615407257619875
+ 8675751495027640363897075486577327802192163339186341827
+ and
+ - 861410691052762088300790587394810074303505896628048305535645
+ 284922135116676755956131724844456716837983264353875219
+
+ - Root 5
+ (x=1629023065307570116876483814580399609058797608540074345321518
+ 03806422383239905014872915974221245198317567396330740):
+ Yields two valid t values:
+ - 100604475543156059528179355793117172998496451568296191191139
+ 8807521437683216171091013202870577238485832047490326971
+ - 15620013383368772677174003254551890147802280979855962
+ 77514975439801739125527323838522116502949589758528550231396418
+
+ Additionally we also have the additive inverses of these t values,
+ which are also valid kernel (non-unique) points. These are generated
+ using the relationship: `(-t) mod p === (p - t) mod p`
+ """
unique_kernel_ts = [
1731081574565817469321317449275278355306982786154072576198758675751495027640363897075486577327802192163339186341827,
861410691052762088300790587394810074303505896628048305535645284922135116676755956131724844456716837983264353875219,
@@ -641,17 +727,20 @@ def generate_g1_map_isogeny_kernel_points(cls) -> List[FP]:
@classmethod
def generate_g2_map_isogeny_kernel_points(cls) -> List[FP2]:
"""
- Return precomputed kernel points for the BLS12-381 G2 map to curve function. These map to
- the G2 identity point `Spec.INF_G2`. They are generated using sage math externally with the
- following script as its significantly faster than using `py_ecc` (200-1000x faster).
-
- For reference we can imagine the map to curve function as a simple 2 step process, where an
- input t value is mapped to a point on the auxiliary curve via a SWU map, and then that
- point is mapped to the BLS curve via a 3-isogeny. For reference:
+ Return precomputed kernel points for the BLS12-381 G2 map to curve
+ function. These map to the G2 identity point `Spec.INF_G2`. They are
+ generated using sage math externally with the following script as its
+ significantly faster than using `py_ecc` (200-1000x faster).
+
+ For reference we can imagine the map to curve function as a simple 2
+ step process, where an input t value is mapped to a point on the
+ auxiliary curve via a SWU map, and then that point is mapped to the
+ BLS curve via a 3-isogeny. For reference:
- https://eips.ethereum.org/assets/eip-2537/field_to_curve
- Note we cannot use sage math directly within EEST as it is not a pure python library and
- requires an external dependency to be installed on the system machine.
+ Note we cannot use sage math directly within EEST as it is not a pure
+ python library and requires an external dependency to be installed on
+ the system machine.
```sage
q = 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB
@@ -694,30 +783,37 @@ def generate_g2_map_isogeny_kernel_points(cls) -> List[FP2]:
print(t)
```
- Add the script contents to a file called `points.sage`, run `sage points.sage`!
+ Add the script contents to a file called `points.sage`, run `sage
+ points.sage`!
Please see the sage math installation guide to replicate:
- https://doc.sagemath.org/html/en/installation/index.html
- As G2 uses an 3-degree isogeny, its kernel contains exactly 3 points on the auxiliary
- curve that maps to the point at infinity on the BLS curve. This includes the point at
- infinity (doesn't concern us as the initial SWU map can never output infinity from any int
- t) and 2 other kernel points.
-
- These 2 other kernel points correspond to 1 x-coord on the curve (since each x-coord
- yields two points with y and -y). Note that this root yields two equal t values due
- to specific properties of the isogeny in Fp2.
-
- However, the G2 case is different from G1 and requires additional verification for y, we
- must check that the computed y^2 actually has a square root in Fp2. Unlike G1, the G2
- singular isogeny kernel polynomial root does not correspond to a valid point on the
- auxiliary curve due to the failure of the additional check.
-
- - Root 1 (x=6*u + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559781):
- Fails because its y^2 is not a square in Fp2.
-
- Due to the failure of the first root, we have no valid kernel points in G2 that map to the
- point at infinity on the BLS curve. This is why we return an empty list here. It is kept
- for consistency with the G1 case, and documentation purposes.
- """ # noqa: E501
+ As G2 uses an 3-degree isogeny, its kernel contains exactly 3 points on
+ the auxiliary curve that maps to the point at infinity on the BLS
+ curve. This includes the point at infinity (doesn't concern us as the
+ initial SWU map can never output infinity from any int t) and 2 other
+ kernel points.
+
+ These 2 other kernel points correspond to 1 x-coord on the curve (since
+ each x-coord yields two points with y and -y). Note that this root
+ yields two equal t values due to specific properties of the isogeny in
+ Fp2.
+
+ However, the G2 case is different from G1 and requires additional
+ verification for y, we must check that the computed y^2 actually has a
+ square root in Fp2. Unlike G1, the G2 singular isogeny kernel
+ polynomial root does not correspond to a valid point on the auxiliary
+ curve due to the failure of the additional check.
+
+ - Root 1 (x=6*u +
+ 4002409555221667393417789825735904156556882819939007885332058136124031650490837
+ 864442687629129015664037894272559781): Fails because its y^2 is not a
+ square in Fp2.
+
+ Due to the failure of the first root, we have no valid kernel points in
+ G2 that map to the point at infinity on the BLS curve. This is why we
+ return an empty list here. It is kept for consistency with the G1 case,
+ and documentation purposes.
+ """ # noqa: E501, W505
return []
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/spec.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/spec.py
index 591ede1934..808bcf11c8 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/spec.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/spec.py
@@ -161,7 +161,8 @@ class Spec:
]
# fmt: on
- # Test constants (from https://github.com/ethereum/bls12-381-tests/tree/eip-2537)
+ # Test constants from
+ # https://github.com/ethereum/bls12-381-tests/tree/eip-2537
P1 = PointG1( # random point in G1
0x112B98340EEE2777CC3C14163DEA3EC97977AC3DC5C70DA32E6E87578F44912E902CCEF9EFE28D4A78B8999DFBCA9426,
0x186B28D92356C4DFEC4B5201AD099DBDEDE3781F8998DDF929B4CD7756192185CA7B8F4EF7088F813270AC3D48868A21,
@@ -249,7 +250,10 @@ def msm_discount(group: BLS12Group, k: int) -> int:
def msm_gas_func_gen(
group: BLS12Group, len_per_pair: int, multiplication_cost: int
) -> Callable[[int], int]:
- """Generate a function that calculates the gas cost for the G1MSM and G2MSM precompiles."""
+ """
+ Generate a function that calculates the gas cost for the G1MSM and G2MSM
+ precompiles.
+ """
def msm_gas(input_length: int) -> int:
"""Calculate gas cost for the G1MSM and G2MSM precompiles."""
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py
index 4dab178a35..b59f1764bd 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py
@@ -1,7 +1,10 @@
"""
-abstract: Tests BLS12_G1ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_G1ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Tests BLS12_G1ADD precompile.
+
+Tests the BLS12_G1ADD precompile implementation from [EIP-2537:
+Precompile for BLS12-381 curve operations]
+(https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -26,8 +29,8 @@
# Test vectors from the reference spec (from the cryptography team)
vectors_from_file("add_G1_bls.json")
+ [
- # Identity (infinity) element test cases.
- # Checks that any point added to the identity element (INF) equals itself.
+ # Identity (infinity) element test cases. Checks that any point added
+ # to the identity element (INF) equals itself.
pytest.param(
Spec.G1 + Spec.INF_G1,
Spec.G1,
@@ -114,15 +117,16 @@
None,
id="point_plus_reflected_point",
),
- # Not in the r-order subgroup test cases.
- # Checks that any point on the curve but not in the subgroup is used for operations.
+ # Not in the r-order subgroup test cases. Checks that any point on the
+ # curve but not in the subgroup is used for operations.
pytest.param(
Spec.P1_NOT_IN_SUBGROUP + Spec.P1_NOT_IN_SUBGROUP,
Spec.P1_NOT_IN_SUBGROUP_TIMES_2,
None,
id="non_sub_plus_non_sub",
),
- pytest.param( # `P1_NOT_IN_SUBGROUP` has an small order subgroup of 3: 3P = INF.
+ pytest.param( # `P1_NOT_IN_SUBGROUP` has an small order subgroup of 3:
+ # 3P = INF.
Spec.P1_NOT_IN_SUBGROUP + Spec.P1_NOT_IN_SUBGROUP_TIMES_2,
Spec.INF_G1,
None,
@@ -164,7 +168,8 @@
None,
id="doubled_non_sub_plus_neg",
),
- # More not in the r-order subgroup test cases, but using random generated points.
+ # More not in the r-order subgroup test cases, but using random
+ # generated points.
pytest.param(
G1_POINTS_NOT_IN_SUBGROUP[0] + Spec.P1,
add_points_g1(G1_POINTS_NOT_IN_SUBGROUP[0], Spec.P1),
@@ -381,6 +386,7 @@ def test_valid(
],
)
@pytest.mark.parametrize("expected_output", [Spec.INVALID], ids=[""])
+@pytest.mark.slow()
def test_invalid(
state_test: StateTestFiller,
pre: Alloc,
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py
index fb69d0e406..307b232269 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests BLS12_G1MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_G1MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Test the BLS12_G1MSM precompile.
+
+Test the BLS12_G1MSM precompile introduced in
+[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -69,7 +71,8 @@
None,
id="multiple_points_zero_scalar",
),
- # Cases with maximum discount table (test vector for gas cost calculation)
+ # Cases with maximum discount table (test vector for gas cost
+ # calculation)
pytest.param(
(Spec.P1 + Scalar(Spec.Q)) * (len(Spec.G1MSM_DISCOUNT_TABLE) - 1),
Spec.INF_G1,
@@ -84,6 +87,7 @@
),
],
)
+@pytest.mark.slow()
def test_valid(
state_test: StateTestFiller,
pre: Alloc,
@@ -173,7 +177,8 @@ def test_valid(
id="scalar_too_large",
),
pytest.param(
- Spec.G1 + Scalar(1).x.to_bytes(16, byteorder="big"), # Invalid scalar length
+ # Invalid scalar length
+ Spec.G1 + Scalar(1).x.to_bytes(16, byteorder="big"),
id="scalar_too_short",
),
pytest.param(
@@ -198,7 +203,8 @@ def test_valid(
id="y_above_p_pos_1",
),
],
- # Input length tests can be found in ./test_bls12_variable_length_input_contracts.py
+ # Input length tests can be found in
+ # ./test_bls12_variable_length_input_contracts.py
)
@pytest.mark.parametrize(
"precompile_gas_modifier", [100_000], ids=[""]
@@ -242,6 +248,7 @@ def test_invalid(
),
],
)
+@pytest.mark.slow()
def test_call_types(
state_test: StateTestFiller,
pre: Alloc,
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py
index 721d63a50b..9824f875bd 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py
@@ -1,7 +1,10 @@
"""
-abstract: Tests BLS12_G1MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_G1MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Tests BLS12_G1MUL precompile.
+
+Tests the BLS12_G1MUL precompile implementation from [EIP-2537:
+Precompile for BLS12-381 curve operations]
+(https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -84,8 +87,8 @@
pytest.param(
Spec.P1 + Scalar(2**256 - 1),
PointG1(
- 0x3DA1F13DDEF2B8B5A46CD543CE56C0A90B8B3B0D6D43DEC95836A5FD2BACD6AA8F692601F870CF22E05DDA5E83F460B, # noqa: E501
- 0x18D64F3C0E9785365CBDB375795454A8A4FA26F30B9C4F6E33CA078EB5C29B7AEA478B076C619BC1ED22B14C95569B2D, # noqa: E501
+ 0x3DA1F13DDEF2B8B5A46CD543CE56C0A90B8B3B0D6D43DEC95836A5FD2BACD6AA8F692601F870CF22E05DDA5E83F460B,
+ 0x18D64F3C0E9785365CBDB375795454A8A4FA26F30B9C4F6E33CA078EB5C29B7AEA478B076C619BC1ED22B14C95569B2D,
),
None,
id="max_scalar_times_point",
@@ -182,7 +185,8 @@ def test_valid(
id="swapped_coordinates_times_0",
),
pytest.param(
- PointG1(0x01, 0x07) + Scalar(0), # Point on wrong curve y^2 = x^3 + 5
+ # Point on wrong curve y^2 = x^3 + 5
+ PointG1(0x01, 0x07) + Scalar(0),
id="point_on_wrong_curve_times_0",
),
pytest.param(
@@ -294,7 +298,8 @@ def test_valid(
Spec.P1_NOT_IN_SUBGROUP + Scalar(Spec.Q + 1),
id="not_in_subgroup_times_q_plus_1",
),
- # More not in the r-order subgroup test cases, but using random generated points.
+ # More not in the r-order subgroup test cases, but using random
+ # generated points.
pytest.param(
G1_POINTS_NOT_IN_SUBGROUP[0] + Scalar(1),
id="rand_not_in_subgroup_0_times_1",
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py
index 17282fdd92..71e71ed7eb 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py
@@ -1,7 +1,10 @@
"""
-abstract: Tests BLS12_G2ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_G2ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Tests BLS12_G2ADD precompile.
+
+Tests the BLS12_G2ADD precompile implementation from [EIP-2537:
+Precompile for BLS12-381 curve operations]
+(https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -26,8 +29,8 @@
# Test vectors from the reference spec (from the cryptography team)
vectors_from_file("add_G2_bls.json")
+ [
- # Identity (infinity) element test cases.
- # Checks that any point added to the identity element (INF) equals itself.
+ # Identity (infinity) element test cases. Checks that any point added
+ # to the identity element (INF) equals itself.
pytest.param(
Spec.G2 + Spec.INF_G2,
Spec.G2,
@@ -115,8 +118,8 @@
None,
id="point_plus_reflected_point",
),
- # Not in the r-order subgroup test cases.
- # Checks that any point on the curve but not in the subgroup is used for operations.
+ # Not in the r-order subgroup test cases. Checks that any point on the
+ # curve but not in the subgroup is used for operations.
pytest.param(
Spec.P2_NOT_IN_SUBGROUP + Spec.P2_NOT_IN_SUBGROUP,
Spec.P2_NOT_IN_SUBGROUP_TIMES_2,
@@ -165,7 +168,8 @@
None,
id="doubled_non_sub_plus_neg",
),
- # More not in the r-order subgroup test cases, but using random generated points.
+ # More not in the r-order subgroup test cases, but using random
+ # generated points.
pytest.param(
G2_POINTS_NOT_IN_SUBGROUP[0] + Spec.P2,
add_points_g2(G2_POINTS_NOT_IN_SUBGROUP[0], Spec.P2),
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py
index c27b8f5599..01d56f9fab 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests BLS12_G2MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_G2MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Test the BLS12_G2MSM precompile.
+
+Test the BLS12_G2MSM precompile introduced in
+[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -69,7 +71,8 @@
None,
id="multiple_points_zero_scalar",
),
- # Cases with maximum discount table (test vector for gas cost calculation)
+ # Cases with maximum discount table (test vector for gas cost
+ # calculation)
pytest.param(
(Spec.P2 + Scalar(Spec.Q)) * (len(Spec.G2MSM_DISCOUNT_TABLE) - 1),
Spec.INF_G2,
@@ -86,6 +89,7 @@
),
],
)
+@pytest.mark.slow()
def test_valid(
state_test: StateTestFiller,
pre: Alloc,
@@ -171,7 +175,8 @@ def test_valid(
id="scalar_too_large",
),
pytest.param(
- Spec.G2 + Scalar(1).x.to_bytes(16, byteorder="big"), # Invalid scalar length
+ # Invalid scalar length
+ Spec.G2 + Scalar(1).x.to_bytes(16, byteorder="big"),
id="scalar_too_short",
),
pytest.param(
@@ -224,7 +229,8 @@ def test_valid(
id="y_c1_above_p_pos_1",
),
],
- # Input length tests can be found in ./test_bls12_variable_length_input_contracts.py
+ # Input length tests can be found in
+ # ./test_bls12_variable_length_input_contracts.py
)
@pytest.mark.parametrize(
"precompile_gas_modifier", [100_000], ids=[""]
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py
index db72f7d756..4256de3afc 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests BLS12_G2MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_G2MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Test the BLS12_G2MUL precompile.
+
+Test the BLS12_G2MUL precompile introduced in
+[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -85,12 +87,12 @@
Spec.P2 + Scalar(2**256 - 1),
PointG2(
(
- 0x2663E1C3431E174CA80E5A84489569462E13B52DA27E7720AF5567941603475F1F9BC0102E13B92A0A21D96B94E9B22, # noqa: E501
- 0x6A80D056486365020A6B53E2680B2D72D8A93561FC2F72B960936BB16F509C1A39C4E4174A7C9219E3D7EF130317C05, # noqa: E501
+ 0x2663E1C3431E174CA80E5A84489569462E13B52DA27E7720AF5567941603475F1F9BC0102E13B92A0A21D96B94E9B22,
+ 0x6A80D056486365020A6B53E2680B2D72D8A93561FC2F72B960936BB16F509C1A39C4E4174A7C9219E3D7EF130317C05,
),
(
- 0xC49EAD39E9EB7E36E8BC25824299661D5B6D0E200BBC527ECCB946134726BF5DBD861E8E6EC946260B82ED26AFE15FB, # noqa: E501
- 0x5397DAD1357CF8333189821B737172B18099ECF7EE8BDB4B3F05EBCCDF40E1782A6C71436D5ACE0843D7F361CBC6DB2, # noqa: E501
+ 0xC49EAD39E9EB7E36E8BC25824299661D5B6D0E200BBC527ECCB946134726BF5DBD861E8E6EC946260B82ED26AFE15FB,
+ 0x5397DAD1357CF8333189821B737172B18099ECF7EE8BDB4B3F05EBCCDF40E1782A6C71436D5ACE0843D7F361CBC6DB2,
),
),
None,
@@ -312,7 +314,8 @@ def test_valid(
Spec.P2_NOT_IN_SUBGROUP + Scalar(Spec.Q + 1),
id="not_in_subgroup_times_q_plus_1",
),
- # More not in the r-order subgroup test cases, but using random generated points.
+ # More not in the r-order subgroup test cases, but using random
+ # generated points.
pytest.param(
G2_POINTS_NOT_IN_SUBGROUP[0] + Scalar(1),
id="rand_not_in_subgroup_0_times_1",
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py
index d2da70d7e9..095df9e888 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests BLS12_MAP_FP2_TO_G2 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_MAP_FP2_TO_G2 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Test the BLS12_MAP_FP2_TO_G2 precompile.
+
+Test the BLS12_MAP_FP2_TO_G2 precompile introduced in
+[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -22,12 +24,12 @@
G2_POINT_ZERO_FP = PointG2(
(
- 0x18320896EC9EEF9D5E619848DC29CE266F413D02DD31D9B9D44EC0C79CD61F18B075DDBA6D7BD20B7FF27A4B324BFCE, # noqa: E501
- 0xA67D12118B5A35BB02D2E86B3EBFA7E23410DB93DE39FB06D7025FA95E96FFA428A7A27C3AE4DD4B40BD251AC658892, # noqa: E501
+ 0x18320896EC9EEF9D5E619848DC29CE266F413D02DD31D9B9D44EC0C79CD61F18B075DDBA6D7BD20B7FF27A4B324BFCE,
+ 0xA67D12118B5A35BB02D2E86B3EBFA7E23410DB93DE39FB06D7025FA95E96FFA428A7A27C3AE4DD4B40BD251AC658892,
),
(
- 0x260E03644D1A2C321256B3246BAD2B895CAD13890CBE6F85DF55106A0D334604FB143C7A042D878006271865BC35941, # noqa: E501
- 0x4C69777A43F0BDA07679D5805E63F18CF4E0E7C6112AC7F70266D199B4F76AE27C6269A3CEEBDAE30806E9A76AADF5C, # noqa: E501
+ 0x260E03644D1A2C321256B3246BAD2B895CAD13890CBE6F85DF55106A0D334604FB143C7A042D878006271865BC35941,
+ 0x4C69777A43F0BDA07679D5805E63F18CF4E0E7C6112AC7F70266D199B4F76AE27C6269A3CEEBDAE30806E9A76AADF5C,
),
)
@@ -47,12 +49,12 @@
FP2((Spec.P - 1, Spec.P - 1)),
PointG2(
(
- 0x9BF1B857D8C15F317F649ACCFA7023EF21CFC03059936B83B487DB476FF9D2FE64C6147140A5F0A436B875F51FFDF07, # noqa: E501
- 0xBB10E09BDF236CB2951BD7BCC044E1B9A6BB5FD4B2019DCC20FFDE851D52D4F0D1A32382AF9D7DA2C5BA27E0F1C69E6, # noqa: E501
+ 0x9BF1B857D8C15F317F649ACCFA7023EF21CFC03059936B83B487DB476FF9D2FE64C6147140A5F0A436B875F51FFDF07,
+ 0xBB10E09BDF236CB2951BD7BCC044E1B9A6BB5FD4B2019DCC20FFDE851D52D4F0D1A32382AF9D7DA2C5BA27E0F1C69E6,
),
(
- 0xDD416A927AB1C15490AB753C973FD377387B12EFCBE6BED2BF768B9DC95A0CA04D1A8F0F30DBC078A2350A1F823CFD3, # noqa: E501
- 0x171565CE4FCD047B35EA6BCEE4EF6FDBFEC8CC73B7ACDB3A1EC97A776E13ACDFEFFC21ED6648E3F0EEC53DDB6C20FB61, # noqa: E501
+ 0xDD416A927AB1C15490AB753C973FD377387B12EFCBE6BED2BF768B9DC95A0CA04D1A8F0F30DBC078A2350A1F823CFD3,
+ 0x171565CE4FCD047B35EA6BCEE4EF6FDBFEC8CC73B7ACDB3A1EC97A776E13ACDFEFFC21ED6648E3F0EEC53DDB6C20FB61,
),
),
None,
@@ -61,8 +63,8 @@
pytest.param(
FP2(
(
- 3510328712861478240121438855244276237335901234329585006107499559909114695366216070652508985150831181717984778988906, # noqa: E501
- 2924545590598115509050131525615277284817672420174395176262156166974132393611647670391999011900253695923948997972401, # noqa: E501
+ 3510328712861478240121438855244276237335901234329585006107499559909114695366216070652508985150831181717984778988906,
+ 2924545590598115509050131525615277284817672420174395176262156166974132393611647670391999011900253695923948997972401,
)
),
Spec.INF_G2,
@@ -101,16 +103,18 @@ def test_isogeny_kernel_values(
tx: Transaction,
):
"""
- Test the BLS12_MAP_FP2_TO_G2 precompile with isogeny kernel values. Note this test only exists
- to align with the G1 test. `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty so there are no cases.
-
- The isogeny kernel is simply the set of special field values, that after the two step mapping
- (first SWU onto an auxiliary curve, then a 3-degree isogeny back to G2), collapse exactly
- to the identity point.
-
- For the G2 case the only kernel element is the point at infinity, and SWU never produces the
- identity point from a finite input t. Hence `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty. Please
- proceed to the generator in `helpers.py` for more details.
+ Test the BLS12_MAP_FP2_TO_G2 precompile with isogeny kernel values. Note
+ this test only exists to align with the G1 test.
+ `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty so there are no cases.
+
+ The isogeny kernel is simply the set of special field values, that after
+ the two step mapping (first SWU onto an auxiliary curve, then a 3-degree
+ isogeny back to G2), collapse exactly to the identity point.
+
+ For the G2 case the only kernel element is the point at infinity, and SWU
+ never produces the identity point from a finite input t. Hence
+ `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty. Please proceed to the generator
+ in `helpers.py` for more details.
"""
state_test(
env=Environment(),
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py
index 6612530513..d8c0d73a2c 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests BLS12_MAP_FP_TO_G1 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_MAP_FP_TO_G1 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Tests BLS12_MAP_FP_TO_G1 precompile.
+
+Tests the BLS12_MAP_FP_TO_G1 precompile implementation from
+[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -21,8 +23,8 @@
]
G1_POINT_ZERO_FP = PointG1(
- 0x11A9A0372B8F332D5C30DE9AD14E50372A73FA4C45D5F2FA5097F2D6FB93BCAC592F2E1711AC43DB0519870C7D0EA415, # noqa: E501
- 0x92C0F994164A0719F51C24BA3788DE240FF926B55F58C445116E8BC6A47CD63392FD4E8E22BDF9FEAA96EE773222133, # noqa: E501
+ 0x11A9A0372B8F332D5C30DE9AD14E50372A73FA4C45D5F2FA5097F2D6FB93BCAC592F2E1711AC43DB0519870C7D0EA415,
+ 0x92C0F994164A0719F51C24BA3788DE240FF926B55F58C445116E8BC6A47CD63392FD4E8E22BDF9FEAA96EE773222133,
)
@@ -40,15 +42,15 @@
pytest.param(
FP(Spec.P - 1),
PointG1(
- 0x1073311196F8EF19477219CCEE3A48035FF432295AA9419EED45D186027D88B90832E14C4F0E2AA4D15F54D1C3ED0F93, # noqa: E501
- 0x16B3A3B2E3DDDF6A11459DDAF657FDE21C4F10282A56029D9B55AB3CE1F41E1CF39AD27E0EA35823C7D3250E81FF3D66, # noqa: E501
+ 0x1073311196F8EF19477219CCEE3A48035FF432295AA9419EED45D186027D88B90832E14C4F0E2AA4D15F54D1C3ED0F93,
+ 0x16B3A3B2E3DDDF6A11459DDAF657FDE21C4F10282A56029D9B55AB3CE1F41E1CF39AD27E0EA35823C7D3250E81FF3D66,
),
None,
id="fp_p_minus_1",
),
pytest.param(
FP(
- 799950832265136997107648781861994410980648980263584507133499364313075404851459407870655748616451882783569609925573 # noqa: E501
+ 799950832265136997107648781861994410980648980263584507133499364313075404851459407870655748616451882783569609925573
),
Spec.INF_G1,
None,
@@ -88,12 +90,12 @@ def test_isogeny_kernel_values(
"""
Test the BLS12_MAP_FP_TO_G1 precompile with isogeny kernel inputs.
- The isogeny kernel is simply the set of special field values, that after the two step mapping
- (first SWU onto an auxiliary curve, then an 11-degree isogeny back to G1), collapse exactly
- to the identity point.
+ The isogeny kernel is simply the set of special field values, that after
+ the two step mapping (first SWU onto an auxiliary curve, then an 11-degree
+ isogeny back to G1), collapse exactly to the identity point.
- Please proceed to the generator in `helpers.py` to see how the isogeny kernel values are
- generated.
+ Please proceed to the generator in `helpers.py` to see how the isogeny
+ kernel values are generated.
"""
state_test(
env=Environment(),
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py
index 4d1d5555eb..d8798201a4 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests BLS12_PAIRING precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12_PAIRING precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Tests BLS12_PAIRING precompile.
+
+Tests the BLS12_PAIRING precompile implementation from
+[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
@@ -147,8 +149,8 @@ def test_valid_multi_inf(
post: dict,
):
"""
- Test maximum input given the current environment gas limit for the BLS12_PAIRING
- precompile.
+ Test maximum input given the current environment gas limit for the
+ BLS12_PAIRING precompile.
"""
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
@@ -347,8 +349,8 @@ def test_invalid_multi_inf(
post: dict,
):
"""
- Test maximum input given the current environment gas limit for the BLS12_PAIRING
- precompile and an invalid tail.
+ Test maximum input given the current environment gas limit for the
+ BLS12_PAIRING precompile and an invalid tail.
"""
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py
index 2e1cc8c008..9c56ff39ac 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py
@@ -1,8 +1,10 @@
"""
-abstract: Tests BLS12 precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests BLS12 precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- before the Prague hard fork is active.
-""" # noqa: E501
+Tests BLS12 precompiles before fork activation.
+
+Tests the BLS12 precompiles behavior before fork activation from
+[EIP-2537: Precompile for BLS12-381 curve operations]
+(https://eips.ethereum.org/EIPS/eip-2537).
+"""
import pytest
diff --git a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py
index 527adb2009..b176da02e9 100644
--- a/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py
+++ b/tests/eest/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py
@@ -1,7 +1,11 @@
"""
-abstract: Tests minimum gas and input length for BLS12_G1MSM, BLS12_G2MSM, BLS12_PAIRING precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
- Tests minimum gas and input length for BLS12_G1MSM, BLS12_G2MSM, BLS12_PAIRING precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537).
-""" # noqa: E501
+Tests minimum gas and input length for BLS12 precompiles.
+
+Tests minimum gas and input length requirements for BLS12_G1MSM,
+BLS12_G2MSM, and BLS12_PAIRING precompiles from [EIP-2537: Precompile
+for BLS12-381 curve operations]
+(https://eips.ethereum.org/EIPS/eip-2537).
+"""
from typing import Callable, List, SupportsBytes
@@ -29,7 +33,10 @@
@pytest.fixture
def input_data() -> bytes:
- """Calldata of the transaction is empty because all input in these tests is zero."""
+ """
+ Calldata of the transaction is empty because all input in these tests is
+ zero.
+ """
return b""
@@ -41,7 +48,9 @@ def gas_modifier() -> int:
@pytest.fixture
def input_length_modifier() -> int:
- """Input length modifier to apply to each element of the precompile_gas_list."""
+ """
+ Input length modifier to apply to each element of the precompile_gas_list.
+ """
return 0
@@ -71,38 +80,36 @@ def call_contract_code(
call_contract_post_storage: Storage,
) -> Bytecode:
"""
- Code of the test contract to validate minimum expected gas in precompiles, as well as
- expected input lengths on all variable-length input precompiles.
+ Code of the test contract to validate minimum expected gas in precompiles,
+ as well as expected input lengths on all variable-length input precompiles.
- Code differs from the one used in all other tests in this file, because it accepts a list of
- precompile gas values and a list of precompile data lengths, and for each pair of values, it
- calls the precompile with the given gas and data length, data being passed to the precompile
- is all zeros.
+ Code differs from the one used in all other tests in this file, because it
+ accepts a list of precompile gas values and a list of precompile data
+ lengths, and for each pair of values, it calls the precompile with the
+ given gas and data length, data being passed to the precompile is all
+ zeros.
Args:
- precompile_address:
- Address of the precompile to call.
- precompile_gas_list:
- List of gas values to be used to call the precompile, one for each call.
- precompile_data_length_list:
- List of data lengths to be used to call the precompile, one for each call.
- gas_modifier:
- Integer to add to the gas passed to the precompile.
- input_length_modifier:
- Integer to add to the length of the input passed to the precompile.
- expected_output:
- Expected output of the contract, it is only used to determine if the call is expected
- to succeed or fail.
- call_opcode:
- Type of call used to call the precompile (Op.CALL, Op.CALLCODE, Op.DELEGATECALL,
- Op.STATICCALL).
- call_contract_post_storage:
- Storage of the test contract after the transaction is executed.
+ precompile_address: Address of the precompile to call.
+ precompile_gas_list: List of gas values to be used to call the
+ precompile, one for each call.
+ precompile_data_length_list: List of data lengths to be used to call
+ the precompile, one for each call.
+ gas_modifier: Integer to add to the gas passed to the precompile.
+ input_length_modifier: Integer to add to the length of the input
+ passed to the precompile.
+ expected_output: Expected output of the contract, it is only used to
+ determine if the call is expected to succeed or fail.
+ call_opcode: Type of call used to call the precompile (Op.CALL,
+ Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL).
+ call_contract_post_storage: Storage of the test contract after the
+ transaction is executed.
"""
expected_output = bytes(expected_output)
- # Depending on the expected output, we can deduce if the call is expected to succeed or fail.
+ # Depending on the expected output, we can deduce if the call is expected
+ # to succeed or fail.
call_succeeds = len(expected_output) > 0
assert len(precompile_gas_list) == len(precompile_data_length_list)
@@ -114,8 +121,9 @@ def call_contract_code(
for precompile_gas, precompile_args_length in zip(
precompile_gas_list, precompile_data_length_list, strict=False
):
- # For each given precompile gas value, and given arguments length, call the precompile
- # with the given gas and call data (all zeros) and compare the result.
+ # For each given precompile gas value, and given arguments length, call
+ # the precompile with the given gas and call data (all zeros) and
+ # compare the result.
code += Op.SSTORE(
call_contract_post_storage.store_next(1 if call_succeeds else 0),
Op.CALL(
@@ -135,7 +143,10 @@ def call_contract_code(
def tx_gas_limit_calculator(
fork: Fork, precompile_gas_list: List[int], max_precompile_input_length: int
) -> int:
- """Calculate the gas used to execute the transaction with the given precompile gas list."""
+ """
+ Calculate the gas used to execute the transaction with the given precompile
+ gas list.
+ """
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
extra_gas = 22_500 * len(precompile_gas_list)
@@ -154,7 +165,9 @@ def tx_gas_limit(
precompile_gas_list: List[int],
precompile_data_length_list: List[int],
) -> int:
- """Transaction gas limit used for the test (Can be overridden in the test)."""
+ """
+ Transaction gas limit used for the test (Can be overridden in the test).
+ """
assert len(input_data) == 0, "Expected empty data in the transaction."
return tx_gas_limit_calculator(fork, precompile_gas_list, max(precompile_data_length_list))
@@ -163,12 +176,13 @@ def get_split_discount_table_by_fork(
gas_fn: Callable, discount_table_length: int, element_length: int
) -> Callable[[Fork], List[ParameterSet]]:
"""
- Get the number of test cases needed to cover the given discount table adjusted for the
- fork transaction gas limit cap.
+ Get the number of test cases needed to cover the given discount table
+ adjusted for the fork transaction gas limit cap.
- The function will return the full discount table as a single test case if the
- fork has no transaction gas limit cap, otherwise it will iterate to determine the
- splits required to fit the full discount table across multiple test cases.
+ The function will return the full discount table as a single test case if
+ the fork has no transaction gas limit cap, otherwise it will iterate to
+ determine the splits required to fit the full discount table across
+ multiple test cases.
"""
def parametrize_by_fork(fork: Fork) -> List[ParameterSet]:
@@ -249,8 +263,9 @@ def test_valid_gas_g1msm(
tx: Transaction,
):
"""
- Test the BLS12_G1MSM discount gas table in full, by expecting the call to succeed for
- all possible input lengths because the appropriate amount of gas is provided.
+ Test the BLS12_G1MSM discount gas table in full, by expecting the call to
+ succeed for all possible input lengths because the appropriate amount of
+ gas is provided.
If any of the calls fail, the test will fail.
"""
@@ -307,8 +322,9 @@ def test_invalid_gas_g1msm(
tx: Transaction,
):
"""
- Test the BLS12_G1MSM discount gas table in full, by expecting the call to fail for
- all possible input lengths because the appropriate amount of gas is not provided.
+ Test the BLS12_G1MSM discount gas table in full, by expecting the call to
+ fail for all possible input lengths because the appropriate amount of gas
+ is not provided.
If any of the calls succeeds, the test will fail.
"""
@@ -371,8 +387,9 @@ def test_invalid_length_g1msm(
tx: Transaction,
):
"""
- Test the BLS12_G1MSM discount gas table in full, by expecting the call to fail for
- all possible input lengths provided because they are too long or short, or zero length.
+ Test the BLS12_G1MSM discount gas table in full, by expecting the call to
+ fail for all possible input lengths provided because they are too long or
+ short, or zero length.
If any of the calls succeeds, the test will fail.
"""
@@ -402,8 +419,9 @@ def test_valid_gas_g2msm(
tx: Transaction,
):
"""
- Test the BLS12_G2MSM discount gas table in full, by expecting the call to succeed for
- all possible input lengths because the appropriate amount of gas is provided.
+ Test the BLS12_G2MSM discount gas table in full, by expecting the call to
+ succeed for all possible input lengths because the appropriate amount of
+ gas is provided.
If any of the calls fail, the test will fail.
"""
@@ -460,8 +478,9 @@ def test_invalid_gas_g2msm(
tx: Transaction,
):
"""
- Test the BLS12_G2MSM discount gas table in full, by expecting the call to fail for
- all possible input lengths because the appropriate amount of gas is not provided.
+ Test the BLS12_G2MSM discount gas table in full, by expecting the call to
+ fail for all possible input lengths because the appropriate amount of gas
+ is not provided.
If any of the calls succeeds, the test will fail.
"""
@@ -524,8 +543,9 @@ def test_invalid_length_g2msm(
tx: Transaction,
):
"""
- Test the BLS12_G2MSM discount gas table in full, by expecting the call to fail for
- all possible input lengths provided because they are too long or short, or zero length.
+ Test the BLS12_G2MSM discount gas table in full, by expecting the call to
+ fail for all possible input lengths provided because they are too long or
+ short, or zero length.
If any of the calls succeeds, the test will fail.
"""
@@ -544,6 +564,7 @@ def test_invalid_length_g2msm(
@pytest.mark.parametrize("gas_modifier", [pytest.param(0, id="exact_gas")])
@pytest.mark.parametrize("expected_output", [Spec.PAIRING_TRUE], ids=[""])
@pytest.mark.parametrize("precompile_address", [Spec.PAIRING])
+@pytest.mark.slow()
def test_valid_gas_pairing(
state_test: StateTestFiller,
env: Environment,
@@ -552,8 +573,8 @@ def test_valid_gas_pairing(
tx: Transaction,
):
"""
- Test the BLS12_PAIRING precompile, by expecting the call to succeed for all possible input
- lengths (up to k == PAIRINGS_TO_TEST).
+ Test the BLS12_PAIRING precompile, by expecting the call to succeed for all
+ possible input lengths (up to k == PAIRINGS_TO_TEST).
If any of the calls fails, the test will fail.
"""
@@ -608,8 +629,9 @@ def test_invalid_gas_pairing(
tx: Transaction,
):
"""
- Test the BLS12_PAIRING precompile, by expecting the call to fail for all possible input
- lengths (up to k == PAIRINGS_TO_TEST) because the appropriate amount of gas is not provided.
+ Test the BLS12_PAIRING precompile, by expecting the call to fail for all
+ possible input lengths (up to k == PAIRINGS_TO_TEST) because the
+ appropriate amount of gas is not provided.
If any of the calls succeeds, the test will fail.
"""
@@ -640,7 +662,9 @@ def test_invalid_zero_length_pairing(
post: dict,
tx: Transaction,
):
- """Test the BLS12_PAIRING precompile by passing an input with zero length."""
+ """
+ Test the BLS12_PAIRING precompile by passing an input with zero length.
+ """
state_test(
env=env,
pre=pre,
@@ -670,8 +694,9 @@ def test_invalid_length_pairing(
tx: Transaction,
):
"""
- Test the BLS12_PAIRING precompile, by expecting the call to fail for all possible input
- lengths (up to k == PAIRINGS_TO_TEST) because the incorrect input length was used.
+ Test the BLS12_PAIRING precompile, by expecting the call to fail for all
+ possible input lengths (up to k == PAIRINGS_TO_TEST) because the incorrect
+ input length was used.
If any of the calls succeeds, the test will fail.
"""
diff --git a/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py b/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py
index 5d9f77b801..28c8c0e341 100644
--- a/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py
+++ b/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935)
- Test [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935).
-""" # noqa: E501
+Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935).
+"""
from typing import Dict, List
@@ -33,14 +32,17 @@ def generate_block_check_code(
check_contract_first: bool = False,
) -> Bytecode:
"""
- Generate EVM code to check that the block hashes are correctly stored in the state.
+ Generate EVM code to check that the block hashes are correctly stored in
+ the state.
Args:
- check_block_number (int): The block number to check.
- current_block_number (int): The current block number where the check is taking place.
- fork_block_number (int): The block number of the fork transition.
- storage (Storage): The storage object to use.
- check_contract_first (bool): Whether to check the contract first, for slot warming checks.
+ check_block_number (int): The block number to check.
+ current_block_number (int): The current block number where the check is
+ taking place.
+ fork_block_number (int): The block number of the fork transition.
+ storage (Storage): The storage object to use.
+ check_contract_first (bool): Whether to check the contract first,
+ for slot warming checks.
"""
contract_ret_offset = 32
@@ -108,13 +110,13 @@ def test_block_hashes_history_at_transition(
blocks_after_fork: int,
):
"""
- Tests that block hashes are stored correctly at the system contract address after the fork
- transition. Block hashes are stored incrementally at the transition until the
- `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards the oldest block hash is replaced by the
- new one.
+ Tests that block hashes are stored correctly at the system contract address
+ after the fork transition. Block hashes are stored incrementally at the
+ transition until the `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards
+ the oldest block hash is replaced by the new one.
- Note: The block hashes before the fork are no longer stored in the contract at the moment of
- the transition.
+ Note: The block hashes before the fork are no longer stored in the contract
+ at the moment of the transition.
"""
blocks: List[Block] = []
assert blocks_before_fork >= 1 and blocks_before_fork < Spec.FORK_TIMESTAMP
@@ -127,9 +129,9 @@ def test_block_hashes_history_at_transition(
for i in range(blocks_before_fork):
txs: List[Transaction] = []
if i == blocks_before_fork - 1:
- # On the last block before the fork, `BLOCKHASH` must return values for the last 256
- # blocks but not for the blocks before that.
- # And `HISTORY_STORAGE_ADDRESS` should be empty.
+ # On the last block before the fork, `BLOCKHASH` must return values
+ # for the last 256 blocks but not for the blocks before that. And
+ # `HISTORY_STORAGE_ADDRESS` should be empty.
code = Bytecode()
storage = Storage()
@@ -165,17 +167,18 @@ def test_block_hashes_history_at_transition(
blocks.append(Block(timestamp=current_block_number, txs=txs))
current_block_number += 1
- # Add blocks after the fork transition to gradually fill up the `HISTORY_SERVE_WINDOW`
+ # Add blocks after the fork transition to gradually fill up the
+ # `HISTORY_SERVE_WINDOW`
for i in range(blocks_after_fork):
txs = []
- # On these blocks, `BLOCKHASH` will still return values for the last 256 blocks, and
- # `HISTORY_STORAGE_ADDRESS` should now serve values for the previous blocks in the new
- # fork.
+ # On these blocks, `BLOCKHASH` will still return values for the last
+ # 256 blocks, and `HISTORY_STORAGE_ADDRESS` should now serve values for
+ # the previous blocks in the new fork.
code = Bytecode()
storage = Storage()
- # Check that each block can return previous blockhashes if `BLOCKHASH_OLD_WINDOW` and or
- # `HISTORY_SERVE_WINDOW`.
+ # Check that each block can return previous blockhashes if
+ # `BLOCKHASH_OLD_WINDOW` and or `HISTORY_SERVE_WINDOW`.
for j in range(current_block_number):
code += generate_block_check_code(
check_block_number=j,
@@ -227,10 +230,10 @@ def test_block_hashes_history(
check_contract_first: bool,
):
"""
- Tests that block hashes are stored correctly at the system contract address after the fork
- transition. Block hashes are stored incrementally at the transition until the
- `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards the oldest block hash is replaced by the
- new one.
+ Tests that block hashes are stored correctly at the system contract address
+ after the fork transition. Block hashes are stored incrementally at the
+ transition until the `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards
+ the oldest block hash is replaced by the new one.
"""
blocks: List[Block] = []
@@ -245,9 +248,9 @@ def test_block_hashes_history(
current_block_number += 1
txs = []
- # On these blocks, `BLOCKHASH` will still return values for the last 256 blocks, and
- # `HISTORY_STORAGE_ADDRESS` should now serve values for the previous blocks in the new
- # fork.
+ # On these blocks, `BLOCKHASH` will still return values for the last 256
+ # blocks, and `HISTORY_STORAGE_ADDRESS` should now serve values for the
+ # previous blocks in the new fork.
code = Bytecode()
storage = Storage()
@@ -321,7 +324,10 @@ def test_block_hashes_history(
def test_block_hashes_call_opcodes(
blockchain_test: BlockchainTestFiller, pre: Alloc, call_opcode: Op
):
- """Test that the call opcodes can be used to call the history contract and get the block hashes.""" # noqa: E501
+ """
+ Test that the call opcodes can be used to call the history contract and get
+ the block hashes.
+ """
blocks = []
blocks.append(Block())
@@ -382,11 +388,11 @@ def test_invalid_history_contract_calls(
reverts: bool,
):
"""
- Test calling the history contract with invalid block numbers, such as blocks from the future
- or overflowing block numbers.
+ Test calling the history contract with invalid block numbers, such as
+ blocks from the future or overflowing block numbers.
- Also test the BLOCKHASH opcode with the same block numbers, which should not affect the
- behavior of the opcode, even after verkle.
+ Also test the BLOCKHASH opcode with the same block numbers, which should
+ not affect the behavior of the opcode, even after verkle.
"""
storage = Storage()
diff --git a/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py b/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py
index 2175b38338..6593bd4527 100644
--- a/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py
+++ b/tests/eest/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935).
- Test system contract deployment for [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935).
-""" # noqa: E501
+Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935).
+"""
from os.path import realpath
from pathlib import Path
@@ -44,7 +43,8 @@ def test_system_contract_deployment(
**kwargs,
):
"""Verify deployment of the block hashes system contract."""
- # Deploy a contract that calls the history contract and verifies the block hashes.
+ # Deploy a contract that calls the history contract and verifies the block
+ # hashes.
yield Block() # Empty block just to have more history in the contract.
# We are going to query blocks even before contract deployment.
@@ -77,27 +77,31 @@ def test_system_contract_deployment(
storage: Dict
if test_type == DeploymentTestType.DEPLOY_BEFORE_FORK:
- # Fork happens at block 2, and the contract is already there, so from block number 1 and
- # after, the block hashes should be there.
+ # Fork happens at block 2, and the contract is already there, so from
+ # block number 1 and after, the block hashes should be there.
storage = {
1: 1, # Block prior to the fork, it's the first hash saved.
2: 1, # Fork block, hash should be there.
- 3: 1, # Empty block added at the start of this function, hash should be there.
+ 3: 1, # Empty block added at the start of this function, hash
+ # should be there.
}
elif test_type == DeploymentTestType.DEPLOY_ON_FORK_BLOCK:
# The contract should have the block hashes after contract deployment.
storage = {
1: 1, # Fork and deployment block, the first hash that gets added.
2: 1, # Deployment block, hash should be there.
- 3: 1, # Empty block added at the start of this function, hash should be there.
+ 3: 1, # Empty block added at the start of this function, hash
+ # should be there.
}
elif test_type == DeploymentTestType.DEPLOY_AFTER_FORK:
# The contract should have the block hashes after contract deployment.
storage = {
1: 0, # Fork block, but contract is not there yet.
- 2: 1, # Deployment block, this is the first hash that gets added because it's added on
+ 2: 1, # Deployment block, this is the first hash that gets added
+ # because it's added on
# the next block.
- 3: 1, # Empty block added at the start of this function, hash should be there.
+ 3: 1, # Empty block added at the start of this function, hash
+ # should be there.
}
post[deployed_contract] = Account(
diff --git a/tests/eest/prague/eip6110_deposits/conftest.py b/tests/eest/prague/eip6110_deposits/conftest.py
index 4c3e88e262..11d9a4bcab 100644
--- a/tests/eest/prague/eip6110_deposits/conftest.py
+++ b/tests/eest/prague/eip6110_deposits/conftest.py
@@ -13,8 +13,8 @@
@pytest.fixture
def update_pre(pre: Alloc, requests: List[DepositInteractionBase]):
"""
- Init state of the accounts. Every deposit transaction defines their own pre-state
- requirements, and this fixture aggregates them all.
+ Init state of the accounts. Every deposit transaction defines their own
+ pre-state requirements, and this fixture aggregates them all.
"""
for d in requests:
d.update_pre(pre)
@@ -34,7 +34,10 @@ def txs(
@pytest.fixture
def block_body_override_requests() -> List[DepositRequest] | None:
- """List of requests that overwrite the requests in the header. None by default."""
+ """
+ List of requests that overwrite the requests in the header. None by
+ default.
+ """
return None
@@ -48,7 +51,9 @@ def exception() -> BlockException | None:
def included_requests(
requests: List[DepositInteractionBase],
) -> List[DepositRequest]:
- """Return the list of deposit requests that should be included in each block."""
+ """
+ Return the list of deposit requests that should be included in each block.
+ """
valid_requests: List[DepositRequest] = []
for d in requests:
diff --git a/tests/eest/prague/eip6110_deposits/helpers.py b/tests/eest/prague/eip6110_deposits/helpers.py
index b664f8413e..8c06c1f307 100644
--- a/tests/eest/prague/eip6110_deposits/helpers.py
+++ b/tests/eest/prague/eip6110_deposits/helpers.py
@@ -77,22 +77,16 @@ class DepositRequest(DepositRequestBase):
"""Deposit request descriptor."""
valid: bool = True
- """
- Whether the deposit request is valid or not.
- """
+ """Whether the deposit request is valid or not."""
gas_limit: int = 1_000_000
- """
- Gas limit for the call.
- """
+ """Gas limit for the call."""
calldata_modifier: Callable[[bytes], bytes] = lambda x: x
- """
- Calldata modifier function.
- """
+ """Calldata modifier function."""
extra_wei: int = 0
"""
- Extra amount in wei to be sent with the deposit.
- If this value modulo 10**9 is not zero, the deposit will be invalid.
- The value can be negative but if the total value is negative, an exception will be raised.
+ Extra amount in wei to be sent with the deposit. If this value modulo 10**9
+ is not zero, the deposit will be invalid. The value can be negative but if
+ the total value is negative, an exception will be raised.
"""
interaction_contract_address: ClassVar[Address] = Address(Spec.DEPOSIT_CONTRACT_ADDRESS)
@@ -100,8 +94,8 @@ class DepositRequest(DepositRequestBase):
@cached_property
def value(self) -> int:
"""
- Return the value of the deposit transaction, equal to the amount in gwei plus the
- extra amount in wei.
+ Return the value of the deposit transaction, equal to the amount in
+ gwei plus the extra amount in wei.
"""
value = (self.amount * 10**9) + self.extra_wei
if value < 0:
@@ -123,13 +117,14 @@ def deposit_data_root(self) -> Hash:
@cached_property
def calldata(self) -> bytes:
"""
- Return the calldata needed to call the beacon chain deposit contract and make the deposit.
+ Return the calldata needed to call the beacon chain deposit contract
+ and make the deposit.
deposit(
- bytes calldata pubkey,
- bytes calldata withdrawal_credentials,
- bytes calldata signature,
- bytes32 deposit_data_root
+ bytes calldata pubkey,
+ bytes calldata withdrawal_credentials,
+ bytes calldata signature,
+ bytes32 deposit_data_root
)
"""
offset_length = 32
@@ -155,11 +150,11 @@ def log(self, *, include_abi_encoding: bool = True) -> bytes:
Return the log data for the deposit event.
event DepositEvent(
- bytes pubkey,
- bytes withdrawal_credentials,
- bytes amount,
- bytes signature,
- bytes index
+ bytes pubkey,
+ bytes withdrawal_credentials,
+ bytes amount,
+ bytes signature,
+ bytes index
);
"""
data = bytearray(576)
@@ -199,17 +194,11 @@ class DepositInteractionBase:
"""Base class for all types of deposit transactions we want to test."""
sender_balance: int = 32_000_000_000_000_000_000 * 100
- """
- Balance of the account that sends the transaction.
- """
+ """Balance of the account that sends the transaction."""
sender_account: EOA | None = None
- """
- Account that sends the transaction.
- """
+ """Account that sends the transaction."""
requests: List[DepositRequest]
- """
- Deposit request to be included in the block.
- """
+ """Deposit request to be included in the block."""
def transactions(self) -> List[Transaction]:
"""Return a transaction for the deposit request."""
@@ -220,13 +209,19 @@ def update_pre(self, pre: Alloc):
raise NotImplementedError
def valid_requests(self, current_minimum_fee: int) -> List[DepositRequest]:
- """Return the list of deposit requests that should be included in the block."""
+ """
+ Return the list of deposit requests that should be included in the
+ block.
+ """
raise NotImplementedError
@dataclass(kw_only=True)
class DepositTransaction(DepositInteractionBase):
- """Class used to describe a deposit originated from an externally owned account."""
+ """
+ Class used to describe a deposit originated from an externally owned
+ account.
+ """
def transactions(self) -> List[Transaction]:
"""Return a transaction for the deposit request."""
@@ -248,7 +243,10 @@ def update_pre(self, pre: Alloc):
self.sender_account = pre.fund_eoa(self.sender_balance)
def valid_requests(self, current_minimum_fee: int) -> List[DepositRequest]:
- """Return the list of deposit requests that should be included in the block."""
+ """
+ Return the list of deposit requests that should be included in the
+ block.
+ """
return [
request
for request in self.requests
@@ -261,34 +259,23 @@ class DepositContract(DepositInteractionBase):
"""Class used to describe a deposit originated from a contract."""
tx_gas_limit: int = 1_000_000
- """
- Gas limit for the transaction.
- """
+ """Gas limit for the transaction."""
tx_value: int = 0
- """
- Value to send with the transaction.
- """
+ """Value to send with the transaction."""
contract_balance: int = 32_000_000_000_000_000_000 * 100
- """
- Balance of the contract that sends the deposit requests.
- """
+ """Balance of the contract that sends the deposit requests."""
contract_address: Address | None = None
- """
- Address of the contract that sends the deposit requests.
- """
+ """Address of the contract that sends the deposit requests."""
entry_address: Address | None = None
- """
- Address to send the transaction to.
- """
+ """Address to send the transaction to."""
call_type: Op = field(default_factory=lambda: Op.CALL)
- """
- Type of call to be made to the deposit contract.
- """
+ """Type of call to be made to the deposit contract."""
call_depth: int = 2
"""
- Frame depth of the beacon chain deposit contract when it executes the deposit requests.
+ Frame depth of the beacon chain deposit contract when it executes the
+ deposit requests.
"""
extra_code: Bytecode = field(default_factory=Bytecode)
"""
@@ -357,5 +344,8 @@ def update_pre(self, pre: Alloc):
)
def valid_requests(self, current_minimum_fee: int) -> List[DepositRequest]:
- """Return the list of deposit requests that should be included in the block."""
+ """
+ Return the list of deposit requests that should be included in the
+ block.
+ """
return [d for d in self.requests if d.valid and d.value >= current_minimum_fee]
diff --git a/tests/eest/prague/eip6110_deposits/test_deposits.py b/tests/eest/prague/eip6110_deposits/test_deposits.py
index 6e3d62fcc1..9574ce4157 100644
--- a/tests/eest/prague/eip6110_deposits/test_deposits.py
+++ b/tests/eest/prague/eip6110_deposits/test_deposits.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests [EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110)
- Test [EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110).
-""" # noqa: E501
+Tests validator deposit functionality.
+
+Tests the validator deposit functionality implementation from
+[EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110).
+"""
from typing import List
@@ -185,7 +187,8 @@
amount=32_000_000_000,
signature=0x03,
index=0x0,
- # From traces, gas used by the first tx is 82,718 so reduce by one here
+ # From traces, gas used by the first tx is 82,718
+ # so reduce by one here
gas_limit=0x1431D,
valid=False,
),
@@ -218,7 +221,8 @@
amount=32_000_000_000,
signature=0x03,
index=0x0,
- # From traces, gas used by the second tx is 68,594, reduce by one here
+ # From traces, gas used by the second tx is 68,594,
+ # reduce by one here
gas_limit=0x10BF1,
valid=False,
),
@@ -314,7 +318,7 @@
signature=0x03,
index=i,
)
- for i in range(500)
+ for i in range(450)
],
tx_gas_limit=16_777_216,
),
@@ -486,7 +490,7 @@
index=i,
valid=False,
)
- for i in range(500)
+ for i in range(450)
],
tx_gas_limit=10_000_000,
),
@@ -838,8 +842,8 @@
valid=False,
)
],
- # Send 32 ETH minus 1 wei to the contract, note `DepositRequest.amount` is in
- # gwei
+ # Send 32 ETH minus 1 wei to the contract, note
+ # `DepositRequest.amount` is in gwei
tx_value=32_000_000_000 * 10**9 - 1,
contract_balance=0,
),
@@ -1182,8 +1186,8 @@ def test_deposit_negative(
blocks: List[Block],
):
"""
- Test producing a block with the incorrect deposits in the body of the block,
- and/or Engine API payload.
+ Test producing a block with the incorrect deposits in the body of the
+ block, and/or Engine API payload.
"""
blockchain_test(
pre=pre,
diff --git a/tests/eest/prague/eip6110_deposits/test_modified_contract.py b/tests/eest/prague/eip6110_deposits/test_modified_contract.py
index bbb1f4fba2..65a10c2b6e 100644
--- a/tests/eest/prague/eip6110_deposits/test_modified_contract.py
+++ b/tests/eest/prague/eip6110_deposits/test_modified_contract.py
@@ -1,4 +1,7 @@
-"""Test variants of the deposit contract which adheres the log-style as described in EIP-6110."""
+"""
+Test variants of the deposit contract which adheres the log-style as described
+in EIP-6110.
+"""
import pytest
@@ -44,8 +47,9 @@
DEFAULT_DEPOSIT_REQUEST_LOG_DATA_DICT = {
"pubkey_data": bytes(DEFAULT_DEPOSIT_REQUEST.pubkey),
"withdrawal_credentials_data": bytes(DEFAULT_DEPOSIT_REQUEST.withdrawal_credentials),
- # Note: after converting to bytes, it is converted to little-endian by `[::-1]`
- # (This happens on-chain also, but this is done by the solidity contract)
+ # Note: after converting to bytes, it is converted to little-endian by
+ # `[::-1]` (This happens on-chain also, but this is done by the solidity
+ # contract)
"amount_data": bytes.fromhex("0" + DEFAULT_DEPOSIT_REQUEST.amount.hex()[2:])[::-1],
"signature_data": bytes(DEFAULT_DEPOSIT_REQUEST.signature),
"index_data": bytes(DEFAULT_DEPOSIT_REQUEST.index),
@@ -77,36 +81,43 @@ def test_extra_logs(
pre: Alloc,
include_deposit_event: bool,
):
- """Test deposit contract emitting more log event types than the ones in mainnet."""
- # Supplant mainnet contract with a variant that emits a `Transfer`` log
- # If `include_deposit_event` is `True``, it will also emit a `DepositEvent` log`
+ """
+ Test deposit contract emitting more log event types than the ones in
+ mainnet.
+ """
+ # Supplant mainnet contract with a variant that emits a `Transfer`` log If
+ # `include_deposit_event` is `True``, it will also emit a `DepositEvent`
+ # log`
# ERC20 token transfer log (Sepolia)
- # https://sepolia.etherscan.io/tx/0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f
- # JSON RPC:
- # curl https://sepolia.infura.io/v3/APIKEY \
- # -X POST \
- # -H "Content-Type: application/json" \
- # -d '{"jsonrpc": "2.0", "method": "eth_getLogs",
- # "params": [{"address": "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D",
- # "blockHash": "0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53"}],
+ # https://sepolia.etherscan.io/tx/
+ # 0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f
+ # JSON RPC: curl https://sepolia.infura.io/v3/APIKEY \ -X POST \ -H
+ # "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "method":
+ # "eth_getLogs", "params": [{"address":
+ # "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D", "blockHash":
+ # "0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53"}],
# "id": 1}'
# {"jsonrpc":"2.0","id":1,"result":
# [{"removed":false,"logIndex":"0x80","transactionIndex":"0x56",
- # "transactionHash":"0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f",
- # "blockHash":"0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53",
+ # "transactionHash":
+ # "0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f",
+ # "blockHash":
+ # "0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53",
# "blockNumber":"0x794fb5",
# "address":"0x7f02c3e3c98b133055b8b348b2ac625669ed295d",
- # "data":"0x0000000000000000000000000000000000000000000000000000000000000001",
- # "topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ # "data":
+ # "0x0000000000000000000000000000000000000000000000000000000000000001",
+ # "topics":
+ # ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
# "0x0000000000000000000000006885e36bfcb68cb383dfe90023a462c03bcb2ae5",
# "0x00000000000000000000000080b5dc88c98e528bf9cb4b7f0f076ac41da24651"]
bytecode = Op.LOG3(
- # ERC-20 token transfer log
- # ERC-20 token transfers are LOG3, since the topic, the sender, and receiver
- # are all topics (the sender and receiver are `indexed` in the solidity event)
+ # ERC-20 token transfer log ERC-20 token transfers are LOG3, since the
+ # topic, the sender, and receiver are all topics (the sender and
+ # receiver are `indexed` in the solidity event)
0,
32,
0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF,
@@ -171,7 +182,9 @@ def test_extra_logs(
def test_invalid_layout(
blockchain_test: BlockchainTestFiller, pre: Alloc, log_argument: str, value: str
):
- """Test deposit contract emitting logs with invalid layouts (sizes/offsets)."""
+ """
+ Test deposit contract emitting logs with invalid layouts (sizes/offsets).
+ """
log_params = {**DEFAULT_DEPOSIT_REQUEST_LOG_DATA_DICT}
log_params[log_argument] = 0 if value == "zero" else 2**256 - 1 # type: ignore
@@ -200,7 +213,12 @@ def test_invalid_layout(
blockchain_test(
pre=pre,
blocks=[
- Block(txs=[tx], exception=BlockException.INVALID_DEPOSIT_EVENT_LAYOUT),
+ Block(
+ txs=[tx],
+ exception=[
+ BlockException.INVALID_DEPOSIT_EVENT_LAYOUT,
+ ],
+ ),
],
post={},
)
@@ -225,7 +243,10 @@ def test_invalid_layout(
)
@pytest.mark.exception_test
def test_invalid_log_length(blockchain_test: BlockchainTestFiller, pre: Alloc, slice_bytes: bool):
- """Test deposit contract emitting logs with invalid log length (one byte more or less)."""
+ """
+ Test deposit contract emitting logs with invalid log length (one byte more
+ or less).
+ """
changed_log = DEFAULT_REQUEST_LOG[:-1] if slice_bytes else DEFAULT_REQUEST_LOG + b"\x00"
bytecode = Om.MSTORE(changed_log) + Op.LOG1(
@@ -251,7 +272,12 @@ def test_invalid_log_length(blockchain_test: BlockchainTestFiller, pre: Alloc, s
blockchain_test(
pre=pre,
blocks=[
- Block(txs=[tx], exception=BlockException.INVALID_DEPOSIT_EVENT_LAYOUT),
+ Block(
+ txs=[tx],
+ exception=[
+ BlockException.INVALID_DEPOSIT_EVENT_LAYOUT,
+ ],
+ ),
],
post={},
)
diff --git a/tests/eest/prague/eip7002_el_triggerable_withdrawals/conftest.py b/tests/eest/prague/eip7002_el_triggerable_withdrawals/conftest.py
index c134463011..ac66187db0 100644
--- a/tests/eest/prague/eip7002_el_triggerable_withdrawals/conftest.py
+++ b/tests/eest/prague/eip7002_el_triggerable_withdrawals/conftest.py
@@ -18,8 +18,8 @@ def update_pre(
blocks_withdrawal_requests: List[List[WithdrawalRequestInteractionBase]],
):
"""
- Init state of the accounts. Every deposit transaction defines their own pre-state
- requirements, and this fixture aggregates them all.
+ Init state of the accounts. Every deposit transaction defines their own
+ pre-state requirements, and this fixture aggregates them all.
"""
for requests in blocks_withdrawal_requests:
for r in requests:
@@ -31,7 +31,10 @@ def included_requests(
update_pre: None, # Fixture is used for its side effects
blocks_withdrawal_requests: List[List[WithdrawalRequestInteractionBase]],
) -> List[List[WithdrawalRequest]]:
- """Return the list of withdrawal requests that should be included in each block."""
+ """
+ Return the list of withdrawal requests that should be included in each
+ block.
+ """
excess_withdrawal_requests = 0
carry_over_requests: List[WithdrawalRequest] = []
per_block_included_requests: List[List[WithdrawalRequest]] = []
@@ -110,8 +113,10 @@ def blocks(
timestamp += 1
return blocks + [
+ # Add an empty block at the end to verify that no more withdrawal
+ # requests are included
Block(
header_verify=Header(requests_hash=Requests()),
timestamp=timestamp,
)
- ] # Add an empty block at the end to verify that no more withdrawal requests are included
+ ]
diff --git a/tests/eest/prague/eip7002_el_triggerable_withdrawals/helpers.py b/tests/eest/prague/eip7002_el_triggerable_withdrawals/helpers.py
index 2a0f7216ad..d8fa578a6c 100644
--- a/tests/eest/prague/eip7002_el_triggerable_withdrawals/helpers.py
+++ b/tests/eest/prague/eip7002_el_triggerable_withdrawals/helpers.py
@@ -17,22 +17,17 @@ class WithdrawalRequest(WithdrawalRequestBase):
fee: int = 0
"""
- Fee to be paid to the system contract for the withdrawal request.
- This is different from `amount` which is the amount of gwei to be withdrawn on the beacon
- chain.
+ Fee to be paid to the system contract for the withdrawal request. This is
+ different from `amount` which is the amount of gwei to be withdrawn on the
+ beacon chain.
+
"""
valid: bool = True
- """
- Whether the withdrawal request is valid or not.
- """
+ """Whether the withdrawal request is valid or not."""
gas_limit: int = 1_000_000
- """
- Gas limit for the call.
- """
+ """Gas limit for the call."""
calldata_modifier: Callable[[bytes], bytes] = lambda x: x
- """
- Calldata modifier function.
- """
+ """Calldata modifier function."""
interaction_contract_address: ClassVar[Address] = Address(
Spec.WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS
@@ -41,23 +36,26 @@ class WithdrawalRequest(WithdrawalRequestBase):
@property
def value(self) -> int:
"""
- Return the value of the call to the withdrawal request contract, equal to the fee
- to be paid.
+ Return the value of the call to the withdrawal request contract, equal
+ to the fee to be paid.
"""
return self.fee
@cached_property
def calldata(self) -> bytes:
"""
- Return the calldata needed to call the withdrawal request contract and make the
- withdrawal.
+ Return the calldata needed to call the withdrawal request contract and
+ make the withdrawal.
"""
return self.calldata_modifier(
self.validator_pubkey + self.amount.to_bytes(8, byteorder="big")
)
def with_source_address(self, source_address: Address) -> "WithdrawalRequest":
- """Return a new instance of the withdrawal request with the source address set."""
+ """
+ Return a new instance of the withdrawal request with the source address
+ set.
+ """
return self.copy(source_address=source_address)
@@ -66,17 +64,11 @@ class WithdrawalRequestInteractionBase:
"""Base class for all types of withdrawal transactions we want to test."""
sender_balance: int = 1_000_000_000_000_000_000
- """
- Balance of the account that sends the transaction.
- """
+ """Balance of the account that sends the transaction."""
sender_account: EOA | None = None
- """
- Account that will send the transaction.
- """
+ """Account that will send the transaction."""
requests: List[WithdrawalRequest]
- """
- Withdrawal request to be included in the block.
- """
+ """Withdrawal request to be included in the block."""
def transactions(self) -> List[Transaction]:
"""Return a transaction for the withdrawal request."""
@@ -87,13 +79,19 @@ def update_pre(self, pre: Alloc):
raise NotImplementedError
def valid_requests(self, current_minimum_fee: int) -> List[WithdrawalRequest]:
- """Return the list of withdrawal requests that should be valid in the block."""
+ """
+ Return the list of withdrawal requests that should be valid in the
+ block.
+ """
raise NotImplementedError
@dataclass(kw_only=True)
class WithdrawalRequestTransaction(WithdrawalRequestInteractionBase):
- """Class used to describe a withdrawal request originated from an externally owned account."""
+ """
+ Class used to describe a withdrawal request originated from an externally
+ owned account.
+ """
def transactions(self) -> List[Transaction]:
"""Return a transaction for the withdrawal request."""
@@ -129,9 +127,7 @@ class WithdrawalRequestContract(WithdrawalRequestInteractionBase):
"""Class used to describe a withdrawal originated from a contract."""
tx_gas_limit: int = 1_000_000
- """
- Gas limit for the transaction.
- """
+ """Gas limit for the transaction."""
contract_balance: int = 1_000_000_000_000_000_000
"""
@@ -142,22 +138,14 @@ class WithdrawalRequestContract(WithdrawalRequestInteractionBase):
Address of the contract that will make the call to the pre-deploy contract.
"""
entry_address: Address | None = None
- """
- Address to send the transaction to.
- """
+ """Address to send the transaction to."""
call_type: Op = field(default_factory=lambda: Op.CALL)
- """
- Type of call to be used to make the withdrawal request.
- """
+ """Type of call to be used to make the withdrawal request."""
call_depth: int = 2
- """
- Frame depth of the pre-deploy contract when it executes the call.
- """
+ """Frame depth of the pre-deploy contract when it executes the call."""
extra_code: Bytecode = field(default_factory=Bytecode)
- """
- Extra code to be added to the contract code.
- """
+ """Extra code to be added to the contract code."""
@property
def contract_code(self) -> Bytecode:
@@ -243,12 +231,12 @@ def get_n_fee_increments(n: int) -> List[int]:
def get_n_fee_increment_blocks(n: int) -> List[List[WithdrawalRequestContract]]:
"""
- Return N blocks that should be included in the test such that each subsequent block has an
- increasing fee for the withdrawal requests.
+ Return N blocks that should be included in the test such that each
+ subsequent block has an increasing fee for the withdrawal requests.
- This is done by calculating the number of withdrawals required to reach the next fee increment
- and creating a block with that number of withdrawal requests plus the number of withdrawals
- required to reach the target.
+ This is done by calculating the number of withdrawals required to reach the
+ next fee increment and creating a block with that number of withdrawal
+ requests plus the number of withdrawals required to reach the target.
"""
blocks = []
previous_excess = 0
diff --git a/tests/eest/prague/eip7002_el_triggerable_withdrawals/spec.py b/tests/eest/prague/eip7002_el_triggerable_withdrawals/spec.py
index e30a15011b..30f9833872 100644
--- a/tests/eest/prague/eip7002_el_triggerable_withdrawals/spec.py
+++ b/tests/eest/prague/eip7002_el_triggerable_withdrawals/spec.py
@@ -1,7 +1,8 @@
"""
Common procedures to test
-[EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
-""" # noqa: E501
+[EIP-7002: Execution layer triggerable
+withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
+"""
from dataclasses import dataclass
diff --git a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py
index 90f690180e..0d1aa8b517 100644
--- a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py
+++ b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
- Test system contract deployment for [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
-""" # noqa: E501
+Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
+"""
from os.path import realpath
from pathlib import Path
diff --git a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py
index 7346a630ae..e47a564ede 100644
--- a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py
+++ b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py
@@ -1,8 +1,6 @@
"""
-abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002)
- Test execution layer triggered exits [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
-
-""" # noqa: E501
+Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
+"""
from typing import List
@@ -91,7 +89,10 @@ def test_extra_withdrawals(
pre: Alloc,
requests_list: List[WithdrawalRequest],
):
- """Test how clients were to behave when more than 16 withdrawals would be allowed per block."""
+ """
+ Test how clients were to behave when more than 16 withdrawals would be
+ allowed per block.
+ """
modified_code: Bytecode = Bytecode()
memory_offset: int = 0
amount_of_requests: int = 0
@@ -116,7 +117,8 @@ def test_extra_withdrawals(
balance=0,
)
- # given a list of withdrawal requests construct a withdrawal request transaction
+ # given a list of withdrawal requests construct a withdrawal request
+ # transaction
withdrawal_request_transaction = WithdrawalRequestTransaction(requests=requests_list)
# prepare withdrawal senders
withdrawal_request_transaction.update_pre(pre=pre)
@@ -144,8 +146,8 @@ def test_extra_withdrawals(
)
def test_system_contract_errors():
"""
- Test system contract raising different errors when called by the system account at the
- end of the block execution.
+ Test system contract raising different errors when called by the system
+ account at the end of the block execution.
To see the list of generated tests, please refer to the
`generate_system_contract_error_test` decorator definition.
diff --git a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py
index d764ceccbc..0613eae236 100644
--- a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py
+++ b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py
@@ -1,8 +1,6 @@
"""
-abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002)
- Test execution layer triggered exits [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
-
-""" # noqa: E501
+Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
+"""
from typing import List
@@ -816,8 +814,8 @@ def test_withdrawal_requests_negative(
exception: BlockException,
):
"""
- Test blocks where the requests list and the actual withdrawal requests that happened in the
- block's transactions do not match.
+ Test blocks where the requests list and the actual withdrawal requests that
+ happened in the block's transactions do not match.
"""
for d in requests:
d.update_pre(pre)
diff --git a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py
index e61cf87b7c..6f9948c038 100644
--- a/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py
+++ b/tests/eest/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py
@@ -1,8 +1,6 @@
"""
-abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002)
- Test execution layer triggered exits [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
-
-""" # noqa: E501
+Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002).
+"""
from os.path import realpath
from pathlib import Path
@@ -57,8 +55,9 @@
validator_pubkey=0x02,
amount=0,
fee=Spec.get_fee(10),
- # First post-fork withdrawal request, will not be included
- # because the inhibitor is cleared at the end of the block
+ # First post-fork withdrawal request, will not
+ # be included because the inhibitor is cleared
+ # at the end of the block
valid=False,
)
],
@@ -91,8 +90,12 @@ def test_withdrawal_requests_during_fork(
blocks: List[Block],
pre: Alloc,
):
- """Test making a withdrawal request to the beacon chain at the time of the fork."""
- # We need to delete the deployed contract that comes by default in the pre state.
+ """
+ Test making a withdrawal request to the beacon chain at the time of the
+ fork.
+ """
+ # We need to delete the deployed contract that comes by default in the pre
+ # state.
pre[Spec.WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS] = Account(
balance=0,
code=bytes(),
diff --git a/tests/eest/prague/eip7251_consolidations/conftest.py b/tests/eest/prague/eip7251_consolidations/conftest.py
index 3fd5b8be64..f116162ca4 100644
--- a/tests/eest/prague/eip7251_consolidations/conftest.py
+++ b/tests/eest/prague/eip7251_consolidations/conftest.py
@@ -18,8 +18,8 @@ def update_pre(
blocks_consolidation_requests: List[List[ConsolidationRequestInteractionBase]],
):
"""
- Init state of the accounts. Every deposit transaction defines their own pre-state
- requirements, and this fixture aggregates them all.
+ Init state of the accounts. Every deposit transaction defines their own
+ pre-state requirements, and this fixture aggregates them all.
"""
for requests in blocks_consolidation_requests:
for r in requests:
@@ -31,7 +31,10 @@ def included_requests(
update_pre: None, # Fixture is used for its side effects
blocks_consolidation_requests: List[List[ConsolidationRequestInteractionBase]],
) -> List[List[ConsolidationRequest]]:
- """Return the list of consolidation requests that should be included in each block."""
+ """
+ Return the list of consolidation requests that should be included in each
+ block.
+ """
excess_consolidation_requests = 0
carry_over_requests: List[ConsolidationRequest] = []
per_block_included_requests: List[List[ConsolidationRequest]] = []
@@ -39,7 +42,8 @@ def included_requests(
# Get fee for the current block
current_minimum_fee = Spec.get_fee(excess_consolidation_requests)
- # With the fee, get the valid consolidation requests for the current block
+ # With the fee, get the valid consolidation requests for the current
+ # block
current_block_requests = []
for w in block_consolidation_requests:
current_block_requests += w.valid_requests(current_minimum_fee)
@@ -111,4 +115,5 @@ def blocks(
header_verify=Header(requests_hash=Requests()),
timestamp=timestamp,
)
- ] # Add an empty block at the end to verify that no more consolidation requests are included
+ ] # Add an empty block at the end to verify that no more consolidation
+ # requests are included
diff --git a/tests/eest/prague/eip7251_consolidations/helpers.py b/tests/eest/prague/eip7251_consolidations/helpers.py
index 466afb8455..20795482db 100644
--- a/tests/eest/prague/eip7251_consolidations/helpers.py
+++ b/tests/eest/prague/eip7251_consolidations/helpers.py
@@ -16,21 +16,13 @@ class ConsolidationRequest(ConsolidationRequestBase):
"""Class used to describe a consolidation request in a test."""
fee: int = 0
- """
- Fee to be paid to the system contract for the consolidation request.
- """
+ """Fee to be paid to the system contract for the consolidation request."""
valid: bool = True
- """
- Whether the consolidation request is valid or not.
- """
+ """Whether the consolidation request is valid or not."""
gas_limit: int = 1_000_000
- """
- Gas limit for the call.
- """
+ """Gas limit for the call."""
calldata_modifier: Callable[[bytes], bytes] = lambda x: x
- """
- Calldata modifier function.
- """
+ """Calldata modifier function."""
interaction_contract_address: ClassVar[Address] = Address(
Spec.CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS
@@ -39,40 +31,39 @@ class ConsolidationRequest(ConsolidationRequestBase):
@property
def value(self) -> int:
"""
- Return the value of the call to the consolidation request contract, equal to the fee
- to be paid.
+ Return the value of the call to the consolidation request contract,
+ equal to the fee to be paid.
"""
return self.fee
@cached_property
def calldata(self) -> bytes:
"""
- Return the calldata needed to call the consolidation request contract and make the
- consolidation.
+ Return the calldata needed to call the consolidation request contract
+ and make the consolidation.
"""
return self.calldata_modifier(self.source_pubkey + self.target_pubkey)
def with_source_address(self, source_address: Address) -> "ConsolidationRequest":
- """Return a new instance of the consolidation request with the source address set."""
+ """
+ Return a new instance of the consolidation request with the source
+ address set.
+ """
return self.copy(source_address=source_address)
@dataclass(kw_only=True)
class ConsolidationRequestInteractionBase:
- """Base class for all types of consolidation transactions we want to test."""
-
- sender_balance: int = 1_000_000_000_000_000_000
"""
- Balance of the account that sends the transaction.
+ Base class for all types of consolidation transactions we want to test.
"""
+
+ sender_balance: int = 1_000_000_000_000_000_000
+ """Balance of the account that sends the transaction."""
sender_account: EOA | None = None
- """
- Account that will send the transaction.
- """
+ """Account that will send the transaction."""
requests: List[ConsolidationRequest]
- """
- Consolidation requests to be included in the block.
- """
+ """Consolidation requests to be included in the block."""
def transactions(self) -> List[Transaction]:
"""Return a transaction for the consolidation request."""
@@ -83,13 +74,19 @@ def update_pre(self, pre: Alloc):
raise NotImplementedError
def valid_requests(self, current_minimum_fee: int) -> List[ConsolidationRequest]:
- """Return the list of consolidation requests that should be valid in the block."""
+ """
+ Return the list of consolidation requests that should be valid in the
+ block.
+ """
raise NotImplementedError
@dataclass(kw_only=True)
class ConsolidationRequestTransaction(ConsolidationRequestInteractionBase):
- """Class to describe a consolidation request originated from an externally owned account."""
+ """
+ Class to describe a consolidation request originated from an externally
+ owned account.
+ """
def transactions(self) -> List[Transaction]:
"""Return a transaction for the consolidation request."""
@@ -125,9 +122,7 @@ class ConsolidationRequestContract(ConsolidationRequestInteractionBase):
"""Class used to describe a consolidation originated from a contract."""
tx_gas_limit: int = 10_000_000
- """
- Gas limit for the transaction.
- """
+ """Gas limit for the transaction."""
contract_balance: int = 1_000_000_000_000_000_000
"""
@@ -138,22 +133,14 @@ class ConsolidationRequestContract(ConsolidationRequestInteractionBase):
Address of the contract that will make the call to the pre-deploy contract.
"""
entry_address: Address | None = None
- """
- Address to send the transaction to.
- """
+ """Address to send the transaction to."""
call_type: Op = field(default_factory=lambda: Op.CALL)
- """
- Type of call to be used to make the consolidation request.
- """
+ """Type of call to be used to make the consolidation request."""
call_depth: int = 2
- """
- Frame depth of the pre-deploy contract when it executes the call.
- """
+ """Frame depth of the pre-deploy contract when it executes the call."""
extra_code: Bytecode = field(default_factory=Bytecode)
- """
- Extra code to be added to the contract code.
- """
+ """Extra code to be added to the contract code."""
@property
def contract_code(self) -> Bytecode:
@@ -239,12 +226,13 @@ def get_n_fee_increments(n: int) -> List[int]:
def get_n_fee_increment_blocks(n: int) -> List[List[ConsolidationRequestContract]]:
"""
- Return N blocks that should be included in the test such that each subsequent block has an
- increasing fee for the consolidation requests.
+ Return N blocks that should be included in the test such that each
+ subsequent block has an increasing fee for the consolidation requests.
- This is done by calculating the number of consolidations required to reach the next fee
- increment and creating a block with that number of consolidation requests plus the number of
- consolidations required to reach the target.
+ This is done by calculating the number of consolidations required to reach
+ the next fee increment and creating a block with that number of
+ consolidation requests plus the number of consolidations required to reach
+ the target.
"""
blocks = []
previous_excess = 0
diff --git a/tests/eest/prague/eip7251_consolidations/test_consolidations.py b/tests/eest/prague/eip7251_consolidations/test_consolidations.py
index bd5f8d81e6..929ba8ba09 100644
--- a/tests/eest/prague/eip7251_consolidations/test_consolidations.py
+++ b/tests/eest/prague/eip7251_consolidations/test_consolidations.py
@@ -1,8 +1,6 @@
"""
-abstract: Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251)
- Test execution layer triggered consolidations [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251).
-
-""" # noqa: E501
+Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251).
+"""
from typing import List
@@ -866,8 +864,8 @@ def test_consolidation_requests_negative(
exception: BlockException,
):
"""
- Test blocks where the requests list and the actual consolidation requests that happened in the
- block's transactions do not match.
+ Test blocks where the requests list and the actual consolidation requests
+ that happened in the block's transactions do not match.
"""
for d in requests:
d.update_pre(pre)
diff --git a/tests/eest/prague/eip7251_consolidations/test_consolidations_during_fork.py b/tests/eest/prague/eip7251_consolidations/test_consolidations_during_fork.py
index 4731b3842f..36f948c102 100644
--- a/tests/eest/prague/eip7251_consolidations/test_consolidations_during_fork.py
+++ b/tests/eest/prague/eip7251_consolidations/test_consolidations_during_fork.py
@@ -1,8 +1,6 @@
"""
-abstract: Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251)
- Test execution layer triggered consolidations [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251).
-
-""" # noqa: E501
+Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251).
+"""
from os.path import realpath
from pathlib import Path
@@ -57,8 +55,9 @@
source_pubkey=0x03,
target_pubkey=0x04,
fee=Spec.get_fee(10),
- # First post-fork consolidation request, will not be included
- # because the inhibitor is cleared at the end of the block
+ # First post-fork consolidation request, will
+ # not be included because the inhibitor is
+ # cleared at the end of the block
valid=False,
)
],
@@ -91,8 +90,12 @@ def test_consolidation_requests_during_fork(
blocks: List[Block],
pre: Alloc,
):
- """Test making a consolidation request to the beacon chain at the time of the fork."""
- # We need to delete the deployed contract that comes by default in the pre state.
+ """
+ Test making a consolidation request to the beacon chain at the time of the
+ fork.
+ """
+ # We need to delete the deployed contract that comes by default in the pre
+ # state.
pre[Spec.CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS] = Account(
balance=0,
code=bytes(),
diff --git a/tests/eest/prague/eip7251_consolidations/test_contract_deployment.py b/tests/eest/prague/eip7251_consolidations/test_contract_deployment.py
index f0a66d2b96..0d195306ac 100644
--- a/tests/eest/prague/eip7251_consolidations/test_contract_deployment.py
+++ b/tests/eest/prague/eip7251_consolidations/test_contract_deployment.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251).
- Test system contract deployment for [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251).
-""" # noqa: E501
+Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251).
+"""
from os.path import realpath
from pathlib import Path
diff --git a/tests/eest/prague/eip7251_consolidations/test_modified_consolidation_contract.py b/tests/eest/prague/eip7251_consolidations/test_modified_consolidation_contract.py
index d29c1177e2..a3f33ac2ec 100644
--- a/tests/eest/prague/eip7251_consolidations/test_modified_consolidation_contract.py
+++ b/tests/eest/prague/eip7251_consolidations/test_modified_consolidation_contract.py
@@ -1,8 +1,6 @@
"""
-abstract: Tests [EIP-7251: Execution layer triggerable consolidation](https://eips.ethereum.org/EIPS/eip-7251)
- Test execution layer triggered exits [EIP-7251: Execution layer triggerable consolidation](https://eips.ethereum.org/EIPS/eip-7251).
-
-""" # noqa: E501
+Tests [EIP-7251: Execution layer triggerable consolidation](https://eips.ethereum.org/EIPS/eip-7251).
+"""
from typing import List
@@ -91,7 +89,9 @@ def test_extra_consolidations(
pre: Alloc,
requests_list: List[ConsolidationRequest],
):
- """Test how clients were to behave with more than 2 consolidations per block."""
+ """
+ Test how clients were to behave with more than 2 consolidations per block.
+ """
modified_code: Bytecode = Bytecode()
memory_offset: int = 0
amount_of_requests: int = 0
@@ -116,7 +116,8 @@ def test_extra_consolidations(
balance=0,
)
- # given a list of consolidation requests construct a consolidation request transaction
+ # given a list of consolidation requests construct a consolidation request
+ # transaction
consolidation_request_transaction = ConsolidationRequestTransaction(requests=requests_list)
# prepare consolidation senders
consolidation_request_transaction.update_pre(pre=pre)
@@ -144,8 +145,8 @@ def test_extra_consolidations(
)
def test_system_contract_errors():
"""
- Test system contract raising different errors when called by the system account at the
- end of the block execution.
+ Test system contract raising different errors when called by the system
+ account at the end of the block execution.
To see the list of generated tests, please refer to the
`generate_system_contract_error_test` decorator definition.
diff --git a/tests/eest/prague/eip7623_increase_calldata_cost/__init__.py b/tests/eest/prague/eip7623_increase_calldata_cost/__init__.py
index 951922c6f9..ef3f7c8099 100644
--- a/tests/eest/prague/eip7623_increase_calldata_cost/__init__.py
+++ b/tests/eest/prague/eip7623_increase_calldata_cost/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623)
- Tests for [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
+Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
"""
diff --git a/tests/eest/prague/eip7623_increase_calldata_cost/conftest.py b/tests/eest/prague/eip7623_increase_calldata_cost/conftest.py
index 5f0a4b50d0..a4f30d2911 100644
--- a/tests/eest/prague/eip7623_increase_calldata_cost/conftest.py
+++ b/tests/eest/prague/eip7623_increase_calldata_cost/conftest.py
@@ -48,8 +48,8 @@ def to(
@pytest.fixture
def protected() -> bool:
"""
- Return whether the transaction is protected or not.
- Only valid for type-0 transactions.
+ Return whether the transaction is protected or not. Only valid for type-0
+ transactions.
"""
return True
@@ -62,7 +62,10 @@ def access_list() -> List[AccessList] | None:
@pytest.fixture
def authorization_refund() -> bool:
- """Return whether the transaction has an existing authority in the authorization list."""
+ """
+ Return whether the transaction has an existing authority in the
+ authorization list.
+ """
return False
@@ -75,9 +78,9 @@ def authorization_list(
"""
Authorization-list for the transaction.
- This fixture needs to be parametrized indirectly in order to generate the authorizations with
- valid signers using `pre` in this function, and the parametrized value should be a list of
- addresses.
+ This fixture needs to be parametrized indirectly in order to generate the
+ authorizations with valid signers using `pre` in this function, and the
+ parametrized value should be a list of addresses.
"""
if not hasattr(request, "param"):
return None
@@ -127,20 +130,24 @@ def tx_data(
intrinsic_gas_data_floor_minimum_delta: int,
) -> Bytes:
"""
- All tests in this file use data that is generated dynamically depending on the case and the
- attributes of the transaction in order to reach the edge cases where the floor gas cost is
- equal or barely greater than the intrinsic gas cost.
+ All tests in this file use data that is generated dynamically depending on
+ the case and the attributes of the transaction in order to reach the edge
+ cases where the floor gas cost is equal or barely greater than the
+ intrinsic gas cost.
We have two different types of tests:
- - FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS: The floor gas cost is less than or equal
- to the intrinsic gas cost, which means that the size of the tokens in the data are not
- enough to trigger the floor gas cost.
- - FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS: The floor gas cost is greater than the intrinsic
- gas cost, which means that the size of the tokens in the data are enough to trigger the
- floor gas cost.
-
- E.g. Given a transaction with a single access list and a single storage key, its intrinsic gas
- cost (as of Prague fork) can be calculated as:
+
+ - FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS: The floor gas cost is
+ less than or equal to the intrinsic gas cost, which means that the size
+ of the tokens in the data are not enough to trigger the floor gas cost.
+
+ - FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS: The floor gas cost is greater
+ than the intrinsic gas cost, which means that the size of the tokens in
+ the data are enough to trigger the floor gas cost.
+
+ E.g. Given a transaction with a single access list and a single storage
+ key, its intrinsic gas cost (as of Prague fork) can be calculated as:
+
- 21,000 gas for the transaction
- 2,400 gas for the access list
- 1,900 gas for the storage key
@@ -152,18 +159,19 @@ def tx_data(
- 40 gas for each non-zero byte in the data
- 10 gas for each zero byte in the data
- Notice that the data included in the transaction affects both the intrinsic gas cost and the
- floor data cost, but at different rates.
+ Notice that the data included in the transaction affects both the intrinsic
+ gas cost and the floor data cost, but at different rates.
- The purpose of this function is to find the exact amount of data where the floor data gas
- cost starts exceeding the intrinsic gas cost.
+ The purpose of this function is to find the exact amount of data where the
+ floor data gas cost starts exceeding the intrinsic gas cost.
- After a binary search we find that adding 717 tokens of data (179 non-zero bytes +
- 1 zero byte) triggers the floor gas cost.
+ After a binary search we find that adding 717 tokens of data (179 non-zero
+ bytes + 1 zero byte) triggers the floor gas cost.
- Therefore, this function will return a Bytes object with 179 non-zero bytes and 1 zero byte
- for `FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS` and a Bytes object with 179 non-zero bytes
- and no zero bytes for `FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS`
+ Therefore, this function will return a Bytes object with 179 non-zero bytes
+ and 1 zero byte for `FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS` and a Bytes
+ object with 179 non-zero bytes and no zero bytes for
+ `FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS`
"""
def tokens_to_data(tokens: int) -> Bytes:
@@ -188,11 +196,11 @@ def transaction_intrinsic_cost_calculator(tokens: int) -> int:
def transaction_data_floor_cost_calculator(tokens: int) -> int:
return fork_data_floor_cost_calculator(data=tokens_to_data(tokens))
- # Start with zero data and check the difference in the gas calculator between the
- # intrinsic gas cost and the floor gas cost.
+ # Start with zero data and check the difference in the gas calculator
+ # between the intrinsic gas cost and the floor gas cost.
if transaction_data_floor_cost_calculator(0) >= transaction_intrinsic_cost_calculator(0):
- # Special case which is a transaction with no extra intrinsic gas costs other than the
- # data cost, any data will trigger the floor gas cost.
+ # Special case which is a transaction with no extra intrinsic gas costs
+ # other than the data cost, any data will trigger the floor gas cost.
if data_test_type == DataTestType.FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS:
return Bytes(b"")
else:
@@ -213,13 +221,15 @@ def tx_gas_delta() -> int:
"""
Gas delta to modify the gas amount included with the transaction.
- If negative, the transaction will be invalid because the intrinsic gas cost is greater than the
- gas limit.
+ If negative, the transaction will be invalid because the intrinsic gas cost
+ is greater than the gas limit.
- This value operates regardless of whether the floor data gas cost is reached or not.
+ This value operates regardless of whether the floor data gas cost is
+ reached or not.
- If the value is greater than zero, the transaction will also be valid and the test will check
- that transaction processing does not consume more gas than it should.
+ If the value is greater than zero, the transaction will also be valid and
+ the test will check that transaction processing does not consume more gas
+ than it should.
"""
return 0
@@ -258,10 +268,11 @@ def tx_intrinsic_gas_cost_including_floor_data_cost(
"""
Transaction intrinsic gas cost.
- The calculated value takes into account the normal intrinsic gas cost and the floor data gas
- cost if it is greater than the intrinsic gas cost.
+ The calculated value takes into account the normal intrinsic gas cost and
+ the floor data gas cost if it is greater than the intrinsic gas cost.
- In other words, this is the value that is required for the transaction to be valid.
+ In other words, this is the value that is required for the transaction to
+ be valid.
"""
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
return intrinsic_gas_cost_calculator(
@@ -290,7 +301,8 @@ def tx_gas_limit(
"""
Gas limit for the transaction.
- The gas delta is added to the intrinsic gas cost to generate different test scenarios.
+ The gas delta is added to the intrinsic gas cost to generate different test
+ scenarios.
"""
return tx_intrinsic_gas_cost_including_floor_data_cost + tx_gas_delta
diff --git a/tests/eest/prague/eip7623_increase_calldata_cost/helpers.py b/tests/eest/prague/eip7623_increase_calldata_cost/helpers.py
index d4235976c3..fc4f94bd63 100644
--- a/tests/eest/prague/eip7623_increase_calldata_cost/helpers.py
+++ b/tests/eest/prague/eip7623_increase_calldata_cost/helpers.py
@@ -16,16 +16,18 @@ def find_floor_cost_threshold(
intrinsic_gas_cost_calculator: Callable[[int], int],
) -> int:
"""
- Find the minimum amount of tokens that will trigger the floor gas cost, by using a binary
- search and the intrinsic gas cost and floor data calculators.
+ Find the minimum amount of tokens that will trigger the floor gas cost, by
+ using a binary search and the intrinsic gas cost and floor data
+ calculators.
"""
- # Start with 1000 tokens and if the intrinsic gas cost is greater than the floor gas cost,
- # multiply the number of tokens by 2 until it's not.
+ # Start with 1000 tokens and if the intrinsic gas cost is greater than the
+ # floor gas cost, multiply the number of tokens by 2 until it's not.
tokens = 1000
while floor_data_gas_cost_calculator(tokens) < intrinsic_gas_cost_calculator(tokens):
tokens *= 2
- # Binary search to find the minimum number of tokens that will trigger the floor gas cost.
+ # Binary search to find the minimum number of tokens that will trigger the
+ # floor gas cost.
left = 0
right = tokens
while left < right:
@@ -39,7 +41,8 @@ def find_floor_cost_threshold(
if floor_data_gas_cost_calculator(tokens) > intrinsic_gas_cost_calculator(tokens):
tokens -= 1
- # Verify that increasing the tokens by one would always trigger the floor gas cost.
+ # Verify that increasing the tokens by one would always trigger the floor
+ # gas cost.
assert (
floor_data_gas_cost_calculator(tokens) <= intrinsic_gas_cost_calculator(tokens)
) and floor_data_gas_cost_calculator(tokens + 1) > intrinsic_gas_cost_calculator(tokens + 1), (
diff --git a/tests/eest/prague/eip7623_increase_calldata_cost/test_execution_gas.py b/tests/eest/prague/eip7623_increase_calldata_cost/test_execution_gas.py
index c0ef506023..53eb2957b5 100644
--- a/tests/eest/prague/eip7623_increase_calldata_cost/test_execution_gas.py
+++ b/tests/eest/prague/eip7623_increase_calldata_cost/test_execution_gas.py
@@ -1,7 +1,6 @@
"""
-abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623)
- Test execution gas consumption after [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
-""" # noqa: E501
+Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
+"""
from typing import List
@@ -41,7 +40,10 @@ class TestGasConsumption:
@pytest.fixture
def intrinsic_gas_data_floor_minimum_delta(self) -> int:
- """Force a minimum delta in order to have some gas to execute the invalid opcode."""
+ """
+ Force a minimum delta in order to have some gas to execute the invalid
+ opcode.
+ """
return 50_000
@pytest.fixture
@@ -49,7 +51,10 @@ def to(
self,
pre: Alloc,
) -> Address | None:
- """Return a contract that consumes all gas when executed by calling an invalid opcode."""
+ """
+ Return a contract that consumes all gas when executed by calling an
+ invalid opcode.
+ """
return pre.deploy_contract(Op.INVALID)
@pytest.mark.parametrize(
@@ -78,7 +83,10 @@ def test_full_gas_consumption(
pre: Alloc,
tx: Transaction,
) -> None:
- """Test executing a transaction that fully consumes its execution gas allocation."""
+ """
+ Test executing a transaction that fully consumes its execution gas
+ allocation.
+ """
tx.expected_receipt = TransactionReceipt(gas_used=tx.gas_limit)
state_test(
pre=pre,
@@ -136,8 +144,8 @@ def to(
@pytest.mark.parametrize(
"tx_gas_delta",
[
- # Test with exact gas and extra gas, to verify that the refund is correctly applied
- # to the full consumed execution gas.
+ # Test with exact gas and extra gas, to verify that the refund is
+ # correctly applied to the full consumed execution gas.
pytest.param(0, id="exact_gas"),
],
)
@@ -148,7 +156,9 @@ def test_gas_consumption_below_data_floor(
tx: Transaction,
tx_floor_data_cost: int,
) -> None:
- """Test executing a transaction that almost consumes the floor data cost."""
+ """
+ Test executing a transaction that almost consumes the floor data cost.
+ """
tx.expected_receipt = TransactionReceipt(gas_used=tx_floor_data_cost)
state_test(
pre=pre,
diff --git a/tests/eest/prague/eip7623_increase_calldata_cost/test_refunds.py b/tests/eest/prague/eip7623_increase_calldata_cost/test_refunds.py
index 10781bb9e0..94908fdf0d 100644
--- a/tests/eest/prague/eip7623_increase_calldata_cost/test_refunds.py
+++ b/tests/eest/prague/eip7623_increase_calldata_cost/test_refunds.py
@@ -1,7 +1,6 @@
"""
-abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623)
- Test applied refunds for [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
-""" # noqa: E501
+Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
+"""
from enum import Enum, Flag, auto
from typing import Dict, List
@@ -35,18 +34,16 @@ class RefundTestType(Enum):
EXECUTION_GAS_MINUS_REFUND_GREATER_THAN_DATA_FLOOR = 0
"""
- The execution gas minus the refund is greater than the data floor, hence the execution gas cost
- is charged.
+ The execution gas minus the refund is greater than the data floor, hence
+ the execution gas cost is charged.
"""
EXECUTION_GAS_MINUS_REFUND_LESS_THAN_DATA_FLOOR = 1
"""
- The execution gas minus the refund is less than the data floor, hence the data floor cost is
- charged.
+ The execution gas minus the refund is less than the data floor, hence the
+ data floor cost is charged.
"""
EXECUTION_GAS_MINUS_REFUND_EQUAL_TO_DATA_FLOOR = 2
- """
- The execution gas minus the refund is equal to the data floor.
- """
+ """The execution gas minus the refund is equal to the data floor."""
class RefundType(Flag):
@@ -56,7 +53,10 @@ class RefundType(Flag):
"""The storage is cleared from a non-zero value."""
AUTHORIZATION_EXISTING_AUTHORITY = auto()
- """The authorization list contains an authorization where the authority exists in the state."""
+ """
+ The authorization list contains an authorization where the authority exists
+ in the state.
+ """
@pytest.fixture
@@ -67,7 +67,10 @@ def data_test_type() -> DataTestType:
@pytest.fixture
def authorization_list(pre: Alloc, refund_type: RefundType) -> List[AuthorizationTuple] | None:
- """Modify fixture from conftest to automatically read the refund_type information."""
+ """
+ Modify fixture from conftest to automatically read the refund_type
+ information.
+ """
if RefundType.AUTHORIZATION_EXISTING_AUTHORITY not in refund_type:
return None
return [AuthorizationTuple(signer=pre.fund_eoa(1), address=Address(1))]
@@ -75,7 +78,10 @@ def authorization_list(pre: Alloc, refund_type: RefundType) -> List[Authorizatio
@pytest.fixture
def ty(refund_type: RefundType) -> int:
- """Modify fixture from conftest to automatically read the refund_type information."""
+ """
+ Modify fixture from conftest to automatically read the refund_type
+ information.
+ """
if RefundType.AUTHORIZATION_EXISTING_AUTHORITY in refund_type:
return 4
return 2
@@ -125,8 +131,8 @@ def code_storage(refund_type: RefundType) -> Dict:
@pytest.fixture
def contract_creating_tx() -> bool:
"""
- Override fixture in order to avoid a circular fixture dependency since
- none of these tests are contract creating transactions.
+ Override fixture in order to avoid a circular fixture dependency since none
+ of these tests are contract creating transactions.
"""
return False
@@ -137,12 +143,14 @@ def intrinsic_gas_data_floor_minimum_delta() -> int:
Induce a minimum delta between the transaction intrinsic gas cost and the
floor data gas cost.
- Since at least one of the cases requires some execution gas expenditure (SSTORE clearing),
- we need to introduce an increment of the floor data cost above the transaction intrinsic gas
- cost, otherwise the floor data cost would always be the below the execution gas cost even
- after the refund is applied.
+ Since at least one of the cases requires some execution gas expenditure
+ (SSTORE clearing), we need to introduce an increment of the floor data cost
+ above the transaction intrinsic gas cost, otherwise the floor data cost
+ would always be the below the execution gas cost even after the refund is
+ applied.
- This value has been set as of Prague and should be adjusted if the gas costs change.
+ This value has been set as of Prague and should be adjusted if the gas
+ costs change.
"""
return 250
@@ -160,10 +168,11 @@ def execution_gas_used(
This gas amount is on top of the transaction intrinsic gas cost.
- If this value were zero it would result in the refund being applied to the execution gas cost
- and the resulting amount being always below the floor data cost, hence we need to find a
- higher value in this function to ensure we get both scenarios where the refund drives
- the execution cost below the floor data cost and above the floor data cost.
+ If this value were zero it would result in the refund being applied to the
+ execution gas cost and the resulting amount being always below the floor
+ data cost, hence we need to find a higher value in this function to ensure
+ we get both scenarios where the refund drives the execution cost below the
+ floor data cost and above the floor data cost.
"""
def execution_gas_cost(execution_gas: int) -> int:
@@ -177,7 +186,8 @@ def execution_gas_cost(execution_gas: int) -> int:
"test to fail. Try increasing the intrinsic_gas_data_floor_minimum_delta fixture."
)
- # Dumb for-loop to find the execution gas cost that will result in the expected refund.
+ # Dumb for-loop to find the execution gas cost that will result in the
+ # expected refund.
while execution_gas_cost(execution_gas) < tx_floor_data_cost:
execution_gas += 1
if refund_test_type == RefundTestType.EXECUTION_GAS_MINUS_REFUND_EQUAL_TO_DATA_FLOOR:
@@ -212,7 +222,8 @@ def to(
"""
Return a contract that consumes the expected execution gas.
- At the moment we naively use JUMPDEST to consume the gas, which can yield very big contracts.
+ At the moment we naively use JUMPDEST to consume the gas, which can yield
+ very big contracts.
Ideally, we can use memory expansion to consume gas.
"""
@@ -232,7 +243,8 @@ def tx_gas_limit(
"""
Gas limit for the transaction.
- The gas delta is added to the intrinsic gas cost to generate different test scenarios.
+ The gas delta is added to the intrinsic gas cost to generate different test
+ scenarios.
"""
tx_gas_limit = tx_intrinsic_gas_cost_before_execution + execution_gas_used
assert tx_gas_limit >= tx_intrinsic_gas_cost_including_floor_data_cost
@@ -265,7 +277,10 @@ def test_gas_refunds_from_data_floor(
refund: int,
refund_test_type: RefundTestType,
) -> None:
- """Test gas refunds deducted from the execution gas cost and not the data floor."""
+ """
+ Test gas refunds deducted from the execution gas cost and not the data
+ floor.
+ """
gas_used = tx_intrinsic_gas_cost_before_execution + execution_gas_used - refund
if refund_test_type == RefundTestType.EXECUTION_GAS_MINUS_REFUND_LESS_THAN_DATA_FLOOR:
assert gas_used < tx_floor_data_cost
@@ -278,17 +293,17 @@ def test_gas_refunds_from_data_floor(
if gas_used < tx_floor_data_cost:
gas_used = tx_floor_data_cost
# This is the actual test verification:
- # - During test filling, the receipt returned by the transition tool (t8n) is verified against
- # the expected receipt.
- # - During test consumption, this is reflected in the balance difference and the state
- # root.
+ # - During test filling, the receipt returned by the transition tool
+ # (t8n) is verified against the expected receipt.
+ # - During test consumption, this is reflected in the balance difference
+ # and the state root.
tx.expected_receipt = TransactionReceipt(gas_used=gas_used)
state_test(
pre=pre,
post={
tx.to: {
- # Verify that the storage was cleared (for storage clear refund).
- # See `code_storage` fixture for more details.
+ # Verify that the storage was cleared (for storage clear
+ # refund). See `code_storage` fixture for more details.
"storage": {0: 0},
}
},
diff --git a/tests/eest/prague/eip7623_increase_calldata_cost/test_transaction_validity.py b/tests/eest/prague/eip7623_increase_calldata_cost/test_transaction_validity.py
index 27457fc328..dba9565f94 100644
--- a/tests/eest/prague/eip7623_increase_calldata_cost/test_transaction_validity.py
+++ b/tests/eest/prague/eip7623_increase_calldata_cost/test_transaction_validity.py
@@ -1,7 +1,6 @@
"""
-abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623)
- Test transaction validity on [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
-""" # noqa: E501
+Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623).
+"""
import pytest
@@ -33,8 +32,9 @@
pytest.mark.parametrize(
"tx_gas_delta",
[
- # Test the case where the included gas is greater than the intrinsic gas to verify that
- # the data floor does not consume more gas than it should.
+ # Test the case where the included gas is greater than the
+ # intrinsic gas to verify that the data floor does not consume more
+ # gas than it should.
pytest.param(1, id="extra_gas"),
pytest.param(0, id="exact_gas"),
pytest.param(-1, id="insufficient_gas", marks=pytest.mark.exception_test),
@@ -81,7 +81,10 @@ def test_transaction_validity_type_0(
pre: Alloc,
tx: Transaction,
) -> None:
- """Test transaction validity for transactions without access lists and contract creation."""
+ """
+ Test transaction validity for transactions without access lists and
+ contract creation.
+ """
state_test(
pre=pre,
post={},
@@ -143,7 +146,10 @@ def test_transaction_validity_type_1_type_2(
pre: Alloc,
tx: Transaction,
) -> None:
- """Test transaction validity for transactions with access lists and contract creation."""
+ """
+ Test transaction validity for transactions with access lists and contract
+ creation.
+ """
state_test(
pre=pre,
post={},
@@ -188,9 +194,9 @@ def test_transaction_validity_type_1_type_2(
],
)
@pytest.mark.parametrize(
- # Blobs don't really have an effect because the blob gas does is not considered in the
- # intrinsic gas calculation, but we still test it to make sure that the transaction is
- # correctly processed.
+ # Blobs don't really have an effect because the blob gas does is not
+ # considered in the intrinsic gas calculation, but we still test it to make
+ # sure that the transaction is correctly processed.
"blob_versioned_hashes",
[
pytest.param(
@@ -219,8 +225,8 @@ def test_transaction_validity_type_3(
tx: Transaction,
) -> None:
"""
- Test transaction validity for transactions with access lists, blobs,
- but no contract creation.
+ Test transaction validity for transactions with access lists, blobs, but no
+ contract creation.
"""
state_test(
pre=pre,
@@ -289,8 +295,8 @@ def test_transaction_validity_type_4(
tx: Transaction,
) -> None:
"""
- Test transaction validity for transactions with access lists, authorization lists, but no
- contract creation.
+ Test transaction validity for transactions with access lists, authorization
+ lists, but no contract creation.
"""
state_test(
pre=pre,
diff --git a/tests/eest/prague/eip7685_general_purpose_el_requests/conftest.py b/tests/eest/prague/eip7685_general_purpose_el_requests/conftest.py
index 1d347199a7..03fa406f0d 100644
--- a/tests/eest/prague/eip7685_general_purpose_el_requests/conftest.py
+++ b/tests/eest/prague/eip7685_general_purpose_el_requests/conftest.py
@@ -29,7 +29,10 @@
def block_body_override_requests(
request: pytest.FixtureRequest,
) -> List[DepositRequest | WithdrawalRequest | ConsolidationRequest] | None:
- """List of requests that overwrite the requests in the header. None by default."""
+ """
+ List of requests that overwrite the requests in the header. None by
+ default.
+ """
if hasattr(request, "param"):
return request.param
return None
@@ -38,9 +41,9 @@ def block_body_override_requests(
@pytest.fixture
def correct_requests_hash_in_header() -> bool:
"""
- Whether to include the correct requests hash in the header so the calculated
- block hash is correct, even though the requests in the new payload parameters might
- be wrong.
+ Whether to include the correct requests hash in the header so the
+ calculated block hash is correct, even though the requests in the new
+ payload parameters might be wrong.
"""
return False
diff --git a/tests/eest/prague/eip7685_general_purpose_el_requests/spec.py b/tests/eest/prague/eip7685_general_purpose_el_requests/spec.py
index 414e47d290..758fe93076 100644
--- a/tests/eest/prague/eip7685_general_purpose_el_requests/spec.py
+++ b/tests/eest/prague/eip7685_general_purpose_el_requests/spec.py
@@ -1,7 +1,8 @@
"""
Common procedures to test
-[EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685).
-""" # noqa: E501
+[EIP-7685: General purpose execution
+layer requests](https://eips.ethereum.org/EIPS/eip-7685).
+"""
from dataclasses import dataclass
diff --git a/tests/eest/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py b/tests/eest/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py
index d11e62cffd..382b1cb404 100644
--- a/tests/eest/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py
+++ b/tests/eest/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py
@@ -1,8 +1,9 @@
"""
-abstract: Tests [EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685)
- Cross testing for withdrawal and deposit request for [EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685).
+Tests EIP-7685 General purpose execution layer requests.
-""" # noqa: E501
+Cross testing for withdrawal and deposit request for
+[EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685).
+"""
from itertools import permutations
from typing import Callable, Dict, Generator, List, Tuple
@@ -299,7 +300,8 @@ def get_contract_permutations(n: int = 3) -> Generator[ParameterSet, None, None]
[
single_consolidation_from_contract(0),
single_consolidation_from_contract(1),
- # the following performs single_withdrawal_from_contract(0) to (16)
+ # the following performs single_withdrawal_from_contract(0) to
+ # (16)
*[
single_withdrawal_from_contract(i)
for i in range(
@@ -307,10 +309,10 @@ def get_contract_permutations(n: int = 3) -> Generator[ParameterSet, None, None]
16,
)
],
- # single_withdrawal_from_contract(16) not allowed cuz only
- # 16 MAX WITHDRAWALS PER BLOCK (EIP-7002)
- #
- # the following performs single_deposit_from_contract(0) to (18)
+ # single_withdrawal_from_contract(16) not allowed cuz only 16
+ # MAX WITHDRAWALS PER BLOCK (EIP-7002)
+ # the following performs single_deposit_from_contract(0) to
+ # (18)
*[
single_deposit_from_contract(i)
for i in range(
@@ -354,8 +356,8 @@ def test_valid_multi_type_request_from_same_tx(
fork: Fork,
):
"""
- Test making a deposit to the beacon chain deposit contract and a withdrawal in
- the same tx.
+ Test making a deposit to the beacon chain deposit contract and a withdrawal
+ in the same tx.
"""
withdrawal_request_fee: int = 1
consolidation_request_fee: int = 1
@@ -440,8 +442,9 @@ def invalid_requests_block_combinations(
"""
Return a list of invalid request combinations for the given fork.
- In the event of a new request type, the `all_request_types` dictionary should be updated
- with the new request type and its corresponding request-generating transaction.
+ In the event of a new request type, the `all_request_types` dictionary
+ should be updated with the new request type and its corresponding
+ request-generating transaction.
Returned parameters are: requests, block_body_override_requests, exception
"""
@@ -474,9 +477,10 @@ def func(fork: Fork) -> List[ParameterSet]:
expected_exceptions: List[BlockException] = [BlockException.INVALID_REQUESTS]
if correct_requests_hash_in_header:
- # The client also might reject the block with an invalid-block-hash error because it
- # might convert the requests in the new payload parameters to the requests hash in the
- # header and compare it with the block hash.
+ # The client also might reject the block with an invalid-block-hash
+ # error because it might convert the requests in the new payload
+ # parameters to the requests hash in the header and compare it with
+ # the block hash.
expected_exceptions.append(BlockException.INVALID_BLOCK_HASH)
# - Empty requests list with invalid hash
@@ -485,8 +489,10 @@ def func(fork: Fork) -> List[ParameterSet]:
[],
[
bytes([i]) for i in range(fork.max_request_type() + 1)
- ], # Using empty requests, calculate the hash using an invalid calculation method:
- # sha256(sha256(b"\0") ++ sha256(b"\1") ++ sha256(b"\2") ++ ...)
+ ], # Using empty requests, calculate the hash using an invalid
+ # calculation method:
+ # sha256(sha256(b"\0") ++ sha256(b"\1") ++ sha256(b"\2") ++
+ # ...)
expected_exceptions,
id="no_requests_and_invalid_hash_calculation_method",
),
@@ -494,7 +500,8 @@ def func(fork: Fork) -> List[ParameterSet]:
[],
[
bytes([]) for _ in range(fork.max_request_type() + 1)
- ], # Using empty requests, calculate the hash using an invalid calculation method:
+ ], # Using empty requests, calculate the hash using an invalid
+ # calculation method:
# sha256(sha256(b"") ++ sha256(b"") ++ sha256(b"") ++ ...)
expected_exceptions,
id="no_requests_and_invalid_hash_calculation_method_2",
@@ -507,9 +514,8 @@ def func(fork: Fork) -> List[ParameterSet]:
[
pytest.param(
[eoa_request],
- [
- block_request
- ], # The request type byte missing because we need to use `Requests`
+ [block_request], # The request type byte missing because we need to
+ # use `Requests`
expected_exceptions,
id=f"single_{request_type}_missing_type_byte",
),
@@ -636,10 +642,11 @@ def test_invalid_multi_type_requests(
"""
Negative testing for all request types in the same block.
- In these tests, the requests hash in the header reflects what's received in the parameters
- portion of the `engine_newPayloadVX` call, so the block hash calculation might pass if
- a client copies the info received verbatim, but block validation must fail after
- the block is executed (via RLP or Engine API).
+ In these tests, the requests hash in the header reflects what's received in
+ the parameters portion of the `engine_newPayloadVX` call, so the block hash
+ calculation might pass if a client copies the info received verbatim, but
+ block validation must fail after the block is executed (via RLP or Engine
+ API).
"""
blockchain_test(
genesis_environment=Environment(),
@@ -665,26 +672,26 @@ def test_invalid_multi_type_requests_engine(
blocks: List[Block],
):
"""
- Negative testing for all request types in the same block with incorrect parameters
- in the Engine API new payload parameters, but with the correct requests hash in the header
- so the block hash is correct.
-
- In these tests, the requests hash in the header reflects what's actually in the executed block,
- so the block might execute properly if the client ignores the requests in the new payload
- parameters.
-
- Note that the only difference between the engine version produced by this test and
- the ones produced by `test_invalid_multi_type_requests` is the
- `blockHash` value in the new payloads, which is calculated using different request hashes
- for each test, but since the request hash is not a value that is included in the payload,
- it might not be immediately apparent.
-
- Also these tests would not fail if the block is imported via RLP (syncing from a peer),
- so we only generate the BlockchainTestEngine for them.
-
- The client also might reject the block with an invalid-block-hash error because it might
- convert the requests in the new payload parameters to the requests hash in the header
- and compare it with the block hash.
+ Negative testing for all request types in the same block with incorrect
+ parameters in the Engine API new payload parameters, but with the correct
+ requests hash in the header so the block hash is correct.
+
+ In these tests, the requests hash in the header reflects what's actually in
+ the executed block, so the block might execute properly if the client
+ ignores the requests in the new payload parameters.
+
+ Note that the only difference between the engine version produced by this
+ test and the ones produced by `test_invalid_multi_type_requests` is the
+ `blockHash` value in the new payloads, which is calculated using different
+ request hashes for each test, but since the request hash is not a value
+ that is included in the payload, it might not be immediately apparent.
+
+ Also these tests would not fail if the block is imported via RLP (syncing
+ from a peer), so we only generate the BlockchainTestEngine for them.
+
+ The client also might reject the block with an invalid-block-hash error
+ because it might convert the requests in the new payload parameters to the
+ requests hash in the header and compare it with the block hash.
"""
blockchain_test(
genesis_environment=Environment(),
diff --git a/tests/eest/prague/eip7702_set_code_tx/helpers.py b/tests/eest/prague/eip7702_set_code_tx/helpers.py
index 83bd4eb91b..8cc2194029 100644
--- a/tests/eest/prague/eip7702_set_code_tx/helpers.py
+++ b/tests/eest/prague/eip7702_set_code_tx/helpers.py
@@ -1,12 +1,15 @@
-"""Helper types, functions and classes for testing EIP-7702 Set Code Transaction."""
+"""
+Helper types, functions and classes for testing EIP-7702 Set Code Transaction.
+"""
from enum import Enum, auto
class AddressType(Enum):
"""
- Different types of addresses used to specify the type of authority that signs an authorization,
- and the type of address to which the authority authorizes to set the code to.
+ Different types of addresses used to specify the type of authority that
+ signs an authorization, and the type of address to which the authority
+ authorizes to set the code to.
"""
EMPTY_ACCOUNT = auto()
diff --git a/tests/eest/prague/eip7702_set_code_tx/test_calls.py b/tests/eest/prague/eip7702_set_code_tx/test_calls.py
index 4bd038293c..54de197656 100644
--- a/tests/eest/prague/eip7702_set_code_tx/test_calls.py
+++ b/tests/eest/prague/eip7702_set_code_tx/test_calls.py
@@ -13,7 +13,7 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
pytestmark = pytest.mark.valid_from("Prague")
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7702.md"
diff --git a/tests/eest/prague/eip7702_set_code_tx/test_gas.py b/tests/eest/prague/eip7702_set_code_tx/test_gas.py
index f37e43a523..48b5cc0831 100644
--- a/tests/eest/prague/eip7702_set_code_tx/test_gas.py
+++ b/tests/eest/prague/eip7702_set_code_tx/test_gas.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests related to gas of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702)
- Tests related to gas of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702).
-""" # noqa: E501
+Tests related to gas of set-code transactions from EIP-7702.
+
+Tests related to gas of set-code transactions from
+[EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702).
+"""
from dataclasses import dataclass
from enum import Enum, auto
@@ -43,7 +45,10 @@
class SignerType(Enum):
- """Different cases of authorization lists for testing gas cost of set-code transactions."""
+ """
+ Different cases of authorization lists for testing gas cost of set-code
+ transactions.
+ """
SINGLE_SIGNER = auto()
MULTIPLE_SIGNERS = auto()
@@ -59,7 +64,10 @@ class AuthorizationInvalidityType(Enum):
class AccessListType(Enum):
- """Different cases of access lists for testing gas cost of set-code transactions."""
+ """
+ Different cases of access lists for testing gas cost of set-code
+ transactions.
+ """
EMPTY = auto()
CONTAINS_AUTHORITY = auto()
@@ -75,8 +83,8 @@ def contains_authority(self) -> bool:
def contains_set_code_address(self) -> bool:
"""
- Return True if the access list contains the address to which the authority authorizes to
- set the code to.
+ Return True if the access list contains the address to which the
+ authority authorizes to set the code to.
"""
return self in {
AccessListType.CONTAINS_SET_CODE_ADDRESS,
@@ -92,21 +100,21 @@ class AuthorityWithProperties:
"""Dataclass to hold the properties of the authority address."""
authority: EOA
- """
- The address of the authority to be used in the transaction.
- """
+ """The address of the authority to be used in the transaction."""
address_type: AddressType
- """
- The type of the address the authority was before the authorization.
- """
+ """The type of the address the authority was before the authorization."""
invalidity_type: AuthorizationInvalidityType | None
"""
- Whether the authorization will be invalid and if so, which type of invalidity it is.
+ Whether the authorization will be invalid and if so, which type of
+ invalidity it is.
"""
@property
def empty(self) -> bool:
- """Return True if the authority address is an empty account before the authorization."""
+ """
+ Return True if the authority address is an empty account before the
+ authorization.
+ """
return self.address_type == AddressType.EMPTY_ACCOUNT
@@ -189,28 +197,29 @@ class AuthorizationWithProperties:
"""Dataclass to hold the properties of the authorization list."""
tuple: AuthorizationTuple
- """
- The authorization tuple to be used in the transaction.
- """
+ """The authorization tuple to be used in the transaction."""
invalidity_type: AuthorizationInvalidityType | None
"""
- Whether the authorization is invalid and if so, which type of invalidity it is.
+ Whether the authorization is invalid and if so, which type of invalidity it
+ is.
"""
authority_type: AddressType
- """
- The type of the address the authority was before the authorization.
- """
+ """The type of the address the authority was before the authorization."""
skip: bool
"""
- Whether the authorization should be skipped and therefore not included in the transaction.
+ Whether the authorization should be skipped and therefore not included in
+ the transaction.
- Used for tests where the authorization was already in the state before the transaction was
- created.
+ Used for tests where the authorization was already in the state before the
+ transaction was created.
"""
@property
def empty(self) -> bool:
- """Return True if the authority address is an empty account before the authorization."""
+ """
+ Return True if the authority address is an empty account before the
+ authorization.
+ """
return self.authority_type == AddressType.EMPTY_ACCOUNT
@@ -227,14 +236,17 @@ def authorization_list_with_properties(
self_sponsored: bool,
re_authorize: bool,
) -> List[AuthorizationWithProperties]:
- """Fixture to return the authorization-list-with-properties for the given case."""
+ """
+ Fixture to return the authorization-list-with-properties for the given
+ case.
+ """
authorization_list: List[AuthorizationWithProperties] = []
environment_chain_id = chain_config.chain_id
match signer_type:
case SignerType.SINGLE_SIGNER:
authority_with_properties = next(authority_iterator)
- # We have to take into account the cases where the nonce has already been increased
- # before the authorization is processed.
+ # We have to take into account the cases where the nonce has
+ # already been increased before the authorization is processed.
increased_nonce = (
self_sponsored
or authority_with_properties.address_type == AddressType.EOA_WITH_SET_CODE
@@ -360,7 +372,10 @@ def authorization_list(
@pytest.fixture()
def authorize_to_address(request: pytest.FixtureRequest, pre: Alloc) -> Address:
- """Fixture to return the address to which the authority authorizes to set the code to."""
+ """
+ Fixture to return the address to which the authority authorizes to set the
+ code to.
+ """
match request.param:
case AddressType.EMPTY_ACCOUNT:
return pre.fund_eoa(0)
@@ -421,14 +436,18 @@ def gas_test_parameter_args(
include_pre_authorized: bool = True,
execution_gas_allowance: bool = False,
):
- """Return the parametrize decorator that can be used in all gas test functions."""
+ """
+ Return the parametrize decorator that can be used in all gas test
+ functions.
+ """
multiple_authorizations_count = 2
defaults = {
"signer_type": SignerType.SINGLE_SIGNER,
"authorization_invalidity_type": None,
"authorizations_count": 1,
- "invalid_authorization_index": -1, # All authorizations are equally invalid
+ "invalid_authorization_index": -1, # All authorizations are equally
+ # invalid
"chain_id_type": ChainIDType.GENERIC,
"authorize_to_address": AddressType.EMPTY_ACCOUNT,
"access_list_case": AccessListType.EMPTY,
@@ -694,7 +713,8 @@ def gas_test_parameter_args(
]
if include_many:
- # Fit as many authorizations as possible within the transaction gas limit.
+ # Fit as many authorizations as possible within the transaction gas
+ # limit.
max_gas = 16_777_216 - 21_000
if execution_gas_allowance:
# Leave some gas for the execution of the test code.
@@ -733,6 +753,7 @@ def gas_test_parameter_args(
@pytest.mark.parametrize(
**gas_test_parameter_args(include_pre_authorized=False, execution_gas_allowance=True)
)
+@pytest.mark.slow()
def test_gas_cost(
state_test: StateTestFiller,
pre: Alloc,
@@ -743,7 +764,10 @@ def test_gas_cost(
access_list: List[AccessList],
sender: EOA,
):
- """Test gas at the execution start of a set-code transaction in multiple scenarios."""
+ """
+ Test gas at the execution start of a set-code transaction in multiple
+ scenarios.
+ """
# Calculate the intrinsic gas cost of the authorizations, by default the
# full empty account cost is charged for each authorization.
intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(
@@ -768,9 +792,10 @@ def test_gas_cost(
Spec.PER_EMPTY_ACCOUNT_COST - Spec.PER_AUTH_BASE_COST
) * discounted_authorizations
- # We calculate the exact gas required to execute the test code.
- # We add SSTORE opcodes in order to make sure that the refund is less than one fifth (EIP-3529)
- # of the total gas used, so we can see the full discount being reflected in most of the tests.
+ # We calculate the exact gas required to execute the test code. We add
+ # SSTORE opcodes in order to make sure that the refund is less than one
+ # fifth (EIP-3529) of the total gas used, so we can see the full discount
+ # being reflected in most of the tests.
gas_costs = fork.gas_costs()
gas_opcode_cost = gas_costs.G_BASE
sstore_opcode_count = 10
@@ -781,8 +806,8 @@ def test_gas_cost(
execution_gas = gas_opcode_cost + push_opcode_cost + sstore_opcode_cost + cold_storage_cost
- # The first opcode that executes in the code is the GAS opcode, which costs 2 gas, so we
- # subtract that from the expected gas measure.
+ # The first opcode that executes in the code is the GAS opcode, which costs
+ # 2 gas, so we subtract that from the expected gas measure.
expected_gas_measure = execution_gas - gas_opcode_cost
test_code_storage = Storage()
@@ -801,7 +826,8 @@ def test_gas_cost(
max_discount = tx_gas_limit // 5
if discount_gas > max_discount:
- # Only one test hits this condition, but it's ok to also test this case.
+ # Only one test hits this condition, but it's ok to also test this
+ # case.
discount_gas = max_discount
gas_used = tx_gas_limit - discount_gas
@@ -841,8 +867,12 @@ def test_account_warming(
sender: EOA,
check_delegated_account_first: bool,
):
- """Test warming of the authority and authorized accounts for set-code transactions."""
- # Overhead cost is the single push operation required for the address to check.
+ """
+ Test warming of the authority and authorized accounts for set-code
+ transactions.
+ """
+ # Overhead cost is the single push operation required for the address to
+ # check.
overhead_cost = 3 * len(Op.CALL.kwargs) # type: ignore
cold_account_cost = 2600
@@ -850,8 +880,8 @@ def test_account_warming(
access_list_addresses = {access_list.address for access_list in access_list}
- # Dictionary to keep track of the addresses to check for warming, and the expected cost of
- # accessing such account.
+ # Dictionary to keep track of the addresses to check for warming, and the
+ # expected cost of accessing such account.
addresses_to_check: Dict[Address, int] = {}
for authorization_with_properties in authorization_list_with_properties:
@@ -861,9 +891,9 @@ def test_account_warming(
authority_contains_delegation_after_authorization = (
authorization_with_properties.invalidity_type is None
- # If the authority already contained a delegation prior to the transaction,
- # even if the authorization is invalid, there will be a delegation when we
- # check the address.
+ # If the authority already contained a delegation prior to the
+ # transaction, even if the authorization is invalid, there will be
+ # a delegation when we check the address.
or authorization_with_properties.authority_type == AddressType.EOA_WITH_SET_CODE
)
@@ -896,8 +926,9 @@ def test_account_warming(
)
if authority_contains_delegation_after_authorization:
- # The double charge for accessing the delegated account, only if the
- # account ends up with a delegation in its code.
+ # The double charge for accessing the delegated account,
+ # only if the account ends up with a delegation in its
+ # code.
access_cost += warm_account_cost
addresses_to_check[authority] = access_cost
@@ -920,8 +951,8 @@ def test_account_warming(
access_cost = warm_account_cost
if (
- # We can only charge the delegated account access cost if the authorization
- # went through
+ # We can only charge the delegated account access cost if
+ # the authorization went through
authority_contains_delegation_after_authorization
):
if (
@@ -959,7 +990,7 @@ def test_account_warming(
callee_code += Op.STOP
callee_address = pre.deploy_contract(
callee_code,
- storage={check_address: 0xDEADBEEF for check_address in addresses_to_check},
+ storage=dict.fromkeys(addresses_to_check, 0xDEADBEEF),
)
tx = Transaction(
@@ -999,8 +1030,8 @@ def test_intrinsic_gas_cost(
valid: bool,
):
"""
- Test sending a transaction with the exact intrinsic gas required and also insufficient
- gas.
+ Test sending a transaction with the exact intrinsic gas required and also
+ insufficient gas.
"""
# Calculate the intrinsic gas cost of the authorizations, by default the
# full empty account cost is charged for each authorization.
@@ -1097,7 +1128,9 @@ def test_call_to_pre_authorized_oog(
fork: Fork,
call_opcode: Op,
):
- """Test additional cost of delegation contract access in call instructions."""
+ """
+ Test additional cost of delegation contract access in call instructions.
+ """
# Delegation contract. It should never be reached by a call.
delegation_code = Op.SSTORE(0, 1)
delegation = pre.deploy_contract(delegation_code)
diff --git a/tests/eest/prague/eip7702_set_code_tx/test_invalid_tx.py b/tests/eest/prague/eip7702_set_code_tx/test_invalid_tx.py
index 75067b08a9..4855a73823 100644
--- a/tests/eest/prague/eip7702_set_code_tx/test_invalid_tx.py
+++ b/tests/eest/prague/eip7702_set_code_tx/test_invalid_tx.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests invalid set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702)
- Tests invalid set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702).
-""" # noqa: E501
+Tests invalid set-code transactions from EIP-7702.
+
+Tests invalid set-code transactions from
+[EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702).
+"""
from enum import Enum, auto
from typing import List, Type
@@ -102,7 +104,10 @@ def test_invalid_auth_signature(
s: int,
delegate_address: Address,
):
- """Test sending a transaction where one of the signature elements is out of range."""
+ """
+ Test sending a transaction where one of the signature elements is out of
+ range.
+ """
tx = Transaction(
gas_limit=100_000,
to=0,
@@ -150,8 +155,8 @@ def test_invalid_tx_invalid_auth_chain_id(
delegate_address: Address,
):
"""
- Test sending a transaction where the chain id field of an authorization overflows the
- maximum value.
+ Test sending a transaction where the chain id field of an authorization
+ overflows the maximum value.
"""
authorization = AuthorizationTuple(
address=delegate_address,
@@ -193,8 +198,8 @@ def test_invalid_tx_invalid_auth_chain_id_encoding(
auth_chain_id: int,
):
"""
- Test sending a transaction where the chain id field of an authorization has an incorrect
- encoding.
+ Test sending a transaction where the chain id field of an authorization has
+ an incorrect encoding.
"""
class ModifiedAuthorizationTuple(AuthorizationTuple):
@@ -243,8 +248,8 @@ def test_invalid_tx_invalid_nonce(
delegate_address: Address,
):
"""
- Test sending a transaction where the nonce field of an authorization overflows the maximum
- value.
+ Test sending a transaction where the nonce field of an authorization
+ overflows the maximum value.
"""
auth_signer = pre.fund_eoa()
@@ -291,8 +296,8 @@ def test_invalid_tx_invalid_nonce_as_list(
delegate_address: Address,
):
"""
- Test sending a transaction where the nonce field of an authorization overflows the maximum
- value.
+ Test sending a transaction where the nonce field of an authorization
+ overflows the maximum value.
"""
auth_signer = pre.fund_eoa()
@@ -333,8 +338,8 @@ def test_invalid_tx_invalid_nonce_encoding(
delegate_address: Address,
):
"""
- Test sending a transaction where the chain id field of an authorization has an incorrect
- encoding.
+ Test sending a transaction where the chain id field of an authorization has
+ an incorrect encoding.
"""
class ModifiedAuthorizationTuple(AuthorizationTuple):
@@ -391,8 +396,8 @@ def test_invalid_tx_invalid_address(
address_type: Type[FixedSizeBytes],
):
"""
- Test sending a transaction where the address field of an authorization is incorrectly
- serialized.
+ Test sending a transaction where the address field of an authorization is
+ incorrectly serialized.
"""
auth_signer = pre.fund_eoa()
@@ -435,8 +440,8 @@ def test_invalid_tx_invalid_authorization_tuple_extra_element(
extra_element_value: int,
):
"""
- Test sending a transaction where the authorization tuple field of the type-4 transaction
- is serialized to contain an extra element.
+ Test sending a transaction where the authorization tuple field of the
+ type-4 transaction is serialized to contain an extra element.
"""
auth_signer = pre.fund_eoa()
@@ -444,7 +449,9 @@ class ExtraElementAuthorizationTuple(AuthorizationTuple):
extra_element: HexNumber # type: ignore
def get_rlp_fields(self) -> List[str]:
- """Append the extra field to the list of fields to be encoded in RLP."""
+ """
+ Append the extra field to the list of fields to be encoded in RLP.
+ """
rlp_fields = super().get_rlp_fields()[:]
rlp_fields.append("extra_element")
return rlp_fields
@@ -496,8 +503,8 @@ def test_invalid_tx_invalid_authorization_tuple_missing_element(
missing_index: int,
):
"""
- Test sending a transaction where the authorization tuple field of the type-4 transaction
- is serialized to miss one element.
+ Test sending a transaction where the authorization tuple field of the
+ type-4 transaction is serialized to miss one element.
"""
auth_signer = pre.fund_eoa()
@@ -505,7 +512,9 @@ class MissingElementAuthorizationTuple(AuthorizationTuple):
missing_element_index: int
def get_rlp_fields(self) -> List[str]:
- """Remove the field that is specified by the missing element index."""
+ """
+ Remove the field that is specified by the missing element index.
+ """
rlp_fields = super().get_rlp_fields()[:]
rlp_fields.pop(self.missing_element_index)
return rlp_fields
@@ -545,8 +554,9 @@ def test_invalid_tx_invalid_authorization_tuple_encoded_as_bytes(
delegate_address: Address,
):
"""
- Test sending a transaction where the authorization tuple field of the type-4 transaction
- is encoded in the outer element as bytes instead of a list of elements.
+ Test sending a transaction where the authorization tuple field of the
+ type-4 transaction is encoded in the outer element as bytes instead of a
+ list of elements.
"""
class ModifiedTransaction(Transaction):
@@ -595,8 +605,8 @@ def test_invalid_tx_invalid_rlp_encoding(
invalid_rlp_mode: InvalidRLPMode,
):
"""
- Test sending a transaction type-4 where the RLP encoding of the transaction is
- invalid.
+ Test sending a transaction type-4 where the RLP encoding of the transaction
+ is invalid.
"""
auth_signer = pre.fund_eoa()
diff --git a/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs.py b/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs.py
index c8d382cb9a..82409427d0 100644
--- a/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs.py
+++ b/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs.py
@@ -1,7 +1,9 @@
"""
-abstract: Tests use of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702)
- Tests use of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702).
-""" # noqa: E501
+Tests use of set-code transactions from EIP-7702.
+
+Tests use of set-code transactions from
+[EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702).
+"""
from enum import StrEnum
from hashlib import sha256
@@ -88,11 +90,11 @@ def test_self_sponsored_set_code(
"""
Test the executing a self-sponsored set-code transaction.
- The transaction is sent to the sender, and the sender is the signer of the only authorization
- tuple in the authorization list.
+ The transaction is sent to the sender, and the sender is the signer of the
+ only authorization tuple in the authorization list.
- The authorization tuple has a nonce of 1 because the self-sponsored transaction increases the
- nonce of the sender from zero to one first.
+ The authorization tuple has a nonce of 1 because the self-sponsored
+ transaction increases the nonce of the sender from zero to one first.
The expected nonce at the end of the transaction is 2.
"""
@@ -128,7 +130,7 @@ def test_self_sponsored_set_code(
pre=pre,
tx=tx,
post={
- set_code_to_address: Account(storage={k: 0 for k in storage}),
+ set_code_to_address: Account(storage=dict.fromkeys(storage, 0)),
sender: Account(
nonce=2,
code=Spec.delegation_designation(set_code_to_address),
@@ -208,7 +210,7 @@ def test_set_code_to_sstore(
tx=tx,
post={
set_code_to_address: Account(
- storage={k: 0 for k in storage},
+ storage=dict.fromkeys(storage, 0),
),
auth_signer: Account(
nonce=2 if self_sponsored else 1,
@@ -268,7 +270,10 @@ def test_set_code_to_sstore_then_sload(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test the executing a simple SSTORE then SLOAD in two separate set-code transactions."""
+ """
+ Test the executing a simple SSTORE then SLOAD in two separate set-code
+ transactions.
+ """
auth_signer = pre.fund_eoa(auth_account_start_balance)
sender = pre.fund_eoa()
@@ -346,8 +351,8 @@ def test_set_code_to_tstore_reentry(
evm_code_type: EVMCodeType,
):
"""
- Test the executing a simple TSTORE in a set-code transaction, which also performs a
- re-entry to TLOAD the value.
+ Test the executing a simple TSTORE in a set-code transaction, which also
+ performs a re-entry to TLOAD the value.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -403,9 +408,10 @@ def test_set_code_to_tstore_available_at_correct_address(
call_eoa_first: bool,
):
"""
- Test TLOADing from slot 2 and then SSTORE this in slot 1, then TSTORE 3 in slot 2.
- This is done both from the EOA which is delegated to account A, and then A is called.
- The storage should stay empty on both the EOA and the delegated account.
+ Test TLOADing from slot 2 and then SSTORE this in slot 1, then TSTORE 3 in
+ slot 2. This is done both from the EOA which is delegated to account A, and
+ then A is called. The storage should stay empty on both the EOA and the
+ delegated account.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -516,13 +522,16 @@ def test_set_code_to_self_destruct(
@pytest.mark.with_all_create_opcodes
+@pytest.mark.slow()
def test_set_code_to_contract_creator(
state_test: StateTestFiller,
pre: Alloc,
create_opcode: Op,
evm_code_type: EVMCodeType,
):
- """Test the executing a contract-creating opcode in a set-code transaction."""
+ """
+ Test the executing a contract-creating opcode in a set-code transaction.
+ """
storage = Storage()
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -677,8 +686,8 @@ def test_set_code_max_depth_call_stack(
fork: Fork,
):
"""
- Test re-entry to delegated account until the max call stack depth possible in a
- transaction is reached.
+ Test re-entry to delegated account until the max call stack depth possible
+ in a transaction is reached.
"""
storage = Storage()
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -799,8 +808,8 @@ def test_set_code_call_set_code(
pre=pre,
tx=tx,
post={
- set_code_to_address_1: Account(storage={k: 0 for k in storage_1}),
- set_code_to_address_2: Account(storage={k: 0 for k in storage_2}),
+ set_code_to_address_1: Account(storage=dict.fromkeys(storage_1, 0)),
+ set_code_to_address_2: Account(storage=dict.fromkeys(storage_2, 0)),
auth_signer_1: Account(
nonce=1,
code=Spec.delegation_designation(set_code_to_address_1),
@@ -867,7 +876,10 @@ def test_tx_into_self_delegating_set_code(
state_test: StateTestFiller,
pre: Alloc,
):
- """Test a transaction that has entry-point into a set-code account that delegates to itself."""
+ """
+ Test a transaction that has entry-point into a set-code account that
+ delegates to itself.
+ """
auth_signer = pre.fund_eoa(auth_account_start_balance)
tx = Transaction(
@@ -902,8 +914,8 @@ def test_tx_into_chain_delegating_set_code(
pre: Alloc,
):
"""
- Test a transaction that has entry-point into a set-code account that delegates to another
- set-code account.
+ Test a transaction that has entry-point into a set-code account that
+ delegates to another set-code account.
"""
auth_signer_1 = pre.fund_eoa(auth_account_start_balance)
auth_signer_2 = pre.fund_eoa(auth_account_start_balance)
@@ -994,7 +1006,10 @@ def test_call_into_chain_delegating_set_code(
pre: Alloc,
call_opcode: Op,
):
- """Test call into a set-code account that delegates to another set-code account."""
+ """
+ Test call into a set-code account that delegates to another set-code
+ account.
+ """
auth_signer_1 = pre.fund_eoa(auth_account_start_balance)
auth_signer_2 = pre.fund_eoa(auth_account_start_balance)
@@ -1310,8 +1325,8 @@ def test_set_code_address_and_authority_warm_state_call_types(
):
"""
Test set to code address and authority warm status after a call to
- authority address, or vice-versa, using all available call opcodes
- without using `GAS` opcode (unavailable in EOF).
+ authority address, or vice-versa, using all available call opcodes without
+ using `GAS` opcode (unavailable in EOF).
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -1376,7 +1391,10 @@ def test_ext_code_on_self_delegating_set_code(
pre: Alloc,
balance: int,
):
- """Test different ext*code operations on a set-code address that delegates to itself."""
+ """
+ Test different ext*code operations on a set-code address that delegates to
+ itself.
+ """
auth_signer = pre.fund_eoa(balance)
slot = count(1)
@@ -1438,8 +1456,8 @@ def test_ext_code_on_chain_delegating_set_code(
pre: Alloc,
):
"""
- Test different ext*code operations on a set-code address that references another delegated
- address.
+ Test different ext*code operations on a set-code address that references
+ another delegated address.
"""
auth_signer_1_balance = 1
auth_signer_2_balance = 0
@@ -1601,8 +1619,9 @@ def test_set_code_to_account_deployed_in_same_tx(
evm_code_type: EVMCodeType,
):
"""
- Test setting the code of an account to an address that is deployed in the same transaction,
- and test calling the set-code address and the deployed contract.
+ Test setting the code of an account to an address that is deployed in the
+ same transaction, and test calling the set-code address and the deployed
+ contract.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -1720,9 +1739,9 @@ def test_set_code_to_self_destructing_account_deployed_in_same_tx(
balance: int,
):
"""
- Test setting the code of an account to an account that contains the SELFDESTRUCT opcode and
- was deployed in the same transaction, and test calling the set-code address and the deployed
- in both sequence orders.
+ Test setting the code of an account to an account that contains the
+ SELFDESTRUCT opcode and was deployed in the same transaction, and test
+ calling the set-code address and the deployed in both sequence orders.
"""
auth_signer = pre.fund_eoa(balance)
if external_sendall_recipient:
@@ -1812,13 +1831,14 @@ def test_set_code_to_self_destructing_account_deployed_in_same_tx(
)
+@pytest.mark.xdist_group(name="bigmem")
def test_set_code_multiple_first_valid_authorization_tuples_same_signer(
state_test: StateTestFiller,
pre: Alloc,
):
"""
- Test setting the code of an account with multiple authorization tuples
- from the same signer.
+ Test setting the code of an account with multiple authorization tuples from
+ the same signer.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -1859,13 +1879,15 @@ def test_set_code_multiple_first_valid_authorization_tuples_same_signer(
)
+@pytest.mark.xdist_group(name="bigmem")
def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_nonce(
state_test: StateTestFiller,
pre: Alloc,
):
"""
- Test setting the code of an account with multiple authorization tuples from the same signer
- and each authorization tuple has an increasing nonce, therefore the last tuple is executed.
+ Test setting the code of an account with multiple authorization tuples from
+ the same signer and each authorization tuple has an increasing nonce,
+ therefore the last tuple is executed.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -1906,14 +1928,16 @@ def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_non
)
+@pytest.mark.xdist_group(name="bigmem")
def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_nonce_self_sponsored(
state_test: StateTestFiller,
pre: Alloc,
):
"""
- Test setting the code of an account with multiple authorization tuples from the same signer
- and each authorization tuple has an increasing nonce, therefore the last tuple is executed,
- and the transaction is self-sponsored.
+ Test setting the code of an account with multiple authorization tuples from
+ the same signer and each authorization tuple has an increasing nonce,
+ therefore the last tuple is executed, and the transaction is
+ self-sponsored.
"""
auth_signer = pre.fund_eoa()
@@ -1959,8 +1983,8 @@ def test_set_code_multiple_valid_authorization_tuples_first_invalid_same_signer(
pre: Alloc,
):
"""
- Test setting the code of an account with multiple authorization tuples from the same signer
- but the first tuple is invalid.
+ Test setting the code of an account with multiple authorization tuples from
+ the same signer but the first tuple is invalid.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -2001,13 +2025,14 @@ def test_set_code_multiple_valid_authorization_tuples_first_invalid_same_signer(
)
+@pytest.mark.xdist_group(name="bigmem")
def test_set_code_all_invalid_authorization_tuples(
state_test: StateTestFiller,
pre: Alloc,
):
"""
- Test setting the code of an account with multiple authorization tuples from the same signer
- and all of them are invalid.
+ Test setting the code of an account with multiple authorization tuples from
+ the same signer and all of them are invalid.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -2040,12 +2065,16 @@ def test_set_code_all_invalid_authorization_tuples(
)
+@pytest.mark.xdist_group(name="bigmem")
def test_set_code_using_chain_specific_id(
state_test: StateTestFiller,
pre: Alloc,
chain_config: ChainConfig,
):
- """Test sending a transaction to set the code of an account using a chain-specific ID."""
+ """
+ Test sending a transaction to set the code of an account using a
+ chain-specific ID.
+ """
auth_signer = pre.fund_eoa(auth_account_start_balance)
success_slot = 1
@@ -2088,6 +2117,7 @@ def test_set_code_using_chain_specific_id(
SECP256K1N_OVER_2 = SECP256K1N // 2
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"v,r,s",
[
@@ -2107,7 +2137,10 @@ def test_set_code_using_valid_synthetic_signatures(
r: int,
s: int,
):
- """Test sending a transaction to set the code of an account using synthetic signatures."""
+ """
+ Test sending a transaction to set the code of an account using synthetic
+ signatures.
+ """
success_slot = 1
set_code = Op.SSTORE(success_slot, 1) + Op.STOP
@@ -2148,6 +2181,7 @@ def test_set_code_using_valid_synthetic_signatures(
)
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"v,r,s",
[
@@ -2155,8 +2189,10 @@ def test_set_code_using_valid_synthetic_signatures(
pytest.param(2, 1, 1, id="v=2"),
pytest.param(27, 1, 1, id="v=27"), # Type-0 transaction valid value
pytest.param(28, 1, 1, id="v=28"), # Type-0 transaction valid value
- pytest.param(35, 1, 1, id="v=35"), # Type-0 replay-protected transaction valid value
- pytest.param(36, 1, 1, id="v=36"), # Type-0 replay-protected transaction valid value
+ pytest.param(35, 1, 1, id="v=35"), # Type-0 replay-protected
+ # transaction valid value
+ pytest.param(36, 1, 1, id="v=36"), # Type-0 replay-protected
+ # transaction valid value
pytest.param(2**8 - 1, 1, 1, id="v=2**8-1"),
# R
pytest.param(1, 0, 1, id="r=0"),
@@ -2187,8 +2223,9 @@ def test_valid_tx_invalid_auth_signature(
s: int,
):
"""
- Test sending a transaction to set the code of an account using synthetic signatures,
- the transaction is valid but the authorization should not go through.
+ Test sending a transaction to set the code of an account using synthetic
+ signatures, the transaction is valid but the authorization should not go
+ through.
"""
success_slot = 1
@@ -2230,8 +2267,9 @@ def test_signature_s_out_of_range(
chain_config: ChainConfig,
):
"""
- Test sending a transaction with an authorization tuple where the signature s value is out of
- range by modifying its value to be `SECP256K1N - S` and flipping the v value.
+ Test sending a transaction with an authorization tuple where the signature
+ s value is out of range by modifying its value to be `SECP256K1N - S` and
+ flipping the v value.
"""
auth_signer = pre.fund_eoa(0)
@@ -2302,8 +2340,8 @@ def test_valid_tx_invalid_chain_id(
invalid_chain_id_case: InvalidChainID,
):
"""
- Test sending a transaction where the chain id field does not match
- the current chain's id.
+ Test sending a transaction where the chain id field does not match the
+ current chain's id.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -2398,11 +2436,11 @@ def test_nonce_validity(
authorization_nonce: int,
):
"""
- Test sending a transaction where the nonce field of an authorization almost overflows the
- maximum value.
+ Test sending a transaction where the nonce field of an authorization almost
+ overflows the maximum value.
- Also test calling the account of the authorization signer in order to verify that the account
- is not warm.
+ Also test calling the account of the authorization signer in order to
+ verify that the account is not warm.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance, nonce=account_nonce)
@@ -2463,8 +2501,8 @@ def test_nonce_overflow_after_first_authorization(
pre: Alloc,
):
"""
- Test sending a transaction with two authorization where the first one bumps the nonce
- to 2**64-1 and the second would result in overflow.
+ Test sending a transaction with two authorization where the first one bumps
+ the nonce to 2**64-1 and the second would result in overflow.
"""
nonce = 2**64 - 2
auth_signer = pre.fund_eoa(auth_account_start_balance, nonce=nonce)
@@ -2540,7 +2578,10 @@ def test_set_code_to_log(
pre: Alloc,
log_opcode: Op,
):
- """Test setting the code of an account to a contract that performs the log operation."""
+ """
+ Test setting the code of an account to a contract that performs the log
+ operation.
+ """
sender = pre.fund_eoa()
log_kwargs = {}
@@ -2589,7 +2630,7 @@ def test_set_code_to_log(
@pytest.mark.with_all_call_opcodes
@pytest.mark.with_all_precompiles
-@EIPChecklist.Precompile.Test.CallContexts.SetCode(eip=[7951, 7883])
+@EIPChecklist.Precompile.Test.CallContexts.SetCode(eip=[7951, 7883, 7823])
def test_set_code_to_precompile(
state_test: StateTestFiller,
pre: Alloc,
@@ -2597,8 +2638,8 @@ def test_set_code_to_precompile(
call_opcode: Op,
):
"""
- Test setting the code of an account to a pre-compile address and executing all call
- opcodes.
+ Test setting the code of an account to a pre-compile address and executing
+ all call opcodes.
"""
auth_signer = pre.fund_eoa(auth_account_start_balance)
@@ -2656,8 +2697,8 @@ def test_set_code_to_precompile_not_enough_gas_for_precompile_execution(
precompile: int,
):
"""
- Test set code to precompile and making direct call in same transaction with intrinsic gas
- only, no extra gas for precompile execution.
+ Test set code to precompile and making direct call in same transaction with
+ intrinsic gas only, no extra gas for precompile execution.
"""
auth_signer = pre.fund_eoa(amount=1)
auth = AuthorizationTuple(address=Address(precompile), nonce=0, signer=auth_signer)
@@ -2731,10 +2772,12 @@ def test_set_code_to_system_contract(
call_value = 0
- # Setup the initial storage of the account to mimic the system contract if required
+ # Setup the initial storage of the account to mimic the system contract if
+ # required
match system_contract:
case Address(0x00000000219AB540356CBB839CBE05303D7705FA): # EIP-6110
- # Deposit contract needs specific storage values, so we set them on the account
+ # Deposit contract needs specific storage values, so we set them on
+ # the account
auth_signer = pre.fund_eoa(
auth_account_start_balance, storage=deposit_contract_initial_storage()
)
@@ -2781,8 +2824,8 @@ def test_set_code_to_system_contract(
caller_payload = consolidation_request.calldata
call_value = consolidation_request.value
case Address(0x0000F90827F1C53A10CB7A02335B175320002935): # EIP-2935
- # This payload is used to identify the number of blocks to be subtracted from the
- # latest block number
+ # This payload is used to identify the number of blocks to be
+ # subtracted from the latest block number
caller_payload = Hash(1)
caller_code_storage[call_return_data_size_slot] = 32
case _:
@@ -2791,8 +2834,8 @@ def test_set_code_to_system_contract(
# Setup the code to call the system contract
match system_contract:
case Address(0x0000F90827F1C53A10CB7A02335B175320002935): # EIP-2935
- # Do a trick here to get the block number of the penultimate block to ensure it is
- # saved in the history contract
+ # Do a trick here to get the block number of the penultimate block
+ # to ensure it is saved in the history contract
check_block_number = Op.SUB(Op.NUMBER, Op.CALLDATALOAD(0))
call_system_contract_code = Op.MSTORE(0, check_block_number) + Op.SSTORE(
call_return_code_slot,
@@ -2837,7 +2880,8 @@ def test_set_code_to_system_contract(
blocks=[
Block(
txs=txs,
- requests_hash=Requests(), # Verify nothing slipped into the requests trie
+ requests_hash=Requests(), # Verify nothing slipped into the
+ # requests trie
)
],
post={
@@ -2878,7 +2922,10 @@ def test_eoa_tx_after_set_code(
evm_code_type: EVMCodeType,
same_block: bool,
):
- """Test sending a transaction from an EOA after code has been set to the account."""
+ """
+ Test sending a transaction from an EOA after code has been set to the
+ account.
+ """
auth_signer = pre.fund_eoa()
set_code = Op.SSTORE(1, Op.ADD(Op.SLOAD(1), 1)) + Op.STOP
@@ -3138,12 +3185,14 @@ def test_delegation_clearing(
self_sponsored: bool,
):
"""
- Test clearing the delegation of an account under a variety of circumstances.
-
- - pre_set_delegation_code: The code to set on the account before clearing delegation, or None
- if the account should not have any code set.
- - self_sponsored: Whether the delegation clearing transaction is self-sponsored.
-
+ Test clearing the delegation of an account under a variety of
+ circumstances.
+
+ - pre_set_delegation_code: The code to set on the account before clearing
+ delegation, or None if the account should not
+ have any code set.
+ - self_sponsored: Whether the delegation clearing transaction is
+ self-sponsored.
""" # noqa: D417
pre_set_delegation_address: Address | None = None
if pre_set_delegation_code is not None:
@@ -3231,10 +3280,11 @@ def test_delegation_clearing_tx_to(
"""
Tests directly calling the account which delegation is being cleared.
- - pre_set_delegation_code: The code to set on the account before clearing delegation, or None
- if the account should not have any code set.
- - self_sponsored: Whether the delegation clearing transaction is self-sponsored.
-
+ - pre_set_delegation_code: The code to set on the account before clearing
+ delegation, or None if the account should not
+ have any code set.
+ - self_sponsored: Whether the delegation clearing transaction is
+ self-sponsored.
""" # noqa: D417
pre_set_delegation_address: Address | None = None
if pre_set_delegation_code is not None:
@@ -3288,11 +3338,11 @@ def test_delegation_clearing_and_set(
pre_set_delegation_code: Bytecode | None,
):
"""
- Tests clearing and setting the delegation again in the same authorization list.
-
- - pre_set_delegation_code: The code to set on the account before clearing delegation, or None
- if the account should not have any code set.
+ Tests clearing and setting the delegation again in the same authorization
+ list.
+ - pre_set_delegation_code: The code to set on the account before clearing
+ delegation, or None if the account should not have any code set.
""" # noqa: D417
pre_set_delegation_address: Address | None = None
if pre_set_delegation_code is not None:
@@ -3354,7 +3404,10 @@ def test_delegation_clearing_failing_tx(
pre: Alloc,
entry_code: Bytecode,
):
- """Test clearing the delegation of an account in a transaction that fails, OOGs or reverts.""" # noqa: D417
+ """
+ Test clearing the delegation of an account in a transaction that fails,
+ OOGs or reverts.
+ """ # noqa: D417
pre_set_delegation_code = Op.RETURN(0, 1)
pre_set_delegation_address = pre.deploy_contract(pre_set_delegation_code)
@@ -3452,8 +3505,10 @@ def test_creating_delegation_designation_contract(
initcode_is_delegation_designation: bool,
):
"""
- Tx -> create -> pointer bytecode
- Attempt to deploy contract with magic bytes result in no contract being created.
+ Tx -> create -> pointer bytecode.
+
+ Attempt to deploy contract with magic bytes result in no
+ contract being created.
"""
env = Environment()
@@ -3508,6 +3563,7 @@ def test_creating_delegation_designation_contract(
),
],
)
+@pytest.mark.slow()
def test_many_delegations(
state_test: StateTestFiller,
fork: Fork,
@@ -3515,14 +3571,16 @@ def test_many_delegations(
signer_balance: int,
):
"""
- Perform as many delegations as possible in a transaction using the entire block gas limit.
+ Perform as many delegations as possible in a transaction using the entire
+ block gas limit.
Every delegation comes from a different signer.
- The account of can be empty or not depending on the `signer_balance` parameter.
+ The account of can be empty or not depending on the `signer_balance`
+ parameter.
- The transaction is expected to succeed and the state after the transaction is expected to have
- the code of the entry contract set to 1.
+ The transaction is expected to succeed and the state after the transaction
+ is expected to have the code of the entry contract set to 1.
"""
env = Environment()
tx_gas_limit_cap = fork.transaction_gas_limit_cap()
@@ -3580,8 +3638,8 @@ def test_invalid_transaction_after_authorization(
pre: Alloc,
):
"""
- Test an invalid block due to a transaction reusing the same nonce as an authorization
- included in a prior transaction.
+ Test an invalid block due to a transaction reusing the same nonce as an
+ authorization included in a prior transaction.
"""
auth_signer = pre.fund_eoa()
recipient = pre.fund_eoa(amount=0)
@@ -3629,8 +3687,8 @@ def test_authorization_reusing_nonce(
pre: Alloc,
):
"""
- Test an authorization reusing the same nonce as a prior transaction included in the same
- block.
+ Test an authorization reusing the same nonce as a prior transaction
+ included in the same block.
"""
auth_signer = pre.fund_eoa()
sender = pre.fund_eoa()
@@ -3687,12 +3745,12 @@ def test_set_code_from_account_with_non_delegating_code(
self_sponsored: bool,
):
"""
- Test that a transaction is correctly rejected,
- if the sender account has a non-delegating code set.
+ Test that a transaction is correctly rejected, if the sender account has a
+ non-delegating code set.
- The auth transaction is sent from sender which has contract code (not delegating)
- But at the same time it has auth tuple that will point this sender account
- To be eoa, delegation, contract .. etc
+ The auth transaction is sent from sender which has contract code (not
+ delegating) But at the same time it has auth tuple that will point this
+ sender account To be eoa, delegation, contract .. etc
"""
sender = pre.fund_eoa(nonce=1)
random_address = pre.fund_eoa(0)
@@ -3712,7 +3770,8 @@ def test_set_code_from_account_with_non_delegating_code(
raise ValueError(f"Unsupported set code type: {set_code_type}")
callee_address = pre.deploy_contract(Op.SSTORE(0, 1) + Op.STOP)
- # Set the sender account to have some code, that is specifically not a delegation.
+ # Set the sender account to have some code, that is specifically not a
+ # delegation.
sender_account = pre[sender]
assert sender_account is not None
sender_account.code = Bytes(Op.STOP)
@@ -3767,6 +3826,7 @@ def test_set_code_from_account_with_non_delegating_code(
],
)
@pytest.mark.exception_test
+@pytest.mark.slow()
def test_set_code_transaction_fee_validations(
state_test: StateTestFiller,
pre: Alloc,
@@ -3774,7 +3834,9 @@ def test_set_code_transaction_fee_validations(
max_priority_fee_per_gas: int,
expected_error: TransactionException,
):
- """Test that a transaction with an insufficient max fee per gas is rejected."""
+ """
+ Test that a transaction with an insufficient max fee per gas is rejected.
+ """
set_to_code = pre.deploy_contract(Op.STOP)
auth_signer = pre.fund_eoa(amount=0)
tx = Transaction(
diff --git a/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs_2.py b/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs_2.py
index 1b7348f5ba..ef4208b76d 100644
--- a/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs_2.py
+++ b/tests/eest/prague/eip7702_set_code_tx/test_set_code_txs_2.py
@@ -1,4 +1,6 @@
-"""A state test for [EIP-7702 SetCodeTX](https://eips.ethereum.org/EIPS/eip-7702)."""
+"""
+A state test for [EIP-7702 SetCodeTX](https://eips.ethereum.org/EIPS/eip-7702).
+"""
from enum import Enum, IntEnum
@@ -14,6 +16,7 @@
BlockchainTestFiller,
Bytes,
Case,
+ CodeGasMeasure,
Conditional,
Environment,
Hash,
@@ -24,10 +27,9 @@
TransactionException,
compute_create_address,
)
-from ethereum_test_tools.code.generators import CodeGasMeasure
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_vm import Macros
+from ethereum_test_vm import Opcodes as Op
from .spec import Spec, ref_spec_7702
@@ -40,8 +42,9 @@ def test_pointer_contract_pointer_loop(state_test: StateTestFiller, pre: Alloc):
"""
Tx -> call -> pointer A -> contract A -> pointer B -> contract loop C.
- Call pointer that goes more level of depth to call a contract loop
- Loop is created only if pointers are set with auth tuples
+ Call pointer that goes more level of depth to call a contract loop.
+
+ Loop is created only if pointers are set with auth tuples.
"""
env = Environment()
@@ -137,8 +140,10 @@ def test_pointer_to_pointer(state_test: StateTestFiller, pre: Alloc):
@pytest.mark.valid_from("Prague")
def test_pointer_normal(blockchain_test: BlockchainTestFiller, pre: Alloc):
"""
- Tx -> call -> pointer A -> contract
- Other normal tx can interact with previously assigned pointers.
+ Tx -> call -> pointer A -> contract.
+
+ Other normal tx can interact with
+ previously assigned pointers.
"""
env = Environment()
@@ -197,8 +202,10 @@ def test_pointer_normal(blockchain_test: BlockchainTestFiller, pre: Alloc):
@pytest.mark.valid_from("Prague")
def test_pointer_measurements(blockchain_test: BlockchainTestFiller, pre: Alloc):
"""
- Check extcode* operations on pointer before and after pointer is set
- Check context opcode results when called under pointer call
+ Check extcode* operations on pointer before and after pointer is set.
+
+ Check context opcode results when called under pointer call.
+
Opcodes have context of an original pointer account (balance, storage).
"""
env = Environment()
@@ -208,7 +215,8 @@ def test_pointer_measurements(blockchain_test: BlockchainTestFiller, pre: Alloc)
storage_normal: Storage = Storage()
storage_pointer: Storage = Storage()
- storage_pointer_code: Storage = Storage() # this storage will be applied to pointer address
+ storage_pointer_code: Storage = Storage() # this storage will be applied
+ # to pointer address
pointer_code = pre.deploy_contract(
balance=200,
code=Op.SSTORE(storage_pointer_code.store_next(pointer, "address"), Op.ADDRESS())
@@ -327,9 +335,10 @@ def test_call_to_precompile_in_pointer_context(
state_test: StateTestFiller, pre: Alloc, precompile: int
):
"""
- Tx -> call -> pointer A -> precompile contract
- Make sure that gas consumed when calling precompiles in normal call are the same
- As from inside the pointer context call.
+ Tx -> call -> pointer A -> precompile contract.
+
+ Make sure that gas consumed when calling precompiles in normal call
+ are the same As from inside the pointer context call.
"""
env = Environment()
@@ -400,11 +409,13 @@ def test_pointer_to_precompile(state_test: StateTestFiller, pre: Alloc, precompi
"""
Tx -> call -> pointer A -> precompile contract.
- In case a delegation designator points to a precompile address, retrieved code is considered
- empty and CALL, CALLCODE, STATICCALL, DELEGATECALL instructions targeting this account will
- execute empty code, i.e. succeed with no execution given enough gas.
+ In case a delegation designator points to a precompile address, retrieved
+ code is considered empty and CALL, CALLCODE, STATICCALL, DELEGATECALL
+ instructions targeting this account will execute empty code, i.e. succeed
+ with no execution given enough gas.
- So call to a pointer that points to a precompile is like call to an empty account
+ So call to a pointer that points to a precompile is like call to an empty
+ account
"""
env = Environment()
@@ -440,7 +451,8 @@ def test_pointer_to_precompile(state_test: StateTestFiller, pre: Alloc, precompi
ret_offset=1000,
ret_size=32,
)
- # pointer call to a precompile with 0 gas always return 1 as if calling empty address
+ # pointer call to a precompile with 0 gas always return 1 as if calling
+ # empty address
+ Op.SSTORE(storage.store_next(1, "pointer_call_result"), Op.MLOAD(1000))
)
@@ -727,9 +739,9 @@ def test_pointer_call_followed_by_direct_call(
):
"""
If we first call by pointer then direct call, will the call/sload be hot
- The direct call will warm because pointer access marks it warm
- But the sload is still cold because
- storage marked hot from pointer's account in a pointer call.
+ The direct call will warm because pointer access marks it warm But the
+ sload is still cold because storage marked hot from pointer's account in a
+ pointer call.
"""
env = Environment()
@@ -747,8 +759,10 @@ def test_pointer_call_followed_by_direct_call(
)
direct_call_gas = (
gas_costs.G_STORAGE_SET
- + gas_costs.G_WARM_ACCOUNT_ACCESS # since previous pointer call, contract is now warm
- + gas_costs.G_COLD_SLOAD # but storage is cold, because it's contract's direct
+ + gas_costs.G_WARM_ACCOUNT_ACCESS # since previous pointer call,
+ # contract is now warm
+ + gas_costs.G_COLD_SLOAD # but storage is cold, because it's
+ # contract's direct
+ opcodes_price
)
@@ -803,7 +817,8 @@ def test_pointer_call_followed_by_direct_call(
@pytest.mark.valid_from("Prague")
def test_pointer_to_static(state_test: StateTestFiller, pre: Alloc):
"""
- Tx -> call -> pointer A -> static -> static violation
+ Tx -> call -> pointer A -> static -> static violation.
+
Verify that static context is active when called under pointer.
"""
env = Environment()
@@ -849,7 +864,8 @@ def test_pointer_to_static(state_test: StateTestFiller, pre: Alloc):
@pytest.mark.valid_from("Prague")
def test_static_to_pointer(state_test: StateTestFiller, pre: Alloc):
"""
- Tx -> staticcall -> pointer A -> static violation
+ Tx -> staticcall -> pointer A -> static violation.
+
Verify that static context is active when make sub call to pointer.
"""
env = Environment()
@@ -895,7 +911,8 @@ def test_static_to_pointer(state_test: StateTestFiller, pre: Alloc):
@pytest.mark.valid_from("EOFv1")
def test_pointer_to_eof(state_test: StateTestFiller, pre: Alloc):
"""
- Tx -> call -> pointer A -> EOF
+ Tx -> call -> pointer A -> EOF.
+
Pointer to eof contract works.
"""
env = Environment()
@@ -1013,7 +1030,9 @@ def test_contract_storage_to_pointer_with_storage(
state_test: StateTestFiller, pre: Alloc, call_type: Op
):
"""
- Tx call -> contract with storage -> pointer A with storage -> storage/tstorage modify
+ Tx call -> contract with storage -> pointer A with storage ->
+ storage/tstorage modify.
+
Check storage/tstorage modifications when interacting with pointers.
"""
env = Environment()
@@ -1056,18 +1075,21 @@ def test_contract_storage_to_pointer_with_storage(
code=Op.TSTORE(third_slot, 1)
+ call_type(address=pointer_b, gas=500_000)
+ Op.SSTORE(third_slot, Op.TLOAD(third_slot))
- # Verify tstorage in contract after interacting with pointer, it must be 0
+ # Verify tstorage in contract after interacting with pointer, it must
+ # be 0
+ Op.MSTORE(0, 1)
+ Op.CALL(address=contract_b, gas=500_000, args_offset=0, args_size=32),
storage={
storage_a.store_next(
- # caller storage is modified when calling pointer with delegate or callcode
+ # caller storage is modified when calling pointer with delegate
+ # or callcode
6 if call_type in [Op.DELEGATECALL, Op.CALLCODE] else 5,
"first_slot",
): 5,
storage_a.store_next(2, "second_slot"): 2,
storage_a.store_next(
- # TSTORE is modified when calling pointer with delegate or callcode
+ # TSTORE is modified when calling pointer with delegate or
+ # callcode
2 if call_type in [Op.DELEGATECALL, Op.CALLCODE] else 1,
"third_slot",
): 3,
@@ -1113,8 +1135,10 @@ class ReentryAction(IntEnum):
@pytest.mark.valid_from("Prague")
def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc):
"""
- Check operations when reenter the pointer again
- TODO: feel free to extend the code checks under given scenarios in switch case.
+ Check operations when reenter the pointer again.
+
+ TODO: feel free to extend the code checks under given scenarios in
+ switch case.
"""
env = Environment()
arg_contract = 0
@@ -1152,7 +1176,8 @@ def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc):
+ Op.STOP(),
),
Case(
- # This code is executed under pointer -> proxy -> pointer context
+ # This code is executed under pointer -> proxy -> pointer
+ # context
condition=Op.EQ(Op.MLOAD(arg_action), ReentryAction.MEASURE_VALUES),
action=Op.SSTORE(storage_pointer_b.store_next(sender, "origin"), Op.ORIGIN())
+ Op.SSTORE(storage_pointer_b.store_next(pointer_b, "address"), Op.ADDRESS())
@@ -1172,7 +1197,8 @@ def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc):
Case(
# This code is executed under
# pointer -> proxy -> pointer -> contract
- # so pointer calling the code of it's dest after reentry to itself
+ # so pointer calling the code of it's dest
+ # after reentry to itself
condition=Op.EQ(Op.MLOAD(arg_action), ReentryAction.MEASURE_VALUES_CONTRACT),
action=Op.SSTORE(storage_b.store_next(sender, "origin"), Op.ORIGIN())
+ Op.SSTORE(slot_reentry_address, Op.ADDRESS())
@@ -1216,9 +1242,11 @@ def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc):
@pytest.mark.valid_from("Prague")
def test_eoa_init_as_pointer(state_test: StateTestFiller, pre: Alloc):
"""
- It was agreed before that senders don't have code
- And there were issues with tests sending transactions from account's with code
- With EIP7702 it is again possible, let's check the test runners are ok.
+ It was agreed before that senders don't have code.
+
+ And there were issues with tests sending transactions from account's
+ with code With EIP7702 it is again possible,
+ let's check the test runners are ok.
"""
env = Environment()
storage = Storage()
@@ -1249,13 +1277,17 @@ def test_call_pointer_to_created_from_create_after_oog_call_again(
"""
Set pointer to account that we are about to create.
- Pointer is set to create address that is yet not in the state
- During the call, address is created. pointer is called from init code to do nothing
+ Pointer is set to create address that is yet not in the state.
+
+ During the call, address is created. pointer is called from init code
+ to do nothing.
+
Then after account is created it is called again to run created code
- Then revert / no revert
+ Then revert / no revert.
- Call pointer again from the upper level to ensure it does not call reverted code
+ Call pointer again from the upper level to ensure it does not call reverted
+ code.
"""
env = Environment()
@@ -1441,6 +1473,7 @@ class DelegationTo(Enum):
RESET = 3
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.valid_from("Prague")
@pytest.mark.parametrize(
"first_delegation", [DelegationTo.CONTRACT_A, DelegationTo.CONTRACT_B, DelegationTo.RESET]
@@ -1536,16 +1569,19 @@ def test_double_auth(
)
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.valid_from("Prague")
def test_pointer_resets_an_empty_code_account_with_storage(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
"""
- So in Block1 we create a sender with empty code, but non empty storage using pointers
- In Block2 we create account that perform suicide, then we check that when calling
- a pointer, that points to newly created account and runs suicide,
- is not deleted as well as its storage.
+ So in Block1 we create a sender with empty code, but non empty storage
+ using pointers.
+
+ In Block2 we create account that perform suicide, then we
+ check that when calling a pointer, that points to newly created account and
+ runs suicide, is not deleted as well as its storage.
This one is a little messy.
"""
@@ -1622,7 +1658,9 @@ def test_pointer_resets_an_empty_code_account_with_storage(
# Block 2
# Sender with storage and pointer code calling selfdestruct on itself
- # But it points to a newly created account, check that pointer storage is not deleted
+ #
+ # But it points to a newly created account, check that pointer
+ # storage is not deleted
suicide_dest = pre.fund_eoa(amount=0)
deploy_code = Op.SSTORE(5, 5) + Op.SELFDESTRUCT(suicide_dest)
sender_storage[5] = 5
@@ -1635,7 +1673,8 @@ def test_pointer_resets_an_empty_code_account_with_storage(
+ Op.SSTORE(1, Op.CREATE(0, 0, Op.CALLDATASIZE()))
+ Op.CALL(address=sender) # run suicide from pointer
+ Op.CALL(address=Op.SLOAD(1)) # run suicide directly
- + Op.CALL(address=another_pointer) # run suicide from pointer that is not sender
+ + Op.CALL(address=another_pointer) # run suicide from pointer that is
+ # not sender
)
newly_created_address = compute_create_address(address=contract_create, nonce=1)
@@ -1677,9 +1716,13 @@ def test_pointer_resets_an_empty_code_account_with_storage(
post=post,
blocks=[
# post = {
- # pointer: Account(nonce=2, balance=0, storage=pointer_storage, code=bytes()),
- # sender: Account(storage=pointer_storage, code=bytes()),
- # }
+ # pointer: Account(nonce=2,
+ # balance=0,
+ # storage=pointer_storage,
+ # code=bytes()
+ # ),
+ # sender: Account(storage=pointer_storage, code=bytes())
+ # }
Block(
txs=[
tx_set_pointer_storage,
@@ -1708,7 +1751,8 @@ def test_set_code_type_tx_pre_fork(
Reject blocks with set code type transactions before the Prague fork.
This test was based on:
- tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_self_sponsored_set_code
+ tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_self_sponsored_set_
+ code
"""
storage = Storage()
sender = pre.fund_eoa()
@@ -1743,7 +1787,7 @@ def test_set_code_type_tx_pre_fork(
pre=pre,
tx=tx,
post={
- set_code_to_address: Account(storage={k: 0 for k in storage}),
+ set_code_to_address: Account(storage=dict.fromkeys(storage, 0)),
sender: Account(
nonce=0,
code="",
@@ -1754,15 +1798,16 @@ def test_set_code_type_tx_pre_fork(
@pytest.mark.valid_from("Prague")
+@pytest.mark.xdist_group(name="bigmem")
def test_delegation_replacement_call_previous_contract(
state_test: StateTestFiller,
pre: Alloc,
fork: Fork,
):
"""
- Test setting the code of an EOA that already has
- delegation, calling the previous delegated contract.
- Previous contract shouldn't be warm when doing the CALL.
+ Test setting the code of an EOA that already has delegation, calling the
+ previous delegated contract. Previous contract shouldn't be warm when doing
+ the CALL.
"""
pre_set_delegation_code = Op.STOP
pre_set_delegation_address = pre.deploy_contract(pre_set_delegation_code)
diff --git a/tests/eest/shanghai/eip3651_warm_coinbase/__init__.py b/tests/eest/shanghai/eip3651_warm_coinbase/__init__.py
index f24c6b66a5..66363cc4b3 100644
--- a/tests/eest/shanghai/eip3651_warm_coinbase/__init__.py
+++ b/tests/eest/shanghai/eip3651_warm_coinbase/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651)
- Tests for [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651).
+Tests for [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651).
"""
diff --git a/tests/eest/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py b/tests/eest/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py
index 0e924a28f6..7f535043ba 100644
--- a/tests/eest/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py
+++ b/tests/eest/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py
@@ -1,9 +1,8 @@
"""
-abstract: Tests [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651)
- Tests for [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651).
+Tests [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651).
-note: Tests ported from:
- - [ethereum/tests/pull/1082](https://github.com/ethereum/tests/pull/1082).
+Tests ported from:
+[ethereum/tests/pull/1082](https://github.com/ethereum/tests/pull/1082).
"""
import pytest
@@ -19,7 +18,7 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .spec import ref_spec_3651
diff --git a/tests/eest/shanghai/eip3855_push0/__init__.py b/tests/eest/shanghai/eip3855_push0/__init__.py
index a8372e6ccf..986e36b549 100644
--- a/tests/eest/shanghai/eip3855_push0/__init__.py
+++ b/tests/eest/shanghai/eip3855_push0/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855)
- Tests for [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855).
+Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855).
"""
diff --git a/tests/eest/shanghai/eip3855_push0/test_push0.py b/tests/eest/shanghai/eip3855_push0/test_push0.py
index 410cbb18bc..aa3e471f46 100644
--- a/tests/eest/shanghai/eip3855_push0/test_push0.py
+++ b/tests/eest/shanghai/eip3855_push0/test_push0.py
@@ -1,9 +1,8 @@
"""
-abstract: Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855)
- Tests for [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855).
+Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855).
-note: Tests ported from:
- - [ethereum/tests/pull/1033](https://github.com/ethereum/tests/pull/1033).
+Tests ported from:
+[ethereum/tests/pull/1033](https://github.com/ethereum/tests/pull/1033).
"""
import pytest
@@ -19,7 +18,7 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .spec import ref_spec_3855
@@ -29,6 +28,7 @@
pytestmark = pytest.mark.valid_from("Shanghai")
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"contract_code,expected_storage",
[
@@ -91,16 +91,21 @@ def test_push0_contracts(
class TestPush0CallContext:
"""
- Tests the PUSH0 operation during various call contexts including:
- - CALL
- - CALLCODE
- - DELEGATECALL
+ Test the PUSH0 operation in various contract call contexts.
+
+ Test PUSH0 in the following contract call contexts:
+
+ - CALL,
+ - CALLCODE,
+ - DELEGATECALL,
- STATICCALL.
"""
@pytest.fixture
def push0_contract_callee(self, pre: Alloc) -> Address:
- """Deploys a PUSH0 contract callee to the pre alloc returning its address."""
+ """
+ Deploys a PUSH0 contract callee to the pre alloc returning its address.
+ """
push0_contract = pre.deploy_contract(Op.MSTORE8(Op.PUSH0, 0xFF) + Op.RETURN(Op.PUSH0, 1))
return push0_contract
@@ -109,8 +114,9 @@ def push0_contract_caller(
self, pre: Alloc, call_opcode: Op, push0_contract_callee: Address
) -> Address:
"""
- Deploy contract responsible for calling the callee PUSH0 contract
- returning its address.
+ Deploy the contract that calls the callee PUSH0 contract into `pre`.
+
+ This fixture returns its address.
"""
call_code = (
Op.SSTORE(0, call_opcode(gas=100_000, address=push0_contract_callee))
@@ -120,6 +126,7 @@ def push0_contract_caller(
)
return pre.deploy_contract(call_code)
+ @pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"call_opcode",
[
diff --git a/tests/eest/shanghai/eip3860_initcode/__init__.py b/tests/eest/shanghai/eip3860_initcode/__init__.py
index 62ee051a08..0d50d930d9 100644
--- a/tests/eest/shanghai/eip3860_initcode/__init__.py
+++ b/tests/eest/shanghai/eip3860_initcode/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860)
- Tests for [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860).
+Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860).
"""
diff --git a/tests/eest/shanghai/eip3860_initcode/helpers.py b/tests/eest/shanghai/eip3860_initcode/helpers.py
index b97e9faf41..0719355caf 100644
--- a/tests/eest/shanghai/eip3860_initcode/helpers.py
+++ b/tests/eest/shanghai/eip3860_initcode/helpers.py
@@ -1,7 +1,7 @@
"""Helpers for the EIP-3860 initcode tests."""
from ethereum_test_tools import Initcode
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
INITCODE_RESULTING_DEPLOYED_CODE = Op.STOP
diff --git a/tests/eest/shanghai/eip3860_initcode/spec.py b/tests/eest/shanghai/eip3860_initcode/spec.py
index 65dad3fcea..67ccec1e53 100644
--- a/tests/eest/shanghai/eip3860_initcode/spec.py
+++ b/tests/eest/shanghai/eip3860_initcode/spec.py
@@ -17,7 +17,9 @@ class ReferenceSpec:
@dataclass(frozen=True)
class Spec:
"""
- Parameters from the EIP-3860 specifications as defined at
+ Define parameters from the EIP-3860 specifications.
+
+ These are the parameters defined at
https://eips.ethereum.org/EIPS/eip-3860#parameters.
"""
diff --git a/tests/eest/shanghai/eip3860_initcode/test_initcode.py b/tests/eest/shanghai/eip3860_initcode/test_initcode.py
index fa52ca0816..c88ff6fc12 100644
--- a/tests/eest/shanghai/eip3860_initcode/test_initcode.py
+++ b/tests/eest/shanghai/eip3860_initcode/test_initcode.py
@@ -1,10 +1,9 @@
"""
-abstract: Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860)
- Tests for [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860).
+Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860).
-note: Tests ported from:
- - [ethereum/tests/pull/990](https://github.com/ethereum/tests/pull/990)
- - [ethereum/tests/pull/1012](https://github.com/ethereum/tests/pull/990)
+Tests ported from:
+- [ethereum/tests/pull/990](https://github.com/ethereum/tests/pull/990)
+- [ethereum/tests/pull/1012](https://github.com/ethereum/tests/pull/990)
"""
from typing import List
@@ -28,7 +27,7 @@
ceiling_division,
compute_create_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .helpers import INITCODE_RESULTING_DEPLOYED_CODE, get_create_id, get_initcode_name
from .spec import Spec, ref_spec_3860
@@ -39,9 +38,7 @@
pytestmark = pytest.mark.valid_from("Shanghai")
-"""
-Initcode templates used throughout the tests
-"""
+"""Initcode templates used throughout the tests"""
INITCODE_ONES_MAX_LIMIT = Initcode(
deploy_code=INITCODE_RESULTING_DEPLOYED_CODE,
initcode_length=Spec.MAX_INITCODE_SIZE,
@@ -112,11 +109,10 @@
SINGLE_BYTE_INITCODE.deployment_gas = 0
SINGLE_BYTE_INITCODE.execution_gas = 0
-"""
-Test cases using a contract creating transaction
-"""
+"""Test cases using a contract creating transaction"""
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"initcode",
[
@@ -136,8 +132,7 @@ def test_contract_creating_tx(
initcode: Initcode,
):
"""
- Tests creating a contract using a transaction with an initcode that is
- on/over the max allowed limit.
+ Test creating a contract with initcode that is on/over the allowed limit.
"""
create_contract_address = compute_create_address(
address=sender,
@@ -208,15 +203,18 @@ def valid_gas_test_case(initcode: Initcode, gas_test_case: str) -> bool:
)
class TestContractCreationGasUsage:
"""
- Tests the following cases that verify the gas cost behavior of a
- contract creating transaction.
-
- 1. Test with exact intrinsic gas minus one, contract create fails
- and tx is invalid.
- 2. Test with exact intrinsic gas, contract create fails,
- but tx is valid.
- 3. Test with exact execution gas minus one, contract create fails,
- but tx is valid.
+ Test the gas cost behavior of a contract creating transaction.
+
+ The following scenarios are tested:
+
+ 1. Test with exact intrinsic gas minus one, contract create fails and tx is
+ invalid.
+
+ 2. Test with exact intrinsic gas, contract create fails, but tx is valid.
+
+ 3. Test with exact execution gas minus one, contract create fails, but tx
+ is valid.
+
4. Test with exact execution gas, contract create succeeds.
Initcode must be within a valid EIP-3860 length.
@@ -225,8 +223,10 @@ class TestContractCreationGasUsage:
@pytest.fixture
def tx_access_list(self) -> List[AccessList]:
"""
- On EIP-7623, we need to use an access list to raise the intrinsic gas cost to
- be above the floor data cost.
+ Return an access list to raise the intrinsic gas cost.
+
+ Upon EIP-7623 activation, we need to use an access list to raise the
+ intrinsic gas cost to be above the floor data cost.
"""
return [AccessList(address=Address(i), storage_keys=[]) for i in range(1, 478)]
@@ -234,7 +234,9 @@ def tx_access_list(self) -> List[AccessList]:
def exact_intrinsic_gas(
self, fork: Fork, initcode: Initcode, tx_access_list: List[AccessList]
) -> int:
- """Calculate the intrinsic tx gas cost."""
+ """
+ Calculate the intrinsic tx gas cost.
+ """
tx_intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
assert tx_intrinsic_gas_cost_calculator(
calldata=initcode,
@@ -254,12 +256,16 @@ def exact_intrinsic_gas(
@pytest.fixture
def exact_execution_gas(self, exact_intrinsic_gas: int, initcode: Initcode) -> int:
- """Calculate total execution gas cost."""
+ """
+ Calculate total execution gas cost.
+ """
return exact_intrinsic_gas + initcode.deployment_gas + initcode.execution_gas
@pytest.fixture
def tx_error(self, gas_test_case: str) -> TransactionException | None:
"""
+ Return the transaction exception, or None, as expected.
+
Check that the transaction is invalid if too little intrinsic gas is
specified, otherwise the tx is valid and succeeds.
"""
@@ -279,7 +285,9 @@ def tx(
exact_execution_gas: int,
) -> Transaction:
"""
- Implement the gas_test_case by setting the gas_limit of the tx
+ Return a tx with `gas_limit` corresponding to the `gas_test_case`.
+
+ Implement the gas_test_case by setting the `gas_limit` of the tx
appropriately and test whether the tx succeeds or fails with
appropriate error.
"""
@@ -317,8 +325,7 @@ def post(
exact_execution_gas: int,
) -> Alloc:
"""
- Test that contract creation fails unless enough execution gas is
- provided.
+ Test contract creation fails unless enough execution gas is provided.
"""
create_contract_address = compute_create_address(
address=sender,
@@ -332,6 +339,7 @@ def post(
return Alloc({create_contract_address: Account(code=initcode.deploy_code)})
return Alloc({create_contract_address: Account.NONEXISTENT})
+ @pytest.mark.slow()
def test_gas_usage(
self,
state_test: StateTestFiller,
@@ -340,7 +348,9 @@ def test_gas_usage(
post: Alloc,
tx: Transaction,
):
- """Test transaction and contract creation behavior for different gas limits."""
+ """
+ Test transaction and contract creation using different gas limits.
+ """
state_test(
env=env,
pre=pre,
@@ -368,18 +378,24 @@ def test_gas_usage(
@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2], ids=get_create_id)
class TestCreateInitcode:
"""
- Test contract creation via the CREATE/CREATE2 opcodes that have an initcode
- that is on/over the max allowed limit.
+ Test contract creation with valid and invalid initcode lengths.
+
+ Test contract creation via CREATE/CREATE2, parametrized by initcode that is
+ on/over the max allowed limit.
"""
@pytest.fixture
def create2_salt(self) -> int:
- """Salt value used for CREATE2 contract creation."""
+ """
+ Salt value used for CREATE2 contract creation.
+ """
return 0xDEADBEEF
@pytest.fixture
def creator_code(self, opcode: Op, create2_salt: int) -> Bytecode:
- """Generate code for the creator contract which performs the CREATE/CREATE2 operation."""
+ """
+ Generate code for the creator contract which calls CREATE/CREATE2.
+ """
return (
Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE)
+ Op.GAS
@@ -414,7 +430,9 @@ def created_contract_address( # noqa: D103
initcode: Initcode,
creator_contract_address: Address,
) -> Address:
- """Calculate address of the contract created by the creator contract."""
+ """
+ Calculate address of the contract created by the creator contract.
+ """
return compute_create_address(
address=creator_contract_address,
nonce=1,
@@ -425,7 +443,9 @@ def created_contract_address( # noqa: D103
@pytest.fixture
def caller_code(self, creator_contract_address: Address) -> Bytecode:
- """Generate code for the caller contract that calls the creator contract."""
+ """
+ Generate code for the caller contract that calls the creator contract.
+ """
return Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.SSTORE(
Op.CALL(5000000, creator_contract_address, 0, 0, Op.CALLDATASIZE, 0, 0), 1
)
@@ -481,6 +501,8 @@ def create2_word_cost(self, opcode: Op, fork: Fork, initcode: Initcode) -> int:
gas_costs = fork.gas_costs()
return ceiling_division(len(initcode), 32) * gas_costs.G_KECCAK_256_WORD
+ @pytest.mark.xdist_group(name="bigmem")
+ @pytest.mark.slow()
def test_create_opcode_initcode(
self,
state_test: StateTestFiller,
@@ -497,8 +519,10 @@ def test_create_opcode_initcode(
create2_word_cost: int,
):
"""
- Test contract creation via the CREATE/CREATE2 opcodes that have an
- initcode that is on/over the max allowed limit.
+ Test contract creation with valid and invalid initcode lengths.
+
+ Test contract creation via CREATE/CREATE2, parametrized by initcode
+ that is on/over the max allowed limit.
"""
if len(initcode) > Spec.MAX_INITCODE_SIZE:
# Call returns 0 as out of gas s[0]==1
diff --git a/tests/eest/shanghai/eip3860_initcode/test_with_eof.py b/tests/eest/shanghai/eip3860_initcode/test_with_eof.py
index ddf9132cc9..f3b7318518 100644
--- a/tests/eest/shanghai/eip3860_initcode/test_with_eof.py
+++ b/tests/eest/shanghai/eip3860_initcode/test_with_eof.py
@@ -1,4 +1,6 @@
-"""Tests interaction between edge case size CREATE / CREATE2 and EOF, including EIP-3860 limits."""
+"""
+Test CREATE / CREATE2 and EOF interaction for EIP-3860 initcode limits.
+"""
import itertools
@@ -14,8 +16,8 @@
Transaction,
compute_create_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE
+from ethereum_test_vm import Opcodes as Op
from .spec import ref_spec_3860
@@ -54,9 +56,12 @@ def test_legacy_create_edge_code_size(
init_code: Bytecode,
):
"""
- Verifies that legacy initcode/deploycode having 0 or max size continues to work in the fork
- where EOF is enabled. Handling of EOF magic prefix and version interferes with the handling
- of legacy creation, so a specific test was proposed to test behavior doesn't change.
+ Test legacy initcode and deployed code edge cases with EOF enabled.
+
+ Verify that legacy initcode/deploycode having 0 or max size continues to
+ work in the fork where EOF is enabled. Handling of EOF magic prefix and
+ version interferes with the handling of legacy creation, so a specific test
+ was proposed to test behavior doesn't change.
"""
env = Environment()
diff --git a/tests/eest/shanghai/eip4895_withdrawals/__init__.py b/tests/eest/shanghai/eip4895_withdrawals/__init__.py
index bb4a893dcb..c10cd7154b 100644
--- a/tests/eest/shanghai/eip4895_withdrawals/__init__.py
+++ b/tests/eest/shanghai/eip4895_withdrawals/__init__.py
@@ -1,5 +1,3 @@
"""
-abstract: Tests [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895)
- Test cases for [EIP-4895: Beacon chain push withdrawals as
- operations](https://eips.ethereum.org/EIPS/eip-4895).
+Tests [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895).
"""
diff --git a/tests/eest/shanghai/eip4895_withdrawals/test_withdrawals.py b/tests/eest/shanghai/eip4895_withdrawals/test_withdrawals.py
index fc9305a83e..a5365c3b0e 100644
--- a/tests/eest/shanghai/eip4895_withdrawals/test_withdrawals.py
+++ b/tests/eest/shanghai/eip4895_withdrawals/test_withdrawals.py
@@ -1,7 +1,5 @@
"""
-abstract: Tests [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895)
- Test cases for [EIP-4895: Beacon chain push withdrawals as
- operations](https://eips.ethereum.org/EIPS/eip-4895).
+Tests for [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895).
"""
from enum import Enum, unique
@@ -23,7 +21,7 @@
TransactionException,
Withdrawal,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
from .spec import ref_spec_4895
@@ -50,11 +48,11 @@ class TestUseValueInTx:
"""
Test that the value from a withdrawal can be used in a transaction.
- 1. `tx_in_withdrawals_block`: Test that the withdrawal value can not be used by a transaction
- in the same block as the withdrawal.
+ 1. `tx_in_withdrawals_block`: Test that the withdrawal value can not be
+ used by a transaction in the same block as the withdrawal.
- 2. `tx_after_withdrawals_block`: Test that the withdrawal value can be used by a transaction
- in the subsequent block.
+ 2. `tx_after_withdrawals_block`: Test that the withdrawal value can be used
+ by a transaction in the subsequent block.
"""
@pytest.fixture
@@ -189,8 +187,7 @@ def test_use_value_in_contract(
def test_balance_within_block(blockchain_test: BlockchainTestFiller, pre: Alloc):
"""
- Test Withdrawal balance increase within the same block,
- inside contract call.
+ Test withdrawal balance increase within the same block in a contract call.
"""
save_balance_on_block_number = Op.SSTORE(
Op.NUMBER,
@@ -304,8 +301,7 @@ def test_multiple_withdrawals_same_address(
blocks: List[Block],
):
"""
- Test Withdrawals can be done to the same address multiple times in
- the same block.
+ Test withdrawals to the same address multiple times in the same block.
"""
# Expected post is the same for both test cases.
post = {}
@@ -323,8 +319,7 @@ def test_many_withdrawals(
pre: Alloc,
):
"""
- Test Withdrawals with a count of N withdrawals in a single block where
- N is a high number not expected to be seen in mainnet.
+ Test an unexpected high number of withdrawals in a single block.
"""
n = 400
withdrawals = []
@@ -362,8 +357,9 @@ def test_self_destructing_account(
):
"""
Test withdrawals can be done to self-destructed accounts.
- Account `0x100` self-destructs and sends all its balance to `0x200`.
- Then, a withdrawal is received at `0x100` with 99 wei.
+
+ Account `0x100` self-destructs and sends all its balance to `0x200`. Then,
+ a withdrawal is received at `0x100` with 99 wei.
"""
self_destruct_code = Op.SELFDESTRUCT(Op.CALLDATALOAD(0))
sender = pre.fund_eoa()
@@ -419,7 +415,7 @@ def test_newly_created_contract(
include_value_in_tx: bool,
request,
):
- """Test Withdrawing to a newly created contract."""
+ """Test withdrawing to a newly created contract."""
sender = pre.fund_eoa()
initcode = Op.RETURN(0, 1)
tx = Transaction(
@@ -463,7 +459,7 @@ def test_no_evm_execution(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
- """Test Withdrawals don't trigger EVM execution."""
+ """Test withdrawals don't trigger EVM execution."""
sender = pre.fund_eoa()
contracts = [pre.deploy_contract(Op.SSTORE(Op.NUMBER, 1)) for _ in range(4)]
blocks = [
@@ -554,16 +550,19 @@ def test_zero_amount(
test_case: ZeroAmountTestCases,
):
"""
- Test withdrawals with zero amount for the following cases, all withdrawals
- are included in one block.
+ Test withdrawal scenarios with a zero amount in a single block.
+
+ All the withdrawals in the following scenarios are included in one block.
1. Two withdrawals of zero amount to two different addresses; one to an
- untouched account, one to an account with a balance.
+ untouched account, one to an account with a balance.
+
2. As 1., but with an additional withdrawal with positive value.
+
3. As 2., but with an additional withdrawal containing the maximum value
possible.
- 4. As 3., but with order of withdrawals in the block reversed.
+ 4. As 3., but with order of withdrawals in the block reversed.
"""
empty_accounts = [pre.fund_eoa(0) for _ in range(3)]
zero_balance_contract = pre.deploy_contract(Op.STOP)
@@ -651,13 +650,15 @@ def test_zero_amount(
)
+@pytest.mark.xdist_group(name="bigmem")
def test_large_amount(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
):
"""
- Test Withdrawals that have a large gwei amount, so that (gwei * 1e9)
- could overflow uint64 but not uint256.
+ Test withdrawals that have a large gwei amount.
+
+ Test such that that (gwei * 1e9) could overflow uint64 but not uint256.
"""
withdrawals: List[Withdrawal] = []
amounts: List[int] = [
@@ -690,8 +691,10 @@ def test_large_amount(
blockchain_test(pre=pre, post=post, blocks=blocks)
+@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize("amount", [0, 1])
@pytest.mark.with_all_precompiles
+@pytest.mark.slow()
def test_withdrawing_to_precompiles(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
diff --git a/tests/eest/static/state_tests/VMTests/vmTests/swapFiller.yml b/tests/eest/static/state_tests/VMTests/vmTests/swapFiller.yml
deleted file mode 100644
index 209c69ecae..0000000000
--- a/tests/eest/static/state_tests/VMTests/vmTests/swapFiller.yml
+++ /dev/null
@@ -1,713 +0,0 @@
-# Check the various swap opcodes
-#
-# NOTE: The functionality of the old swap2errorFiller.json is available in
-# GeneralStateTests/stStackTests/underflowTest.
-#
-# I fail to see the point of the old swapjump1
-#
-# We can't use lll with SWAP, swap, or push (lll needs to manage the stack
-# on its own). Instead, we do
-# [1] PUSH1 0x00
-# [3] PUSH1 0x01
-# [5] PUSH1 0x02
-# .
-# .
-# .
-# [31] PUSH1 0x0F
-# [33] PUSH1 0x10
-# [34] **** OPCODE BEING TESTED
-# [36] PUSH1 0x00
-# [37] SSTORE put stack top at @@0
-# [39] PUSH1 0x01
-# [40] SSTORE put next value down at @@1
-# .
-# .
-# .
-# [78] PUSH1 0x0E
-# [79] SSTORE
-# [81] PUSH1 0x0F
-# [82] SSTORE
-
-swap:
-
- env:
- currentCoinbase: 2adc25665018aa1fe0e6bc666dac8fc2697ff9ba
- currentDifficulty: 0x20000
- currentGasLimit: 100000000
- currentNumber: 1
- currentTimestamp: 1000
-
- _info:
- comment: Ori Pomerantz qbzzt1@gmail.com
-
- pre:
-
- # SWAP1
- 0000000000000000000000000000000000001000:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: :raw 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601090600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP2
- 0000000000000000000000000000000000001001:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: :raw 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601091600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP3
- 0000000000000000000000000000000000001002:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: :raw 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601092600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP4
- 0000000000000000000000000000000000001003:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601093600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
-
-
- # SWAP5
- 0000000000000000000000000000000000001004:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601094600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP6
- 0000000000000000000000000000000000001005:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601095600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP7
- 0000000000000000000000000000000000001006:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601096600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP8
- 0000000000000000000000000000000000001007:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601097600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
-
-
- # SWAP9
- 0000000000000000000000000000000000001008:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601098600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP10
- 0000000000000000000000000000000000001009:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601099600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP11
- 000000000000000000000000000000000000100A:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109A600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP12
- 000000000000000000000000000000000000100B:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109B600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
-
-
- # SWAP13
- 000000000000000000000000000000000000100C:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109C600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP14
- 000000000000000000000000000000000000100D:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109D600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP15
- 000000000000000000000000000000000000100E:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109E600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
- # SWAP16
- 000000000000000000000000000000000000100F:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109F600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55
- # PUSH1 0x01 ... PUSH1 0x10@@
- # @@ is the opcode being tested
- nonce: '0'
- storage: {}
-
-
-
-
-
-
-
-
- cccccccccccccccccccccccccccccccccccccccc:
- balance: '0x0ba1a9ce0ba1a9ce'
- code: |
- {
- (call (gas) (+ 0x1000 $4) 0 0 0 0 0)
- }
- nonce: '0'
- storage: {}
-
-
- a94f5374fce5edbc8e2a8697c15331677e6ebf0b:
- balance: 0x100000000000
- code: '0x'
- nonce: '0'
- storage: {}
-
-
-
-
- transaction:
- data:
- - :label swap1 :abi f(uint) 0
- - :label swap2 :abi f(uint) 1
- - :label swap3 :abi f(uint) 2
- - :label swap4 :abi f(uint) 3
- - :label swap5 :abi f(uint) 4
- - :label swap6 :abi f(uint) 5
- - :label swap7 :abi f(uint) 6
- - :label swap8 :abi f(uint) 7
- - :label swap9 :abi f(uint) 8
- - :label swap10 :abi f(uint) 9
- - :label swap11 :abi f(uint) 10
- - :label swap12 :abi f(uint) 11
- - :label swap13 :abi f(uint) 12
- - :label swap14 :abi f(uint) 13
- - :label swap15 :abi f(uint) 14
- - :label swap16 :abi f(uint) 15
-
- gasLimit:
- - '16777216'
- gasPrice: '10'
- nonce: '0'
- to: cccccccccccccccccccccccccccccccccccccccc
- value:
- - '1'
- secretKey: "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"
-
-
- expect:
- - indexes:
- data: :label swap1
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001000:
- storage:
- 0x00: 0x0F
- 0x01: 0x10
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap2
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001001:
- storage:
- 0x00: 0x0E
- 0x01: 0x0F
- 0x02: 0x10
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap3
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001002:
- storage:
- 0x00: 0x0D
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x10
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap4
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001003:
- storage:
- 0x00: 0x0C
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x10
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
-
- - indexes:
- data: :label swap5
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001004:
- storage:
- 0x00: 0x0B
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x10
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap6
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001005:
- storage:
- 0x00: 0x0A
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x10
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap7
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001006:
- storage:
- 0x00: 0x09
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x10
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap8
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001007:
- storage:
- 0x00: 0x08
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x10
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
-
- - indexes:
- data: :label swap9
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001008:
- storage:
- 0x00: 0x07
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x10
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap10
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 0000000000000000000000000000000000001009:
- storage:
- 0x00: 0x06
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x10
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap11
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 000000000000000000000000000000000000100A:
- storage:
- 0x00: 0x05
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x10
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap12
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 000000000000000000000000000000000000100B:
- storage:
- 0x00: 0x04
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x10
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
-
-
-
- - indexes:
- data: :label swap13
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 000000000000000000000000000000000000100C:
- storage:
- 0x00: 0x03
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x10
- 0x0E: 0x02
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap14
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 000000000000000000000000000000000000100D:
- storage:
- 0x00: 0x02
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x10
- 0x0F: 0x01
-
-
- - indexes:
- data: :label swap15
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 000000000000000000000000000000000000100E:
- storage:
- 0x00: 0x01
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x10
-
-
- - indexes:
- data: :label swap16
- gas: !!int -1
- value: !!int -1
- network:
- - '>=Cancun'
- result:
- 000000000000000000000000000000000000100F:
- storage:
- 0x00: 0x00
- 0x01: 0x0F
- 0x02: 0x0E
- 0x03: 0x0D
- 0x04: 0x0C
- 0x05: 0x0B
- 0x06: 0x0A
- 0x07: 0x09
- 0x08: 0x08
- 0x09: 0x07
- 0x0A: 0x06
- 0x0B: 0x05
- 0x0C: 0x04
- 0x0D: 0x03
- 0x0E: 0x02
- 0x0F: 0x01
diff --git a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json b/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json
deleted file mode 100644
index fdca1044d1..0000000000
--- a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "CREATE_ContractSuicideDuringInit" : {
- "env" : {
- "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
- "currentDifficulty" : "0x020000",
- "currentGasLimit" : "10000000",
- "currentNumber" : "1",
- "currentTimestamp" : "1000"
- },
- "expect" : [
- {
- "indexes" : {
- "data" : -1,
- "gas" : -1,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
- "shouldnotexist" : "1"
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "storage" : {
- "0x01" : "0x0c"
- }
- }
- }
- }
- ],
- "pre" :
- {
- "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "1000000000000",
- "code" : "",
- "nonce" : "0",
- "storage" : {
- }
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "// code" : "This indicates that a call from transaction was initiated",
- "code" : "{[[1]]12}",
- "nonce" : "0",
- "storage" : {
- }
- }
- },
- "transaction" : {
- "// data" : "{(CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b)}",
- "data" : [
- ":raw 0x6000600060006000600073c94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f1506d64600c6000556000526005601bf360005273c94f5374fce5edbc8e2a8697c15331677e6ebf0bff"
- ],
- "gasLimit" : [
- "150000"
- ],
- "gasPrice" : "10",
- "nonce" : "0",
- "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
- "to" : "",
- "value" : [
- "0"
- ]
- }
- }
-}
diff --git a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json b/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json
deleted file mode 100644
index 8b13ce103a..0000000000
--- a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json
+++ /dev/null
@@ -1,80 +0,0 @@
-{
- "CREATE_ContractSuicideDuringInit_ThenStoreThenReturn" : {
- "env" : {
- "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
- "currentDifficulty" : "0x020000",
- "currentGasLimit" : "10000000",
- "currentNumber" : "1",
- "currentTimestamp" : "1000"
- },
- "expect" : [
- {
- "indexes" : {
- "data" : -1,
- "gas" : -1,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
- "shouldnotexist" : "1"
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "storage" : {
- "0x01" : "0x0c"
- }
- },
- "d94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "10",
- "storage" : {
- "0x01" : "0x00"
- }
- }
- }
- }
- ],
- "pre" :
- {
- "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "1000000000000",
- "code" : "",
- "nonce" : "0",
- "storage" : {
- }
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "// code" : "This indicates that a call from transaction was initiated",
- "code" : "{[[1]]12}",
- "nonce" : "0",
- "storage" : {
- }
- },
- "d94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "// code" : "This indicates that a call from transaction was initiated",
- "code" : "{[[1]]12}",
- "nonce" : "0",
- "storage" : {
- }
- }
- },
- "transaction" : {
- "// data" : "{ (CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT 0xd94f5374fce5edbc8e2a8697c15331677e6ebf0b) (CALL 60000 0xd94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) [[0]]11 (RETURN 18 14)}",
- "data" : [
- ":raw 0x6000600060006000600073c94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f1506d64600c6000556000526005601bf360005273d94f5374fce5edbc8e2a8697c15331677e6ebf0bff6000600060006000600073d94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f150600b600055600e6012f3"
- ],
- "gasLimit" : [
- "600000"
- ],
- "gasPrice" : "10",
- "nonce" : "0",
- "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
- "to" : "",
- "value" : [
- "10"
- ]
- }
- }
-}
diff --git a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json b/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json
deleted file mode 100644
index e2ce0d3a8a..0000000000
--- a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "CREATE_ContractSuicideDuringInit_WithValue" : {
- "env" : {
- "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
- "currentDifficulty" : "0x020000",
- "currentGasLimit" : "10000000",
- "currentNumber" : "1",
- "currentTimestamp" : "1000"
- },
- "expect" : [
- {
- "indexes" : {
- "data" : -1,
- "gas" : -1,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
- "shouldnotexist" : "1"
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "10",
- "storage" : {
- "0x01" : "0x0c"
- }
- }
- }
- }
- ],
- "pre" :
- {
- "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "1000000000000",
- "code" : "",
- "nonce" : "0",
- "storage" : {
- }
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "// code" : "This indicates that a call from transaction was initiated",
- "code" : "{[[1]]12}",
- "nonce" : "0",
- "storage" : {
- }
- }
- },
- "transaction" : {
- "// data" : "{(CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b)}",
- "data" : [
- ":raw 0x6000600060006000600073c94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f1506d64600c6000556000526005601bf360005273c94f5374fce5edbc8e2a8697c15331677e6ebf0bff"
- ],
- "gasLimit" : [
- "150000"
- ],
- "gasPrice" : "10",
- "nonce" : "0",
- "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
- "to" : "",
- "value" : [
- "10"
- ]
- }
- }
-}
diff --git a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json b/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json
deleted file mode 100644
index fe8bf0a99d..0000000000
--- a/tests/eest/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "CREATE_ContractSuicideDuringInit_WithValueToItself" : {
- "env" : {
- "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
- "currentDifficulty" : "0x020000",
- "currentGasLimit" : "10000000",
- "currentNumber" : "1",
- "currentTimestamp" : "1000"
- },
- "expect" : [
- {
- "network" : [">=Cancun"],
- "result" : {
- "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
- "shouldnotexist" : "1"
- },
- "1a3e089e89a1d995552b4005c40cd5c8832b929b" : {
- "shouldnotexist" : "1"
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "storage" : {
- "0x01" : "0x0c"
- }
- }
- }
- }
- ],
- "pre" :
- {
- "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
- "balance" : "0",
- "code" : "",
- "nonce" : "1",
- "storage" : {
- }
- },
- "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "100000000000000",
- "code" : "",
- "nonce" : "0",
- "storage" : {
- }
- },
- "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "0",
- "// code" : "This indicates that a call from transaction was initiated",
- "code" : "{[[1]]12}",
- "nonce" : "0",
- "storage" : {
- }
- }
- },
- "transaction" : {
- "data" : [
- "{(CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT (ADDRESS))}"
- ],
- "gasLimit" : [
- "150000"
- ],
- "gasPrice" : "10",
- "nonce" : "0",
- "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
- "to" : "",
- "value" : [
- "10"
- ]
- }
- }
-}
diff --git a/tests/eest/static/state_tests/stSStoreTest/InitCollisionNonZeroNonceFiller.json b/tests/eest/static/state_tests/stSStoreTest/InitCollisionNonZeroNonceFiller.json
deleted file mode 100644
index ea62807efd..0000000000
--- a/tests/eest/static/state_tests/stSStoreTest/InitCollisionNonZeroNonceFiller.json
+++ /dev/null
@@ -1,161 +0,0 @@
-{
- "InitCollisionNonZeroNonce" : {
- "_info" : {
- "comment" : "account already has storage X. create -> in init code change that account's storage -> 0 -> change it to X again "
- },
- "env" : {
- "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
- "currentDifficulty" : "0x020000",
- "currentGasLimit" : "10000000",
- "currentNumber" : "1",
- "currentTimestamp" : "1000"
- },
- "expect" : [
- {
- "//comment" : "Collision on transaction create",
- "indexes" : {
- "data" : [0],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- },
- {
- "//comment" : "Collision on create2",
- "indexes" : {
- "data" : [1],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- },
- {
- "//comment" : "Collision on create2 and REVERT",
- "indexes" : {
- "data" : [2],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- },
- {
- "//comment" : "Collision on create2 and OOG",
- "indexes" : {
- "data" : [3],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- }
- ],
- "pre" :
- {
- "" : {
- "balance" : "1000000000000",
- "code" : "",
- "nonce" : "1",
- "storage" : {
- }
- },
- "" : {
- "//comment" : "transaction create account",
- "balance" : "",
- "code" : "",
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "//comment" : "Create2 account",
- "balance" : "",
- "code" : "",
- "nonce" : "1",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "balance" : "",
- "code" : "{ [[1]] 1 [[1]] 0 [[2]] 1 [[2]] 0 [[3]] 1 [[3]] 0 [[4]] 1 [[4]] 0 [[5]] 1 [[5]] 0 [[6]] 1 [[6]] 0 [[7]] 1 [[7]] 0 [[8]] 1 [[8]] 0 [[9]] 1 [[9]] 0 [[10]] 1 [[10]] 0 [[11]] 1 [[11]] 0 [[12]] 1 [[12]] 0 [[13]] 1 [[13]] 0 [[14]] 1 [[14]] 0 [[15]] 1 [[15]] 0 [[16]] 1 [[16]] 0 [[1]] 1 }",
- "nonce" : "1",
- "storage" : {
- }
- }
- },
- "transaction" : {
- "data" : [
- "{ (SSTORE 1 0) (SSTORE 1 1) }",
- "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (STOP) ) }",
- "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (REVERT 0 0) (STOP) ) }",
- "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (CALL 200000 0 0 0 0 0) (STOP) ) }"
- ],
- "gasLimit" : [
- "200000"
- ],
- "gasPrice" : "10",
- "nonce" : "1",
- "secretKey" : "",
- "to" : "",
- "value" : [
- "0"
- ]
- }
- }
-}
diff --git a/tests/eest/static/state_tests/stSStoreTest/InitCollisionParisFiller.json b/tests/eest/static/state_tests/stSStoreTest/InitCollisionParisFiller.json
deleted file mode 100644
index 77efbc57e0..0000000000
--- a/tests/eest/static/state_tests/stSStoreTest/InitCollisionParisFiller.json
+++ /dev/null
@@ -1,169 +0,0 @@
-{
- "InitCollisionParis" : {
- "_info" : {
- "comment" : "account already has storage X. create -> in init code change that account's storage -> 0 -> change it to X again "
- },
- "env" : {
- "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
- "currentDifficulty" : "0x020000",
- "currentGasLimit" : "10000000",
- "currentNumber" : "1",
- "currentTimestamp" : "1000"
- },
- "expect" : [
- {
- "//comment" : "Collision on transaction create",
- "indexes" : {
- "data" : [0],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- },
- {
- "//comment" : "Collision on create2",
- "indexes" : {
- "data" : [1],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- },
- {
- "//comment" : "Collision on create2 and REVERT",
- "indexes" : {
- "data" : [2],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- },
- {
- "//comment" : "Collision on create2 and OOG",
- "indexes" : {
- "data" : [3],
- "gas" : 0,
- "value" : -1
- },
- "network" : [">=Cancun"],
- "result" : {
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "balance" : "10",
- "nonce" : "0",
- "storage" : {
- "0x01" : "0x01"
- }
- }
- }
- }
- ],
- "pre" :
- {
- "" : {
- "balance" : "1000000000000",
- "code" : "",
- "nonce" : "0",
- "storage" : {
- }
- },
- "" : {
- "//comment" : "transaction create account",
- "balance" : "10",
- "code" : "",
- "nonce" : "",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "//comment" : "Create2 account",
- "balance" : "10",
- "code" : "",
- "nonce" : "",
- "storage" : {
- "0x01" : "0x01"
- }
- },
- "" : {
- "balance" : "",
- "code" : "{ [[1]] 1 [[1]] 0 [[2]] 1 [[2]] 0 [[3]] 1 [[3]] 0 [[4]] 1 [[4]] 0 [[5]] 1 [[5]] 0 [[6]] 1 [[6]] 0 [[7]] 1 [[7]] 0 [[8]] 1 [[8]] 0 [[9]] 1 [[9]] 0 [[10]] 1 [[10]] 0 [[11]] 1 [[11]] 0 [[12]] 1 [[12]] 0 [[13]] 1 [[13]] 0 [[14]] 1 [[14]] 0 [[15]] 1 [[15]] 0 [[16]] 1 [[16]] 0 [[1]] 1 }",
- "nonce" : "",
- "storage" : {
- }
- }
- },
- "transaction" : {
- "data" : [
- "{ (SSTORE 1 0) (SSTORE 1 1) }",
- "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (STOP) ) }",
- "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (REVERT 0 0) (STOP) ) }",
- "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (CALL 200000 0 0 0 0 0) (STOP) ) }"
- ],
- "gasLimit" : [
- "200000"
- ],
- "gasPrice" : "10",
- "nonce" : "0",
- "secretKey" : "",
- "to" : "",
- "value" : [
- "0"
- ]
- }
- }
-}
diff --git a/tests/eest/unscheduled/__init__.py b/tests/eest/unscheduled/__init__.py
index c0bc59e8d5..f4907906a2 100644
--- a/tests/eest/unscheduled/__init__.py
+++ b/tests/eest/unscheduled/__init__.py
@@ -1 +1,4 @@
-"""Test cases for unscheduled EVM functionality. A temporary home for features that are not yet CFI'd for inclusion in the next hardfork.""" # noqa: E501
+"""
+Test cases for unscheduled EVM functionality. A temporary home for features
+that are not yet CFI'd for inclusion in the next hardfork.
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/__init__.py
index 39b893bb4a..47bb9a0684 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/__init__.py
@@ -1,6 +1,6 @@
"""
-abstract: Test cases for [EIP-7692: EVM Object Format (EOFv1) Meta](https://eips.ethereum.org/EIPS/eip-7692)
- Test cases for the EIPs included in [EIP-7692 EOFv1 Meta](https://eips.ethereum.org/EIPS/eip-7692).
+Test cases for [EIP-7692: EVM Object Format (EOFv1) Meta](https://eips.ethereum.org/EIPS/eip-7692).
+ Test cases for the EIPs included in EIP-7692 EOFv1 Meta.
* [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663).
* [EIP-3540: EOF - EVM Object Format v1](https://eips.ethereum.org/EIPS/eip-3540).
@@ -16,7 +16,7 @@
## Devnet Specifications
-- [ethpandaops/eof-devnet-0](https://notes.ethereum.org/@ethpandaops/eof-devnet-0).
-""" # noqa: E501
+ - [ethpandaops/eof-devnet-0](https://notes.ethereum.org/@ethpandaops/eof-devnet-0).
+"""
EOF_FORK_NAME = "EOFv1"
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py
index de9eb0a8f9..3d69914537 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py
@@ -1,5 +1,10 @@
"""
-abstract: Test cases for [EIP-3540: EOF - EVM Object Format v1](https://eips.ethereum.org/EIPS/eip-3540)
- EIP-3540 introduces a structured format for EVM bytecode, with separate sections for code and data.
- Opcodes introduced: None (defines a new bytecode structure but no new opcodes).
-""" # noqa: E501
+EOF - EVM Object Format v1 tests.
+
+Test cases for
+[EIP-3540: EOF - EVM Object Format v1](https://eips.ethereum.org/EIPS/eip-3540).
+
+EIP-3540 introduces a structured format for EVM bytecode, with separate
+sections for code and data. Opcodes introduced: None (defines a new
+bytecode structure but no new opcodes).
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py
index 4d273ec5ac..9f5e816191 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py
@@ -2,7 +2,7 @@
from typing import List
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_vm import Opcodes as Op
V1_EOF_OPCODES: List[Op] = [
# new eof ops
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py
index c7310bcaf0..314c699838 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py
@@ -1,4 +1,7 @@
-"""EOF Container: check how every opcode behaves in the middle of the valid eof container code."""
+"""
+EOF Container: check how every opcode behaves in the middle of the valid eof
+container code.
+"""
import itertools
from typing import Any, Dict, Generator, List, Tuple
@@ -22,7 +25,8 @@
all_opcodes = set(Op)
undefined_opcodes = set(UndefinedOpcodes)
-# Invalid Opcodes will produce EOFException.UNDEFINED_INSTRUCTION when used in EOFContainer
+# Invalid Opcodes will produce EOFException.UNDEFINED_INSTRUCTION when used in
+# EOFContainer
invalid_eof_opcodes = {
Op.CODESIZE,
Op.SELFDESTRUCT,
@@ -44,7 +48,8 @@
valid_eof_opcodes = all_opcodes - invalid_eof_opcodes
-# Halting the execution opcodes can be placed without STOP instruction at the end
+# Halting the execution opcodes can be placed without STOP instruction at the
+# end
halting_opcodes = {
Op.STOP,
Op.RETURNCODE,
@@ -53,7 +58,8 @@
Op.INVALID,
}
-# Opcodes that end the code section and can be placed without STOP instruction at the end
+# Opcodes that end the code section and can be placed without STOP instruction
+# at the end
section_terminating_opcodes = {
Op.RETF,
Op.JUMPF,
@@ -62,7 +68,8 @@
data_portion_opcodes = {op for op in all_opcodes if op.has_data_portion()}
-# NOTE: `sorted` is used to ensure that the tests are collected in a deterministic order.
+# NOTE: `sorted` is used to ensure that the tests are collected in a
+# deterministic order.
@pytest.mark.parametrize(
@@ -74,8 +81,7 @@ def test_all_opcodes_in_container(
opcode: Opcode,
):
"""
- Test all opcodes inside valid container
- 257 because 0x5B is duplicated.
+ Test all opcodes inside valid container 257 because 0x5B is duplicated.
"""
data_portion = 1 if opcode == Op.CALLF else 0
opcode_with_data_portion = opcode[data_portion] if opcode.has_data_portion() else opcode
@@ -134,7 +140,10 @@ def test_invalid_opcodes_after_stop(
opcode: Opcode,
terminating_opcode: Opcode,
):
- """Test that an invalid opcode placed after STOP (terminating instruction) invalidates EOF."""
+ """
+ Test that an invalid opcode placed after STOP (terminating instruction)
+ invalidates EOF.
+ """
terminating_code = Bytecode(terminating_opcode)
match terminating_opcode: # Enhance the code for complex opcodes.
case Op.RETURNCODE:
@@ -180,8 +189,9 @@ def test_all_invalid_terminating_opcodes(
):
"""Test all opcodes that are invalid as the last opcode in a container."""
if opcode.has_data_portion():
- # Add the appropriate data portion to the opcode by using the get_item method.
- # On the CALLF opcode we need to reference the second code section, hence the [1] index.
+ # Add the appropriate data portion to the opcode by using the get_item
+ # method. On the CALLF opcode we need to reference the second code
+ # section, hence the [1] index.
opcode = opcode[0] if opcode != Op.CALLF else opcode[1]
bytecode = (Op.PUSH0 * opcode.min_stack_height) + opcode
@@ -322,11 +332,13 @@ def test_all_unreachable_terminating_opcodes_before_stop(
@pytest.mark.parametrize(
"exception",
# We test two types of exceptions here:
- # 1. Invalid max stack height, where we modify the `max_stack_height` field of the code section
- # to the maximum stack height allowed by the EIP-3540, so the code still has to be checked
- # for stack overflow.
- # 2. Max stack height above limit, where we don't modify the `max_stack_height` field of the
- # code section, so the actual code doesn't have to be verified for the stack overflow.
+ # 1. Invalid max stack height, where we modify the `max_stack_height`
+ # field of the code section to the maximum stack height allowed by
+ # the EIP-3540, so the code still has to be checked for stack overflow.
+ #
+ # 2. Max stack height above limit, where we don't modify the
+ # `max_stack_height` field of the code section, so the actual
+ # code doesn't have to be verified for the stack overflow.
[EOFException.INVALID_MAX_STACK_INCREASE, EOFException.MAX_STACK_INCREASE_ABOVE_LIMIT],
)
def test_all_opcodes_stack_overflow(
@@ -334,7 +346,9 @@ def test_all_opcodes_stack_overflow(
opcode: Opcode,
exception: EOFException,
):
- """Test stack overflow on all opcodes that push more items than they pop."""
+ """
+ Test stack overflow on all opcodes that push more items than they pop.
+ """
opcode = opcode[0] if opcode.has_data_portion() else opcode
assert opcode.pushed_stack_items - opcode.popped_stack_items == 1
@@ -347,7 +361,8 @@ def test_all_opcodes_stack_overflow(
kwargs: Dict[str, Any] = {"code": bytecode}
if exception == EOFException.INVALID_MAX_STACK_INCREASE:
- # Lie about the max stack height to make the code be checked for stack overflow.
+ # Lie about the max stack height to make the code be checked for stack
+ # overflow.
kwargs["max_stack_height"] = MAX_STACK_INCREASE_LIMIT
sections = [Section.Code(**kwargs)]
@@ -367,13 +382,17 @@ def valid_opcode_combinations(
truncate_all_options: List[bool],
opcodes: List[Opcode],
) -> Generator[Tuple[bool, bool, Opcode], None, None]:
- """Create valid parameter combinations for test_truncated_data_portion_opcodes()."""
+ """
+ Create valid parameter combinations for
+ test_truncated_data_portion_opcodes().
+ """
for opcode, truncate_all, compute_max_stack_height in itertools.product(
opcodes, truncate_all_options, compute_max_stack_height_options
):
opcode_with_data_portion: bytes = bytes(opcode[1])
- # Skip invalid or redundant combinations to avoid using pytest.skip in the test
+ # Skip invalid or redundant combinations to avoid using pytest.skip in
+ # the test
if len(opcode_with_data_portion) == 2 and truncate_all:
continue
if (
@@ -401,7 +420,8 @@ def test_truncated_data_portion_opcodes(
"""
opcode_with_data_portion: bytes = bytes(opcode[1])
- # Compose instruction bytes with empty imm bytes (truncate_all) or 1 byte shorter imm bytes.
+ # Compose instruction bytes with empty imm bytes (truncate_all) or 1 byte
+ # shorter imm bytes.
opcode_bytes = opcode_with_data_portion[0:1] if truncate_all else opcode_with_data_portion[:-1]
if opcode.min_stack_height > 0:
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py
index 1cc141fc03..5dfbccb173 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py
@@ -27,7 +27,8 @@ def test_max_size(
over_limit: int,
):
"""Verify EOF container valid at maximum size, invalid above."""
- # Expand the minimal EOF code by more noop code, reaching the desired target container size.
+ # Expand the minimal EOF code by more noop code, reaching the desired
+ # target container size.
code = Container(
sections=[
Section.Code(
@@ -52,7 +53,10 @@ def test_above_max_size_raw(
eof_test: EOFTestFiller,
size: int,
):
- """Verify EOF container invalid above maximum size, regardless of header contents."""
+ """
+ Verify EOF container invalid above maximum size, regardless of header
+ contents.
+ """
code = Op.INVALID * size
eof_test(
container=Container(raw_bytes=code),
@@ -101,7 +105,10 @@ def test_section_after_end_of_container(
eof_test: EOFTestFiller,
code: Container,
):
- """Verify EOF container is invalid if any of sections declares above container size."""
+ """
+ Verify EOF container is invalid if any of sections declares above container
+ size.
+ """
eof_test(
container=code,
expect_exception=EOFException.INVALID_SECTION_BODIES_SIZE,
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py
index ce669cad84..b06ab65fbe 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py
@@ -5,7 +5,6 @@
import pytest
from ethereum_test_tools import EOFException, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import (
AutoSection,
Container,
@@ -19,6 +18,7 @@
MAX_CODE_SECTIONS,
MAX_STACK_INCREASE_LIMIT,
)
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -406,13 +406,15 @@ def test_valid_containers(
validity_error=EOFException.MISSING_CODE_HEADER,
),
Container(
- # EOF code containing multiple type headers, second one matches code length
+ # EOF code containing multiple type headers, second one matches
+ # code length
name="multiple_type_headers_2",
raw_bytes="ef0001010004010001ff00000000800000fe",
validity_error=EOFException.MISSING_CODE_HEADER,
),
Container(
- # EOF code containing multiple type headers followed by 2 code sections
+ # EOF code containing multiple type headers followed by 2 code
+ # sections
name="multiple_type_headers_3",
sections=[
Section(kind=SectionKind.TYPE, data="00800000"),
@@ -486,8 +488,8 @@ def test_valid_containers(
],
),
# The basic `no_section_terminator` cases just remove the terminator
- # and the `00` for zeroth section inputs looks like one. Error is because
- # the sections are wrongly sized.
+ # and the `00` for zeroth section inputs looks like one. Error is
+ # because the sections are wrongly sized.
Container(
name="no_section_terminator",
header_terminator=bytes(),
@@ -521,9 +523,9 @@ def test_valid_containers(
EOFException.INVALID_FIRST_SECTION_TYPE,
],
),
- # The following cases just remove the terminator
- # and the `00` for zeroth section inputs looks like one. Section bodies
- # are as the size prescribes here, so the error is about the inputs of zeroth section.
+ # The following cases just remove the terminator and the `00` for
+ # zeroth section inputs looks like one. Section bodies are as the size
+ # prescribes here, so the error is about the inputs of zeroth section.
Container(
name="no_section_terminator_section_bodies_ok_1",
header_terminator=bytes(),
@@ -536,8 +538,8 @@ def test_valid_containers(
sections=[Section.Code(code=Op.JUMPDEST * 2 + Op.STOP, custom_size=2)],
validity_error=EOFException.INVALID_FIRST_SECTION_TYPE,
),
- # Here the terminator is missing but made to look like a different section
- # or arbitrary byte
+ # Here the terminator is missing but made to look like a different
+ # section or arbitrary byte
Container(
name="no_section_terminator_nonzero",
header_terminator=b"01",
@@ -625,7 +627,8 @@ def test_valid_containers(
Container(
name="empty_code_section",
sections=[Section.Code(code="0x")],
- # TODO the exception must be about code section EOFException.INVALID_CODE_SECTION,
+ # TODO the exception must be about code section
+ # EOFException.INVALID_CODE_SECTION,
validity_error=EOFException.ZERO_SECTION_SIZE,
),
Container(
@@ -634,7 +637,8 @@ def test_valid_containers(
Section.Code(code="0x"),
Section.Data(data="0xDEADBEEF"),
],
- # TODO the exception must be about code section EOFException.INVALID_CODE_SECTION,
+ # TODO the exception must be about code section
+ # EOFException.INVALID_CODE_SECTION,
validity_error=EOFException.ZERO_SECTION_SIZE,
),
Container(
@@ -684,7 +688,8 @@ def test_valid_containers(
Container(
name="data_section_without_code_section",
sections=[Section.Data(data="0xDEADBEEF")],
- # TODO the actual exception should be EOFException.MISSING_CODE_HEADER
+ # TODO the actual exception should be
+ # EOFException.MISSING_CODE_HEADER
validity_error=[EOFException.ZERO_SECTION_SIZE, EOFException.UNEXPECTED_HEADER_KIND],
),
Container(
@@ -1059,7 +1064,8 @@ def test_valid_containers(
Section.Code(code=Op.POP + Op.RETF, code_inputs=1),
Section.Code(Op.STOP),
],
- # TODO the actual exception should be EOFException.INVALID_TYPE_BODY,
+ # TODO the actual exception should be
+ # EOFException.INVALID_TYPE_BODY,
validity_error=EOFException.INVALID_FIRST_SECTION_TYPE,
),
Container(
@@ -1068,7 +1074,8 @@ def test_valid_containers(
Section.Code(code=Op.PUSH0, code_outputs=1),
Section.Code(Op.STOP),
],
- # TODO the actual exception should be EOFException.INVALID_TYPE_BODY,
+ # TODO the actual exception should be
+ # EOFException.INVALID_TYPE_BODY,
validity_error=EOFException.INVALID_FIRST_SECTION_TYPE,
),
Container(
@@ -1158,7 +1165,8 @@ def test_valid_containers(
max_stack_height=1024,
),
],
- # TODO auto types section generation probably failed, the exception must be about code
+ # TODO auto types section generation probably failed, the exception
+ # must be about code
validity_error=EOFException.MAX_STACK_INCREASE_ABOVE_LIMIT,
),
],
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py
index 3970dd5fd7..5263afbedc 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py
@@ -23,13 +23,16 @@ def test_eof_example(eof_test: EOFTestFiller):
# TYPES section is constructed automatically based on CODE
# CODE section
Section.Code(
- code=Op.CALLF[1](Op.PUSH0) + Op.STOP, # bytecode to be deployed in the body
+ code=Op.CALLF[1](Op.PUSH0) + Op.STOP, # bytecode to be
+ # deployed in the body
# Code: call section 1 with a single zero as input, then stop.
- max_stack_increase=1, # define code header (in body) stack size
+ max_stack_increase=1, # define code header (in body) stack
+ # size
),
# There can be multiple code sections
Section.Code(
- # Remove input and call section 2 with no inputs, then remove output and return
+ # Remove input and call section 2 with no inputs, then remove
+ # output and return
code=Op.POP + Op.CALLF[2]() + Op.POP + Op.RETF,
code_inputs=1,
code_outputs=0,
@@ -64,45 +67,56 @@ def test_eof_example(eof_test: EOFTestFiller):
def test_eof_example_custom_fields(eof_test: EOFTestFiller):
"""Example of python EOF container class tuning."""
- # if you need to overwrite certain structure bytes, you can use customization
- # this is useful for unit testing the eof structure format, you can reorganize sections
- # and overwrite the header bytes for testing purposes
- # most of the combinations are covered by the unit tests
+ # if you need to overwrite certain structure bytes, you can use
+ # customization. this is useful for unit testing the eof structure format,
+ # you can reorganize sections and overwrite the header bytes for testing
+ # purposes. most of the combinations are covered by the unit tests
# This features are subject for development and will change in the future
eof_code = Container(
name="valid_container_example_2",
- magic=b"\xef\x00", # magic can be overwritten for test purposes, (default is 0xEF00)
- version=b"\x01", # version can be overwritten for testing purposes (default is 0x01)
- header_terminator=b"\x00", # terminator byte can be overwritten (default is 0x00)
- extra=b"", # extra bytes to be trailed after the container body bytes (default is None)
+ magic=b"\xef\x00", # magic can be overwritten for test purposes,
+ # (default is 0xEF00)
+ version=b"\x01", # version can be overwritten for testing purposes
+ # (default is 0x01)
+ header_terminator=b"\x00", # terminator byte can be overwritten
+ # (default is 0x00)
+ extra=b"", # extra bytes to be trailed after the container body bytes
+ # (default is None)
sections=[
# TYPES section is constructed automatically based on CODE
# CODE section
Section.Code(
- code=Op.PUSH1(2)
- + Op.STOP, # this is the actual bytecode to be deployed in the body
+ code=Op.PUSH1(2) + Op.STOP, # this is the actual bytecode to be deployed in the
+ # body
max_stack_height=1, # define code header (in body) stack size
),
# DATA section
Section.Data(
data="0xef",
- # custom_size overrides the size bytes, so you can put only 1 byte into data
- # but still make the header size of 2 to produce invalid section
+ # custom_size overrides the size bytes, so you can put only 1
+ # byte into data but still make the header size of 2 to produce
+ # invalid section
+ #
# if custom_size != len(data), the section will be invalid
custom_size=1,
),
],
# auto generate types section based on provided code sections
- # AutoSection.ONLY_BODY - means the section will be generated only for the body bytes
- # AutoSection.ONLY_BODY - means the section will be generated only for the header bytes
+ # AutoSection.ONLY_BODY - means the section will be generated only for
+ # the body bytes
+ #
+ # AutoSection.ONLY_BODY - means the section will be generated only for
+ # the header bytes
auto_type_section=AutoSection.AUTO,
# auto generate default data section (0x empty), by default is True
auto_data_section=True,
# auto sort section by order 01 02 03 04
- # AutoSection.ONLY_BODY - means the sorting will be done only for the body bytes
- # AutoSection.ONLY_BODY - means the section will be done only for the header bytes
+ # AutoSection.ONLY_BODY - means the sorting will be done only for the
+ # body bytes
+ # AutoSection.ONLY_BODY - means the section will be done only for the
+ # header bytes
auto_sort_sections=AutoSection.AUTO,
)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py
index 676610b9de..609ebb643c 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py
@@ -4,8 +4,8 @@
from ethereum_test_base_types import Storage
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py
index 212d86f502..9d36525d65 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py
@@ -5,9 +5,9 @@
import pytest
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_CODE_SECTIONS, MAX_RETURN_STACK_HEIGHT
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -419,7 +419,7 @@ def test_eof_functions_contract_call_within_deep_nested(
sender=sender,
)
post = {
- callee_address: Account(storage={i: 1 for i in range(MAX_CODE_SECTIONS)}),
+ callee_address: Account(storage=dict.fromkeys(range(MAX_CODE_SECTIONS), 1)),
nested_callee_address: Account(
storage={
0: 1,
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py
index 0dfabd0445..3916f8570f 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py
@@ -48,7 +48,8 @@
pytest.param(Op.DATASIZE, id="DATASIZE"),
pytest.param(Op.DATACOPY(0, 0, 32), id="DATACOPY"),
pytest.param(Op.EOFCREATE[0](0, 0, 0, 0), id="EOFCREATE"),
- # pytest.param(Op.TXCREATE(0, 0, 0, 0, 0), id="TXCREATE"), not EOF-only anymore
+ # pytest.param(Op.TXCREATE(0, 0, 0, 0, 0), id="TXCREATE"), not EOF-only
+ # anymore
pytest.param(Op.RETURNCODE[0], id="RETURNCODE"),
]
@@ -67,7 +68,8 @@ def test_opcodes_in_legacy(state_test: StateTestFiller, pre: Alloc, code: Opcode
)
post = {
- # assert the canary is not over-written. If it was written then the EOF opcode was valid
+ # assert the canary is not over-written. If it was written then the EOF
+ # opcode was valid
address_test_contract: Account(storage={slot_code_executed: value_non_execution_canary}),
}
@@ -209,7 +211,8 @@ def test_opcodes_in_eof_calling_legacy(
)
post = {
- # assert the canary is not over-written. If it was written then the EOF opcode was valid
+ # assert the canary is not over-written. If it was written then the EOF
+ # opcode was valid
address_test_contract: Account(storage={slot_code_executed: value_non_execution_canary}),
address_entry_contract: Account(
storage={
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py
index 4292914e63..d1b11bea5c 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py
@@ -18,10 +18,14 @@
@pytest.mark.parametrize(
**extend_with_defaults(
defaults={
- "skip_header_listing": False, # second section is mentioned in code header array
- "skip_body_listing": False, # second section code is in container's body
- "skip_types_body_listing": False, # code input bytes not listed in container's body
- "skip_types_header_listing": False, # code input bytes size not added to types section size # noqa: E501
+ # second section is mentioned in code header array
+ "skip_header_listing": False,
+ # second section code is in container's body
+ "skip_body_listing": False,
+ # code input bytes not listed in container's body
+ "skip_types_body_listing": False,
+ # code input bytes size not added to types section size
+ "skip_types_header_listing": False,
"expected_code": "",
"expected_exception": None,
},
@@ -30,7 +34,8 @@
{
"skip_header_listing": True,
"skip_body_listing": True,
- "expected_code": "ef00010100080200010003ff00040000800001000000003050000bad60A7", # noqa: E501
+ "expected_code": "ef00010100080200010003ff0004000080000"
+ "1000000003050000bad60A7",
"expected_exception": [
EOFException.INVALID_TYPE_SECTION_SIZE,
EOFException.INVALID_SECTION_BODIES_SIZE,
@@ -42,7 +47,8 @@
{
"skip_header_listing": True,
"skip_body_listing": False,
- "expected_code": "ef00010100080200010003ff00040000800001000000003050003050000bad60A7", # noqa: E501
+ "expected_code": "ef00010100080200010003ff0004000080000"
+ "1000000003050003050000bad60A7",
"expected_exception": [
EOFException.INVALID_TYPE_SECTION_SIZE,
EOFException.INVALID_SECTION_BODIES_SIZE,
@@ -54,7 +60,8 @@
{
"skip_header_listing": False,
"skip_body_listing": True,
- "expected_code": "ef000101000802000200030003ff00040000800001000000003050000bad60A7", # noqa: E501
+ "expected_code": "ef000101000802000200030003ff000400008"
+ "00001000000003050000bad60A7",
"expected_exception": [
EOFException.UNREACHABLE_CODE_SECTIONS,
EOFException.TOPLEVEL_CONTAINER_TRUNCATED,
@@ -66,7 +73,8 @@
{
"skip_header_listing": False,
"skip_body_listing": False,
- "expected_code": "ef000101000802000200030003ff00040000800001000000003050003050000bad60A7", # noqa: E501
+ "expected_code": "ef000101000802000200030003ff000400008"
+ "00001000000003050003050000bad60A7",
"expected_exception": EOFException.UNREACHABLE_CODE_SECTIONS,
},
id="layout_ok_code_bad",
@@ -125,7 +133,8 @@ def test_code_section_header_body_mismatch(
skip_body_listing=skip_body_listing,
# whether to not print its input bytes in containers body
skip_types_body_listing=skip_types_body_listing,
- # whether to not calculate its input bytes size in types section's header
+ # whether to not calculate its input bytes size in types
+ # section's header
skip_types_header_listing=skip_types_header_listing,
),
Section.Data("0x0bad60A7"),
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py
index 8e5f7c6da0..aae8c4af0b 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py
@@ -36,7 +36,9 @@ class CasePosition(Enum):
def get_expected_code_exception(
section_kind, section_test, test_position
) -> tuple[str, EOFExceptionInstanceOrList | None]:
- """Verification vectors with code and exception based on test combinations."""
+ """
+ Verification vectors with code and exception based on test combinations.
+ """
match (section_kind, section_test, test_position):
case (SectionKind.TYPE, SectionTest.MISSING, CasePosition.HEADER):
return (
@@ -64,7 +66,8 @@ def get_expected_code_exception(
case (SectionKind.TYPE, SectionTest.WRONG_ORDER, CasePosition.BODY):
return (
"ef00010100040200010003ff00010030500000800001ef",
- # TODO why invalid first section type? it should say that the body incorrect
+ # TODO why invalid first section type? it should say that the
+ # body incorrect
EOFException.INVALID_FIRST_SECTION_TYPE,
)
case (SectionKind.TYPE, SectionTest.WRONG_ORDER, CasePosition.BODY_AND_HEADER):
@@ -80,8 +83,8 @@ def get_expected_code_exception(
case (SectionKind.CODE, SectionTest.MISSING, CasePosition.BODY):
return (
"ef00010100040200010003ff00010000800001ef",
- # TODO should be an exception of empty code bytes, because it can understand that
- # last byte is data section byte
+ # TODO should be an exception of empty code bytes, because it
+ # can understand that last byte is data section byte
[EOFException.INVALID_SECTION_BODIES_SIZE, EOFException.UNEXPECTED_HEADER_KIND],
)
case (SectionKind.CODE, SectionTest.MISSING, CasePosition.BODY_AND_HEADER):
@@ -230,17 +233,17 @@ def test_container_section_order(
test_position: CasePosition,
):
"""
- Test containers section being out of order in the header and/or body.
- This extends and follows the convention of the test_section_order()
- for the optional container section.
+ Test containers section being out of order in the header and/or body. This
+ extends and follows the convention of the test_section_order() for the
+ optional container section.
"""
if container_position == 2:
pytest.skip("Skip valid container section position")
section_code = Section.Code(
code=Op.EOFCREATE[0](0, 0, 0, 0)
- # TODO: Migrated tests had the following infinite loop, so it is kept here
- # to equalize code coverage.
+ # TODO: Migrated tests had the following infinite loop, so it is kept
+ # here to equalize code coverage.
+ Op.RJUMP[0]
+ Op.STOP()
)
@@ -270,7 +273,8 @@ def get_expected_exception():
return EOFException.INVALID_FIRST_SECTION_TYPE
case 1, CasePosition.BODY: # Messes up with the code section
return EOFException.UNDEFINED_INSTRUCTION
- case 3, CasePosition.BODY: # Data section messes up with the container section
+ case 3, CasePosition.BODY: # Data section messes up with the
+ # container section
return EOFException.INVALID_MAGIC
case 0, CasePosition.HEADER | CasePosition.BODY_AND_HEADER:
return EOFException.MISSING_TYPE_HEADER
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py
index 6fecfe1799..f5ea074b85 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py
@@ -120,7 +120,9 @@ def test_section_size(
section_kind: SectionKind,
exception: EOFExceptionInstanceOrList,
):
- """Test custom_size is auto, more or less than the actual size of the section."""
+ """
+ Test custom_size is auto, more or less than the actual size of the section.
+ """
eof_code = Container()
if section_size != SectionSize.NORMAL and section_kind == SectionKind.TYPE:
@@ -183,8 +185,8 @@ def test_section_size(
@pytest.mark.parametrize(
"truncation_len, exception",
[
- # The original container is not valid by itself because its 2-byte code section
- # starts with the terminating instruction: INVALID.
+ # The original container is not valid by itself because its 2-byte code
+ # section starts with the terminating instruction: INVALID.
pytest.param(0, EOFException.UNREACHABLE_INSTRUCTIONS),
pytest.param(1, EOFException.INVALID_SECTION_BODIES_SIZE, id="EOF1_truncated_section_2"),
pytest.param(3, EOFException.INVALID_SECTION_BODIES_SIZE, id="EOF1_truncated_section_1"),
@@ -198,7 +200,8 @@ def test_truncated_container_without_data(
):
"""
Test takes a semi-valid container and removes some bytes from its tail.
- Migrated from EOFTests/efValidation/EOF1_truncated_section_.json (cases without data section).
+ Migrated from EOFTests/efValidation/EOF1_truncated_section_.json (cases
+ without data section).
"""
container = Container(sections=[Section.Code(Op.INVALID + Op.INVALID)])
bytecode = bytes(container)
@@ -222,8 +225,9 @@ def test_truncated_container_with_data(
exception: EOFException,
):
"""
- Test takes a valid container with data and removes some bytes from its tail.
- Migrated from EOFTests/efValidation/EOF1_truncated_section_.json (cases with data section).
+ Test takes a valid container with data and removes some bytes from its
+ tail. Migrated from EOFTests/efValidation/EOF1_truncated_section_.json
+ (cases with data section).
"""
data = b"\xaa\xbb"
container = Container(
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py
index 4eef21b71a..f08cf8e60e 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py
@@ -1,5 +1,7 @@
"""
-abstract: Test cases for [EIP-4200: EOF - Static relative jumps](https://eips.ethereum.org/EIPS/eip-4200)
- EIP-4200 replaces dynamic jump instructions with relative jump offsets for improved control flow predictability.
- Opcodes introduced: `RJUMP` (`0xE0`), `RJUMPI` (`0xE1`), `RJUMPV` (`0xE2`).
-""" # noqa: E501
+Test cases for [EIP-4200: EOF - Static relative jumps](https://eips.ethereum.org/EIPS/eip-4200).
+
+EIP-4200 replaces dynamic jump instructions with relative jump offsets for
+improved control flow predictability. Opcodes introduced: `RJUMP` (`0xE0`),
+`RJUMPI` (`0xE1`), `RJUMPV` (`0xE2`).
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py
index 96fdef127f..490bea5297 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py
@@ -3,10 +3,10 @@
import pytest
from ethereum_test_tools import Account, EOFException, EOFStateTestFiller, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE
from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import JumpDirection, slot_code_worked, value_code_worked
@@ -39,7 +39,9 @@ def test_rjump_negative(
def test_rjump_positive_negative(
eof_state_test: EOFStateTestFiller,
):
- """EOF1V4200_0001 (Valid) EOF code containing RJUMP (Positive, Negative)."""
+ """
+ EOF1V4200_0001 (Valid) EOF code containing RJUMP (Positive, Negative).
+ """
eof_state_test(
container=Container.Code(
Op.PUSH0
@@ -68,7 +70,10 @@ def test_rjump_zero(
def test_rjump_maxes(
eof_state_test: EOFStateTestFiller,
):
- """EOF1V4200_0003 EOF with RJUMP containing the max positive and negative offset (32767)."""
+ """
+ EOF1V4200_0003 EOF with RJUMP containing the max positive and negative
+ offset (32767).
+ """
eof_state_test(
container=Container.Code(
Op.PUSH0
@@ -87,8 +92,8 @@ def test_rjump_max_bytecode_size(
eof_test: EOFTestFiller,
):
"""
- EOF1V4200_0003 EOF with RJUMP containing the maximum offset that does not exceed the maximum
- bytecode size.
+ EOF1V4200_0003 EOF with RJUMP containing the maximum offset that does not
+ exceed the maximum bytecode size.
"""
noop_count = MAX_BYTECODE_SIZE - 27
code = (
@@ -128,8 +133,8 @@ def test_rjump_into_header(
offset: int,
):
"""
- EOF1I4200_0003 (Invalid) EOF code containing RJUMP with target outside code bounds
- (Jumping into header).
+ EOF1I4200_0003 (Invalid) EOF code containing RJUMP with target outside code
+ bounds (Jumping into header).
"""
eof_test(
container=Container.Code(Op.RJUMP[offset]),
@@ -141,8 +146,8 @@ def test_rjump_before_header(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0004 (Invalid) EOF code containing RJUMP with target outside code bounds
- (Jumping before code begin).
+ EOF1I4200_0004 (Invalid) EOF code containing RJUMP with target outside code
+ bounds (Jumping before code begin).
"""
eof_test(
container=Container.Code(Op.RJUMP[-23]),
@@ -154,8 +159,8 @@ def test_rjump_into_data(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0005 (Invalid) EOF code containing RJUMP with target outside code bounds
- (Jumping into data section).
+ EOF1I4200_0005 (Invalid) EOF code containing RJUMP with target outside code
+ bounds (Jumping into data section).
"""
eof_test(
container=Container(
@@ -171,7 +176,10 @@ def test_rjump_into_data(
def test_rjump_outside_other_section_before(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMP with target outside code bounds (prior code section)."""
+ """
+ EOF code containing RJUMP with target outside code bounds (prior code
+ section).
+ """
eof_test(
container=Container(
sections=[
@@ -186,7 +194,10 @@ def test_rjump_outside_other_section_before(
def test_rjump_outside_other_section_after(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMP with target outside code bounds (Subsequent code section)."""
+ """
+ EOF code containing RJUMP with target outside code bounds (Subsequent code
+ section).
+ """
eof_test(
container=Container(
sections=[
@@ -203,8 +214,8 @@ def test_rjump_after_container(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0006 (Invalid) EOF code containing RJUMP with target outside code bounds
- (Jumping after code end).
+ EOF1I4200_0006 (Invalid) EOF code containing RJUMP with target outside code
+ bounds (Jumping after code end).
"""
eof_test(
container=Container.Code(Op.RJUMP[2]),
@@ -216,8 +227,8 @@ def test_rjump_to_code_end(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0007 (Invalid) EOF code containing RJUMP with target outside code bounds
- (Jumping to code end).
+ EOF1I4200_0007 (Invalid) EOF code containing RJUMP with target outside code
+ bounds (Jumping to code end).
"""
eof_test(
container=Container.Code(Op.RJUMP[1] + Op.STOP),
@@ -230,7 +241,10 @@ def test_rjump_into_self_data_portion(
eof_test: EOFTestFiller,
offset: int,
):
- """EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP immediate."""
+ """
+ EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP
+ immediate.
+ """
eof_test(
container=Container.Code(Op.RJUMP[-offset] + Op.STOP),
expect_exception=EOFException.INVALID_RJUMP_DESTINATION,
@@ -241,8 +255,8 @@ def test_rjump_into_self_remaining_code(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP but remaining
- unreachable code.
+ EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP
+ but remaining unreachable code.
"""
eof_test(
container=Container.Code(Op.RJUMP[-len(Op.RJUMP[0])] + Op.STOP),
@@ -269,7 +283,10 @@ def test_rjump_into_self(
def test_rjump_into_self_pre_code(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMP with target self RJUMP with non-zero stack before RJUMP."""
+ """
+ EOF code containing RJUMP with target self RJUMP with non-zero stack before
+ RJUMP.
+ """
eof_test(
container=Container.Code(Op.PUSH1[0] + Op.RJUMP[-len(Op.RJUMP[0])]),
)
@@ -455,8 +472,8 @@ def test_rjump_valid_forward(
container: Container,
):
"""
- Validate a valid code section containing at least one forward RJUMP.
- These tests exercise the stack height validation.
+ Validate a valid code section containing at least one forward RJUMP. These
+ tests exercise the stack height validation.
"""
eof_test(container=container)
@@ -551,8 +568,8 @@ def test_rjump_valid_backward(
container: Container,
):
"""
- Validate a valid code section containing at least one backward RJUMP.
- These tests exercise the stack height validation.
+ Validate a valid code section containing at least one backward RJUMP. These
+ tests exercise the stack height validation.
"""
eof_test(container=container)
@@ -560,7 +577,10 @@ def test_rjump_valid_backward(
def test_rjump_into_stack_height_diff(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMP with target instruction that causes stack height difference."""
+ """
+ EOF code containing RJUMP with target instruction that causes stack height
+ difference.
+ """
eof_test(
container=Container.Code(Op.PUSH1[0] + Op.RJUMP[-(len(Op.RJUMP[0]) + len(Op.PUSH1[0]))]),
expect_exception=EOFException.STACK_HEIGHT_MISMATCH,
@@ -570,7 +590,10 @@ def test_rjump_into_stack_height_diff(
def test_rjump_into_stack_height_diff_2(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMP with target instruction that cause stack height difference."""
+ """
+ EOF code containing RJUMP with target instruction that cause stack height
+ difference.
+ """
eof_test(
container=Container.Code(
Op.PUSH1[0] + Op.POP + Op.RJUMP[-(len(Op.RJUMP[0]) + len(Op.POP))]
@@ -757,8 +780,8 @@ def test_rjump_backward_invalid_max_stack_height(
container: Container,
):
"""
- Validate a code section containing at least one backward RJUMP
- invalid because of the incorrect max stack height.
+ Validate a code section containing at least one backward RJUMP invalid
+ because of the incorrect max stack height.
"""
eof_test(container=container, expect_exception=EOFException.STACK_HEIGHT_MISMATCH)
@@ -766,7 +789,10 @@ def test_rjump_backward_invalid_max_stack_height(
def test_rjump_into_stack_underflow(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMP with target instruction that cause stack underflow."""
+ """
+ EOF code containing RJUMP with target instruction that cause stack
+ underflow.
+ """
eof_test(
container=Container.Code(
Op.ORIGIN
@@ -783,7 +809,10 @@ def test_rjump_into_stack_underflow(
def test_rjump_into_rjump(
eof_test: EOFTestFiller,
):
- """EOF1I4200_0009 (Invalid) EOF code containing RJUMP with target other RJUMP immediate."""
+ """
+ EOF1I4200_0009 (Invalid) EOF code containing RJUMP with target other RJUMP
+ immediate.
+ """
eof_test(
container=Container.Code(Op.RJUMP[1] + Op.RJUMP[0]),
expect_exception=EOFException.INVALID_RJUMP_DESTINATION,
@@ -793,7 +822,10 @@ def test_rjump_into_rjump(
def test_rjump_into_rjumpi(
eof_test: EOFTestFiller,
):
- """EOF1I4200_0010 (Invalid) EOF code containing RJUMP with target RJUMPI immediate."""
+ """
+ EOF1I4200_0010 (Invalid) EOF code containing RJUMP with target RJUMPI
+ immediate.
+ """
eof_test(
container=Container.Code(Op.RJUMP[5] + Op.STOP + Op.PUSH1[1] + Op.RJUMPI[-6] + Op.STOP),
expect_exception=EOFException.INVALID_RJUMP_DESTINATION,
@@ -802,7 +834,10 @@ def test_rjump_into_rjumpi(
@pytest.mark.parametrize("jump", [JumpDirection.FORWARD, JumpDirection.BACKWARD])
def test_rjump_into_push_1(eof_test: EOFTestFiller, jump: JumpDirection):
- """EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH1 immediate."""
+ """
+ EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH1
+ immediate.
+ """
code = (
Op.PUSH1[1] + Op.RJUMP[-4] if jump == JumpDirection.BACKWARD else Op.RJUMP[1] + Op.PUSH1[1]
) + Op.STOP
@@ -860,7 +895,10 @@ def test_rjump_into_push_n(
jump: JumpDirection,
data_portion_end: bool,
):
- """EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH2+ immediate."""
+ """
+ EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH2+
+ immediate.
+ """
data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F
if jump == JumpDirection.FORWARD:
offset = data_portion_length if data_portion_end else 1
@@ -885,7 +923,10 @@ def test_rjump_into_rjumpv(
target_rjumpv_table_size: int,
data_portion_end: bool,
):
- """EOF1I4200_0012 (Invalid) EOF code containing RJUMP with target RJUMPV immediate."""
+ """
+ EOF1I4200_0012 (Invalid) EOF code containing RJUMP with target RJUMPV
+ immediate.
+ """
invalid_destination = 4 + (2 * target_rjumpv_table_size) if data_portion_end else 4
target_jump_table = [0 for _ in range(target_rjumpv_table_size)]
eof_test(
@@ -909,7 +950,10 @@ def test_rjump_into_callf(
eof_test: EOFTestFiller,
data_portion_end: bool,
):
- """EOF1I4200_0013 (Invalid) EOF code containing RJUMP with target CALLF immediate."""
+ """
+ EOF1I4200_0013 (Invalid) EOF code containing RJUMP with target CALLF
+ immediate.
+ """
invalid_destination = 2 if data_portion_end else 1
eof_test(
container=Container(
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py
index f4739cf508..dd1647eb95 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py
@@ -12,10 +12,10 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE
from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import (
@@ -129,7 +129,9 @@ def test_rjumpi_condition_zero(
pre: Alloc,
calldata: bytes,
):
- """Test RJUMPI contract switching based on external input (condition zero)."""
+ """
+ Test RJUMPI contract switching based on external input (condition zero).
+ """
env = Environment()
sender = pre.fund_eoa(10**18)
contract_address = pre.deploy_contract(
@@ -221,7 +223,10 @@ def test_rjumpi_zero(
def test_rjumpi_max_forward(
eof_state_test: EOFStateTestFiller,
):
- """EOF1V4200_0007 (Valid) EOF with RJUMPI containing the maximum offset (32767)."""
+ """
+ EOF1V4200_0007 (Valid) EOF with RJUMPI containing the maximum offset
+ (32767).
+ """
eof_state_test(
container=Container(
sections=[
@@ -730,8 +735,8 @@ def test_rjumpi_valid_forward(
container: Container,
):
"""
- Validate a valid code section containing at least one forward RJUMPI.
- These tests exercise the stack height validation.
+ Validate a valid code section containing at least one forward RJUMPI. These
+ tests exercise the stack height validation.
"""
eof_test(container=container)
@@ -909,8 +914,8 @@ def test_rjumpi_max_bytecode_size(
eof_test: EOFTestFiller,
):
"""
- EOF1V4200_0003 EOF with RJUMPI containing the maximum offset that does not exceed the maximum
- bytecode size.
+ EOF1V4200_0003 EOF with RJUMPI containing the maximum offset that does not
+ exceed the maximum bytecode size.
"""
noop_count = MAX_BYTECODE_SIZE - 24
code = Op.RJUMPI[len(Op.NOOP) * noop_count](Op.ORIGIN) + (Op.NOOP * noop_count) + Op.STOP
@@ -957,8 +962,8 @@ def test_rjumpi_into_header(
offset: int,
):
"""
- EOF1I4200_0016 (Invalid) EOF code containing RJUMPI with target outside code bounds
- (Jumping into header).
+ EOF1I4200_0016 (Invalid) EOF code containing RJUMPI with target outside
+ code bounds (Jumping into header).
"""
eof_test(
container=Container(
@@ -976,8 +981,8 @@ def test_rjumpi_jump_before_header(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0017 (Invalid) EOF code containing RJUMPI with target outside code bounds
- (Jumping to before code begin).
+ EOF1I4200_0017 (Invalid) EOF code containing RJUMPI with target outside
+ code bounds (Jumping to before code begin).
"""
eof_test(
container=Container(
@@ -995,8 +1000,8 @@ def test_rjumpi_into_data(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0018 (Invalid) EOF code containing RJUMPI with target outside code bounds
- (Jumping into data section).
+ EOF1I4200_0018 (Invalid) EOF code containing RJUMPI with target outside
+ code bounds (Jumping into data section).
"""
eof_test(
container=Container(
@@ -1015,8 +1020,8 @@ def test_rjumpi_after_container(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0019 (Invalid) EOF code containing RJUMPI with target outside code bounds
- (Jumping to after code end).
+ EOF1I4200_0019 (Invalid) EOF code containing RJUMPI with target outside
+ code bounds (Jumping to after code end).
"""
eof_test(
container=Container(
@@ -1034,8 +1039,8 @@ def test_rjumpi_to_code_end(
eof_test: EOFTestFiller,
):
"""
- EOF1I4200_0020 (Invalid) EOF code containing RJUMPI with target outside code bounds
- (Jumping to code end).
+ EOF1I4200_0020 (Invalid) EOF code containing RJUMPI with target outside
+ code bounds (Jumping to code end).
"""
eof_test(
container=Container(
@@ -1055,8 +1060,8 @@ def test_rjumpi_into_self_data_portion(
offset: int,
):
"""
- EOF1I4200_0021 (Invalid) EOF code containing RJUMPI with target same RJUMPI immediate
- (with offset).
+ EOF1I4200_0021 (Invalid) EOF code containing RJUMPI with target same RJUMPI
+ immediate (with offset).
"""
eof_test(
container=Container(
@@ -1076,8 +1081,8 @@ def test_rjumpi_into_self(
stack_height_spread: int,
):
"""
- EOF code containing RJUMPI targeting itself (-3).
- This can never be valid because this is backward jump and RJUMPI consumes one stack item.
+ EOF code containing RJUMPI targeting itself (-3). This can never be valid
+ because this is backward jump and RJUMPI consumes one stack item.
"""
# Create variadic stack height by the parametrized spread.
stack_spread_code = Bytecode()
@@ -1099,7 +1104,10 @@ def test_rjumpi_into_self(
def test_rjumpi_into_stack_height_diff(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMPI with target instruction that causes stack height difference."""
+ """
+ EOF code containing RJUMPI with target instruction that causes stack height
+ difference.
+ """
eof_test(
container=Container(
sections=[
@@ -1118,7 +1126,10 @@ def test_rjumpi_into_stack_height_diff(
def test_rjumpi_into_stack_underflow(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMPI with target instruction that cause stack underflow."""
+ """
+ EOF code containing RJUMPI with target instruction that cause stack
+ underflow.
+ """
eof_test(
container=Container(
sections=[
@@ -1134,7 +1145,10 @@ def test_rjumpi_into_stack_underflow(
def test_rjumpi_skips_stack_underflow(
eof_test: EOFTestFiller,
):
- """EOF code containing RJUMPI where the default path produces a stack underflow."""
+ """
+ EOF code containing RJUMPI where the default path produces a stack
+ underflow.
+ """
eof_test(
container=Container(
sections=[
@@ -1148,7 +1162,10 @@ def test_rjumpi_skips_stack_underflow(
def test_rjumpi_into_rjump(
eof_test: EOFTestFiller,
):
- """EOF1I4200_0023 (Invalid) EOF code containing RJUMPI with target RJUMP immediate."""
+ """
+ EOF1I4200_0023 (Invalid) EOF code containing RJUMPI with target RJUMP
+ immediate.
+ """
eof_test(
container=Container(
sections=[
@@ -1164,7 +1181,10 @@ def test_rjumpi_into_rjump(
def test_rjumpi_into_rjumpi(
eof_test: EOFTestFiller,
):
- """EOF1I4200_0022 (Invalid) EOF code containing RJUMPI with target other RJUMPI immediate."""
+ """
+ EOF1I4200_0022 (Invalid) EOF code containing RJUMPI with target other
+ RJUMPI immediate.
+ """
eof_test(
container=Container(
sections=[
@@ -1187,7 +1207,10 @@ def test_rjumpi_into_push_1(
eof_test: EOFTestFiller,
jump: JumpDirection,
):
- """EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH1 immediate."""
+ """
+ EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH1
+ immediate.
+ """
code = (
Op.PUSH1[1] + Op.RJUMPI[-4]
if jump == JumpDirection.BACKWARD
@@ -1251,7 +1274,10 @@ def test_rjumpi_into_push_n(
jump: JumpDirection,
data_portion_end: bool,
):
- """EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH2+ immediate."""
+ """
+ EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH2+
+ immediate.
+ """
data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F
if jump == JumpDirection.FORWARD:
offset = data_portion_length if data_portion_end else 1
@@ -1280,7 +1306,10 @@ def test_rjumpi_into_rjumpv(
target_rjumpv_table_size: int,
data_portion_end: bool,
):
- """EOF1I4200_0025 (Invalid) EOF code containing RJUMPI with target RJUMPV immediate."""
+ """
+ EOF1I4200_0025 (Invalid) EOF code containing RJUMPI with target RJUMPV
+ immediate.
+ """
invalid_destination = 4 + (2 * target_rjumpv_table_size) if data_portion_end else 4
target_jump_table = [0 for _ in range(target_rjumpv_table_size)]
eof_test(
@@ -1309,7 +1338,10 @@ def test_rjumpi_into_callf(
eof_test: EOFTestFiller,
data_portion_end: bool,
):
- """EOF1I4200_0026 (Invalid) EOF code containing RJUMPI with target CALLF immediate."""
+ """
+ EOF1I4200_0026 (Invalid) EOF code containing RJUMPI with target CALLF
+ immediate.
+ """
invalid_destination = 2 if data_portion_end else 1
eof_test(
container=Container(
@@ -1474,8 +1506,8 @@ def test_rjumpi_stack_validation(
):
"""
Check that you can get to the same opcode with two different stack heights
- Spec now allows this:
- 4.b in https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation.
+ Spec now allows this: 4.b in
+ https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation.
"""
container = Container.Code(code=Op.RJUMPI[1](1) + Op.ADDRESS + Op.NOOP + Op.STOP)
eof_test(
@@ -1490,7 +1522,8 @@ def test_rjumpi_at_the_end(
"""
Test invalid RJUMPI as the end of a code section.
https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation 4.i:
- This implies that the last instruction must be a terminating instruction or RJUMP.
+ This implies that the last instruction must be a terminating instruction or
+ RJUMP.
"""
eof_test(
container=Container(
@@ -1611,8 +1644,8 @@ def test_double_rjumpi_stack_height_mismatch(
eof_test: EOFTestFiller,
):
"""
- Test stack height check of the backward RJUMP
- targeted by two RJUMPIs with the non-uniform stack height range.
+ Test stack height check of the backward RJUMP targeted by two RJUMPIs with
+ the non-uniform stack height range.
"""
eof_test(
container=Container(
@@ -1635,8 +1668,8 @@ def test_double_rjumpi_invalid_max_stack_height(
eof_test: EOFTestFiller,
):
"""
- Test max stack height of the final block
- targeted by two RJUMPIs with the non-uniform stack height range.
+ Test max stack height of the final block targeted by two RJUMPIs with the
+ non-uniform stack height range.
"""
eof_test(
container=Container(
@@ -1848,7 +1881,7 @@ def test_rjumpi_backward_invalid_max_stack_height(
container: Container,
):
"""
- Validate a code section containing at least one backward RJUMPI
- invalid because of the incorrect max stack height.
+ Validate a code section containing at least one backward RJUMPI invalid
+ because of the incorrect max stack height.
"""
eof_test(container=container, expect_exception=EOFException.STACK_HEIGHT_MISMATCH)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py
index 1fbbd28deb..6d32799aae 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py
@@ -3,9 +3,9 @@
import pytest
from ethereum_test_tools import Account, EOFException, EOFStateTestFiller, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import JumpDirection, slot_code_worked, slot_conditional_result, value_code_worked
@@ -200,7 +200,10 @@ def test_rjumpv_full_table(
eof_state_test: EOFStateTestFiller,
target: int,
):
- """EOF1V4200_0012/13/14/15 (Valid) EOF with RJUMPV table size 256 (target parameterized)."""
+ """
+ EOF1V4200_0012/13/14/15 (Valid) EOF with RJUMPV table size 256 (target
+ parameterized).
+ """
eof_state_test(
container=Container(
sections=[
@@ -220,7 +223,10 @@ def test_rjumpv_full_table(
def test_rjumpv_max_forwards(
eof_state_test: EOFStateTestFiller,
):
- """EOF1V4200_0016 (Valid) EOF with RJUMPV containing the maximum offset (32767)."""
+ """
+ EOF1V4200_0016 (Valid) EOF with RJUMPV containing the maximum offset
+ (32767).
+ """
eof_state_test(
container=Container(
sections=[
@@ -240,7 +246,10 @@ def test_rjumpv_max_forwards(
def test_rjumpv_truncated_empty(
eof_test: EOFTestFiller,
):
- """EOF1I4200_0027 (Invalid) EOF code containing RJUMPV with max_index 0 but no immediates."""
+ """
+ EOF1I4200_0027 (Invalid) EOF code containing RJUMPV with max_index 0 but no
+ immediates.
+ """
eof_test(
container=Container(
sections=[
@@ -290,8 +299,8 @@ def test_rjumpv_into_header(
invalid_index: int,
):
"""
- EOF1I4200_0031 (Invalid) EOF code containing RJUMPV with target outside code bounds
- (Jumping into header).
+ EOF1I4200_0031 (Invalid) EOF code containing RJUMPV with target outside
+ code bounds (Jumping into header).
"""
invalid_destination = -5 - (2 * table_size)
jump_table = [0 for _ in range(table_size)]
@@ -324,8 +333,8 @@ def test_rjumpv_before_container(
offset: int,
):
"""
- EOF1I4200_0032 (Invalid) EOF code containing RJUMPV with target outside code bounds
- (Jumping to before code begin).
+ EOF1I4200_0032 (Invalid) EOF code containing RJUMPV with target outside
+ code bounds (Jumping to before code begin).
"""
invalid_destination = offset - (2 * table_size)
jump_table = [0 for _ in range(table_size)]
@@ -356,8 +365,8 @@ def test_rjumpv_into_data(
invalid_index: int,
):
"""
- EOF1I4200_0033 (Invalid) EOF code containing RJUMPV with target outside code bounds
- (Jumping into data section).
+ EOF1I4200_0033 (Invalid) EOF code containing RJUMPV with target outside
+ code bounds (Jumping into data section).
"""
invalid_destination = 2
jump_table = [0 for _ in range(table_size)]
@@ -389,8 +398,8 @@ def test_rjumpv_after_container(
invalid_index: int,
):
"""
- EOF1I4200_0034 (Invalid) EOF code containing RJUMPV with target outside code bounds
- (Jumping to after code end).
+ EOF1I4200_0034 (Invalid) EOF code containing RJUMPV with target outside
+ code bounds (Jumping to after code end).
"""
invalid_destination = 2
jump_table = [0 for _ in range(table_size)]
@@ -421,8 +430,8 @@ def test_rjumpv_at_end(
invalid_index: int,
):
"""
- EOF1I4200_0035 (Invalid) EOF code containing RJUMPV with target outside code bounds
- (Jumping to code end).
+ EOF1I4200_0035 (Invalid) EOF code containing RJUMPV with target outside
+ code bounds (Jumping to code end).
"""
invalid_destination = 1
jump_table = [0 for _ in range(table_size)]
@@ -458,7 +467,10 @@ def test_rjumpv_into_self_data_portion(
invalid_index: int,
data_portion_end: bool,
):
- """EOF1I4200_0036 (Invalid) EOF code containing RJUMPV with target same RJUMPV immediate."""
+ """
+ EOF1I4200_0036 (Invalid) EOF code containing RJUMPV with target same RJUMPV
+ immediate.
+ """
invalid_destination = -1 if data_portion_end else -(2 * table_size) - 1
jump_table = [0 for _ in range(table_size)]
jump_table[invalid_index] = invalid_destination
@@ -490,8 +502,8 @@ def test_rjumpv_into_self(
stack_height_spread: int,
):
"""
- EOF code containing RJUMPV targeting itself.
- This can never be valid because this is backward jump and RJUMPV consumes one stack item.
+ EOF code containing RJUMPV targeting itself. This can never be valid
+ because this is backward jump and RJUMPV consumes one stack item.
"""
# Create variadic stack height by the parametrized spread.
stack_spread_code = Bytecode()
@@ -527,7 +539,10 @@ def test_rjumpv_into_stack_height_diff(
table_size: int,
invalid_index: int,
):
- """EOF code containing RJUMPV with target instruction that causes stack height difference."""
+ """
+ EOF code containing RJUMPV with target instruction that causes stack height
+ difference.
+ """
jump_table = [0 for _ in range(table_size)]
jump_table[invalid_index] = -(len(Op.RJUMPV[jump_table]) + len(Op.PUSH1[0]) + len(Op.PUSH1[0]))
@@ -556,7 +571,10 @@ def test_rjumpv_into_stack_underflow(
table_size: int,
invalid_index: int,
):
- """EOF code containing RJUMPV with target instruction that cause stack underflow."""
+ """
+ EOF code containing RJUMPV with target instruction that cause stack
+ underflow.
+ """
jump_table = [0 for _ in range(table_size)]
jump_table[invalid_index] = 1
eof_test(
@@ -580,7 +598,10 @@ def test_rjumpv_skips_stack_underflow(
eof_test: EOFTestFiller,
table_size: int,
):
- """EOF code containing RJUMPV where the default path produces a stack underflow."""
+ """
+ EOF code containing RJUMPV where the default path produces a stack
+ underflow.
+ """
jump_table = [1 for _ in range(table_size)]
eof_test(
container=Container(
@@ -611,7 +632,10 @@ def test_rjumpv_into_rjump(
invalid_index: int,
data_portion_end: bool,
):
- """EOF1I4200_0037 (Invalid) EOF code containing RJUMPV with target RJUMP immediate."""
+ """
+ EOF1I4200_0037 (Invalid) EOF code containing RJUMPV with target RJUMP
+ immediate.
+ """
invalid_destination = 3 if data_portion_end else 2
jump_table = [0 for _ in range(table_size)]
jump_table[invalid_index] = invalid_destination
@@ -651,7 +675,10 @@ def test_rjumpv_into_rjumpi(
invalid_index: int,
data_portion_end: bool,
):
- """EOF1I4200_0038 (Invalid) EOF code containing RJUMPV with target RJUMPI immediate."""
+ """
+ EOF1I4200_0038 (Invalid) EOF code containing RJUMPV with target RJUMPI
+ immediate.
+ """
invalid_destination = 5 if data_portion_end else 4
jump_table = [0 for _ in range(table_size)]
jump_table[invalid_index] = invalid_destination
@@ -692,7 +719,10 @@ def test_rjumpv_into_push_1(
table_size: int,
invalid_index: int,
):
- """EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSH1 immediate."""
+ """
+ EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSH1
+ immediate.
+ """
if jump == JumpDirection.FORWARD:
invalid_destination = 2
jump_table = [0 for _ in range(table_size)]
@@ -777,7 +807,10 @@ def test_rjumpv_into_push_n(
invalid_index: int,
data_portion_end: bool,
):
- """EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSHN immediate."""
+ """
+ EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSHN
+ immediate.
+ """
data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F
if jump == JumpDirection.FORWARD:
invalid_destination = data_portion_length + 1 if data_portion_end else 2
@@ -830,7 +863,10 @@ def test_rjumpv_into_rjumpv(
invalid_index: int,
data_portion_end: bool,
):
- """EOF1I4200_0040 (Invalid) EOF code containing RJUMPV with target other RJUMPV immediate."""
+ """
+ EOF1I4200_0040 (Invalid) EOF code containing RJUMPV with target other
+ RJUMPV immediate.
+ """
invalid_destination = 4 + (2 * target_table_size) if data_portion_end else 4
source_jump_table = [0 for _ in range(source_table_size)]
source_jump_table[invalid_index] = invalid_destination
@@ -871,7 +907,10 @@ def test_rjumpv_into_callf(
invalid_index: int,
data_portion_end: bool,
):
- """EOF1I4200_0041 (Invalid) EOF code containing RJUMPV with target CALLF immediate."""
+ """
+ EOF1I4200_0041 (Invalid) EOF code containing RJUMPV with target CALLF
+ immediate.
+ """
invalid_destination = 2 if data_portion_end else 1
jump_table = [0 for _ in range(table_size)]
jump_table[invalid_index] = invalid_destination
@@ -1104,7 +1143,8 @@ def test_rjumpv_at_the_end(
):
"""
https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation 4.i:
- This implies that the last instruction may be a terminating instruction or RJUMPV.
+ This implies that the last instruction may be a terminating instruction or
+ RJUMPV.
"""
eof_test(
container=Container(
@@ -1546,8 +1586,8 @@ def test_rjumpv_valid_forward(
container: Container,
):
"""
- Validate a valid code section containing at least one forward RJUMPV.
- These tests exercise the stack height validation.
+ Validate a valid code section containing at least one forward RJUMPV. These
+ tests exercise the stack height validation.
"""
eof_test(container=container)
@@ -1849,7 +1889,7 @@ def test_rjumpv_backward_invalid_max_stack_height(
container: Container,
):
"""
- Validate a code section containing at least one backward RJUMPV
- invalid because of the incorrect max stack height.
+ Validate a code section containing at least one backward RJUMPV invalid
+ because of the incorrect max stack height.
"""
eof_test(container=container, expect_exception=EOFException.STACK_HEIGHT_MISMATCH)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py
index 20c62ac752..3889e56081 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py
@@ -1,5 +1,7 @@
"""
-abstract: Test cases for [EIP-4750: EOF - Functions](https://eips.ethereum.org/EIPS/eip-4750)
- EIP-4750 formalizes functions in the EVM object format, introducing callable units of code.
- Opcodes introduced: `CALLF` (`0xE3`), `RETF` (`0xE4`).
-""" # noqa: E501
+Test cases for [EIP-4750: EOF - Functions](https://eips.ethereum.org/EIPS/eip-4750).
+
+EIP-4750 formalizes functions in the EVM object format, introducing
+callable units of code. Opcodes introduced: `CALLF` (`0xE3`), `RETF`
+(`0xE4`).
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py b/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py
index 30adfa59c2..b0b1d2a0f5 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py
@@ -73,7 +73,9 @@ def test_callf_factorial(eof_state_test: EOFStateTestFiller, n, result):
((0, 1), (1, 1), (13, 233), (27, 196418)),
)
def test_callf_fibonacci(eof_state_test: EOFStateTestFiller, n, result):
- """Test fibonacci sequence implementation with recursive CALLF instructions."""
+ """
+ Test fibonacci sequence implementation with recursive CALLF instructions.
+ """
eof_state_test(
container=Container(
sections=[
@@ -454,11 +456,14 @@ def test_callf_sneaky_stack_overflow(
pre: Alloc,
):
"""
- CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule #3 triggers.
+ CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule
+ #3 triggers.
Code Section 0 - Mostly fills the stack
- Code Section 1 - jumper to 2, so container verification passes (we want a runtime failure)
- Code Section 2 - Could require too much stack, but doesn't as it JUMPFs to 3
+ Code Section 1 - jumper to 2, so container verification passes (we want a
+ runtime failure)
+ Code Section 2 - Could require too much stack, but doesn't as it JUMPFs
+ to 3
Code Section 3 - Writes canary values
The intent is to catch implementations of CALLF that don't enforce rule #3
@@ -552,17 +557,18 @@ def test_callf_max_stack(
pre: Alloc,
):
"""
- CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule #4 triggers.
+ CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule
+ #4 triggers.
- Code Section 0 - calls #1 with the configured height, but we load some operands so the
- return stack does not overflow
- Code Section 1 - expands stack, calls #2, THEN recursively calls itself until input is zero,
- and returns.
+ Code Section 0 - calls #1 with the configured height, but we load some
+ operands so the return stack does not overflow
+ Code Section 1 - expands stack, calls #2, THEN recursively calls itself
+ until input is zero, and returns.
Code Section 2 - Just returns, zero inputs, zero outputs
- This will catch CALLF execution rule #3: always fail if the operand stack is full. Not
- checking rule 3 results in a call to section 2 and not overfilling the stack (as it is just
- RETF).
+ This will catch CALLF execution rule #3: always fail if the operand stack
+ is full. Not checking rule 3 results in a call to section 2 and not
+ overfilling the stack (as it is just RETF).
"""
env = Environment()
sender = pre.fund_eoa()
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py b/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py
index c781249137..e1df510d68 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py
@@ -5,7 +5,6 @@
import pytest
from ethereum_test_tools import EOFException, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import (
@@ -13,6 +12,7 @@
MAX_CODE_SECTIONS,
MAX_STACK_INCREASE_LIMIT,
)
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -379,7 +379,10 @@ def test_eof_validity(
eof_test: EOFTestFiller,
container: Container,
):
- """Test EOF container validation for features around EIP-4750 / Functions / Code Sections."""
+ """
+ Test EOF container validation for features around EIP-4750 / Functions /
+ Code Sections.
+ """
eof_test(container=container)
@@ -475,7 +478,9 @@ def test_invalid_code_section_index(
eof_test: EOFTestFiller,
container: Container,
):
- """Test cases for CALLF instructions with invalid target code section index."""
+ """
+ Test cases for CALLF instructions with invalid target code section index.
+ """
eof_test(container=container, expect_exception=EOFException.INVALID_CODE_SECTION_INDEX)
@@ -637,8 +642,8 @@ def test_unreachable_code_sections(
container: Container,
):
"""
- Test cases for EOF unreachable code sections
- (i.e. code sections not reachable from the code section 0).
+ Test cases for EOF unreachable code sections (i.e. code sections not
+ reachable from the code section 0).
"""
eof_test(container=container, expect_exception=EOFException.UNREACHABLE_CODE_SECTIONS)
@@ -646,9 +651,10 @@ def test_unreachable_code_sections(
@pytest.mark.parametrize("callee_outputs", [1, 2, MAX_CODE_OUTPUTS])
def test_callf_stack_height_limit_exceeded(eof_test, callee_outputs):
"""
- Test for invalid EOF code containing CALLF instruction exceeding the stack height limit.
- The code reaches the maximum runtime stack height (1024)
- which is above the EOF limit for the stack height in the type section (1023).
+ Test for invalid EOF code containing CALLF instruction exceeding the stack
+ height limit. The code reaches the maximum runtime stack height (1024)
+ which is above the EOF limit for the stack height in the type section
+ (1023).
"""
callf_stack_height = MAX_RUNTIME_STACK_HEIGHT - callee_outputs
container = Container(
@@ -669,7 +675,9 @@ def test_callf_stack_height_limit_exceeded(eof_test, callee_outputs):
@pytest.mark.parametrize("stack_height", [512, 513, 1023])
def test_callf_stack_overflow(eof_test: EOFTestFiller, stack_height: int):
- """Test CALLF instruction recursively calling itself causing stack overflow."""
+ """
+ Test CALLF instruction recursively calling itself causing stack overflow.
+ """
container = Container(
sections=[
Section.Code(code=Op.CALLF[1] + Op.STOP),
@@ -689,7 +697,10 @@ def test_callf_stack_overflow(eof_test: EOFTestFiller, stack_height: int):
@pytest.mark.parametrize("stack_height", [1, 2])
def test_callf_stack_overflow_after_callf(eof_test: EOFTestFiller, stack_height: int):
- """Test CALLF instruction calling next function causing stack overflow at validation time."""
+ """
+ Test CALLF instruction calling next function causing stack overflow at
+ validation time.
+ """
container = Container(
sections=[
Section.Code(code=Op.CALLF[1] + Op.STOP),
@@ -823,7 +834,10 @@ def test_callf_stack_overflow_variable_stack_4(eof_test: EOFTestFiller):
@pytest.mark.parametrize("stack_height", [2, 3])
def test_callf_validate_outputs(eof_test: EOFTestFiller, stack_height: int):
- """Test CALLF instruction when calling a function returning more outputs than expected."""
+ """
+ Test CALLF instruction when calling a function returning more outputs than
+ expected.
+ """
container = Container(
sections=[
Section.Code(code=Op.CALLF[1] + Op.STOP, max_stack_height=1),
@@ -1074,10 +1088,11 @@ def test_callf_with_inputs_stack_overflow_variable_stack(
)
def test_callf_stack_overflow_by_outputs(eof_test, callee_outputs, max_stack_height):
"""
- Test for invalid EOF code containing CALLF instruction exceeding the runtime stack height limit
- by calling a function with at least one output. The computed stack height of the code section 0
- is always above the maximum allowed in the EOF type section. Therefore, the test declares
- an invalid max_stack_height.
+ Test for invalid EOF code containing CALLF instruction exceeding the
+ runtime stack height limit by calling a function with at least one output.
+ The computed stack height of the code section 0 is always above the maximum
+ allowed in the EOF type section. Therefore, the test declares an invalid
+ max_stack_height.
"""
callf_stack_height = (MAX_RUNTIME_STACK_HEIGHT + 1) - callee_outputs
container = Container(
@@ -1102,10 +1117,10 @@ def test_callf_stack_overflow_by_outputs(eof_test, callee_outputs, max_stack_hei
)
def test_callf_stack_overflow_by_height(eof_test, callee_stack_height):
"""
- Test for invalid EOF code containing CALLF instruction exceeding the runtime stack height limit
- by calling a function with 2+ maximum stack height.
- The callee with the maximum stack height of 1 is valid because runtime limit (1024)
- is 1 bigger than the EOF limit (1023).
+ Test for invalid EOF code containing CALLF instruction exceeding the
+ runtime stack height limit by calling a function with 2+ maximum stack
+ height. The callee with the maximum stack height of 1 is valid because
+ runtime limit (1024) is 1 bigger than the EOF limit (1023).
"""
container = Container(
sections=[
@@ -1234,8 +1249,8 @@ def test_returning_section_aborts(
eof_test: EOFTestFiller,
):
"""
- Test EOF container validation where in the same code section we have returning
- and nonreturning terminating instructions.
+ Test EOF container validation where in the same code section we have
+ returning and nonreturning terminating instructions.
"""
container = Container(
name="returning_section_aborts",
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py
index fb5897d4ed..3935e40789 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py
@@ -1,5 +1,8 @@
"""
-abstract: Test cases for [EIP-5450: EOF - Stack Validation](https://eips.ethereum.org/EIPS/eip-5450)
- EIP-5450 defines stack validation requirements to ensure consistent behavior during execution.
- Opcodes introduced: None (specifies validation rules for stack usage).
-""" # noqa: E501
+Tests for
+[EIP-5450: EOF - Stack Validation](https://eips.ethereum.org/EIPS/eip-5450).
+
+EIP-5450 defines stack validation requirements to ensure consistent
+behavior during execution. Opcodes introduced: None (specifies validation
+rules for stack usage).
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py b/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py
index 424c584582..f85edd1f12 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py
@@ -1,4 +1,7 @@
-"""Code validation of CALLF, JUMPF, RETF opcodes in conjunction with static relative jumps."""
+"""
+Code validation of CALLF, JUMPF, RETF opcodes in conjunction with static
+relative jumps.
+"""
import itertools
from enum import Enum, auto, unique
@@ -8,10 +11,10 @@
from ethereum_test_exceptions.exceptions import EOFException
from ethereum_test_tools import Account, EOFStateTestFiller, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_STACK_INCREASE_LIMIT, NON_RETURNING_SECTION
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from ..eip3540_eof_v1.test_all_opcodes_in_container import valid_eof_opcodes
@@ -51,7 +54,9 @@ def __str__(self) -> str:
@unique
class RjumpSpot(Enum):
- """Possible spots in the code section layout where the RJUMP* is injected."""
+ """
+ Possible spots in the code section layout where the RJUMP* is injected.
+ """
BEGINNING = auto()
BEFORE_TERMINATION = auto()
@@ -65,14 +70,16 @@ def rjump_code_with(
rjump_kind: RjumpKind | None, code_so_far_len: int, next_code: Bytecode
) -> Tuple[Bytecode, bool, bool, bool]:
"""
- Unless `rjump_kind` is None generates a code snippet with an RJUMP* instruction.
- For some kinds `code_so_far_len` must be code length in bytes preceding the snippet.
- For some kinds `next_code_len` must be code length in bytes of some code which follows.
+ Unless `rjump_kind` is None generates a code snippet with an RJUMP*
+ instruction. For some kinds `code_so_far_len` must be code length in bytes
+ preceding the snippet. For some kinds `next_code_len` must be code length
+ in bytes of some code which follows.
- It is expected that the snippet and the jump target are valid, but the resulting code
- or its stack balance might not.
+ It is expected that the snippet and the jump target are valid, but the
+ resulting code or its stack balance might not.
- Also returns some traits of the snippet: `is_backwards`, `pops` and `pushes`
+ Also returns some traits of the snippet: `is_backwards`, `pops` and
+ `pushes`
"""
body = Bytecode()
@@ -124,8 +131,9 @@ def rjump_code_with(
raise TypeError("unknown rjumps value" + str(rjump_kind))
if jumps_over_next:
- # This is against intuition, but if the code we're jumping over pushes, the path
- # which misses it will be short of stack items, as if the RJUMP* popped and vice versa.
+ # This is against intuition, but if the code we're jumping over pushes,
+ # the path which misses it will be short of stack items, as if the
+ # RJUMP* popped and vice versa.
if next_code.pushed_stack_items > next_code.popped_stack_items:
pops = True
elif next_code.popped_stack_items > next_code.pushed_stack_items:
@@ -136,10 +144,11 @@ def rjump_code_with(
def call_code_with(inputs, outputs, call: Bytecode) -> Bytecode:
"""
- Generate code snippet with the `call` bytecode provided and its respective input/output
- management.
+ Generate code snippet with the `call` bytecode provided and its respective
+ input/output management.
- `inputs` and `outputs` are understood as those of the code section we're generating for.
+ `inputs` and `outputs` are understood as those of the code section we're
+ generating for.
"""
body = Bytecode()
@@ -168,8 +177,8 @@ def section_code_with(
"""
Generate code section with RJUMP* and CALLF/RETF instructions.
- Also returns some traits of the section: `has_invalid_back_jump`, `rjump_snippet_pops`,
- `rjump_snippet_pushes`, `rjump_falls_off_code`
+ Also returns some traits of the section: `has_invalid_back_jump`,
+ `rjump_snippet_pops`, `rjump_snippet_pushes`, `rjump_falls_off_code`
"""
code = Bytecode()
code.pushed_stack_items, code.max_stack_height = (inputs, inputs)
@@ -214,7 +223,8 @@ def section_code_with(
RjumpKind.RJUMPI_OVER_NEXT_NESTED,
RjumpKind.RJUMPV_EMPTY_AND_OVER_NEXT,
]:
- # Jump over termination or jump over body, but there is nothing after the body.
+ # Jump over termination or jump over body, but there is nothing
+ # after the body.
rjump_falls_off_code = True
code += termination
@@ -260,10 +270,12 @@ def test_rjumps_callf_retf(
"""
Test EOF container validation for EIP-4200 vs EIP-4750 interactions.
- Each test's code consists of `num_sections` code sections, which call into one another
- and then return. Code may include RJUMP* snippets of `rjump_kind` in various `rjump_spots`.
+ Each test's code consists of `num_sections` code sections, which call into
+ one another and then return. Code may include RJUMP* snippets of
+ `rjump_kind` in various `rjump_spots`.
"""
- # Zeroth section has always 0 inputs and 0 outputs, so is excluded from param
+ # Zeroth section has always 0 inputs and 0 outputs, so is excluded from
+ # param
inputs = (0,) + inputs
outputs = (0,) + outputs
@@ -316,7 +328,8 @@ def test_rjumps_callf_retf(
container_has_invalid_back_jump = True
if rjump_snippet_pops:
container_has_rjump_pops = True
- # Pushes to the stack never affect the zeroth section, because it `STOP`s and not `RETF`s.
+ # Pushes to the stack never affect the zeroth section, because it
+ # `STOP`s and not `RETF`s.
if rjump_snippet_pushes and section_idx != 0:
container_has_rjump_pushes = True
if rjump_falls_off_code:
@@ -371,10 +384,11 @@ def test_rjumps_jumpf_nonreturning(
rjump_spot: RjumpSpot,
):
"""
- Test EOF container validation for EIP-4200 vs EIP-6206 interactions on non-returning
- functions.
+ Test EOF container validation for EIP-4200 vs EIP-6206 interactions on
+ non-returning functions.
"""
- # Zeroth section has always 0 inputs and 0 outputs, so is excluded from param
+ # Zeroth section has always 0 inputs and 0 outputs, so is excluded from
+ # param
inputs = (0,) + inputs
sections = []
@@ -394,8 +408,9 @@ def test_rjumps_jumpf_nonreturning(
call = None
termination = Op.STOP
- # `section_has_invalid_back_jump` - never happens: we excluded RJUMP from the end
- # `rjump_snippet_pushes` - never happens: we never RETF where too large stack would fail
+ # `section_has_invalid_back_jump` - never happens: we excluded RJUMP
+ # from the end `rjump_snippet_pushes` - never happens: we never RETF
+ # where too large stack would fail
(
code,
_section_has_invalid_back_jump,
@@ -463,8 +478,8 @@ def test_all_opcodes_stack_underflow(
eof_test: EOFTestFiller, op: Op, stack_height: int, spread: int
):
"""
- Test EOF validation failing due to stack overflow
- caused by the specific instruction `op`.
+ Test EOF validation failing due to stack overflow caused by the specific
+ instruction `op`.
"""
code = Bytecode()
@@ -579,7 +594,9 @@ def test_all_opcodes_stack_underflow(
ids=lambda x: x.name,
)
def test_stack_underflow_examples(eof_test, container):
- """Test EOF validation failing due to stack underflow at basic instructions."""
+ """
+ Test EOF validation failing due to stack underflow at basic instructions.
+ """
eof_test(container=container, expect_exception=EOFException.STACK_UNDERFLOW)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py b/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py
index a4586a3787..5c9fa2fa5b 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py
@@ -4,7 +4,6 @@
from ethereum_test_exceptions import EOFException
from ethereum_test_tools import Account, EOFStateTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import (
@@ -12,6 +11,7 @@
MAX_STACK_INCREASE_LIMIT,
NON_RETURNING_SECTION,
)
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -27,12 +27,13 @@ def test_execution_at_max_stack_height(
eof_state_test: EOFStateTestFiller, code_inputs: int, call_op: Op
):
"""
- Test execution at the maximum runtime operand stack height (1024).
- EOF doesn't allow to increase the stack height of a single code section more than 1023.
- The effect of the maximum runtime stack height is achieved by using non-zero number
- of the code section inputs and increasing the runtime stack to the limit accordingly.
- The test pushes consecutive numbers starting from 0 (including inputs).
- At the maximum stack height SSTORE is used so it should store 1022 at key 1023.
+ Test execution at the maximum runtime operand stack height (1024). EOF
+ doesn't allow to increase the stack height of a single code section more
+ than 1023. The effect of the maximum runtime stack height is achieved by
+ using non-zero number of the code section inputs and increasing the runtime
+ stack to the limit accordingly. The test pushes consecutive numbers
+ starting from 0 (including inputs). At the maximum stack height SSTORE is
+ used so it should store 1022 at key 1023.
"""
max_stack_increase = MAX_RUNTIME_STACK_HEIGHT - code_inputs
container = Container(
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py
index b2391ecb03..dcd27c79cd 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py
@@ -1,5 +1,7 @@
"""
-abstract: Test cases for [EIP-6206: EOF - JUMPF and non-returning functions](https://eips.ethereum.org/EIPS/eip-6206)
- EIP-6206 adds a conditional forward jump instruction and support for functions without return values.
- Opcodes introduced: `JUMPF` (`0xE5`).
-""" # noqa: E501
+Test cases for [EIP-6206: EOF - JUMPF and non-returning functions](https://
+eips.ethereum.org/EIPS/eip-6206).
+
+EIP-6206 adds a conditional forward jump instruction and support for
+functions without return values. Opcodes introduced: `JUMPF` (`0xE5`).
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py
index 56b2a5fc7c..b26d7702de 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py
@@ -5,10 +5,10 @@
from ethereum_test_base_types import Storage
from ethereum_test_specs import StateTestFiller
from ethereum_test_tools import Account, Environment, EOFException, EOFStateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types import Alloc
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import NON_RETURNING_SECTION
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import (
@@ -299,7 +299,10 @@ def test_jumpf_way_too_large(
def test_jumpf_to_nonexistent_section(
eof_state_test: EOFStateTestFiller,
):
- """Tests JUMPF jumping to valid section number but where the section does not exist."""
+ """
+ Tests JUMPF jumping to valid section number but where the section does not
+ exist.
+ """
eof_state_test(
container=Container(
sections=[
@@ -358,7 +361,9 @@ def test_jumpf_stack_size_1024(
def test_jumpf_with_inputs_stack_size_1024(
eof_state_test: EOFStateTestFiller,
):
- """Test stack reaching 1024 items in target function of JUMPF with inputs."""
+ """
+ Test stack reaching 1024 items in target function of JUMPF with inputs.
+ """
eof_state_test(
container=Container(
sections=[
@@ -381,7 +386,10 @@ def test_jumpf_with_inputs_stack_size_1024(
def test_jumpf_stack_size_1024_at_push(
eof_state_test: EOFStateTestFiller,
):
- """Test stack reaching 1024 items in JUMPF target function at PUSH0 instruction."""
+ """
+ Test stack reaching 1024 items in JUMPF target function at PUSH0
+ instruction.
+ """
eof_state_test(
container=Container(
sections=[
@@ -430,13 +438,18 @@ def test_jumpf_stack_overflow(
eof_state_test: EOFStateTestFiller,
):
"""
- Test rule #2 in execution semantics, where we make sure we have enough stack to guarantee
- safe execution (the "reserved stack rule") max possible stack will not exceed 1024. But some
- executions may not overflow the stack, so we need to ensure the rule is checked.
+ Test rule #2 in execution semantics, where we make sure we have enough
+ stack to guarantee safe execution (the "reserved stack rule") max possible
+ stack will not exceed 1024. But some executions may not overflow the stack,
+ so we need to ensure the rule is checked.
`no_overflow` - the stack does not overflow at JUMPF call, executes to end
- `rule_overflow` - reserved stack rule triggers, but execution would not overflow if allowed
- `execution_overflow` - execution would overflow (but still blocked by reserved stack rule)
+
+ `rule_overflow` - reserved stack rule triggers, but execution would not
+ overflow if allowed
+
+ `execution_overflow` - execution would overflow (but still blocked by
+ reserved stack rule)
"""
eof_state_test(
container=Container(
@@ -482,7 +495,10 @@ def test_jumpf_stack_overflow(
def test_jumpf_with_inputs_stack_size_1024_at_push(
eof_state_test: EOFStateTestFiller,
):
- """Test stack reaching 1024 items in JUMPF target function with inputs at PUSH0 instruction."""
+ """
+ Test stack reaching 1024 items in JUMPF target function with inputs at
+ PUSH0 instruction.
+ """
eof_state_test(
container=Container(
sections=[
@@ -520,7 +536,9 @@ def test_jumpf_with_inputs_stack_size_1024_at_push(
def test_jumpf_with_inputs_stack_overflow(
eof_state_test: EOFStateTestFiller,
):
- """Test stack overflowing 1024 items in JUMPF target function with inputs."""
+ """
+ Test stack overflowing 1024 items in JUMPF target function with inputs.
+ """
eof_state_test(
container=Container(
sections=[
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py
index ade091a3f8..f54946a307 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py
@@ -4,9 +4,9 @@
from ethereum_test_specs import EOFTestFiller
from ethereum_test_tools import Account, EOFException, EOFStateTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import slot_code_worked, value_code_worked
@@ -33,8 +33,8 @@ def test_jumpf_stack_non_returning_rules(
stack_height: int,
):
"""
- Tests for JUMPF validation stack rules. Non-returning section cases.
- Valid cases are executed.
+ Tests for JUMPF validation stack rules. Non-returning section cases. Valid
+ cases are executed.
"""
container = Container(
name="stack-non-retuning_h-%d_ti-%d" % (stack_height, target_inputs),
@@ -90,8 +90,8 @@ def test_jumpf_stack_returning_rules(
stack_diff: int,
):
"""
- Tests for JUMPF validation stack rules. Returning section cases.
- Valid cases are executed.
+ Tests for JUMPF validation stack rules. Returning section cases. Valid
+ cases are executed.
"""
if target_outputs > source_outputs:
# These create invalid containers without JUMPF validation, Don't test.
@@ -297,7 +297,10 @@ def test_jumpf_self_variadic_stack_overflow(eof_test: EOFTestFiller):
def test_jumpf_variadic_stack_overflow(
eof_test: EOFTestFiller, stack_height: int, callee_stack_height: int
):
- """Test JUMPF stack validation causing stack overflow with variable stack height."""
+ """
+ Test JUMPF stack validation causing stack overflow with variable stack
+ height.
+ """
container = Container(
sections=[
Section.Code(
@@ -346,7 +349,10 @@ def test_jumpf_with_inputs_stack_overflow(
def test_jumpf_with_inputs_stack_overflow_variable_stack(
eof_test: EOFTestFiller, stack_height: int, callee_stack_increase: int
):
- """Test JUMPF with variable stack depending on RJUMPI calling function with inputs."""
+ """
+ Test JUMPF with variable stack depending on RJUMPI calling function with
+ inputs.
+ """
container = Container(
sections=[
Section.Code(
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py
index 80e2e61ef2..886a39e758 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py
@@ -3,9 +3,9 @@
import pytest
from ethereum_test_tools import Account, EOFException, EOFStateTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import NON_RETURNING_SECTION
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import slot_code_worked, value_code_worked
@@ -32,8 +32,8 @@ def test_jumpf_target_rules(
target_outputs: int,
):
"""
- Validate the target section rules of JUMPF, and execute valid cases.
- We are not testing stack so a lot of the logic is to get correct stack values.
+ Validate the target section rules of JUMPF, and execute valid cases. We are
+ not testing stack so a lot of the logic is to get correct stack values.
"""
source_non_returning = source_outputs == NON_RETURNING_SECTION
source_height = 0 if source_non_returning else source_outputs
@@ -43,10 +43,11 @@ def test_jumpf_target_rules(
target_height = 0 if target_non_returning else target_outputs
target_section_index = 2
- # Because we are testing the target and not the stack height validation we need to do some work
- # to make sure the stack passes validation.
+ # Because we are testing the target and not the stack height validation we
+ # need to do some work to make sure the stack passes validation.
- # `source_extra_push` is how many more pushes we need to match our stack commitments
+ # `source_extra_push` is how many more pushes we need to match our stack
+ # commitments
source_extra_push = max(0, source_height - target_height)
source_section = Section.Code(
code=Op.PUSH0 * (source_height)
@@ -60,8 +61,9 @@ def test_jumpf_target_rules(
max_stack_height=source_height + max(1, source_extra_push),
)
- # `delta` is how many stack items the target output is from the input height, and tracks the
- # number of pushes or (if negative) pops the target needs to do to match output commitments
+ # `delta` is how many stack items the target output is from the input
+ # height, and tracks the number of pushes or (if negative) pops the target
+ # needs to do to match output commitments
delta = 0 if target_non_returning or source_non_returning else target_outputs - source_height
target_section = Section.Code(
code=((Op.PUSH0 * delta) if delta >= 0 else (Op.POP * -delta))
@@ -116,7 +118,7 @@ def test_jumpf_multi_target_rules(
eof_state_test: EOFStateTestFiller,
):
"""
- NOT IMPLEMENTED:
- Test a section that contains multiple JUMPF to different targets with different outputs.
+ NOT IMPLEMENTED: Test a section that contains multiple JUMPF to different
+ targets with different outputs.
"""
pass
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py
index 6abc91cf9e..4fe3100e93 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py
@@ -3,9 +3,9 @@
import pytest
from ethereum_test_tools import EOFException, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -111,7 +111,9 @@ def test_invalid_code_section_index(
eof_test: EOFTestFiller,
container: Container,
):
- """Test cases for JUMPF instructions with invalid target code section index."""
+ """
+ Test cases for JUMPF instructions with invalid target code section index.
+ """
eof_test(container=container, expect_exception=EOFException.INVALID_CODE_SECTION_INDEX)
@@ -119,8 +121,8 @@ def test_returning_section_aborts_jumpf(
eof_test: EOFTestFiller,
):
"""
- Test EOF container validation where in the same code section we have returning
- and nonreturning terminating instructions.
+ Test EOF container validation where in the same code section we have
+ returning and nonreturning terminating instructions.
"""
container = Container(
sections=[
@@ -141,7 +143,10 @@ def test_returning_section_aborts_jumpf(
@pytest.mark.parametrize("stack_height", [512, 513, 1023])
def test_jumpf_self_stack_overflow(eof_test: EOFTestFiller, stack_height: int):
- """Test JUMPF instruction jumping to itself causing validation time stack overflow."""
+ """
+ Test JUMPF instruction jumping to itself causing validation time stack
+ overflow.
+ """
container = Container(
sections=[
Section.Code(
@@ -162,7 +167,10 @@ def test_jumpf_self_stack_overflow(eof_test: EOFTestFiller, stack_height: int):
def test_jumpf_other_stack_overflow(
eof_test: EOFTestFiller, stack_height: int, stack_height_other: int
):
- """Test JUMPF instruction jumping to other section causing validation time stack overflow."""
+ """
+ Test JUMPF instruction jumping to other section causing validation time
+ stack overflow.
+ """
container = Container(
sections=[
Section.Code(
@@ -202,7 +210,10 @@ def test_jumpf_to_non_returning(eof_test: EOFTestFiller, stack_height: int, code
@pytest.mark.parametrize("code_inputs", [0, 1, 3, 5])
def test_jumpf_to_non_returning_variable_stack(eof_test: EOFTestFiller, code_inputs: int):
- """Test JUMPF jumping to a non-returning function with stack depending on RJUMPI."""
+ """
+ Test JUMPF jumping to a non-returning function with stack depending on
+ RJUMPI.
+ """
container = Container(
sections=[
Section.Code(
@@ -266,7 +277,10 @@ def test_jumpf_to_returning_variable_stack_1(
code_outputs: int,
stack_increase: int,
):
- """Test JUMPF with variable stack jumping to a returning function increasing the stack."""
+ """
+ Test JUMPF with variable stack jumping to a returning function increasing
+ the stack.
+ """
exception = None
if code_inputs >= 3 or code_outputs + 1 < 3: # 3 = Section 1's max stack
exception = EOFException.STACK_UNDERFLOW
@@ -305,7 +319,10 @@ def test_jumpf_to_returning_variable_stack_2(
code_outputs: int,
stack_decrease: int,
):
- """Test JUMPF with variable stack jumping to a returning function decreasing the stack."""
+ """
+ Test JUMPF with variable stack jumping to a returning function decreasing
+ the stack.
+ """
exceptions = []
if code_inputs >= 3 or code_outputs + 1 < 3: # 3 = Section 1's max stack
exceptions.append(EOFException.STACK_UNDERFLOW)
@@ -336,7 +353,10 @@ def test_jumpf_to_returning_variable_stack_2(
def test_jumpf_to_returning_variable_stack_3(eof_test: EOFTestFiller):
- """Test JUMPF with variable stack jumping to a returning function increasing the stack."""
+ """
+ Test JUMPF with variable stack jumping to a returning function increasing
+ the stack.
+ """
container = Container(
sections=[
Section.Code(code=Op.CALLF[1] + Op.STOP, max_stack_height=2),
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py
index 4ecf0a5831..d40bdb0eb7 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py
@@ -3,9 +3,9 @@
import pytest
from ethereum_test_tools import EOFException, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import NON_RETURNING_SECTION, Container, ContainerKind, Section
from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -31,7 +31,9 @@
[0, 1, 0x7F, 0x81, 0xFF],
)
def test_first_section_returning(eof_test: EOFTestFiller, code: Bytecode, outputs: int):
- """Test EOF validation failing because the first section is not non-returning."""
+ """
+ Test EOF validation failing because the first section is not non-returning.
+ """
eof_test(
container=Container(
sections=[Section.Code(code, code_outputs=outputs)],
@@ -62,7 +64,10 @@ def test_first_section_returning(eof_test: EOFTestFiller, code: Bytecode, output
def test_first_section_with_inputs(
eof_test: EOFTestFiller, code: Bytecode, inputs: int, outputs: int
):
- """Test EOF validation failing because the first section has non-zero number of inputs."""
+ """
+ Test EOF validation failing because the first section has non-zero number
+ of inputs.
+ """
eof_test(
container=Container(
sections=[
@@ -94,7 +99,10 @@ def test_first_section_with_inputs(
],
)
def test_returning_section_not_returning(eof_test: EOFTestFiller, code_section: Section):
- """Test EOF validation failing due to returning section with no RETF or JUMPF-to-returning."""
+ """
+ Test EOF validation failing due to returning section with no RETF or
+ JUMPF-to-returning.
+ """
eof_test(
container=Container(
sections=[
@@ -118,8 +126,8 @@ def test_returning_section_not_returning(eof_test: EOFTestFiller, code_section:
)
def test_returning_section_returncode(eof_test: EOFTestFiller, code_section: Section):
"""
- Test EOF validation failing because a returning section has no RETF or JUMPF-to-returning -
- RETURNCODE version.
+ Test EOF validation failing because a returning section has no RETF or
+ JUMPF-to-returning - RETURNCODE version.
"""
eof_test(
container=Container(
@@ -148,7 +156,10 @@ def test_returning_section_returncode(eof_test: EOFTestFiller, code_section: Sec
@first
@code_prefix
def test_retf_in_nonreturning(eof_test: EOFTestFiller, first: bool, code_prefix: Bytecode):
- """Test EOF validation failing due to non-returning section with the RETF instruction."""
+ """
+ Test EOF validation failing due to non-returning section with the RETF
+ instruction.
+ """
sections = [Section.Code(code_prefix + Op.RETF, code_outputs=NON_RETURNING_SECTION)]
if not first: # Prefix sections with additional valid JUMPF to invalid section
sections = [Section.Code(Op.JUMPF[1])] + sections
@@ -162,7 +173,10 @@ def test_retf_in_nonreturning(eof_test: EOFTestFiller, first: bool, code_prefix:
@first
@code_prefix
def test_jumpf_in_nonreturning(eof_test: EOFTestFiller, first: bool, code_prefix: Bytecode):
- """Test EOF validation failing due to non-returning section with the JUMPF instruction."""
+ """
+ Test EOF validation failing due to non-returning section with the JUMPF
+ instruction.
+ """
invalid_section = Section.Code(
code_prefix + Op.JUMPF[1 if first else 2],
code_outputs=NON_RETURNING_SECTION,
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py
index d75f39a597..01a78b4734 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py
@@ -1,8 +1,10 @@
"""
-abstract: Test cases for [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663)
- EIP-663 defines new stack manipulation instructions that allow accessing the stack at higher depths.
- Opcodes introduced: `DUPN` (`0xE6`), `SWAPN` (`0xE7`), `EXCHANGEN` (`0xE8`).
-""" # noqa: E501
+Test cases for EIP-663 SWAPN, DUPN and EXCHANGE instructions
+ [EIP-663](https://eips.ethereum.org/EIPS/eip-663) defines new stack
+ manipulation instructions that allow accessing the stack at higher depths.
+ Opcodes introduced: `DUPN` (`0xE6`), `SWAPN` (`0xE7`), `EXCHANGEN`
+ (`0xE8`).
+"""
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-663.md"
REFERENCE_SPEC_VERSION = "b658bb87fe039d29e9475d5cfaebca9b92e0fca2"
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py
index 997e89808f..a68cae5681 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py
@@ -1,7 +1,8 @@
"""
-abstract: Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663)
- Tests for the DUPN instruction.
-""" # noqa: E501
+DUPN instruction tests
+ Tests for DUPN instruction in
+ [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663).
+"""
import pytest
@@ -15,9 +16,9 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_STACK_INCREASE_LIMIT
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py
index 0c7c490485..583c10d89b 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py
@@ -1,7 +1,6 @@
"""
-abstract: Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663)
- Tests for the EXCHANGE instruction.
-""" # noqa: E501
+Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663).
+"""
import pytest
@@ -15,8 +14,8 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py
index 47e8c6bfaf..b0d14af35d 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py
@@ -1,7 +1,4 @@
-"""
-abstract: Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663)
- Tests for the SWAPN instruction.
-""" # noqa: E501
+"""Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663)."""
import pytest
@@ -15,9 +12,9 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_STACK_INCREASE_LIMIT
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py
index 63bedd7fd2..672c24a740 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py
@@ -1,8 +1,11 @@
"""
-abstract: Test cases for [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069)
- EIP-7069 proposes modifications to `CALL` instructions to align with the structured EOF format.
- Opcodes introduced: `EXTCALL` (`0xF8`), `EXTDELEGATECALL` (`0xF9`), `EXTSTATICCALL` (`0xFB`), `RETURNDATALOAD` (`0xF7`).
-""" # noqa: E501
+Test cases for EIP-7069 Revamped CALL instructions
+ [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069)
+ proposes modifications to `CALL` instructions to align with the
+ structured EOF format. Opcodes introduced: `EXTCALL` (`0xF8`),
+ `EXTDELEGATECALL` (`0xF9`), `EXTSTATICCALL` (`0xFB`), `RETURNDATALOAD`
+ (`0xF7`).
+"""
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7069.md"
REFERENCE_SPEC_VERSION = "1795943aeacc86131d5ab6bb3d65824b3b1d4cad"
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py
index 66dd853fac..a2180dca07 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py
@@ -5,8 +5,8 @@
import pytest
from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import value_exceptional_abort_canary
@@ -65,7 +65,10 @@ def test_address_space_extension(
target_opcode: Op,
target_account_type: str,
):
- """Test contacts with possibly extended address and fail if address is too large."""
+ """
+ Test contacts with possibly extended address and fail if address is too
+ large.
+ """
env = Environment()
ase_address = len(target_address) > 20
@@ -167,11 +170,12 @@ def test_address_space_extension(
caller_storage[slot_target_returndata] = stripped_address
case Op.CALLCODE | Op.DELEGATECALL:
caller_storage[slot_target_call_status] = LEGACY_CALL_SUCCESS
- # CALLCODE and DELEGATECALL call will call the stripped address
- # but will change the sender to self
+ # CALLCODE and DELEGATECALL call will call the stripped
+ # address but will change the sender to self
caller_storage[slot_target_returndata] = address_caller
case Op.EXTCALL | Op.EXTSTATICCALL:
- # EXTCALL and EXTSTATICCALL will fault if calling an ASE address
+ # EXTCALL and EXTSTATICCALL will fault if calling an ASE
+ # address
if ase_address:
caller_storage[slot_target_call_status] = value_exceptional_abort_canary
caller_storage[slot_target_returndata] = value_exceptional_abort_canary
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py
index a5bdc1958f..99faf72283 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py
@@ -1,13 +1,14 @@
"""
-abstract: Tests [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069)
- Tests for the RETURNDATALOAD instruction.
-""" # noqa: E501
+Call data tests for EXT*CALL instructions
+ Tests for call data handling in
+ [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069).
+"""
import pytest
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION
@@ -61,8 +62,8 @@ def test_extcalls_inputdata(
"""
Tests call data into EXTCALL including multiple offset conditions.
- Caller pushes data into memory, then calls the target. Target writes 64 bytes of call data
- to storage and a success byte.
+ Caller pushes data into memory, then calls the target. Target writes 64
+ bytes of call data to storage and a success byte.
"""
env = Environment()
@@ -148,8 +149,8 @@ def test_extdelegatecall_inputdata(
"""
Tests call data into EXTDELEGATECALL including multiple offset conditions.
- Caller pushes data into memory, then calls the target. Target writes 64 bytes of call data
- to storage and a success byte.
+ Caller pushes data into memory, then calls the target. Target writes 64
+ bytes of call data to storage and a success byte.
"""
env = Environment()
@@ -232,8 +233,8 @@ def test_extstaticcall_inputdata(
"""
Tests call data into EXTSTATICCALL including multiple offset conditions.
- Caller pushes data into memory, then calls the target. Target writes 64 bytes of call data
- to storage and a success byte.
+ Caller pushes data into memory, then calls the target. Target writes 64
+ bytes of call data to storage and a success byte.
"""
env = Environment()
@@ -312,8 +313,8 @@ def test_calldata_remains_after_subcall(
"""
Tests call data remains after a call to another contract.
- Caller pushes data into memory, then calls the target. Target calls 3rd contract. 3rd contract
- returns. Target writes calldata to storage.
+ Caller pushes data into memory, then calls the target. Target calls 3rd
+ contract. 3rd contract returns. Target writes calldata to storage.
"""
env = Environment()
@@ -494,18 +495,21 @@ def test_extcalls_input_offset(
"""
Tests call data into EXT*CALL including multiple offset conditions.
- Returner returns a success value, which caller stores. If memory expansion cost is less than
- 2 billion gas call succeeds. Else whole transaction aborts, leaving canaries in memory.
+ Returner returns a success value, which caller stores. If memory expansion
+ cost is less than 2 billion gas call succeeds. Else whole transaction
+ aborts, leaving canaries in memory.
- The name id of `*-mem-cost` refers to the bit-length of the result of the calculated memory
- expansion cost. Their length choice is designed to cause problems on shorter bit-length
- representations with native integers.
+ The name id of `*-mem-cost` refers to the bit-length of the result of the
+ calculated memory expansion cost. Their length choice is designed to cause
+ problems on shorter bit-length representations with native integers.
- The `offset_field` param indicates what part of the input data arguments are being tested,
- either the offset of the data in memory or the size of the data in memory.
+ The `offset_field` param indicates what part of the input data arguments
+ are being tested, either the offset of the data in memory or the size of
+ the data in memory.
- The `test_arg` param is the value passed into the field being tested (offset or size),
- intending to trigger integer size bugs for that particular field.
+ The `test_arg` param is the value passed into the field being tested
+ (offset or size), intending to trigger integer size bugs for that
+ particular field.
"""
env = Environment(gas_limit=1_000_000_000)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py
index 66ebac993a..55c2c67ba8 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py
@@ -15,11 +15,10 @@
Storage,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.helpers import compute_eofcreate_address
-from ethereum_test_vm.bytecode import Bytecode
-from ethereum_test_vm.evm_types import EVMCodeType
+from ethereum_test_vm import Bytecode, EVMCodeType
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .spec import (
@@ -366,8 +365,8 @@ def test_eof_calls_eof_mstore(
identity = Address(0x04)
-# `blake2f`` is chosen for the test because it fails unless args_size == 213, which is what we are
-# interested in.
+# `blake2f`` is chosen for the test because it fails unless args_size == 213,
+# which is what we are interested in.
blake2f = Address(0x09)
# `p256verify` / RIP-7212 has been in and out of prague and osaka.
# Hence we need to test explicitly
@@ -844,7 +843,9 @@ def test_eof_calls_static_flag_with_value(
sender: EOA,
opcode: Op,
):
- """Test EOF contracts calls handle static flag and sending value correctly."""
+ """
+ Test EOF contracts calls handle static flag and sending value correctly.
+ """
env = Environment()
noop_callee_address = pre.deploy_contract(Container.Code(Op.STOP))
@@ -923,13 +924,16 @@ def test_eof_calls_min_callee_gas(
reverts: bool,
):
"""
- Test EOF contracts calls do light failure when retained/callee gas is not enough.
+ Test EOF contracts calls do light failure when retained/callee gas is not
+ enough.
- Premise of the test is that there exists a range of `gas_limit` values, which are enough
- for all instructions to execute, but call's returned value is 1, meaning not enough for gas
- allowances (MIN_RETAINED_GAS and MIN_CALLEE_GAS) - ones marked with `reverts==False`.
+ Premise of the test is that there exists a range of `gas_limit` values,
+ which are enough for all instructions to execute, but call's returned value
+ is 1, meaning not enough for gas allowances (MIN_RETAINED_GAS and
+ MIN_CALLEE_GAS) - ones marked with `reverts==False`.
- Once we provide both allowances, the RJUMPI condition is no longer met and `reverts==True`.
+ Once we provide both allowances, the RJUMPI condition is no longer met and
+ `reverts==True`.
"""
env = Environment()
@@ -940,7 +944,8 @@ def test_eof_calls_min_callee_gas(
Container.Code(
Op.SSTORE(slot_code_worked, value_code_worked)
+ Op.EQ(opcode(address=noop_callee_address, value=value), EXTCALL_REVERT)
- # If the return code isn't 1, it means gas was enough to cover the allowances.
+ # If the return code isn't 1, it means gas was enough to cover the
+ # allowances.
+ Op.RJUMPI[len(revert_block)]
+ revert_block
+ Op.STOP
@@ -948,7 +953,8 @@ def test_eof_calls_min_callee_gas(
balance=value,
)
- # `no_oog_gas` is minimum amount of gas_limit which makes the transaction not go oog.
+ # `no_oog_gas` is minimum amount of gas_limit which makes the transaction
+ # not go oog.
push_operations = 3 + len(opcode.kwargs) # type: ignore
no_oog_gas = (
21_000
@@ -995,7 +1001,10 @@ def test_eof_calls_with_value(
balance: int,
value: int,
):
- """Test EOF contracts calls handle value calls with and without enough balance."""
+ """
+ Test EOF contracts calls handle value calls with and without enough
+ balance.
+ """
env = Environment()
noop_callee_address = pre.deploy_contract(Container.Code(Op.STOP))
@@ -1048,24 +1057,30 @@ def test_eof_calls_msg_depth(
):
"""
Test EOF contracts calls handle msg depth limit correctly (1024).
- NOTE: due to block gas limit and the 63/64th rule this limit is unlikely to be hit
- on mainnet.
+
+ Note:
+ due to block gas limit and the 63/64th rule this limit is unlikely
+ to be hit on mainnet.
+
"""
- # Not a precise gas_limit formula, but enough to exclude risk of gas causing the failure.
+ # Not a precise gas_limit formula, but enough to exclude risk of gas
+ # causing the failure.
gas_limit = int(200000 * (64 / 63) ** 1024)
env = Environment(gas_limit=gas_limit)
# Flow of the test:
- # `callee_code` is recursively calling itself, passing msg depth as calldata
- # (kept with the `MSTORE(0, ADD(...))`). When maximum msg depth is reached
- # the call fails and starts returning. The deep-most frame returns:
+ # `callee_code` is recursively calling itself, passing msg depth as
+ # calldata (kept with the `MSTORE(0, ADD(...))`). When maximum msg depth is
+ # reached the call fails and starts returning. The deep-most frame returns:
# - current reached msg depth (expected to be the maximum 1024), with the
# `MSTORE(32, ADD(...))`
- # - the respective return code of the EXT*CALL (expected to be 1 - light failure), with the
- # `MSTORE(64, NOOP)`. Note the `NOOP` is just to appease the `Op.MSTORE` call, the return
- # code value is actually coming from the `Op.DUP1`
- # When unwinding the msg call stack, the intermediate frames return whatever the deeper callee
- # returned with the `RETURNDATACOPY` instruction.
+ # - the respective return code of the EXT*CALL (expected to be 1 - light
+ # failure), with the `MSTORE(64, NOOP)`. Note the `NOOP` is just to
+ # appease the `Op.MSTORE` call, the return code value is actually
+ # coming from the `Op.DUP1`
+ # When unwinding the msg call stack, the intermediate frames return
+ # whatever the deeper callee returned with the `RETURNDATACOPY`
+ # instruction.
# Memory offsets layout:
# - 0 - input - msg depth
@@ -1085,8 +1100,10 @@ def test_eof_calls_msg_depth(
# duplicate return code for the `returndatacopy_block` below
+ Op.DUP1
# if return code was:
- # - 1, we're in the deep-most frame, `deep_most_result_block` returns the actual result
- # - 0, we're in an intermediate frame, `returndatacopy_block` only passes on the result
+ # - 1, we're in the deep-most frame, `deep_most_result_block` returns
+ # the actual result
+ # - 0, we're in an intermediate frame, `returndatacopy_block` only
+ # passes on the result
+ Op.RJUMPI[rjump_offset]
+ returndatacopy_block
+ deep_most_result_block
@@ -1140,8 +1157,8 @@ def test_extdelegate_call_targets(
call_from_initcode: bool,
):
"""
- Test EOF contracts extdelegatecalling various targets, especially resolved via 7702
- delegation.
+ Test EOF contracts extdelegatecalling various targets, especially resolved
+ via 7702 delegation.
"""
env = Environment()
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py
index bd42af22e3..638adc05c5 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py
@@ -1,15 +1,16 @@
"""
-abstract: Tests [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069)
- Tests gas consumption.
-""" # noqa: E501
+Gas consumption tests for EXT*CALL instructions
+ Tests for gas consumption in
+ [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069).
+"""
import pytest
from ethereum_test_base_types import Address
from ethereum_test_forks import Fork
from ethereum_test_tools import Alloc, Environment, StateTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from ..gas_test import gas_test
@@ -32,9 +33,9 @@ def state_env() -> Environment:
"""
Prepare the environment for all state test cases.
- Main difference is that the excess blob gas is not increased by the target, as
- there is no genesis block -> block 1 transition, and therefore the excess blob gas
- is not decreased by the target.
+ Main difference is that the excess blob gas is not increased by the target,
+ as there is no genesis block -> block 1 transition, and therefore the
+ excess blob gas is not decreased by the target.
"""
return Environment()
@@ -124,7 +125,10 @@ def test_ext_calls_gas(
new_account: bool,
mem_expansion_bytes: int,
):
- """Tests variations of EXT*CALL gas, both warm and cold, without and with mem expansions."""
+ """
+ Tests variations of EXT*CALL gas, both warm and cold, without and with mem
+ expansions.
+ """
address_target = (
pre.fund_eoa(0) if new_account else pre.deploy_contract(Container.Code(Op.STOP))
)
@@ -154,11 +158,12 @@ def test_transfer_gas_is_cleared(
value: int,
):
"""
- Test that EXT*CALL call doesn't charge for value transfer, even if the outer call
- transferred value.
+ Test that EXT*CALL call doesn't charge for value transfer, even if the
+ outer call transferred value.
- NOTE: This is particularly possible for EXTDELEGATECALL, which carries over the value sent
- in the outer call, however, we extend the test to all 3 EXT*CALL opcodes for good measure.
+ NOTE: This is particularly possible for EXTDELEGATECALL, which carries over
+ the value sent in the outer call, however, we extend the test to all 3
+ EXT*CALL opcodes for good measure.
"""
noop_callee_address = pre.deploy_contract(Container.Code(Op.STOP))
@@ -176,8 +181,8 @@ def test_transfer_gas_is_cleared(
subject_code=Op.EXTCALL,
subject_balance=5 * value,
tear_down_code=Op.STOP,
- # NOTE: CALL_WITH_VALUE_GAS is charged only once on the outer EXTCALL, while the base
- # call gas - twice.
+ # NOTE: CALL_WITH_VALUE_GAS is charged only once on the outer EXTCALL,
+ # while the base call gas - twice.
cold_gas=2 * COLD_ACCOUNT_ACCESS_GAS
+ (CALL_WITH_VALUE_GAS if value > 0 else 0)
+ push_gas,
@@ -196,8 +201,8 @@ def test_late_account_create(
opcode: Op,
):
"""
- Test EXTCALL to a non-existent account after another EXT*CALL has called it and not
- created it.
+ Test EXTCALL to a non-existent account after another EXT*CALL has called it
+ and not created it.
"""
empty_address = Address(0xDECAFC0DE)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py
index f5b6112c0b..7b99727594 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py
@@ -52,7 +52,10 @@ def subcall_exact_cost(
dest: int,
length: int,
) -> int:
- """Return exact cost of the subcall, based on the initial memory and the length of the copy."""
+ """
+ Return exact cost of the subcall, based on the initial memory and the
+ length of the copy.
+ """
cost_memory_bytes = fork.memory_expansion_gas_calculator()
returndatacopy_cost = 3
@@ -78,8 +81,9 @@ def bytecode_storage(
memory_expansion_address: Address,
) -> Tuple[Bytecode, Storage.StorageDictType]:
"""
- Prepare bytecode and storage for the test, based on the expected result of the subcall
- (whether it succeeds or fails depending on the length of the memory expansion).
+ Prepare bytecode and storage for the test, based on the expected result of
+ the subcall (whether it succeeds or fails depending on the length of the
+ memory expansion).
"""
bytecode = Bytecode()
storage = {}
@@ -213,7 +217,10 @@ def test_returndatacopy_memory_expansion(
post: Mapping[str, Account],
tx: Transaction,
):
- """Perform RETURNDATACOPY operations that expand the memory, and verify the gas it costs."""
+ """
+ Perform RETURNDATACOPY operations that expand the memory, and verify the
+ gas it costs.
+ """
state_test(
env=env,
pre=pre,
@@ -266,8 +273,8 @@ def test_returndatacopy_huge_memory_expansion(
tx: Transaction,
):
"""
- Perform RETURNDATACOPY operations that expand the memory by huge amounts, and verify that it
- correctly runs out of gas.
+ Perform RETURNDATACOPY operations that expand the memory by huge amounts,
+ and verify that it correctly runs out of gas.
"""
state_test(
env=env,
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py
index 37b0363c0a..8c75d1af34 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py
@@ -1,15 +1,16 @@
"""
-abstract: Tests [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069)
- Tests for the RETURNDATALOAD instruction.
-""" # noqa: E501
+RETURNDATALOAD instruction tests
+ Tests for RETURNDATALOAD instruction in
+ [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069).
+"""
from typing import cast
import pytest
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Storage, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION
@@ -82,14 +83,16 @@ def test_returndatacopy_handling(
size: int,
):
"""
- Tests ReturnDataLoad including multiple offset conditions and differing legacy vs. eof
- boundary conditions.
+ Tests ReturnDataLoad including multiple offset conditions and differing
+ legacy vs. eof boundary conditions.
entrypoint creates a "0xff" test area of memory, delegate calls to caller.
- Caller is either EOF or legacy, as per parameter. Calls returner and copies the return data
- based on offset and size params. Cases are expected to trigger boundary violations.
+ Caller is either EOF or legacy, as per parameter. Calls returner and
+ copies the return data based on offset and size params. Cases are expected
+ to trigger boundary violations.
- Entrypoint copies the test area to storage slots, and the expected result is asserted.
+ Entrypoint copies the test area to storage slots, and the expected result
+ is asserted.
"""
env = Environment()
@@ -215,9 +218,10 @@ def test_returndataload_handling(
offset: int,
):
"""
- Much simpler than returndatacopy, no memory or boosted call. Returner is called
- and results are stored in storage slot, which is asserted for expected values.
- The parameters offset and return data are configured to test boundary conditions.
+ Much simpler than returndatacopy, no memory or boosted call. Returner is
+ called and results are stored in storage slot, which is asserted for
+ expected values. The parameters offset and return data are configured to
+ test boundary conditions.
"""
env = Environment()
@@ -283,16 +287,17 @@ def test_returndatacopy_oob(
opcode: Op,
):
"""
- Extends the RETURNDATACOPY test for correct out-of-bounds behavior, by checking if the
- caller frame's context being EOF or legacy doesn't impact the execution logic of the
- RETURNDATACOPY instance under test.
+ Extends the RETURNDATACOPY test for correct out-of-bounds behavior, by
+ checking if the caller frame's context being EOF or legacy doesn't impact
+ the execution logic of the RETURNDATACOPY instance under test.
"""
env = Environment()
sender = pre.fund_eoa()
- # Both callee codes below make an OOB (out-of-bounds) RETURNDATACOPY of one byte,
- # which they then attempt to return (Legacy should exceptionally halt on RETURNDATACOPY).
+ # Both callee codes below make an OOB (out-of-bounds) RETURNDATACOPY of one
+ # byte, which they then attempt to return (Legacy should exceptionally halt
+ # on RETURNDATACOPY).
address_callee_eof = pre.deploy_contract(
code=Container(
sections=[
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py
index 845a31a74a..ee7f967e8f 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py
@@ -1,5 +1,9 @@
"""
-abstract: Test cases for [EIP-7480: EOF - Data section access instructions](https://eips.ethereum.org/EIPS/eip-7480)
- EIP-7480 specifies instructions for accessing data stored in the dedicated data section of the EOF format.
- Opcodes introduced: `DATALOAD` (`0xD0`), `DATALOADN` (`0xD1`), `DATASIZE` (`0xD2`), `DATACOPY` (`0xD3`).
-""" # noqa: E501
+Test cases for EOF Data section access instructions for EIP-7480.
+
+EIP-7480 specifies instructions for accessing data stored in the dedicated
+data section of the EOF format. Full specification: [EIP-7480: EOF - Data
+section access instructions](https://eips.ethereum.org/EIPS/eip-7480).
+Opcodes introduced: `DATALOAD` (`0xD0`), `DATALOADN` (`0xD1`), `DATASIZE`
+(`0xD2`), `DATACOPY` (`0xD3`).
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py
index 0189f632d4..23df4e4336 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py
@@ -3,9 +3,9 @@
import pytest
from ethereum_test_tools import EOFException, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_INITCODE_SIZE
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py
index 238cfe7cc8..2770011f6c 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py
@@ -4,8 +4,8 @@
from ethereum_test_specs import EOFStateTestFiller
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -36,7 +36,10 @@ def test_dataloadn(eof_state_test: EOFStateTestFiller, index: int, suffix_len: i
def create_data_test(offset: int, datasize: int):
- """Generate data load operators test cases based on load offset and data section size."""
+ """
+ Generate data load operators test cases based on load offset and data
+ section size.
+ """
data = b"".join(i.to_bytes(length=2, byteorder="big") for i in range(1, datasize // 2 + 1))
assert len(data) == datasize
overhang = min(32, offset + 32 - datasize)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py
index a57fd99910..90c2ec6756 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py
@@ -15,8 +15,8 @@
Storage,
Transaction,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
@@ -52,7 +52,10 @@ def subcall_exact_cost(
dest: int,
length: int,
) -> int:
- """Return exact cost of the subcall, based on the initial memory and the length of the copy."""
+ """
+ Return exact cost of the subcall, based on the initial memory and the
+ length of the copy.
+ """
cost_memory_bytes = fork.memory_expansion_gas_calculator()
datacopy_cost = 3
@@ -78,8 +81,9 @@ def bytecode_storage(
memory_expansion_address: Address,
) -> Tuple[Bytecode, Storage.StorageDictType]:
"""
- Prepare bytecode and storage for the test, based on the expected result of the subcall
- (whether it succeeds or fails depending on the length of the memory expansion).
+ Prepare bytecode and storage for the test, based on the expected result of
+ the subcall (whether it succeeds or fails depending on the length of the
+ memory expansion).
"""
bytecode = Bytecode()
storage = {}
@@ -223,7 +227,10 @@ def test_datacopy_memory_expansion(
post: Mapping[str, Account],
tx: Transaction,
):
- """Perform DATACOPY operations that expand the memory, and verify the gas it costs to do so."""
+ """
+ Perform DATACOPY operations that expand the memory, and verify the gas it
+ costs to do so.
+ """
state_test(
env=env,
pre=pre,
@@ -286,8 +293,8 @@ def test_datacopy_huge_memory_expansion(
tx: Transaction,
):
"""
- Perform DATACOPY operations that expand the memory by huge amounts, and verify that it
- correctly runs out of gas.
+ Perform DATACOPY operations that expand the memory by huge amounts, and
+ verify that it correctly runs out of gas.
"""
state_test(
env=env,
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py
index 886cfd7db2..4156e92a7a 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py
@@ -1,19 +1,26 @@
"""
-abstract: Test cases for [EIP-7620: EOF Contract Creation](https://eips.ethereum.org/EIPS/eip-7620)
- EIP-7620 replaces `CREATE` and `CREATE2` with `EOFCREATE` for deploying contracts in the EOF format.
- Opcodes introduced: `EOFCREATE` (`0xEC`), `RETURNCODE` (`0xEE`).
+Test cases for EOF Contract Creation for EIP-7620.
+EIP-7620 replaces `CREATE` and `CREATE2` with `EOFCREATE` for deploying
+contracts in the EOF format.
-EOFCREATE, RETURNCODE, and container tests
+Full specification:
+[EIP-7620: EOF Contract Creation](https://eips.ethereum.org/EIPS/eip-7620).
-evmone tests not ported
+Opcodes introduced: `EOFCREATE` (`0xEC`), `RETURNCODE` (`0xEE`).
-- create_tx_with_eof_initcode - This calls it invalid, it is now the way to add EOF contacts to state
-- eofcreate_extcall_returncode - per the new initcode mode tests you cannot have RETURNCODE
- in a deployed contract
-- eofcreate_dataloadn_referring_to_auxdata - covered by
- tests.unscheduled.eip7480_data_section.test_data_opcodes.test_data_section_succeed
-- eofcreate_initcontainer_return - RETURN is banned in initcode containers
-- eofcreate_initcontainer_stop - STOP is banned in initcode containers
+EOFCREATE, RETURNCODE, and container tests.
+
+evmone tests not ported:
+- create_tx_with_eof_initcode: This calls it invalid, it is now the way to
+ add EOF contacts to state
+- eofcreate_extcall_returncode: Per the new initcode
+ mode tests you cannot have RETURNCODE in a
+ deployed contract
+- eofcreate_dataloadn_referring_to_auxdata: covered by
+ tests.unscheduled.eip7480_data_section.
+ test_data_opcodes.test_data_section_succeed
+- eofcreate_initcontainer_return: RETURN is banned in initcode containers
+- eofcreate_initcontainer_stop: STOP is banned in initcode containers
- All TXCREATE tests.
-""" # noqa: E501
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py
index 460ed2b5d3..e8a6846adb 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py
@@ -14,9 +14,9 @@
Transaction,
compute_eofcreate_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from ..eip7069_extcall.spec import EXTCALL_SUCCESS
@@ -76,7 +76,10 @@ def test_eofcreate_then_dataload(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies that a contract returned with auxdata does not overwrite the parent data."""
+ """
+ Verifies that a contract returned with auxdata does not overwrite the
+ parent data.
+ """
env = Environment()
sender = pre.fund_eoa()
small_auxdata_container = Container(
@@ -124,7 +127,9 @@ def test_eofcreate_then_call(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies a simple EOFCREATE case, and then calls the deployed contract."""
+ """
+ Verifies a simple EOFCREATE case, and then calls the deployed contract.
+ """
env = Environment()
callable_contract = Container(
sections=[
@@ -314,7 +319,9 @@ def test_eofcreate_in_initcode(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies an EOFCREATE occurring within initcode creates that contract."""
+ """
+ Verifies an EOFCREATE occurring within initcode creates that contract.
+ """
nested_initcode_subcontainer = Container(
sections=[
Section.Code(
@@ -368,7 +375,10 @@ def test_eofcreate_in_initcode_reverts(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies an EOFCREATE occurring in an initcode is rolled back when the initcode reverts."""
+ """
+ Verifies an EOFCREATE occurring in an initcode is rolled back when the
+ initcode reverts.
+ """
nested_initcode_subcontainer = Container(
sections=[
Section.Code(
@@ -422,7 +432,10 @@ def test_return_data_cleared(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies the return data is not reused from a extcall but is cleared upon eofcreate."""
+ """
+ Verifies the return data is not reused from a extcall but is cleared upon
+ eofcreate.
+ """
env = Environment()
value_return_canary = 0x4158675309
value_return_canary_size = 5
@@ -518,8 +531,10 @@ def test_address_collision(
contract_address: Account(
storage={
slot_create_address: salt_zero_address,
- slot_create_address_2: EOFCREATE_FAILURE, # had an in-transaction collision
- slot_create_address_3: EOFCREATE_FAILURE, # had a pre-existing collision
+ # had an in-transaction collision
+ slot_create_address_2: EOFCREATE_FAILURE,
+ # had a pre-existing collision
+ slot_create_address_3: EOFCREATE_FAILURE,
slot_code_worked: value_code_worked,
}
)
@@ -540,7 +555,10 @@ def test_eofcreate_revert_eof_returndata(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies the return data is not being deployed, even if happens to be valid EOF."""
+ """
+ Verifies the return data is not being deployed, even if happens to be valid
+ EOF.
+ """
env = Environment()
code_reverts_with_calldata = Container(
name="Initcode Subcontainer reverting with its calldata",
@@ -638,7 +656,9 @@ def test_eofcreate_truncated_container(
data_len: int,
data_section_size: int,
):
- """EOFCREATE instruction targeting a container with truncated data section."""
+ """
+ EOFCREATE instruction targeting a container with truncated data section.
+ """
assert data_len < data_section_size
eof_test(
container=Container(
@@ -716,7 +736,8 @@ def test_eofcreate_context(
elif expected_result == "selfbalance":
expected_bytes = eofcreate_value
elif expected_result == "factorybalance":
- # Factory receives value from sender and passes on eofcreate_value as endowment.
+ # Factory receives value from sender and passes on eofcreate_value as
+ # endowment.
expected_bytes = value - eofcreate_value
else:
raise TypeError("Unexpected expected_result", expected_result)
@@ -747,7 +768,10 @@ def test_eofcreate_memory_context(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies an EOFCREATE frame enjoys a separate EVM memory from its caller frame."""
+ """
+ Verifies an EOFCREATE frame enjoys a separate EVM memory from its caller
+ frame.
+ """
env = Environment()
destination_storage = Storage()
contract_storage = Storage()
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py
index 8a40c601c8..1b3872b5c0 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py
@@ -11,9 +11,9 @@
Transaction,
compute_eofcreate_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from ..eip7069_extcall.spec import EXTCALL_FAILURE, EXTCALL_REVERT, LEGACY_CALL_FAILURE
@@ -142,8 +142,8 @@ def test_initcode_aborts(
"""
-Size of the factory portion of test_eofcreate_deploy_sizes, but as the runtime code is dynamic, we
-have to use a pre-calculated size
+Size of the factory portion of test_eofcreate_deploy_sizes, but as the runtime
+code is dynamic, we have to use a pre-calculated size
"""
factory_size = 78
@@ -172,7 +172,10 @@ def test_eofcreate_deploy_sizes(
pre: Alloc,
target_deploy_size: int,
):
- """Verifies a mix of runtime contract sizes mixing success and multiple size failure modes."""
+ """
+ Verifies a mix of runtime contract sizes mixing success and multiple size
+ failure modes.
+ """
env = Environment()
runtime_container = Container(
@@ -215,9 +218,9 @@ def test_eofcreate_deploy_sizes(
sender = pre.fund_eoa()
contract_address = pre.deploy_contract(code=factory_container)
- # Storage in 0 should have the address,
- # Storage 1 is a canary of 1 to make sure it tried to execute, which also covers cases of
- # data+code being greater than initcode_size_max, which is allowed.
+ # Storage in 0 should have the address, Storage 1 is a canary of 1 to make
+ # sure it tried to execute, which also covers cases of data+code being
+ # greater than initcode_size_max, which is allowed.
success = target_deploy_size <= MAX_BYTECODE_SIZE
post = {
contract_address: Account(
@@ -260,8 +263,8 @@ def test_eofcreate_deploy_sizes_tx(
target_deploy_size: int,
):
"""
- Verifies a mix of runtime contract sizes mixing success and multiple size failure modes
- where the initcontainer is included in a transaction.
+ Verifies a mix of runtime contract sizes mixing success and multiple size
+ failure modes where the initcontainer is included in a transaction.
"""
raise NotImplementedError("Not implemented")
@@ -278,7 +281,9 @@ def test_eofcreate_deploy_sizes_tx(
],
)
def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_size: int):
- """Exercises a number of auxdata size violations, and one maxcode success."""
+ """
+ Exercises a number of auxdata size violations, and one maxcode success.
+ """
env = Environment()
auxdata_bytes = b"a" * auxdata_size
@@ -309,8 +314,11 @@ def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_
deployed_container_size = len(smallest_runtime_subcontainer) + auxdata_size
- # Storage in 0 will have address in first test, 0 in all other cases indicating failure
- # Storage 1 in 1 is a canary to see if EOFCREATE opcode halted
+ # Storage in 0 will have address in first test, 0 in all other cases
+ # indicating failure
+ #
+ # Storage 1 in 1 is a canary to see if EOFCREATE opcode
+ # halted
success = deployed_container_size <= MAX_BYTECODE_SIZE
post = {
contract_address: Account(
@@ -351,8 +359,8 @@ def test_eofcreate_insufficient_stipend(
value: int,
):
"""
- Exercises an EOFCREATE that fails because the calling account does not have enough ether to
- pay the stipend.
+ Exercises an EOFCREATE that fails because the calling account does not have
+ enough ether to pay the stipend.
"""
env = Environment()
initcode_container = Container(
@@ -370,7 +378,9 @@ def test_eofcreate_insufficient_stipend(
code=initcode_container,
balance=value - 1,
)
- # create will fail but not trigger a halt, so canary at storage 1 should be set
+ # create will fail but not trigger a halt, so canary at storage 1 should be
+ # set
+ #
# also validate target created contract fails
post = {
contract_address: Account(
@@ -395,7 +405,10 @@ def test_insufficient_initcode_gas(
state_test: StateTestFiller,
pre: Alloc,
):
- """Exercises an EOFCREATE when there is not enough gas for the initcode charge."""
+ """
+ Exercises an EOFCREATE when there is not enough gas for the initcode
+ charge.
+ """
env = Environment()
initcode_data = b"a" * 0x5000
@@ -455,7 +468,10 @@ def test_insufficient_gas_memory_expansion(
state_test: StateTestFiller,
pre: Alloc,
):
- """Exercises EOFCREATE when the memory for auxdata has not been expanded but is requested."""
+ """
+ Exercises EOFCREATE when the memory for auxdata has not been expanded but
+ is requested.
+ """
env = Environment()
auxdata_size = 0x5000
@@ -513,7 +529,10 @@ def test_insufficient_returncode_auxdata_gas(
state_test: StateTestFiller,
pre: Alloc,
):
- """Exercises a RETURNCODE when there is not enough gas for the initcode charge."""
+ """
+ Exercises a RETURNCODE when there is not enough gas for the initcode
+ charge.
+ """
env = Environment()
auxdata_size = 0x5000
@@ -583,7 +602,8 @@ def test_insufficient_returncode_auxdata_gas(
Op.EXTSTATICCALL,
],
)
-@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag check comes first
+@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag
+# check comes first
@pytest.mark.parametrize(
"initcode",
[smallest_initcode_subcontainer, aborting_container],
@@ -664,14 +684,18 @@ def test_eof_eofcreate_msg_depth(
):
"""
Test EOFCREATE handles msg depth limit correctly (1024).
- NOTE: due to block gas limit and the 63/64th rule this limit is unlikely to be hit
- on mainnet.
- NOTE: See `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py::test_eof_calls_msg_depth`
- for more explanations and comments. Most notable deviation from that test is that here
- calls and `EOFCREATE`s alternate in order to reach the max depth. `who_fails` decides
- whether the failing depth 1024 will be on a call or on an `EOFCREATE` to happen.
- """ # noqa: E501
- # Not a precise gas_limit formula, but enough to exclude risk of gas causing the failure.
+
+ NOTE: due to block gas limit and the 63/64th rule this limit is
+ unlikely to be hit on mainnet.
+ NOTE: See `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/
+ test_calls.py::test_eof_calls_msg_depth` for more explanations and
+ comments. Most notable deviation from that test is that here calls
+ and `EOFCREATE`s alternate in order to reach the max depth.
+ `who_fails` decides whether the failing depth 1024 will be on a call
+ or on an `EOFCREATE` to happen.
+ """
+ # Not a precise gas_limit formula, but enough to exclude risk of gas
+ # causing the failure.
gas_limit = int(20000000 * (64 / 63) ** 1024)
env = Environment(gas_limit=gas_limit)
sender = pre.fund_eoa()
@@ -730,8 +754,9 @@ def test_eof_eofcreate_msg_depth(
)
)
- # Only bumps the msg call depth "register" and forwards to the `calling_contract_address`.
- # If it is used it makes the "failing" depth of 1024 to happen on EOFCREATE, instead of CALL.
+ # Only bumps the msg call depth "register" and forwards to the
+ # `calling_contract_address`. If it is used it makes the "failing" depth of
+ # 1024 to happen on EOFCREATE, instead of CALL.
passthrough_address = pre.deploy_contract(
Container.Code(
Op.MSTORE(0, 1) + Op.EXTCALL(address=calling_contract_address, args_size=32) + Op.STOP
@@ -768,12 +793,15 @@ def test_reentrant_eofcreate(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies a reentrant EOFCREATE case, where EIP-161 prevents conflict via nonce bump."""
+ """
+ Verifies a reentrant EOFCREATE case, where EIP-161 prevents conflict via
+ nonce bump.
+ """
env = Environment()
# Calls into the factory contract with 1 as input.
reenter_code = Op.MSTORE(0, 1) + Op.EXTCALL(address=Op.CALLDATALOAD(32), args_size=32)
- # Initcode: if given 0 as 1st word of input will call into the factory again.
- # 2nd word of input is the address of the factory.
+ # Initcode: if given 0 as 1st word of input will call into the factory
+ # again. 2nd word of input is the address of the factory.
initcontainer = Container(
sections=[
Section.Code(
@@ -786,15 +814,19 @@ def test_reentrant_eofcreate(
Section.Container(smallest_runtime_subcontainer),
]
)
- # Factory: Passes on its input into the initcode. It's 0 first time, 1 the second time.
- # Saves the result of deployment in slot 0 first time, 1 the second time.
+ # Factory:
+ # Passes on its input into the initcode.
+ # It's 0 first time, 1 the second time.
+ # Saves the result of deployment in slot 0 first time, 1 the
+ # second time.
contract_address = pre.deploy_contract(
code=Container(
sections=[
Section.Code(
Op.CALLDATACOPY(0, 0, 32)
+ Op.MSTORE(32, Op.ADDRESS)
- # 1st word - copied from input (reenter flag), 2nd word - `this.address`.
+ # 1st word - copied from input (reenter flag)
+ # 2nd word - `this.address`
+ Op.SSTORE(Op.CALLDATALOAD(0), Op.EOFCREATE[0](input_size=64))
+ Op.STOP,
),
@@ -803,13 +835,18 @@ def test_reentrant_eofcreate(
),
storage={0: 0xB17D, 1: 0xB17D}, # a canary to be overwritten
)
- # Flow is: reenter flag 0 -> factory -> reenter flag 0 -> initcode -> reenter ->
- # reenter flag 1 -> factory -> reenter flag 1 -> (!) initcode -> stop,
- # if the EIP-161 nonce bump is not implemented. If it is, it fails before second
- # inicode marked (!).
+ # Flow is:
+ # reenter flag 0 -> factory -> reenter flag 0 -> initcode ->
+ # reenter -> reenter flag 1 -> factory -> reenter flag 1 -> (!) initcode
+ # -> stop
+ # if the EIP-161 nonce bump is not implemented.
+ #
+ # If it is, it fails before second inicode marked (!).
+ #
# Storage in 0 should have the address from the outer EOFCREATE.
- # Storage in 1 should have 0 from the inner EOFCREATE.
- # For the created contract storage in `slot_counter` should be 1 as initcode executes only once
+ # Storage in 1 should have 0 from the inner EOFCREATE. For the created
+ # contract storage in `slot_counter` should be 1 as initcode
+ # executes only once.
post = {
contract_address: Account(
storage={
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py
index e010dd40ee..c3019da962 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py
@@ -4,8 +4,8 @@
from ethereum_test_forks import Fork
from ethereum_test_tools import Alloc, Environment, StateTestFiller, compute_eofcreate_address
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from ..gas_test import gas_test
@@ -130,8 +130,9 @@ def test_eofcreate_gas(
for a in salt_addresses:
pre.fund_address(a, 1)
- # Using `TLOAD` / `TSTORE` to work around warm/cold gas differences. We need a counter to pick
- # a distinct salt on each `EOFCREATE` and avoid running into address conflicts.
+ # Using `TLOAD` / `TSTORE` to work around warm/cold gas differences. We
+ # need a counter to pick a distinct salt on each `EOFCREATE` and avoid
+ # running into address conflicts.
code_increment_counter = (
Op.TLOAD(slot_counter) + Op.DUP1 + Op.TSTORE(slot_counter, Op.PUSH1(1) + Op.ADD)
)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py
index ebd607293f..d6ab9c2a09 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py
@@ -11,10 +11,10 @@
Transaction,
)
from ethereum_test_tools import Initcode as LegacyInitcode
-from ethereum_test_tools.vm.opcode import Opcodes
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container
from ethereum_test_types.helpers import compute_create_address
+from ethereum_test_vm import Opcodes
+from ethereum_test_vm import Opcodes as Op
from ....prague.eip7702_set_code_tx.spec import Spec
from .. import EOF_FORK_NAME
@@ -56,7 +56,10 @@ def test_cross_version_creates_fail_light(
legacy_create_opcode: Opcodes,
initcode: Bytes | Container,
):
- """Verifies that CREATE and CREATE2 cannot run EOF initcodes and fail early on attempt."""
+ """
+ Verifies that CREATE and CREATE2 cannot run EOF initcodes and fail early on
+ attempt.
+ """
env = Environment()
sender = pre.fund_eoa()
@@ -66,7 +69,8 @@ def test_cross_version_creates_fail_light(
contract_address = pre.deploy_contract(
code=Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE)
+ Op.SSTORE(slot_create_address, legacy_create_opcode(size=Op.CALLDATASIZE))
- # Approximates whether code until here consumed the 63/64th gas given to subcall
+ # Approximates whether code until here consumed the 63/64th gas given
+ # to subcall
+ Op.SSTORE(slot_all_subcall_gas_gone, Op.LT(Op.GAS, tx_gas_limit // 64))
+ Op.SSTORE(slot_code_worked, value_code_worked)
+ Op.STOP
@@ -126,8 +130,8 @@ def test_cross_version_creates_fail_hard(
initcode: Bytes,
):
"""
- Verifies that CREATE and CREATE2 fail hard on attempt to run initcode starting with `EF` but
- not `EF00`.
+ Verifies that CREATE and CREATE2 fail hard on attempt to run initcode
+ starting with `EF` but not `EF00`.
"""
env = Environment()
@@ -138,7 +142,8 @@ def test_cross_version_creates_fail_hard(
contract_address = pre.deploy_contract(
code=Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE)
+ Op.SSTORE(slot_create_address, legacy_create_opcode(size=Op.CALLDATASIZE))
- # Approximates whether code until here consumed the 63/64th gas given to subcall
+ # Approximates whether code until here consumed the 63/64th gas given
+ # to subcall
+ Op.SSTORE(slot_all_subcall_gas_gone, Op.LT(Op.GAS, tx_gas_limit // 64))
+ Op.SSTORE(slot_code_worked, value_code_worked)
+ Op.STOP
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py
index 8b0bb756a6..15eed022ae 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py
@@ -4,9 +4,9 @@
from ethereum_test_base_types import Account, Storage
from ethereum_test_tools import Alloc, Environment, StateTestFiller, compute_eofcreate_address
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types import Transaction
from ethereum_test_types.eof.v1 import Container, Section
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import (
@@ -62,18 +62,20 @@ def test_eofcreate_memory(
"""
Tests auxdata sizes in EOFCREATE including multiple offset conditions.
- EOFCREATE either succeeds or fails based on memory access cost, resulting in new address
- or zero in the create address slot.
+ EOFCREATE either succeeds or fails based on memory access cost, resulting
+ in new address or zero in the create address slot.
- The name id of `*-mem-cost` refers to the bit-length of the result of the calculated memory
- expansion cost. Their length choice is designed to cause problems on shorter bit-length
- representations with native integers.
+ The name id of `*-mem-cost` refers to the bit-length of the result of the
+ calculated memory expansion cost. Their length choice is designed to cause
+ problems on shorter bit-length representations with native integers.
- The `offset_field` param indicates what part of the input data arguments are being tested,
- either the offset of the data in memory or the size of the data in memory.
+ The `offset_field` param indicates what part of the input data arguments
+ are being tested, either the offset of the data in memory or the size of
+ the data in memory.
- The `test_arg` param is the value passed into the field being tested (offset or size),
- intending to trigger integer size bugs for that particular field.
+ The `test_arg` param is the value passed into the field being tested
+ (offset or size), intending to trigger integer size bugs for that
+ particular field.
"""
env = Environment(gas_limit=2_000_000_000)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py
index 788933fcf9..e945768371 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py
@@ -5,10 +5,10 @@
from ethereum_test_base_types import Account
from ethereum_test_specs import StateTestFiller
from ethereum_test_tools import Alloc, EOFException, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types import Environment, Transaction, compute_eofcreate_address
from ethereum_test_types.eof.v1 import Container, ContainerKind, Section
from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import (
@@ -203,18 +203,21 @@ def test_returncode_memory_expansion(
success: bool,
):
"""
- Attempts an EOFCREATE with a possibly too-large auxdata. Create either fails due to gas
- or contract too large, resulting in address or zero on failure in the create address slot.
+ Attempts an EOFCREATE with a possibly too-large auxdata. Create either
+ fails due to gas or contract too large, resulting in address or zero on
+ failure in the create address slot.
- The name id of `*-mem-cost` refers to the bit-length of the result of the calculated memory
- expansion cost. Their length choice is designed to cause problems on shorter bit-length
- representations with native integers.
+ The name id of `*-mem-cost` refers to the bit-length of the result of the
+ calculated memory expansion cost. Their length choice is designed to cause
+ problems on shorter bit-length representations with native integers.
- The `offset_field` param indicates what part of the input data arguments are being tested,
- either the offset of the data in memory or the size of the data in memory.
+ The `offset_field` param indicates what part of the input data arguments
+ are being tested, either the offset of the data in memory or the size of
+ the data in memory.
- The `test_arg` param is the value passed into the field being tested (offset or size),
- intending to trigger integer size bugs for that particular field.
+ The `test_arg` param is the value passed into the field being tested
+ (offset or size), intending to trigger integer size bugs for that
+ particular field.
"""
env = Environment(gas_limit=2_000_000_000)
sender = pre.fund_eoa(10**27)
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py
index acd6f0a67d..8c796feb75 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py
@@ -3,10 +3,10 @@
import pytest
from ethereum_test_tools import Account, EOFException, EOFStateTestFiller, EOFTestFiller
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, ContainerKind, Section
from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE
from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from .helpers import slot_code_worked, value_code_worked
@@ -264,7 +264,10 @@ def test_container_combos_deeply_nested_valid(
code_section: Section,
first_sub_container: Container,
):
- """Test valid subcontainer reference / opcode combos on a deep container nesting level."""
+ """
+ Test valid subcontainer reference / opcode combos on a deep container
+ nesting level.
+ """
valid_container = Container(
sections=[
code_section,
@@ -314,7 +317,10 @@ def test_container_combos_deeply_nested_invalid(
code_section: Section,
first_sub_container: Container,
):
- """Test invalid subcontainer reference / opcode combos on a deep container nesting level."""
+ """
+ Test invalid subcontainer reference / opcode combos on a deep container
+ nesting level.
+ """
invalid_container = Container(
sections=[
code_section,
@@ -380,7 +386,10 @@ def test_container_combos_non_first_code_sections_valid(
first_sub_container: Container,
container_kind: ContainerKind,
):
- """Test valid subcontainer reference / opcode combos in a non-first code section."""
+ """
+ Test valid subcontainer reference / opcode combos in a non-first code
+ section.
+ """
eof_test(
container=Container(
sections=[Section.Code(Op.JUMPF[i]) for i in range(1, 1024)]
@@ -419,7 +428,10 @@ def test_container_combos_non_first_code_sections_invalid(
first_sub_container: Container,
container_kind: ContainerKind,
):
- """Test invalid subcontainer reference / opcode combos in a non-first code section."""
+ """
+ Test invalid subcontainer reference / opcode combos in a non-first code
+ section.
+ """
eof_test(
container=Container(
sections=[Section.Code(Op.JUMPF[i]) for i in range(1, 1024)]
@@ -431,7 +443,9 @@ def test_container_combos_non_first_code_sections_invalid(
def test_container_both_kinds_same_sub(eof_test: EOFTestFiller):
- """Test subcontainer conflicts (both EOFCREATE and RETURNCODE Reference)."""
+ """
+ Test subcontainer conflicts (both EOFCREATE and RETURNCODE Reference).
+ """
eof_test(
container=Container(
sections=[
@@ -460,8 +474,8 @@ def test_container_ambiguous_kind(
eof_test: EOFTestFiller, container_idx: int, sub_container: Section
):
"""
- Test ambiguous container kind:
- a single subcontainer reference by both EOFCREATE and RETURNCODE.
+ Test ambiguous container kind: a single subcontainer reference by both
+ EOFCREATE and RETURNCODE.
"""
sections = [
Section.Code(
@@ -504,7 +518,10 @@ def test_container_both_kinds_different_sub(eof_test: EOFTestFiller):
def test_container_multiple_eofcreate_references(eof_test: EOFTestFiller):
- """Test multiple references to the same subcontainer from an EOFCREATE operation."""
+ """
+ Test multiple references to the same subcontainer from an EOFCREATE
+ operation.
+ """
eof_test(
container=Container(
sections=[
@@ -518,7 +535,10 @@ def test_container_multiple_eofcreate_references(eof_test: EOFTestFiller):
def test_container_multiple_returncode_references(eof_test: EOFTestFiller):
- """Test multiple references to the same subcontainer from a RETURNCONTACT operation."""
+ """
+ Test multiple references to the same subcontainer from a RETURNCONTACT
+ operation.
+ """
eof_test(
container=Container(
sections=[
@@ -611,7 +631,8 @@ def test_deep_container(
"""
Test a very deeply nested container.
- This test skips generating a state test because the initcode size is too large.
+ This test skips generating a state test because the initcode size is too
+ large.
"""
container = deepest_container
last_container = deepest_container
@@ -785,7 +806,8 @@ def test_wide_container(eof_test: EOFTestFiller, width: int, exception: EOFExcep
ef0001010004020001000603000100000014ff000200008000016000e0000000ef000101000402000100
01ff00000000800000fe""",
# Originally this test was "valid" but against the current spec
- # it contains two errors: data section truncated and orphan subcontainer.
+ # it contains two errors: data section truncated and orphan
+ # subcontainer.
validity_error=EOFException.TOPLEVEL_CONTAINER_TRUNCATED,
),
id="orphan_subcontainer_0_and_truncated_data",
@@ -812,7 +834,8 @@ def test_wide_container(eof_test: EOFTestFiller, width: int, exception: EOFExcep
Section.Code(Op.EOFCREATE[0](0, 0, 0, 0) + Op.STOP),
Section.Container("aabbccddeeff"),
],
- # The original test has been modified to reference the subcontainer by EOFCREATE.
+ # The original test has been modified to reference the
+ # subcontainer by EOFCREATE.
validity_error=EOFException.INVALID_MAGIC,
),
id="subcontainer_0_with_invalid_prefix",
@@ -896,7 +919,10 @@ def test_migrated_eofcreate(eof_test: EOFTestFiller, container: Container):
def test_dangling_initcode_subcontainer_bytes(
eof_test: EOFTestFiller,
):
- """Initcode mode EOF Subcontainer test with subcontainer containing dangling bytes."""
+ """
+ Initcode mode EOF Subcontainer test with subcontainer containing dangling
+ bytes.
+ """
eof_test(
container=Container(
sections=[
@@ -916,7 +942,10 @@ def test_dangling_initcode_subcontainer_bytes(
def test_dangling_runtime_subcontainer_bytes(
eof_test: EOFTestFiller,
):
- """Runtime mode EOF Subcontainer test with subcontainer containing dangling bytes."""
+ """
+ Runtime mode EOF Subcontainer test with subcontainer containing dangling
+ bytes.
+ """
eof_test(
container=Container(
sections=[
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py
index b893e42d5a..ddd4426793 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py
@@ -1,4 +1,3 @@
"""
-abstract: Test cases for
-[EIP-7873: TXCREATE and InitcodeTransaction](https://eips.ethereum.org/EIPS/eip-7873).
-""" # noqa: E501
+Test cases for [EIP-7873: TXCREATE and InitcodeTransaction](https://eips.ethereum.org/EIPS/eip-7873).
+"""
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py
index 87ad9fa1e3..842fd90e8e 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py
@@ -10,7 +10,7 @@
StateTestFiller,
Transaction,
)
-from ethereum_test_tools.code.generators import Initcode as LegacyInitcode
+from ethereum_test_tools import Initcode as LegacyInitcode
from ethereum_test_types import TransactionReceipt
from ethereum_test_types.eof.v1 import Container
@@ -99,9 +99,9 @@ def test_legacy_create_tx_prefix_initcode(
initcode: Bytes,
):
"""
- Test that a legacy contract creation tx behaves as it did before EIP-7873 for
- initcode stating with `EF`.
- The transaction should be valid but fail on executing of the first byte `EF`.
+ Test that a legacy contract creation tx behaves as it did before EIP-7873
+ for initcode stating with `EF`. The transaction should be valid but fail on
+ executing of the first byte `EF`.
"""
env = Environment()
sender = pre.fund_eoa()
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py
index bd7dd21295..049cca1406 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py
@@ -13,9 +13,9 @@
Transaction,
compute_eofcreate_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from ..eip7069_extcall.spec import EXTCALL_SUCCESS, LEGACY_CALL_SUCCESS
@@ -67,7 +67,10 @@ def test_txcreate_then_dataload(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies that a contract returned with auxdata does not overwrite the parent data."""
+ """
+ Verifies that a contract returned with auxdata does not overwrite the
+ parent data.
+ """
env = Environment()
sender = pre.fund_eoa()
small_auxdata_container = Container(
@@ -110,7 +113,9 @@ def test_txcreate_then_dataload(
@pytest.mark.with_all_evm_code_types
def test_txcreate_then_call(state_test: StateTestFiller, pre: Alloc, evm_code_type: EVMCodeType):
- """Verifies a simple TXCREATE case, and then calls the deployed contract."""
+ """
+ Verifies a simple TXCREATE case, and then calls the deployed contract.
+ """
env = Environment()
callable_contract = Container(
sections=[
@@ -294,8 +299,8 @@ def test_txcreate_in_initcode(
"""
Verifies an TXCREATE occurring within initcode creates that contract.
- Via the `outer_create_reverts` also verifies a TXCREATE occurring in an initcode is rolled back
- when the initcode reverts.
+ Via the `outer_create_reverts` also verifies a TXCREATE occurring in an
+ initcode is rolled back when the initcode reverts.
"""
smallest_initcode_subcontainer_hash = smallest_initcode_subcontainer.hash
inner_create_bytecode = (
@@ -303,8 +308,8 @@ def test_txcreate_in_initcode(
if inner_create_opcode == Op.TXCREATE
else Op.EOFCREATE[1](0, 0, 0, 0)
)
- # The terminating code of the inner initcontainer, the RJUMPI is a trick to not need to deal
- # with the subcontainer indices
+ # The terminating code of the inner initcontainer, the RJUMPI is a trick to
+ # not need to deal with the subcontainer indices
revert_code = Op.REVERT(0, 0)
terminating_code = (
Op.RJUMPI[len(revert_code)](0) + revert_code + Op.RETURNCODE[0](0, 0)
@@ -385,7 +390,10 @@ def test_return_data_cleared(
pre: Alloc,
evm_code_type: EVMCodeType,
):
- """Verifies the return data is not reused from a extcall but is cleared upon TXCREATE."""
+ """
+ Verifies the return data is not reused from a extcall but is cleared upon
+ TXCREATE.
+ """
env = Environment()
value_return_canary = 0x4158675309
value_return_canary_size = 5
@@ -472,8 +480,10 @@ def test_address_collision(
contract_address: Account(
storage={
slot_create_address: salt_zero_address,
- slot_create_address_2: TXCREATE_FAILURE, # had an in-transaction collision
- slot_create_address_3: TXCREATE_FAILURE, # had a pre-existing collision
+ # had an in-transaction collision
+ slot_create_address_2: TXCREATE_FAILURE,
+ # had a pre-existing collision
+ slot_create_address_3: TXCREATE_FAILURE,
slot_code_worked: value_code_worked,
}
)
@@ -494,7 +504,10 @@ def test_txcreate_revert_eof_returndata(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies the return data is not being deployed, even if happens to be valid EOF."""
+ """
+ Verifies the return data is not being deployed, even if happens to be valid
+ EOF.
+ """
env = Environment()
code_reverts_with_calldata = Container(
name="Initcode Subcontainer reverting with its calldata",
@@ -602,7 +615,8 @@ def test_txcreate_context(
elif expected_result == "selfbalance":
expected_bytes = txcreate_value
elif expected_result == "factorybalance":
- # Factory receives value from sender and passes on eofcreate_value as endowment.
+ # Factory receives value from sender and passes on eofcreate_value as
+ # endowment.
expected_bytes = value - txcreate_value
else:
raise TypeError("Unexpected expected_result", expected_result)
@@ -634,7 +648,10 @@ def test_txcreate_memory_context(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies an TXCREATE frame enjoys a separate EVM memory from its caller frame."""
+ """
+ Verifies an TXCREATE frame enjoys a separate EVM memory from its caller
+ frame.
+ """
env = Environment()
destination_storage = Storage()
contract_storage = Storage()
@@ -680,7 +697,10 @@ def test_short_data_subcontainer(
state_test: StateTestFiller,
pre: Alloc,
):
- """Deploy a subcontainer where the data is "short" and filled by deployment code."""
+ """
+ Deploy a subcontainer where the data is "short" and filled by deployment
+ code.
+ """
env = Environment()
sender = pre.fund_eoa()
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py
index 035861ae40..2fd8170545 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py
@@ -14,10 +14,10 @@
Transaction,
compute_eofcreate_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from .. import EOF_FORK_NAME
from ..eip7069_extcall.spec import EXTCALL_FAILURE, EXTCALL_REVERT, LEGACY_CALL_FAILURE
@@ -177,8 +177,8 @@ def test_initcode_aborts(
"""
-Size of the initcode portion of test_txcreate_deploy_sizes, but as the runtime code is dynamic, we
-have to use a pre-calculated size
+Size of the initcode portion of test_txcreate_deploy_sizes, but as the runtime
+code is dynamic, we have to use a pre-calculated size
"""
initcode_size = 32
@@ -199,7 +199,11 @@ def test_txcreate_deploy_sizes(
pre: Alloc,
target_deploy_size: int,
):
- """Verifies a mix of runtime contract sizes mixing success and multiple size failure modes."""
+ """
+ Verify a mix of runtime contract sizes.
+
+ This mixes success and multiple size failure modes.
+ """
env = Environment()
runtime_container = Container(
@@ -237,9 +241,9 @@ def test_txcreate_deploy_sizes(
+ Op.SSTORE(slot_code_worked, value_code_worked)
+ Op.STOP
)
- # Storage in 0 should have the address,
- # Storage 1 is a canary of 1 to make sure it tried to execute, which also covers cases of
- # data+code being greater than initcode_size_max, which is allowed.
+ # Storage in 0 should have the address, Storage 1 is a canary of 1 to make
+ # sure it tried to execute, which also covers cases of data+code being
+ # greater than initcode_size_max, which is allowed.
success = target_deploy_size <= MAX_BYTECODE_SIZE
post = {
contract_address: Account(
@@ -277,7 +281,9 @@ def test_txcreate_deploy_sizes(
],
)
def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_size: int):
- """Exercises a number of auxdata size violations, and one maxcode success."""
+ """
+ Exercises a number of auxdata size violations, and one maxcode success.
+ """
env = Environment()
auxdata_bytes = b"a" * auxdata_size
@@ -305,7 +311,9 @@ def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_
deployed_container_size = len(smallest_runtime_subcontainer) + auxdata_size
- # Storage in 0 will have address in first test, 0 in all other cases indicating failure
+ # Storage in 0 will have address in first test, 0 in all other cases
+ # indicating failure
+ #
# Storage 1 in 1 is a canary to see if TXCREATE opcode halted
success = deployed_container_size <= MAX_BYTECODE_SIZE
post = {
@@ -347,8 +355,8 @@ def test_txcreate_insufficient_stipend(
value: int,
):
"""
- Exercises an TXCREATE that fails because the calling account does not have enough ether to
- pay the stipend.
+ Exercises an TXCREATE that fails because the calling account does not have
+ enough ether to pay the stipend.
"""
env = Environment()
sender = pre.fund_eoa(10**11)
@@ -362,7 +370,9 @@ def test_txcreate_insufficient_stipend(
+ Op.STOP,
balance=value - 1,
)
- # create will fail but not trigger a halt, so canary at storage 1 should be set
+ # create will fail but not trigger a halt, so canary at storage 1
+ # should be set
+ #
# also validate target created contract fails
post = {
contract_address: Account(
@@ -384,7 +394,9 @@ def test_txcreate_insufficient_stipend(
@pytest.mark.with_all_evm_code_types
def test_insufficient_initcode_gas(state_test: StateTestFiller, pre: Alloc, fork: Fork):
- """Exercises an TXCREATE when there is not enough gas for the constant charge."""
+ """
+ Exercises an TXCREATE when there is not enough gas for the constant charge.
+ """
env = Environment()
initcode_container = Container(
@@ -440,7 +452,10 @@ def test_insufficient_gas_memory_expansion(
pre: Alloc,
fork: Fork,
):
- """Exercises TXCREATE when the memory for auxdata has not been expanded but is requested."""
+ """
+ Exercises TXCREATE when the memory for auxdata has not been expanded but is
+ requested.
+ """
env = Environment()
auxdata_size = 0x5000
@@ -493,7 +508,10 @@ def test_insufficient_returncode_auxdata_gas(
pre: Alloc,
fork: Fork,
):
- """Exercises a RETURNCODE when there is not enough gas for the initcode charge."""
+ """
+ Exercises a RETURNCODE when there is not enough gas for the initcode
+ charge.
+ """
env = Environment()
auxdata_size = 0x5000
@@ -517,8 +535,8 @@ def test_insufficient_returncode_auxdata_gas(
slot_code_worked: value_canary_to_be_overwritten,
},
)
- # 63/64ths is not enough to cover RETURNCODE memory expansion. Unfortunately the 1/64th left
- # won't realistically accommodate a SSTORE
+ # 63/64ths is not enough to cover RETURNCODE memory expansion.
+ # Unfortunately the 1/64th left won't realistically accommodate a SSTORE
auxdata_size_words = (auxdata_size + 31) // 32
gas_limit = (
32_000
@@ -555,7 +573,8 @@ def test_insufficient_returncode_auxdata_gas(
Op.EXTSTATICCALL,
],
)
-@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag check comes first
+@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag
+# check comes first
@pytest.mark.parametrize(
"initcode",
[smallest_initcode_subcontainer, aborting_container],
@@ -582,7 +601,8 @@ def test_static_flag_txcreate(
)
calling_address = pre.deploy_contract(
calling_code,
- # Need to override the global value from the `with_all_evm_code_types` marker.
+ # Need to override the global value from the `with_all_evm_code_types`
+ # marker.
evm_code_type=EVMCodeType.EOF_V1 if opcode == Op.EXTSTATICCALL else EVMCodeType.LEGACY,
)
@@ -626,14 +646,17 @@ def test_eof_txcreate_msg_depth(
):
"""
Test TXCREATE handles msg depth limit correctly (1024).
- NOTE: due to block gas limit and the 63/64th rule this limit is unlikely to be hit
- on mainnet.
- NOTE: See `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py::test_eof_calls_msg_depth`
- for more explanations and comments. Most notable deviation from that test is that here
- calls and `TXCREATE`s alternate in order to reach the max depth. `who_fails` decides
- whether the failing depth 1024 will be on a call or on an `TXCREATE` to happen.
- """ # noqa: E501
- # Not a precise gas_limit formula, but enough to exclude risk of gas causing the failure.
+ NOTE: due to block gas limit and the 63/64th rule this limit is
+ unlikely to be hit on mainnet.
+ NOTE: See
+ `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py::
+ test_eof_calls_msg_depth` for more explanations and comments.
+ Most notable deviation from that test is that here calls and `TXCREATE`s
+ alternate in order to reach the max depth. `who_fails` decides whether
+ the failing depth 1024 will be on a call or on an `TXCREATE` to happen.
+ """
+ # Not a precise gas_limit formula, but enough to exclude risk of gas
+ # causing the failure.
gas_limit = int(20000000 * (64 / 63) ** 1024)
env = Environment(gas_limit=gas_limit)
@@ -694,8 +717,9 @@ def test_eof_txcreate_msg_depth(
)
)
- # Only bumps the msg call depth "register" and forwards to the `calling_contract_address`.
- # If it is used it makes the "failing" depth of 1024 to happen on TXCREATE, instead of CALL.
+ # Only bumps the msg call depth "register" and forwards to the
+ # `calling_contract_address`. If it is used it makes the "failing" depth of
+ # 1024 to happen on TXCREATE, instead of CALL.
passthrough_address = pre.deploy_contract(
Container.Code(
Op.MSTORE(0, 1) + Op.EXTCALL(address=calling_contract_address, args_size=32) + Op.STOP
@@ -734,12 +758,15 @@ def test_reentrant_txcreate(
state_test: StateTestFiller,
pre: Alloc,
):
- """Verifies a reentrant TXCREATE case, where EIP-161 prevents conflict via nonce bump."""
+ """
+ Verifies a reentrant TXCREATE case, where EIP-161 prevents conflict via
+ nonce bump.
+ """
env = Environment()
# Calls into the factory contract with 1 as input.
reenter_code = Op.MSTORE(0, 1) + Op.EXTCALL(address=Op.CALLDATALOAD(32), args_size=32)
- # Initcode: if given 0 as 1st word of input will call into the factory again.
- # 2nd word of input is the address of the factory.
+ # Initcode: if given 0 as 1st word of input will call into the factory
+ # again. 2nd word of input is the address of the factory.
initcontainer = Container(
sections=[
Section.Code(
@@ -753,12 +780,15 @@ def test_reentrant_txcreate(
]
)
initcode_hash = initcontainer.hash
- # Factory: Passes on its input into the initcode. It's 0 first time, 1 the second time.
- # Saves the result of deployment in slot 0 first time, 1 the second time.
+ # Factory:
+ # Passes on its input into the initcode.
+ # It's 0 first time, 1 the second time.
+ # Saves the result of deployment in slot 0 first time, 1 the second time.
contract_address = pre.deploy_contract(
code=Op.CALLDATACOPY(0, 0, 32)
+ Op.MSTORE(32, Op.ADDRESS)
- # 1st word - copied from input (reenter flag), 2nd word - `this.address`.
+ # 1st word - copied from input (reenter flag)
+ # 2nd word - `this.address`
+ Op.SSTORE(
Op.CALLDATALOAD(0),
Op.TXCREATE(tx_initcode_hash=initcode_hash, input_size=64),
@@ -766,13 +796,15 @@ def test_reentrant_txcreate(
+ Op.STOP,
storage={0: 0xB17D, 1: 0xB17D}, # a canary to be overwritten
)
- # Flow is: reenter flag 0 -> factory -> reenter flag 0 -> initcode -> reenter ->
- # reenter flag 1 -> factory -> reenter flag 1 -> (!) initcode -> stop,
- # if the EIP-161 nonce bump is not implemented. If it is, it fails before second
- # inicode marked (!).
+ # Flow is: reenter flag 0 -> factory -> reenter flag 0 -> initcode
+ # -> reenter -> reenter flag 1 -> factory -> reenter flag 1
+ # -> (!) initcode -> stop,
+ # if the EIP-161 nonce bump is not implemented. If it is, it fails before
+ # second initcode marked (!).
# Storage in 0 should have the address from the outer TXCREATE.
# Storage in 1 should have 0 from the inner TXCREATE.
- # For the created contract storage in `slot_counter` should be 1 as initcode executes only once
+ # For the created contract storage in `slot_counter` should be 1 as
+ # initcode executes only once
post = {
contract_address: Account(
storage={
@@ -814,7 +846,10 @@ def test_invalid_container_deployment(
pre: Alloc,
reason: str,
):
- """Verify contract is not deployed when an invalid container deployment is attempted."""
+ """
+ Verify contract is not deployed when an invalid container deployment is
+ attempted.
+ """
env = Environment()
sender = pre.fund_eoa()
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py
index dfa07b48d4..1fca0845e6 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py
@@ -17,9 +17,9 @@
Transaction,
compute_eofcreate_address,
)
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
-from ethereum_test_vm.bytecode import Bytecode
+from ethereum_test_vm import Bytecode
+from ethereum_test_vm import Opcodes as Op
from ....prague.eip7702_set_code_tx.spec import Spec
from .. import EOF_FORK_NAME
@@ -88,8 +88,10 @@ def __str__(self) -> str:
class Factory(Enum):
"""
- Kinds of systems leading up to a call to TXCREATE. DIRECT just puts the TXCREATE in the
- code it generates, while *CALL ones call into another account which does the TXCREATE.
+ Kinds of systems leading up to a call to TXCREATE.
+
+ DIRECT just puts the TXCREATE in the code it generates, while *CALL ones
+ call into another account which does the TXCREATE.
"""
DIRECT = auto()
@@ -107,9 +109,10 @@ def creation_snippet(
input_size: int,
) -> Tuple[Bytecode, Address | None]:
"""
- Return snippet to cause TXCREATE to be called along with an address which
- will end up in the `compute_eofcreate_address`, or None if that would be the snippet
- itself.
+ Return snippet to cause TXCREATE to be called along with an address.
+
+ This will end up in the `compute_eofcreate_address` or None if that
+ would be the snippet itself.
"""
if evm_code_type not in [EVMCodeType.LEGACY, EVMCodeType.EOF_V1]:
raise Exception(f"Test needs to be updated for {evm_code_type}")
@@ -119,7 +122,8 @@ def creation_snippet(
)
# Snippet which returns the TXCREATE result to caller
callee_txcreate_code = Op.MSTORE(0, txcreate_code) + Op.RETURN(0, 32)
- # Snippet which recovers the TXCREATE result from returndata (wipes memory afterwards)
+ # Snippet which recovers the TXCREATE result from returndata (wipes
+ # memory afterwards)
returndataload_code = (
Op.RETURNDATALOAD
if evm_code_type == EVMCodeType.EOF_V1
@@ -175,8 +179,7 @@ def test_txcreate_validates(
access_list_a: bool,
):
"""
- Verifies proper validation of initcode on TXCREATE in various circumstances of the
- opcode.
+ Verifies proper validation of initcode on TXCREATE in various scenarios.
"""
env = Environment()
snippet_a, factory_address_a = factory_a.creation_snippet(
diff --git a/tests/eest/unscheduled/eip7692_eof_v1/gas_test.py b/tests/eest/unscheduled/eip7692_eof_v1/gas_test.py
index d0425caf79..eaeeb1fd83 100644
--- a/tests/eest/unscheduled/eip7692_eof_v1/gas_test.py
+++ b/tests/eest/unscheduled/eip7692_eof_v1/gas_test.py
@@ -4,9 +4,9 @@
from ethereum_test_base_types.base_types import Address
from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Container, Section
from ethereum_test_vm import Bytecode, EVMCodeType
+from ethereum_test_vm import Opcodes as Op
from .eip7069_extcall.spec import (
LEGACY_CALL_FAILURE,
@@ -43,9 +43,9 @@ def gas_test(
"""
Create State Test to check the gas cost of a sequence of EOF code.
- `setup_code` and `tear_down_code` are called multiple times during the test, and MUST NOT have
- any side-effects which persist across message calls, and in particular, any effects on the gas
- usage of `subject_code`.
+ `setup_code` and `tear_down_code` are called multiple times during the
+ test, and MUST NOT have any side-effects which persist across message
+ calls, and in particular, any effects on the gas usage of `subject_code`.
"""
if cold_gas <= 0:
raise ValueError(f"Target gas allocations (cold_gas) must be > 0, got {cold_gas}")
@@ -68,7 +68,8 @@ def gas_test(
balance=subject_balance,
address=subject_address,
)
- # 2 times GAS, POP, CALL, 6 times PUSH1 - instructions charged for at every gas run
+ # 2 times GAS, POP, CALL, 6 times PUSH1 - instructions charged for at every
+ # gas run
gas_single_gas_run = 2 * 2 + 2 + WARM_ACCOUNT_ACCESS_GAS + 6 * 3
address_legacy_harness = pre.deploy_contract(
code=(
@@ -109,11 +110,15 @@ def gas_test(
+ (Op.DUP2 + Op.SWAP1 + Op.SUB + Op.PUSH2(slot_cold_gas) + Op.SSTORE)
+ (
(
- # do an oog gas run, unless skipped with `out_of_gas_testing=False`:
- # - DUP7 is the gas of the baseline gas run, after other CALL args were pushed
+ # do an oog gas run, unless skipped with
+ # `out_of_gas_testing=False`:
+ #
+ # - DUP7 is the gas of the baseline gas run, after other
+ # CALL args were pushed
# - subtract the gas charged by the harness
# - add warm gas charged by the subject
- # - subtract `oog_difference` to cause OOG exception (1 by default)
+ # - subtract `oog_difference` to cause OOG exception
+ # (1 by default)
Op.SSTORE(
slot_oog_call_result,
Op.CALL(
@@ -121,7 +126,8 @@ def gas_test(
address=address_subject,
),
)
- # sanity gas run: not subtracting 1 to see if enough gas makes the call succeed
+ # sanity gas run: not subtracting 1 to see if enough gas
+ # makes the call succeed
+ Op.SSTORE(
slot_sanity_call_result,
Op.CALL(
@@ -135,7 +141,8 @@ def gas_test(
else Op.STOP
)
),
- evm_code_type=EVMCodeType.LEGACY, # Needs to be legacy to use GAS opcode
+ evm_code_type=EVMCodeType.LEGACY, # Needs to be legacy to use GAS
+ # opcode
)
post = {
diff --git a/tox.ini b/tox.ini
index de618d1c50..977d8ff681 100644
--- a/tox.ini
+++ b/tox.ini
@@ -15,10 +15,10 @@ extras =
test
doc
commands =
- codespell -I whitelist.txt src tests --skip 'src/ethereum_spec_tests,tests/eest'
- ruff check src tests --exclude src/ethereum_spec_tests,tests/eest
- ruff format src tests --check --exclude src/ethereum_spec_tests,tests/eest
- mypy src tests --exclude "src/ethereum_spec_tests/*|tests/json_infra/fixtures/*|tests/eest/*" --namespace-packages
+ codespell -I whitelist.txt src tests packages --skip 'tests/eest'
+ ruff check src tests packages --exclude tests/eest
+ ruff format src tests packages --check --exclude tests/eest
+ mypy src tests --exclude "tests/json_infra/fixtures/*|tests/eest/*" --namespace-packages # TODO: add packages directory
ethereum-spec-lint
uv lock --check
diff --git a/uv.lock b/uv.lock
index 6c0aad0575..675a155e20 100644
--- a/uv.lock
+++ b/uv.lock
@@ -6,6 +6,12 @@ resolution-markers = [
"python_full_version < '3.13'",
]
+[manifest]
+members = [
+ "ethereum-execution",
+ "ethereum-execution-tests",
+]
+
[[package]]
name = "annotated-types"
version = "0.7.0"
@@ -33,6 +39,79 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" },
]
+[[package]]
+name = "babel"
+version = "2.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" },
+]
+
+[[package]]
+name = "backrefs"
+version = "5.9"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/eb/a7/312f673df6a79003279e1f55619abbe7daebbb87c17c976ddc0345c04c7b/backrefs-5.9.tar.gz", hash = "sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59", size = 5765857, upload-time = "2025-06-22T19:34:13.97Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/19/4d/798dc1f30468134906575156c089c492cf79b5a5fd373f07fe26c4d046bf/backrefs-5.9-py310-none-any.whl", hash = "sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f", size = 380267, upload-time = "2025-06-22T19:34:05.252Z" },
+ { url = "https://files.pythonhosted.org/packages/55/07/f0b3375bf0d06014e9787797e6b7cc02b38ac9ff9726ccfe834d94e9991e/backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf", size = 392072, upload-time = "2025-06-22T19:34:06.743Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa", size = 397947, upload-time = "2025-06-22T19:34:08.172Z" },
+ { url = "https://files.pythonhosted.org/packages/10/bf/fa31834dc27a7f05e5290eae47c82690edc3a7b37d58f7fb35a1bdbf355b/backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b", size = 399843, upload-time = "2025-06-22T19:34:09.68Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/24/b29af34b2c9c41645a9f4ff117bae860291780d73880f449e0b5d948c070/backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9", size = 411762, upload-time = "2025-06-22T19:34:11.037Z" },
+ { url = "https://files.pythonhosted.org/packages/41/ff/392bff89415399a979be4a65357a41d92729ae8580a66073d8ec8d810f98/backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60", size = 380265, upload-time = "2025-06-22T19:34:12.405Z" },
+]
+
+[[package]]
+name = "beautifulsoup4"
+version = "4.14.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "soupsieve" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/77/e9/df2358efd7659577435e2177bfa69cba6c33216681af51a707193dec162a/beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e", size = 625822, upload-time = "2025-09-29T10:05:42.613Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/94/fe/3aed5d0be4d404d12d36ab97e2f1791424d9ca39c2f754a6285d59a3b01d/beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515", size = 106392, upload-time = "2025-09-29T10:05:43.771Z" },
+]
+
+[[package]]
+name = "bracex"
+version = "2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" },
+]
+
+[[package]]
+name = "cairocffi"
+version = "1.7.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cffi" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/70/c5/1a4dc131459e68a173cbdab5fad6b524f53f9c1ef7861b7698e998b837cc/cairocffi-1.7.1.tar.gz", hash = "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b", size = 88096, upload-time = "2024-06-18T10:56:06.741Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl", hash = "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f", size = 75611, upload-time = "2024-06-18T10:55:59.489Z" },
+]
+
+[[package]]
+name = "cairosvg"
+version = "2.8.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cairocffi" },
+ { name = "cssselect2" },
+ { name = "defusedxml" },
+ { name = "pillow" },
+ { name = "tinycss2" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ab/b9/5106168bd43d7cd8b7cc2a2ee465b385f14b63f4c092bb89eee2d48c8e67/cairosvg-2.8.2.tar.gz", hash = "sha256:07cbf4e86317b27a92318a4cac2a4bb37a5e9c1b8a27355d06874b22f85bef9f", size = 8398590, upload-time = "2025-05-15T06:56:32.653Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/67/48/816bd4aaae93dbf9e408c58598bc32f4a8c65f4b86ab560864cb3ee60adb/cairosvg-2.8.2-py3-none-any.whl", hash = "sha256:eab46dad4674f33267a671dce39b64be245911c901c70d65d2b7b0821e852bf5", size = 45773, upload-time = "2025-05-15T06:56:28.552Z" },
+]
+
[[package]]
name = "cattrs"
version = "25.1.1"
@@ -150,43 +229,43 @@ wheels = [
[[package]]
name = "ckzg"
-version = "2.1.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/55/df/f6db8e83bd4594c1ea685cd37fb81d5399e55765aae16d1a8a9502598f4e/ckzg-2.1.1.tar.gz", hash = "sha256:d6b306b7ec93a24e4346aa53d07f7f75053bc0afc7398e35fa649e5f9d48fcc4", size = 1120500, upload-time = "2025-03-31T21:24:12.324Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/95/2c/44120b2d9dcb0246d67a1f28b9eaa625c499014d4d42561467e28eedd285/ckzg-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:465e2b71cf9dc383f66f1979269420a0da9274a3a9e98b1a4455e84927dfe491", size = 116378, upload-time = "2025-03-31T21:22:36.96Z" },
- { url = "https://files.pythonhosted.org/packages/23/88/c5b89ba9a730fee5e089be9e0c7048fb6707c1a0e4b6c30fcf725c3eef44/ckzg-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ee2f26f17a64ad0aab833d637b276f28486b82a29e34f32cf54b237b8f8ab72d", size = 100202, upload-time = "2025-03-31T21:22:37.799Z" },
- { url = "https://files.pythonhosted.org/packages/ee/11/b0a473e80346db52ad9a629bc9fd8f773c718ed78932ea3a70392306ffc3/ckzg-2.1.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99cc2c4e9fb8c62e3e0862c7f4df9142f07ba640da17fded5f6e0fd09f75909f", size = 175595, upload-time = "2025-03-31T21:22:39.013Z" },
- { url = "https://files.pythonhosted.org/packages/52/fa/17a7e125d07a96dd6dce4db7262231f7583856b2be5d5b7df59e04bfa188/ckzg-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773dd016693d74aca1f5d7982db2bad7dde2e147563aeb16a783f7e5f69c01fe", size = 161681, upload-time = "2025-03-31T21:22:40.257Z" },
- { url = "https://files.pythonhosted.org/packages/57/bd/46d6b90bf53da732f9adab7593d132a0834ed4f2f7659b4c7414d8f78d39/ckzg-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af2b2144f87ba218d8db01382a961b3ecbdde5ede4fa0d9428d35f8c8a595ba", size = 170471, upload-time = "2025-03-31T21:22:41.513Z" },
- { url = "https://files.pythonhosted.org/packages/9d/98/113c7704749d037d75f23240ffc5c46dfe8416de574b946438587835715f/ckzg-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8f55e63d3f7c934a2cb53728ed1d815479e177aca8c84efe991c2920977cff6", size = 173595, upload-time = "2025-03-31T21:22:42.534Z" },
- { url = "https://files.pythonhosted.org/packages/2f/d5/05fca6dcb5a19327be491157794eafc3d7498daf615c2ff5a5b745852945/ckzg-2.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ecb42aaa0ffa427ff14a9dde9356ba69e5ae6014650b397af55b31bdae7a9b6e", size = 188417, upload-time = "2025-03-31T21:22:43.466Z" },
- { url = "https://files.pythonhosted.org/packages/72/36/131ae2dfc82d0fdc98fae8e3bbfe71ff14265bb434b23bd07b585afc6d61/ckzg-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5a01514239f12fb1a7ad9009c20062a4496e13b09541c1a65f97e295da648c70", size = 183286, upload-time = "2025-03-31T21:22:44.732Z" },
- { url = "https://files.pythonhosted.org/packages/c5/6a/d371b27024422b25228fc11fa57b1ba7756a94cc9fb0c75da292c235fdaa/ckzg-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:6516b9684aae262c85cf7fddd8b585b8139ad20e08ec03994e219663abbb0916", size = 98819, upload-time = "2025-03-31T21:22:45.57Z" },
- { url = "https://files.pythonhosted.org/packages/93/a1/9c07513dd0ea01e5db727e67bd2660f3b300a4511281cdb8d5e04afa1cfd/ckzg-2.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c60e8903344ce98ce036f0fabacce952abb714cad4607198b2f0961c28b8aa72", size = 116421, upload-time = "2025-03-31T21:22:46.434Z" },
- { url = "https://files.pythonhosted.org/packages/27/04/b69a0dfbb2722a14c98a52973f276679151ec56a14178cb48e6f2e1697bc/ckzg-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4299149dd72448e5a8d2d1cc6cc7472c92fc9d9f00b1377f5b017c089d9cd92", size = 100216, upload-time = "2025-03-31T21:22:47.633Z" },
- { url = "https://files.pythonhosted.org/packages/2e/24/9cc850d0b8ead395ad5064de67c7c91adacaf31b6b35292ab53fbd93270b/ckzg-2.1.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:025dd31ffdcc799f3ff842570a2a6683b6c5b01567da0109c0c05d11768729c4", size = 175764, upload-time = "2025-03-31T21:22:48.768Z" },
- { url = "https://files.pythonhosted.org/packages/c0/c1/eb13ba399082a98b932f10b230ec08e6456051c0ce3886b3f6d8548d11ab/ckzg-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b42ab8385c273f40a693657c09d2bba40cb4f4666141e263906ba2e519e80bd", size = 161885, upload-time = "2025-03-31T21:22:50.05Z" },
- { url = "https://files.pythonhosted.org/packages/57/c7/58baa64199781950c5a8c6139a46e1acff0f057a36e56769817400eb87fb/ckzg-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1be3890fc1543f4fcfc0063e4baf5c036eb14bcf736dabdc6171ab017e0f1671", size = 170757, upload-time = "2025-03-31T21:22:51.282Z" },
- { url = "https://files.pythonhosted.org/packages/65/bd/4b8e1c70972c98829371b7004dc750a45268c5d3442d602e1b62f13ca867/ckzg-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b754210ded172968b201e2d7252573af6bf52d6ad127ddd13d0b9a45a51dae7b", size = 173761, upload-time = "2025-03-31T21:22:52.6Z" },
- { url = "https://files.pythonhosted.org/packages/1f/32/c3fd1002f97ba3e0c5b1d9ab2c8fb7a6f475fa9b80ed9c4fa55975501a54/ckzg-2.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2f8fda87865897a269c4e951e3826c2e814427a6cdfed6731cccfe548f12b36", size = 188666, upload-time = "2025-03-31T21:22:53.47Z" },
- { url = "https://files.pythonhosted.org/packages/e2/d9/91cf5a8169ee60c9397c975163cbca34432571f94facec5f8c0086bb47d8/ckzg-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:98e70b5923d77c7359432490145e9d1ab0bf873eb5de56ec53f4a551d7eaec79", size = 183652, upload-time = "2025-03-31T21:22:54.351Z" },
- { url = "https://files.pythonhosted.org/packages/25/d4/8c9f6b852f99926862344b29f0c59681916ccfec2ac60a85952a369e0bca/ckzg-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:42af7bde4ca45469cd93a96c3d15d69d51d40e7f0d30e3a20711ebd639465fcb", size = 98816, upload-time = "2025-03-31T21:22:55.23Z" },
- { url = "https://files.pythonhosted.org/packages/b7/9a/fa698b12e97452d11dd314e0335aae759725284ef6e1c1665aed56b1cd3e/ckzg-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e4edfdaf87825ff43b9885fabfdea408737a714f4ce5467100d9d1d0a03b673", size = 116426, upload-time = "2025-03-31T21:22:56.108Z" },
- { url = "https://files.pythonhosted.org/packages/a1/a6/8cccd308bd11b49b40eecad6900b5769da117951cac33e880dd25e851ef7/ckzg-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:815fd2a87d6d6c57d669fda30c150bc9bf387d47e67d84535aa42b909fdc28ea", size = 100219, upload-time = "2025-03-31T21:22:56.982Z" },
- { url = "https://files.pythonhosted.org/packages/30/0e/63573d816c1292b9a4d70eb6a7366b3593d29a977794039e926805a76ca0/ckzg-2.1.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32466e809b1ab3ff01d3b0bb0b9912f61dcf72957885615595f75e3f7cc10e5", size = 175725, upload-time = "2025-03-31T21:22:58.213Z" },
- { url = "https://files.pythonhosted.org/packages/86/f6/a279609516695ad3fb8b201098c669ba3b2844cbf4fa0d83a0f02b9bb29b/ckzg-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f11b73ccf37b12993f39a7dbace159c6d580aacacde6ee17282848476550ddbc", size = 161835, upload-time = "2025-03-31T21:22:59.448Z" },
- { url = "https://files.pythonhosted.org/packages/39/e4/8cf7aef7dc05a777cb221e94046f947c6fe5317159a8dae2cd7090d52ef2/ckzg-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3b9433a1f2604bd9ac1646d3c83ad84a850d454d3ac589fe8e70c94b38a6b0", size = 170759, upload-time = "2025-03-31T21:23:01.022Z" },
- { url = "https://files.pythonhosted.org/packages/0b/17/b34e3c08eb36bc67e338b114f289b2595e581b8bdc09a8f12299a1db5d2f/ckzg-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b7d7e1b5ea06234558cd95c483666fd785a629b720a7f1622b3cbffebdc62033", size = 173787, upload-time = "2025-03-31T21:23:01.974Z" },
- { url = "https://files.pythonhosted.org/packages/2e/f0/aff87c3ed80713453cb6c84fe6fbb7582d86a7a5e4460fda2a497d47f489/ckzg-2.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9f5556e6675866040cc4335907be6c537051e7f668da289fa660fdd8a30c9ddb", size = 188722, upload-time = "2025-03-31T21:23:02.966Z" },
- { url = "https://files.pythonhosted.org/packages/44/d9/1f08bfb8fd1cbb8c7513e7ad3fb76bbb5c3fb446238c1eba582276e4d905/ckzg-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55b2ba30c5c9daac0c55f1aac851f1b7bf1f7aa0028c2db4440e963dd5b866d6", size = 183686, upload-time = "2025-03-31T21:23:03.905Z" },
- { url = "https://files.pythonhosted.org/packages/a3/ff/434f6d2893cbdfad00c20d17e9a52d426ca042f5e980d5c3db96bc6b6e15/ckzg-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:10d201601fc8f28c0e8cec3406676797024dd374c367bbeec5a7a9eac9147237", size = 98817, upload-time = "2025-03-31T21:23:05.2Z" },
- { url = "https://files.pythonhosted.org/packages/7f/ba/7d9c1f9cec7e0e382653c72165896194a05743e589b1dae2aa80236aa87f/ckzg-2.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4b0c850bd6cad22ac79b2a2ab884e0e7cd2b54a67d643cd616c145ebdb535a11", size = 113188, upload-time = "2025-03-31T21:23:46.337Z" },
- { url = "https://files.pythonhosted.org/packages/2f/92/9728f5ccc1c5e87c6c5ae7941250a447b61fd5a63aadbc15249e29c21bcf/ckzg-2.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:26951f36bb60c9150bbd38110f5e1625596f9779dad54d1d492d8ec38bc84e3a", size = 96208, upload-time = "2025-03-31T21:23:47.255Z" },
- { url = "https://files.pythonhosted.org/packages/39/63/5e27d587bd224fee70cb66b022e7c4ef95d0e091e08ee76c25ec12094b0d/ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe12445e49c4bee67746b7b958e90a973b0de116d0390749b0df351d94e9a8c", size = 126158, upload-time = "2025-03-31T21:23:48.195Z" },
- { url = "https://files.pythonhosted.org/packages/43/98/e0a45946575a7b823d8ee0b47afb104b6017e54e1208f07da2529bc01900/ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71c5d4f66f09de4a99271acac74d2acb3559a77de77a366b34a91e99e8822667", size = 102812, upload-time = "2025-03-31T21:23:49.16Z" },
- { url = "https://files.pythonhosted.org/packages/cb/50/718ca7b03e4b89b18cdf99cc3038050105b0acbf9b612c23cd513093c6de/ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42673c1d007372a4e8b48f6ef8f0ce31a9688a463317a98539757d1e2fb1ecc7", size = 111327, upload-time = "2025-03-31T21:23:50.126Z" },
- { url = "https://files.pythonhosted.org/packages/29/c5/80e5a0c6967d02d801150104320484a258e5a49bd191e198643e74039320/ckzg-2.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:57a7dc41ec6b69c1d9117eb61cf001295e6b4f67a736020442e71fb4367fb1a5", size = 98847, upload-time = "2025-03-31T21:23:51.084Z" },
+version = "2.1.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b1/e8/b262fff67d6bcaecd19c71d19ebea9184a1204e00368664e1544a2511bd8/ckzg-2.1.5.tar.gz", hash = "sha256:e48e092f9b89ebb6aaa195de2e2bb72ad2d4b35c87d3a15e4545f13c51fbbe30", size = 1123745, upload-time = "2025-09-30T19:09:13.391Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/32/d82185ecd05a91d1a35229c587eac9c518b30693c4c983ffde37e1f5a1a2/ckzg-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cead4ba760a49eaa4d7a50a0483aad9727d6103fc00c408aef15f2cd8f8dec7b", size = 116304, upload-time = "2025-09-30T19:07:44.531Z" },
+ { url = "https://files.pythonhosted.org/packages/94/a7/d22f813e032a7380f758d437348d791e8609a5c8ef2bd3654201f85a0047/ckzg-2.1.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3156983ba598fa05f0136325125e75197e4cf24ded255aaa6ace068cede92932", size = 99811, upload-time = "2025-09-30T19:07:45.311Z" },
+ { url = "https://files.pythonhosted.org/packages/41/62/82ee6852a629bd9a783fb7787bcc2ee6e8c00c26b4ceb821a17484081760/ckzg-2.1.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d05e2c9466b2a4214dc19da35ea4cae636e033f3434768b982d37317a0f9c520", size = 176458, upload-time = "2025-09-30T19:07:46.433Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/00/5c68bb77f12eab6ba464f3955263e515ae988ddfc4bc57023b54b60feda0/ckzg-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c754bbc253cfce8814d633f135be4891e6f83a50125f418fee01323ba306f59a", size = 161841, upload-time = "2025-09-30T19:07:47.261Z" },
+ { url = "https://files.pythonhosted.org/packages/42/b3/c75079d270a7895ba6b5a95f86674d5c95f2f7e0db03328f1b21dc9a90eb/ckzg-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2b766d4aed52c8c717322f2af935da0b916bf59fbba771adb822499b45e491", size = 171101, upload-time = "2025-09-30T19:07:48.471Z" },
+ { url = "https://files.pythonhosted.org/packages/63/bf/81c533231f3bdc0029a0ec8abef9c24b2eaf929a044a77c15b6da54b91dc/ckzg-2.1.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dd7a296475baa5f20b5e7972448d4cb2f44d00b920d680de756c90c512af1c3b", size = 173403, upload-time = "2025-09-30T19:07:49.288Z" },
+ { url = "https://files.pythonhosted.org/packages/58/6e/bbfd04b25185c6371020dd1f1c3eb0557e36878ad6cdd78a1ea2bb47d8df/ckzg-2.1.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:97d3e93b3d94031fbd376005d86bf9b2c230ecfb4a4f4ced3b06b4aeefae6c9f", size = 188738, upload-time = "2025-09-30T19:07:50.64Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/83/ab3cd495a2b37b72b4d886276b3669f101c4927b1d54b7e528aa537362ab/ckzg-2.1.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3d2d35ba937f002b72a9a168696d0073a8e5912fa7058e77a06c370b86586401", size = 183202, upload-time = "2025-09-30T19:07:51.544Z" },
+ { url = "https://files.pythonhosted.org/packages/19/37/4ad60c2879b5e6988337b776f580b7aacb40ae6c05ef264e9835bed35e80/ckzg-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:ce2047071353ee099d44aa6575974648663204eb9b42354bfa5ac6f9b8fb63e9", size = 100965, upload-time = "2025-09-30T19:07:52.437Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/9f/3ef8acd201e4d098af6bc368991ac1469a5390399abd1e78307fffb65218/ckzg-2.1.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:edead535bd9afef27b8650bba09659debd4f52638aee5ec1ab7d2c9d7e86953c", size = 116333, upload-time = "2025-09-30T19:07:53.223Z" },
+ { url = "https://files.pythonhosted.org/packages/25/c2/202947c143336185180216a4939296d824cbffca4e1438d0fe696daf1904/ckzg-2.1.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc78622855de3d47767cdeecfdf58fd58911f43a0fa783524e414b7e75149020", size = 99822, upload-time = "2025-09-30T19:07:54.06Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/20/ace67811fbabcfece937f8286cdd96f5668757b8944a74630b6454131545/ckzg-2.1.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:094add5f197a3d278924ec1480d258f3b8b0e9f8851ae409eec83a21a738bffe", size = 176595, upload-time = "2025-09-30T19:07:54.792Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/65/127fa59aae21688887249ec1caa92dabaced331de5cb4e0224216270c3d0/ckzg-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b4b05f798784400e8c4dedaf1a1d57bbbc54de790855855add876fff3c9f629", size = 162014, upload-time = "2025-09-30T19:07:55.776Z" },
+ { url = "https://files.pythonhosted.org/packages/35/de/dcaa260f6f5aca83eb9017ea0c691d3d37458e08e24dcad5efcd348d807e/ckzg-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64aef50a1cf599041b9af018bc885a3fad6a20bbaf443fc45f0457cb47914610", size = 171396, upload-time = "2025-09-30T19:07:56.583Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/72/f87db164d687759ae0666a2188c5f5d11a62cac9093464efbedc1f69f4e1/ckzg-2.1.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0171484eedc42b9417a79e33aff3f35d48915b01c54f42c829b891947ac06551", size = 173548, upload-time = "2025-09-30T19:07:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/03/ad/b5a88a445f27dbd39eece56edffbe986bf356003bded75f79ef59e2b37c9/ckzg-2.1.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2342b98acd7b6e6e33fbbc48ccec9093e1652461daf4353115adcd708498efcd", size = 188988, upload-time = "2025-09-30T19:07:59.496Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/57/42fbf29d39bd3f11a673a4e61af41b5485aa0ecf99473a0d4afc2528d24b/ckzg-2.1.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cbce75c1e17fa60b5c33bae5069b8533cf5a4d028ef7d1f755b14a16f72307cf", size = 183513, upload-time = "2025-09-30T19:08:00.341Z" },
+ { url = "https://files.pythonhosted.org/packages/27/c0/ef4c9e9256088e5a425cedb80f26e2a0c853128571b027d8174caf97b2f6/ckzg-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:827be2aeffc8a10bfb39b8dad45def82164dfcde735818c4053f5064474ae1b4", size = 100992, upload-time = "2025-09-30T19:08:01.633Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/4b/089392b6f0015bb368b453f26330c643bf0087f77835df2328a1da2af401/ckzg-2.1.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d955f4e18bb9a9b3a6f55114052edd41650c29edd5f81e417c8f01abace8207", size = 116340, upload-time = "2025-09-30T19:08:02.478Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/45/4d8b70f69f0bc67e9262ec68200707d2d92a27e712cda2c163ebd4b4dcfa/ckzg-2.1.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0c0961a685761196264aa49b1cf06e8a2b2add4d57987853d7dd7a7240dc5de7", size = 99822, upload-time = "2025-09-30T19:08:03.65Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/95/4193e4af65dc4839fa9fe07efad689fe726303b3ba62ee2f46c403458bec/ckzg-2.1.5-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:badb1c7dc6b932bed2c3f7695e1ce3e4bcc9601706136957408ac2bde5dd0892", size = 176586, upload-time = "2025-09-30T19:08:04.818Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/9e/850f48cb41685f5016028dbde8f7846ce9c56bfdc2e9e0f3df1a975263fe/ckzg-2.1.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58d92816b9babaee87bd9f23be10c07d5d07c709be184aa7ea08ddb2bcf2541c", size = 161970, upload-time = "2025-09-30T19:08:05.734Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/df/a9993dc124e95eb30059c108efd83a1504709cf069d3bee0745d450262a0/ckzg-2.1.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cf39f9abe8b3f1a71188fb601a8589672ee40eb0671fc36d8cdf4e78f00f43f", size = 171364, upload-time = "2025-09-30T19:08:06.979Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/03/78e8a723c1b832766e5698f7b39cc8dc27da95b62bc5c738a59564cb5f2c/ckzg-2.1.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:999df675674d8d31528fd9b9afd548e86decc86447f5555b451237e7953fd63f", size = 173571, upload-time = "2025-09-30T19:08:08.173Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/64/27f96201c6d78fbdb9a0812cf45dded974c4d03d876dac11d9c764ef858f/ckzg-2.1.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c39a1c7b32ac345cc44046076fd069ad6b7e6f7bef230ef9be414c712c4453b8", size = 189014, upload-time = "2025-09-30T19:08:09.045Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/6e/82177c4530265694f7ec151821c79351a07706dda4d8b23e8b37d0c122f0/ckzg-2.1.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4564765b0cc65929eca057241b9c030afac1dbae015f129cb60ca6abd6ff620", size = 183530, upload-time = "2025-09-30T19:08:09.867Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/41/1edfbd007b0398321defeedf6ad2d9f86a73f6a99d5ca4b4944bf6f2d757/ckzg-2.1.5-cp313-cp313-win_amd64.whl", hash = "sha256:55013b36514b8176197655b929bc53f020aa51a144331720dead2efc3793ed85", size = 100992, upload-time = "2025-09-30T19:08:10.719Z" },
+ { url = "https://files.pythonhosted.org/packages/03/bd/4cc75266991d2420c3212614dc6e659490bcb8c1a03a638ff688cc775ff8/ckzg-2.1.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0ae260c705a82d9cf4b88eaa2e8f86263c23d99d4ec282f22838f27d24f9306c", size = 113098, upload-time = "2025-09-30T19:08:49.956Z" },
+ { url = "https://files.pythonhosted.org/packages/d6/4c/fc5e6a3463b8d8bb36d21230f41fee13d5ba3fe3f594f1c20bb9bab1fab3/ckzg-2.1.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:7c21b0a4ad05a9e32e715118695d7a0912b4ee73198d63cc98de4d585597627e", size = 95811, upload-time = "2025-09-30T19:08:50.883Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/2e/3be3977c57a51f516f2897d543ddca7901659ae1705b5dc3dbf54e0b66f2/ckzg-2.1.5-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0577aee9848d7a9cef750ff6f303f586caf33da986a762ca57ac0c57e59fb6d", size = 126633, upload-time = "2025-09-30T19:08:51.734Z" },
+ { url = "https://files.pythonhosted.org/packages/72/3b/8314ca493654bd035cc0a66308cec9a1089cf3bc33c2837e3e265345f3cc/ckzg-2.1.5-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e15faa1145b2408e17e3b2f0b159de325b0198615aa30268bb6cd8f4385ed745", size = 102844, upload-time = "2025-09-30T19:08:52.621Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/9b/1729ee420865a71e68f18880341b37ef980c2881674dc0b06460253ef25e/ckzg-2.1.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d009dba9838630183610008a81bd80aafb389d45d8293d7a2fff7a5ea82266", size = 111739, upload-time = "2025-09-30T19:08:53.54Z" },
+ { url = "https://files.pythonhosted.org/packages/40/40/f259e2bf986d39717427bc12baa8189cd43f9675e81cd3bcab639e593614/ckzg-2.1.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:df66d2be54d91f74aded4ceb71e7b1f789e2636a3015f438904a22ec9de750f1", size = 101018, upload-time = "2025-09-30T19:08:54.391Z" },
]
[[package]]
@@ -363,6 +442,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f6/34/31a1604c9a9ade0fdab61eb48570e09a796f4d9836121266447b0eaf7feb/cryptography-45.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f", size = 3331106, upload-time = "2025-07-02T13:06:18.058Z" },
]
+[[package]]
+name = "cssselect2"
+version = "0.8.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "tinycss2" },
+ { name = "webencodings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/9f/86/fd7f58fc498b3166f3a7e8e0cddb6e620fe1da35b02248b1bd59e95dbaaa/cssselect2-0.8.0.tar.gz", hash = "sha256:7674ffb954a3b46162392aee2a3a0aedb2e14ecf99fcc28644900f4e6e3e9d3a", size = 35716, upload-time = "2025-03-05T14:46:07.988Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0f/e7/aa315e6a749d9b96c2504a1ba0ba031ba2d0517e972ce22682e3fccecb09/cssselect2-0.8.0-py3-none-any.whl", hash = "sha256:46fc70ebc41ced7a32cd42d58b1884d72ade23d21e5a4eaaf022401c13f0e76e", size = 15454, upload-time = "2025-03-05T14:46:06.463Z" },
+]
+
[[package]]
name = "cytoolz"
version = "1.0.1"
@@ -416,6 +508,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/40/eb/dde173cf2357084ca9423950be1f2f11ab11d65d8bd30165bfb8fd4213e9/cytoolz-1.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:90e577e08d3a4308186d9e1ec06876d4756b1e8164b92971c69739ea17e15297", size = 362898, upload-time = "2024-12-13T05:46:12.771Z" },
]
+[[package]]
+name = "defusedxml"
+version = "0.7.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" },
+]
+
[[package]]
name = "docc"
version = "0.3.1"
@@ -525,34 +626,6 @@ doc = [
{ name = "docc" },
{ name = "fladrif" },
]
-fill = [
- { name = "ckzg" },
- { name = "click" },
- { name = "coincurve" },
- { name = "colorlog" },
- { name = "eth-abi" },
- { name = "ethereum-hive" },
- { name = "ethereum-rlp" },
- { name = "ethereum-types" },
- { name = "gitpython" },
- { name = "joblib" },
- { name = "pydantic" },
- { name = "pyjwt" },
- { name = "pytest-custom-report" },
- { name = "pytest-html" },
- { name = "pytest-json-report" },
- { name = "pytest-metadata" },
- { name = "pytest-regex" },
- { name = "pyyaml" },
- { name = "questionary" },
- { name = "requests-unixsocket2" },
- { name = "rich" },
- { name = "semver" },
- { name = "tenacity" },
- { name = "trie" },
- { name = "types-pyyaml" },
- { name = "typing-extensions" },
-]
lint = [
{ name = "codespell" },
{ name = "mypy" },
@@ -564,6 +637,7 @@ optimized = [
{ name = "rust-pyspec-glue" },
]
test = [
+ { name = "ethereum-execution-tests" },
{ name = "filelock" },
{ name = "gitpython" },
{ name = "libcst" },
@@ -580,59 +654,160 @@ tools = [
[package.metadata]
requires-dist = [
- { name = "ckzg", marker = "extra == 'fill'", specifier = ">=2.1.1" },
- { name = "click", marker = "extra == 'fill'", specifier = ">=8.1.0,<9" },
{ name = "codespell", marker = "extra == 'lint'", specifier = "==2.4.1" },
{ name = "coincurve", specifier = ">=20,<21" },
- { name = "coincurve", marker = "extra == 'fill'", specifier = ">=20.0.0,<21" },
- { name = "colorlog", marker = "extra == 'fill'", specifier = ">=6.7.0,<7" },
{ name = "cryptography", specifier = ">=45.0.1,<46" },
{ name = "docc", marker = "extra == 'doc'", specifier = ">=0.3.0,<0.4.0" },
- { name = "eth-abi", marker = "extra == 'fill'", specifier = ">=5.2.0" },
{ name = "ethash", marker = "extra == 'optimized'", specifier = ">=1.1.0,<2" },
- { name = "ethereum-hive", marker = "extra == 'fill'", specifier = ">=0.1.0a1,<1.0.0" },
+ { name = "ethereum-execution-tests", marker = "extra == 'test'", editable = "packages/tests" },
{ name = "ethereum-rlp", specifier = ">=0.1.4,<0.2" },
- { name = "ethereum-rlp", marker = "extra == 'fill'", specifier = ">=0.1.3,<0.2" },
{ name = "ethereum-types", specifier = ">=0.2.4,<0.3" },
- { name = "ethereum-types", marker = "extra == 'fill'", specifier = ">=0.2.1,<0.3" },
{ name = "filelock", marker = "extra == 'test'", specifier = ">=3.15.1,<4" },
{ name = "fladrif", marker = "extra == 'doc'", specifier = ">=0.2.0,<0.3.0" },
- { name = "gitpython", marker = "extra == 'fill'", specifier = ">=3.1.31,<4" },
{ name = "gitpython", marker = "extra == 'test'", specifier = ">=3.1.0,<3.2" },
- { name = "joblib", marker = "extra == 'fill'", specifier = ">=1.4.2" },
{ name = "libcst", marker = "extra == 'test'", specifier = ">=1.8,<2" },
{ name = "libcst", marker = "extra == 'tools'", specifier = ">=1.8,<2" },
{ name = "mypy", marker = "extra == 'lint'", specifier = "==1.17.0" },
{ name = "platformdirs", marker = "extra == 'tools'", specifier = ">=4.2,<5" },
{ name = "py-ecc", specifier = ">=8.0.0b2,<9" },
{ name = "pycryptodome", specifier = ">=3.22,<4" },
- { name = "pydantic", marker = "extra == 'fill'", specifier = ">=2.11.0,<3" },
- { name = "pyjwt", marker = "extra == 'fill'", specifier = ">=2.3.0,<3" },
{ name = "pytest", marker = "extra == 'test'", specifier = ">=8,<9" },
{ name = "pytest-cov", marker = "extra == 'test'", specifier = ">=4.1.0,<5" },
- { name = "pytest-custom-report", marker = "extra == 'fill'", specifier = ">=1.0.1,<2" },
- { name = "pytest-html", marker = "extra == 'fill'", specifier = ">=4.1.0,<5" },
- { name = "pytest-json-report", marker = "extra == 'fill'", specifier = ">=1.5.0,<2" },
- { name = "pytest-metadata", marker = "extra == 'fill'", specifier = ">=3,<4" },
- { name = "pytest-regex", marker = "extra == 'fill'", specifier = ">=0.2.0,<0.3" },
{ name = "pytest-xdist", marker = "extra == 'test'", specifier = ">=3.3.1,<4" },
- { name = "pyyaml", marker = "extra == 'fill'", specifier = ">=6.0.2,<7" },
- { name = "questionary", marker = "extra == 'fill'", specifier = ">=2.1.0,<3" },
{ name = "requests", marker = "extra == 'test'" },
{ name = "requests-cache", marker = "extra == 'test'", specifier = ">=1.2.1,<2" },
- { name = "requests-unixsocket2", marker = "extra == 'fill'", specifier = ">=0.4.0" },
- { name = "rich", marker = "extra == 'fill'", specifier = ">=13.7.0,<14" },
{ name = "ruff", marker = "extra == 'lint'", specifier = "==0.13.2" },
{ name = "rust-pyspec-glue", marker = "extra == 'optimized'", specifier = ">=0.0.9,<0.1.0" },
- { name = "semver", marker = "extra == 'fill'", specifier = ">=3.0.1,<4" },
- { name = "tenacity", marker = "extra == 'fill'", specifier = ">8.2.0,<9" },
- { name = "trie", marker = "extra == 'fill'", specifier = ">=3.1.0,<4" },
- { name = "types-pyyaml", marker = "extra == 'fill'", specifier = ">=6.0.12.20240917,<7" },
{ name = "typing-extensions", specifier = ">=4.4" },
- { name = "typing-extensions", marker = "extra == 'fill'", specifier = ">=4.12.2,<5" },
{ name = "vulture", marker = "extra == 'lint'", specifier = "==2.14.0" },
]
-provides-extras = ["test", "fill", "lint", "tools", "doc", "optimized"]
+provides-extras = ["test", "lint", "tools", "doc", "optimized"]
+
+[[package]]
+name = "ethereum-execution-tests"
+version = "1.0.0"
+source = { editable = "packages/tests" }
+dependencies = [
+ { name = "ckzg" },
+ { name = "click" },
+ { name = "coincurve" },
+ { name = "colorlog" },
+ { name = "eth-abi" },
+ { name = "ethereum-execution" },
+ { name = "ethereum-hive" },
+ { name = "ethereum-rlp" },
+ { name = "ethereum-types" },
+ { name = "filelock" },
+ { name = "gitpython" },
+ { name = "joblib" },
+ { name = "pydantic" },
+ { name = "pyjwt" },
+ { name = "pytest" },
+ { name = "pytest-custom-report" },
+ { name = "pytest-html" },
+ { name = "pytest-json-report" },
+ { name = "pytest-metadata" },
+ { name = "pytest-regex" },
+ { name = "pytest-xdist" },
+ { name = "pyyaml" },
+ { name = "questionary" },
+ { name = "requests" },
+ { name = "requests-unixsocket2" },
+ { name = "rich" },
+ { name = "semver" },
+ { name = "tenacity" },
+ { name = "trie" },
+ { name = "types-pyyaml" },
+ { name = "typing-extensions" },
+]
+
+[package.optional-dependencies]
+docs = [
+ { name = "cairosvg" },
+ { name = "codespell" },
+ { name = "lxml" },
+ { name = "markdown" },
+ { name = "mike" },
+ { name = "mkdocs" },
+ { name = "mkdocs-click" },
+ { name = "mkdocs-gen-files" },
+ { name = "mkdocs-git-authors-plugin" },
+ { name = "mkdocs-glightbox" },
+ { name = "mkdocs-literate-nav" },
+ { name = "mkdocs-material" },
+ { name = "mkdocs-material-extensions" },
+ { name = "mkdocstrings" },
+ { name = "mkdocstrings-python" },
+ { name = "pillow" },
+ { name = "pyspelling" },
+ { name = "setuptools" },
+]
+lint = [
+ { name = "mypy" },
+ { name = "ruff" },
+ { name = "types-requests" },
+]
+test = [
+ { name = "pytest-cov" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "cairosvg", marker = "extra == 'docs'", specifier = ">=2.7.0,<3" },
+ { name = "ckzg", specifier = ">=2.1.3,<3" },
+ { name = "click", specifier = ">=8.1.0,<9" },
+ { name = "codespell", marker = "extra == 'docs'", specifier = ">=2.4.1,<3" },
+ { name = "coincurve", specifier = ">=20.0.0,<21" },
+ { name = "colorlog", specifier = ">=6.7.0,<7" },
+ { name = "eth-abi", specifier = ">=5.2.0" },
+ { name = "ethereum-execution", editable = "." },
+ { name = "ethereum-hive", specifier = ">=0.1.0a1,<1.0.0" },
+ { name = "ethereum-rlp", specifier = ">=0.1.3,<0.2" },
+ { name = "ethereum-types", specifier = ">=0.2.1,<0.3" },
+ { name = "filelock", specifier = ">=3.15.1,<4" },
+ { name = "gitpython", specifier = ">=3.1.31,<4" },
+ { name = "joblib", specifier = ">=1.4.2" },
+ { name = "lxml", marker = "extra == 'docs'", specifier = ">=6.0.0,<7" },
+ { name = "markdown", marker = "extra == 'docs'", specifier = "==3.8" },
+ { name = "mike", marker = "extra == 'docs'", specifier = ">=1.1.2,<2" },
+ { name = "mkdocs", marker = "extra == 'docs'", specifier = ">=1.4.3,<2" },
+ { name = "mkdocs-click", marker = "extra == 'docs'", specifier = ">=0.8,<1" },
+ { name = "mkdocs-gen-files", marker = "extra == 'docs'", specifier = ">=0.5.0,<1" },
+ { name = "mkdocs-git-authors-plugin", marker = "extra == 'docs'", specifier = ">=0.7.1,<1" },
+ { name = "mkdocs-glightbox", marker = "extra == 'docs'", specifier = ">=0.3.4,<1" },
+ { name = "mkdocs-literate-nav", marker = "extra == 'docs'", specifier = ">=0.6.0,<1" },
+ { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.1.14,<10" },
+ { name = "mkdocs-material-extensions", marker = "extra == 'docs'", specifier = ">=1.1.1,<2" },
+ { name = "mkdocstrings", marker = "extra == 'docs'", specifier = ">=0.21.2,<1" },
+ { name = "mkdocstrings-python", marker = "extra == 'docs'", specifier = ">=1.0.0,<2" },
+ { name = "mypy", marker = "extra == 'lint'", specifier = "==1.17.0" },
+ { name = "pillow", marker = "extra == 'docs'", specifier = ">=10.0.1,<11" },
+ { name = "pydantic", specifier = ">=2.11.0,<3" },
+ { name = "pyjwt", specifier = ">=2.3.0,<3" },
+ { name = "pyspelling", marker = "extra == 'docs'", specifier = ">=2.8.2,<3" },
+ { name = "pytest", specifier = ">=8,<9" },
+ { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=4.1.0,<5" },
+ { name = "pytest-custom-report", specifier = ">=1.0.1,<2" },
+ { name = "pytest-html", specifier = ">=4.1.0,<5" },
+ { name = "pytest-json-report", specifier = ">=1.5.0,<2" },
+ { name = "pytest-metadata", specifier = ">=3,<4" },
+ { name = "pytest-regex", specifier = ">=0.2.0,<0.3" },
+ { name = "pytest-xdist", specifier = ">=3.3.1,<4" },
+ { name = "pyyaml", specifier = ">=6.0.2,<7" },
+ { name = "questionary", specifier = ">=2.1.0,<3" },
+ { name = "requests", specifier = ">=2.31.0,<3" },
+ { name = "requests-unixsocket2", specifier = ">=0.4.0" },
+ { name = "rich", specifier = ">=13.7.0,<14" },
+ { name = "ruff", marker = "extra == 'lint'", specifier = "==0.13.2" },
+ { name = "semver", specifier = ">=3.0.1,<4" },
+ { name = "setuptools", marker = "extra == 'docs'", specifier = "==78.0.2" },
+ { name = "tenacity", specifier = ">=9.0.0,<10" },
+ { name = "trie", specifier = ">=3.1.0,<4" },
+ { name = "types-pyyaml", specifier = ">=6.0.12.20240917,<7" },
+ { name = "types-requests", marker = "extra == 'lint'", specifier = ">=2.31,<2.33" },
+ { name = "typing-extensions", specifier = ">=4.12.2,<5" },
+]
+provides-extras = ["test", "lint", "docs"]
[[package]]
name = "ethereum-hive"
@@ -698,6 +873,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c4/53/2e6b79e51ed771be268dde26caa57c64d5552fd49019c7a66f9ee18330be/fladrif-0.2.0-py3-none-any.whl", hash = "sha256:34ce53c2084159d7d5cd2f886db62ca9db0569d7d1c17799ab99e62831d4c53b", size = 6371, upload-time = "2023-08-10T18:04:11.559Z" },
]
+[[package]]
+name = "ghp-import"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "python-dateutil" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943, upload-time = "2022-05-02T15:47:16.11Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" },
+]
+
[[package]]
name = "gitdb"
version = "4.0.12"
@@ -722,6 +909,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/9a/4114a9057db2f1462d5c8f8390ab7383925fe1ac012eaa42402ad65c2963/GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110", size = 207599, upload-time = "2025-01-02T07:32:40.731Z" },
]
+[[package]]
+name = "griffe"
+version = "1.14.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ec/d7/6c09dd7ce4c7837e4cdb11dce980cb45ae3cd87677298dc3b781b6bce7d3/griffe-1.14.0.tar.gz", hash = "sha256:9d2a15c1eca966d68e00517de5d69dd1bc5c9f2335ef6c1775362ba5b8651a13", size = 424684, upload-time = "2025-09-05T15:02:29.167Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/b1/9ff6578d789a89812ff21e4e0f80ffae20a65d5dd84e7a17873fe3b365be/griffe-1.14.0-py3-none-any.whl", hash = "sha256:0e9d52832cccf0f7188cfe585ba962d2674b241c01916d780925df34873bceb0", size = 144439, upload-time = "2025-09-05T15:02:27.511Z" },
+]
+
[[package]]
name = "hexbytes"
version = "1.3.1"
@@ -731,6 +930,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8d/e0/3b31492b1c89da3c5a846680517871455b30c54738486fc57ac79a5761bd/hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7", size = 5074, upload-time = "2025-05-14T16:45:16.179Z" },
]
+[[package]]
+name = "html5lib"
+version = "1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+ { name = "webencodings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215, upload-time = "2020-06-22T23:32:38.834Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173, upload-time = "2020-06-22T23:32:36.781Z" },
+]
+
[[package]]
name = "idna"
version = "3.10"
@@ -840,6 +1052,117 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d3/8f/da755d6d517eb8ec9664afae967b00a9b8dd567bbbb350e261359c1b47fc/libcst-1.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:4f14f5045766646ed9e8826b959c6d07194788babed1e0ba08c94ea4f39517e3", size = 1974355, upload-time = "2025-06-13T20:56:18.064Z" },
]
+[[package]]
+name = "lxml"
+version = "6.0.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/aa/88/262177de60548e5a2bfc46ad28232c9e9cbde697bd94132aeb80364675cb/lxml-6.0.2.tar.gz", hash = "sha256:cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62", size = 4073426, upload-time = "2025-09-22T04:04:59.287Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/77/d5/becbe1e2569b474a23f0c672ead8a29ac50b2dc1d5b9de184831bda8d14c/lxml-6.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:13e35cbc684aadf05d8711a5d1b5857c92e5e580efa9a0d2be197199c8def607", size = 8634365, upload-time = "2025-09-22T04:00:45.672Z" },
+ { url = "https://files.pythonhosted.org/packages/28/66/1ced58f12e804644426b85d0bb8a4478ca77bc1761455da310505f1a3526/lxml-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b1675e096e17c6fe9c0e8c81434f5736c0739ff9ac6123c87c2d452f48fc938", size = 4650793, upload-time = "2025-09-22T04:00:47.783Z" },
+ { url = "https://files.pythonhosted.org/packages/11/84/549098ffea39dfd167e3f174b4ce983d0eed61f9d8d25b7bf2a57c3247fc/lxml-6.0.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac6e5811ae2870953390452e3476694196f98d447573234592d30488147404d", size = 4944362, upload-time = "2025-09-22T04:00:49.845Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/bd/f207f16abf9749d2037453d56b643a7471d8fde855a231a12d1e095c4f01/lxml-6.0.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5aa0fc67ae19d7a64c3fe725dc9a1bb11f80e01f78289d05c6f62545affec438", size = 5083152, upload-time = "2025-09-22T04:00:51.709Z" },
+ { url = "https://files.pythonhosted.org/packages/15/ae/bd813e87d8941d52ad5b65071b1affb48da01c4ed3c9c99e40abb266fbff/lxml-6.0.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de496365750cc472b4e7902a485d3f152ecf57bd3ba03ddd5578ed8ceb4c5964", size = 5023539, upload-time = "2025-09-22T04:00:53.593Z" },
+ { url = "https://files.pythonhosted.org/packages/02/cd/9bfef16bd1d874fbe0cb51afb00329540f30a3283beb9f0780adbb7eec03/lxml-6.0.2-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:200069a593c5e40b8f6fc0d84d86d970ba43138c3e68619ffa234bc9bb806a4d", size = 5344853, upload-time = "2025-09-22T04:00:55.524Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/89/ea8f91594bc5dbb879734d35a6f2b0ad50605d7fb419de2b63d4211765cc/lxml-6.0.2-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d2de809c2ee3b888b59f995625385f74629707c9355e0ff856445cdcae682b7", size = 5225133, upload-time = "2025-09-22T04:00:57.269Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/37/9c735274f5dbec726b2db99b98a43950395ba3d4a1043083dba2ad814170/lxml-6.0.2-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:b2c3da8d93cf5db60e8858c17684c47d01fee6405e554fb55018dd85fc23b178", size = 4677944, upload-time = "2025-09-22T04:00:59.052Z" },
+ { url = "https://files.pythonhosted.org/packages/20/28/7dfe1ba3475d8bfca3878365075abe002e05d40dfaaeb7ec01b4c587d533/lxml-6.0.2-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:442de7530296ef5e188373a1ea5789a46ce90c4847e597856570439621d9c553", size = 5284535, upload-time = "2025-09-22T04:01:01.335Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/cf/5f14bc0de763498fc29510e3532bf2b4b3a1c1d5d0dff2e900c16ba021ef/lxml-6.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2593c77efde7bfea7f6389f1ab249b15ed4aa5bc5cb5131faa3b843c429fbedb", size = 5067343, upload-time = "2025-09-22T04:01:03.13Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/b0/bb8275ab5472f32b28cfbbcc6db7c9d092482d3439ca279d8d6fa02f7025/lxml-6.0.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3e3cb08855967a20f553ff32d147e14329b3ae70ced6edc2f282b94afbc74b2a", size = 4725419, upload-time = "2025-09-22T04:01:05.013Z" },
+ { url = "https://files.pythonhosted.org/packages/25/4c/7c222753bc72edca3b99dbadba1b064209bc8ed4ad448af990e60dcce462/lxml-6.0.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ed6c667fcbb8c19c6791bbf40b7268ef8ddf5a96940ba9404b9f9a304832f6c", size = 5275008, upload-time = "2025-09-22T04:01:07.327Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/8c/478a0dc6b6ed661451379447cdbec77c05741a75736d97e5b2b729687828/lxml-6.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b8f18914faec94132e5b91e69d76a5c1d7b0c73e2489ea8929c4aaa10b76bbf7", size = 5248906, upload-time = "2025-09-22T04:01:09.452Z" },
+ { url = "https://files.pythonhosted.org/packages/2d/d9/5be3a6ab2784cdf9accb0703b65e1b64fcdd9311c9f007630c7db0cfcce1/lxml-6.0.2-cp311-cp311-win32.whl", hash = "sha256:6605c604e6daa9e0d7f0a2137bdc47a2e93b59c60a65466353e37f8272f47c46", size = 3610357, upload-time = "2025-09-22T04:01:11.102Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/7d/ca6fb13349b473d5732fb0ee3eec8f6c80fc0688e76b7d79c1008481bf1f/lxml-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e5867f2651016a3afd8dd2c8238baa66f1e2802f44bc17e236f547ace6647078", size = 4036583, upload-time = "2025-09-22T04:01:12.766Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/a2/51363b5ecd3eab46563645f3a2c3836a2fc67d01a1b87c5017040f39f567/lxml-6.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:4197fb2534ee05fd3e7afaab5d8bfd6c2e186f65ea7f9cd6a82809c887bd1285", size = 3680591, upload-time = "2025-09-22T04:01:14.874Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/c8/8ff2bc6b920c84355146cd1ab7d181bc543b89241cfb1ebee824a7c81457/lxml-6.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a59f5448ba2ceccd06995c95ea59a7674a10de0810f2ce90c9006f3cbc044456", size = 8661887, upload-time = "2025-09-22T04:01:17.265Z" },
+ { url = "https://files.pythonhosted.org/packages/37/6f/9aae1008083bb501ef63284220ce81638332f9ccbfa53765b2b7502203cf/lxml-6.0.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e8113639f3296706fbac34a30813929e29247718e88173ad849f57ca59754924", size = 4667818, upload-time = "2025-09-22T04:01:19.688Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/ca/31fb37f99f37f1536c133476674c10b577e409c0a624384147653e38baf2/lxml-6.0.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a8bef9b9825fa8bc816a6e641bb67219489229ebc648be422af695f6e7a4fa7f", size = 4950807, upload-time = "2025-09-22T04:01:21.487Z" },
+ { url = "https://files.pythonhosted.org/packages/da/87/f6cb9442e4bada8aab5ae7e1046264f62fdbeaa6e3f6211b93f4c0dd97f1/lxml-6.0.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:65ea18d710fd14e0186c2f973dc60bb52039a275f82d3c44a0e42b43440ea534", size = 5109179, upload-time = "2025-09-22T04:01:23.32Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/20/a7760713e65888db79bbae4f6146a6ae5c04e4a204a3c48896c408cd6ed2/lxml-6.0.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c371aa98126a0d4c739ca93ceffa0fd7a5d732e3ac66a46e74339acd4d334564", size = 5023044, upload-time = "2025-09-22T04:01:25.118Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/b0/7e64e0460fcb36471899f75831509098f3fd7cd02a3833ac517433cb4f8f/lxml-6.0.2-cp312-cp312-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:700efd30c0fa1a3581d80a748157397559396090a51d306ea59a70020223d16f", size = 5359685, upload-time = "2025-09-22T04:01:27.398Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/e1/e5df362e9ca4e2f48ed6411bd4b3a0ae737cc842e96877f5bf9428055ab4/lxml-6.0.2-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c33e66d44fe60e72397b487ee92e01da0d09ba2d66df8eae42d77b6d06e5eba0", size = 5654127, upload-time = "2025-09-22T04:01:29.629Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/d1/232b3309a02d60f11e71857778bfcd4acbdb86c07db8260caf7d008b08f8/lxml-6.0.2-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90a345bbeaf9d0587a3aaffb7006aa39ccb6ff0e96a57286c0cb2fd1520ea192", size = 5253958, upload-time = "2025-09-22T04:01:31.535Z" },
+ { url = "https://files.pythonhosted.org/packages/35/35/d955a070994725c4f7d80583a96cab9c107c57a125b20bb5f708fe941011/lxml-6.0.2-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:064fdadaf7a21af3ed1dcaa106b854077fbeada827c18f72aec9346847cd65d0", size = 4711541, upload-time = "2025-09-22T04:01:33.801Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/be/667d17363b38a78c4bd63cfd4b4632029fd68d2c2dc81f25ce9eb5224dd5/lxml-6.0.2-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fbc74f42c3525ac4ffa4b89cbdd00057b6196bcefe8bce794abd42d33a018092", size = 5267426, upload-time = "2025-09-22T04:01:35.639Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/47/62c70aa4a1c26569bc958c9ca86af2bb4e1f614e8c04fb2989833874f7ae/lxml-6.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6ddff43f702905a4e32bc24f3f2e2edfe0f8fde3277d481bffb709a4cced7a1f", size = 5064917, upload-time = "2025-09-22T04:01:37.448Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/55/6ceddaca353ebd0f1908ef712c597f8570cc9c58130dbb89903198e441fd/lxml-6.0.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6da5185951d72e6f5352166e3da7b0dc27aa70bd1090b0eb3f7f7212b53f1bb8", size = 4788795, upload-time = "2025-09-22T04:01:39.165Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/e8/fd63e15da5e3fd4c2146f8bbb3c14e94ab850589beab88e547b2dbce22e1/lxml-6.0.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:57a86e1ebb4020a38d295c04fc79603c7899e0df71588043eb218722dabc087f", size = 5676759, upload-time = "2025-09-22T04:01:41.506Z" },
+ { url = "https://files.pythonhosted.org/packages/76/47/b3ec58dc5c374697f5ba37412cd2728f427d056315d124dd4b61da381877/lxml-6.0.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2047d8234fe735ab77802ce5f2297e410ff40f5238aec569ad7c8e163d7b19a6", size = 5255666, upload-time = "2025-09-22T04:01:43.363Z" },
+ { url = "https://files.pythonhosted.org/packages/19/93/03ba725df4c3d72afd9596eef4a37a837ce8e4806010569bedfcd2cb68fd/lxml-6.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f91fd2b2ea15a6800c8e24418c0775a1694eefc011392da73bc6cef2623b322", size = 5277989, upload-time = "2025-09-22T04:01:45.215Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/80/c06de80bfce881d0ad738576f243911fccf992687ae09fd80b734712b39c/lxml-6.0.2-cp312-cp312-win32.whl", hash = "sha256:3ae2ce7d6fedfb3414a2b6c5e20b249c4c607f72cb8d2bb7cc9c6ec7c6f4e849", size = 3611456, upload-time = "2025-09-22T04:01:48.243Z" },
+ { url = "https://files.pythonhosted.org/packages/f7/d7/0cdfb6c3e30893463fb3d1e52bc5f5f99684a03c29a0b6b605cfae879cd5/lxml-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:72c87e5ee4e58a8354fb9c7c84cbf95a1c8236c127a5d1b7683f04bed8361e1f", size = 4011793, upload-time = "2025-09-22T04:01:50.042Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/7b/93c73c67db235931527301ed3785f849c78991e2e34f3fd9a6663ffda4c5/lxml-6.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:61cb10eeb95570153e0c0e554f58df92ecf5109f75eacad4a95baa709e26c3d6", size = 3672836, upload-time = "2025-09-22T04:01:52.145Z" },
+ { url = "https://files.pythonhosted.org/packages/53/fd/4e8f0540608977aea078bf6d79f128e0e2c2bba8af1acf775c30baa70460/lxml-6.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9b33d21594afab46f37ae58dfadd06636f154923c4e8a4d754b0127554eb2e77", size = 8648494, upload-time = "2025-09-22T04:01:54.242Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/f4/2a94a3d3dfd6c6b433501b8d470a1960a20ecce93245cf2db1706adf6c19/lxml-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c8963287d7a4c5c9a432ff487c52e9c5618667179c18a204bdedb27310f022f", size = 4661146, upload-time = "2025-09-22T04:01:56.282Z" },
+ { url = "https://files.pythonhosted.org/packages/25/2e/4efa677fa6b322013035d38016f6ae859d06cac67437ca7dc708a6af7028/lxml-6.0.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1941354d92699fb5ffe6ed7b32f9649e43c2feb4b97205f75866f7d21aa91452", size = 4946932, upload-time = "2025-09-22T04:01:58.989Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/0f/526e78a6d38d109fdbaa5049c62e1d32fdd70c75fb61c4eadf3045d3d124/lxml-6.0.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb2f6ca0ae2d983ded09357b84af659c954722bbf04dea98030064996d156048", size = 5100060, upload-time = "2025-09-22T04:02:00.812Z" },
+ { url = "https://files.pythonhosted.org/packages/81/76/99de58d81fa702cc0ea7edae4f4640416c2062813a00ff24bd70ac1d9c9b/lxml-6.0.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb2a12d704f180a902d7fa778c6d71f36ceb7b0d317f34cdc76a5d05aa1dd1df", size = 5019000, upload-time = "2025-09-22T04:02:02.671Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/35/9e57d25482bc9a9882cb0037fdb9cc18f4b79d85df94fa9d2a89562f1d25/lxml-6.0.2-cp313-cp313-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:6ec0e3f745021bfed19c456647f0298d60a24c9ff86d9d051f52b509663feeb1", size = 5348496, upload-time = "2025-09-22T04:02:04.904Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/8e/cb99bd0b83ccc3e8f0f528e9aa1f7a9965dfec08c617070c5db8d63a87ce/lxml-6.0.2-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:846ae9a12d54e368933b9759052d6206a9e8b250291109c48e350c1f1f49d916", size = 5643779, upload-time = "2025-09-22T04:02:06.689Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/34/9e591954939276bb679b73773836c6684c22e56d05980e31d52a9a8deb18/lxml-6.0.2-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef9266d2aa545d7374938fb5c484531ef5a2ec7f2d573e62f8ce722c735685fd", size = 5244072, upload-time = "2025-09-22T04:02:08.587Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/27/b29ff065f9aaca443ee377aff699714fcbffb371b4fce5ac4ca759e436d5/lxml-6.0.2-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:4077b7c79f31755df33b795dc12119cb557a0106bfdab0d2c2d97bd3cf3dffa6", size = 4718675, upload-time = "2025-09-22T04:02:10.783Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/9f/f756f9c2cd27caa1a6ef8c32ae47aadea697f5c2c6d07b0dae133c244fbe/lxml-6.0.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a7c5d5e5f1081955358533be077166ee97ed2571d6a66bdba6ec2f609a715d1a", size = 5255171, upload-time = "2025-09-22T04:02:12.631Z" },
+ { url = "https://files.pythonhosted.org/packages/61/46/bb85ea42d2cb1bd8395484fd72f38e3389611aa496ac7772da9205bbda0e/lxml-6.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8f8d0cbd0674ee89863a523e6994ac25fd5be9c8486acfc3e5ccea679bad2679", size = 5057175, upload-time = "2025-09-22T04:02:14.718Z" },
+ { url = "https://files.pythonhosted.org/packages/95/0c/443fc476dcc8e41577f0af70458c50fe299a97bb6b7505bb1ae09aa7f9ac/lxml-6.0.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2cbcbf6d6e924c28f04a43f3b6f6e272312a090f269eff68a2982e13e5d57659", size = 4785688, upload-time = "2025-09-22T04:02:16.957Z" },
+ { url = "https://files.pythonhosted.org/packages/48/78/6ef0b359d45bb9697bc5a626e1992fa5d27aa3f8004b137b2314793b50a0/lxml-6.0.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dfb874cfa53340009af6bdd7e54ebc0d21012a60a4e65d927c2e477112e63484", size = 5660655, upload-time = "2025-09-22T04:02:18.815Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/ea/e1d33808f386bc1339d08c0dcada6e4712d4ed8e93fcad5f057070b7988a/lxml-6.0.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb8dae0b6b8b7f9e96c26fdd8121522ce5de9bb5538010870bd538683d30e9a2", size = 5247695, upload-time = "2025-09-22T04:02:20.593Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/47/eba75dfd8183673725255247a603b4ad606f4ae657b60c6c145b381697da/lxml-6.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:358d9adae670b63e95bc59747c72f4dc97c9ec58881d4627fe0120da0f90d314", size = 5269841, upload-time = "2025-09-22T04:02:22.489Z" },
+ { url = "https://files.pythonhosted.org/packages/76/04/5c5e2b8577bc936e219becb2e98cdb1aca14a4921a12995b9d0c523502ae/lxml-6.0.2-cp313-cp313-win32.whl", hash = "sha256:e8cd2415f372e7e5a789d743d133ae474290a90b9023197fd78f32e2dc6873e2", size = 3610700, upload-time = "2025-09-22T04:02:24.465Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/0a/4643ccc6bb8b143e9f9640aa54e38255f9d3b45feb2cbe7ae2ca47e8782e/lxml-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:b30d46379644fbfc3ab81f8f82ae4de55179414651f110a1514f0b1f8f6cb2d7", size = 4010347, upload-time = "2025-09-22T04:02:26.286Z" },
+ { url = "https://files.pythonhosted.org/packages/31/ef/dcf1d29c3f530577f61e5fe2f1bd72929acf779953668a8a47a479ae6f26/lxml-6.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:13dcecc9946dca97b11b7c40d29fba63b55ab4170d3c0cf8c0c164343b9bfdcf", size = 3671248, upload-time = "2025-09-22T04:02:27.918Z" },
+ { url = "https://files.pythonhosted.org/packages/03/15/d4a377b385ab693ce97b472fe0c77c2b16ec79590e688b3ccc71fba19884/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:b0c732aa23de8f8aec23f4b580d1e52905ef468afb4abeafd3fec77042abb6fe", size = 8659801, upload-time = "2025-09-22T04:02:30.113Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/e8/c128e37589463668794d503afaeb003987373c5f94d667124ffd8078bbd9/lxml-6.0.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4468e3b83e10e0317a89a33d28f7aeba1caa4d1a6fd457d115dd4ffe90c5931d", size = 4659403, upload-time = "2025-09-22T04:02:32.119Z" },
+ { url = "https://files.pythonhosted.org/packages/00/ce/74903904339decdf7da7847bb5741fc98a5451b42fc419a86c0c13d26fe2/lxml-6.0.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:abd44571493973bad4598a3be7e1d807ed45aa2adaf7ab92ab7c62609569b17d", size = 4966974, upload-time = "2025-09-22T04:02:34.155Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/d3/131dec79ce61c5567fecf82515bd9bc36395df42501b50f7f7f3bd065df0/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:370cd78d5855cfbffd57c422851f7d3864e6ae72d0da615fca4dad8c45d375a5", size = 5102953, upload-time = "2025-09-22T04:02:36.054Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/ea/a43ba9bb750d4ffdd885f2cd333572f5bb900cd2408b67fdda07e85978a0/lxml-6.0.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:901e3b4219fa04ef766885fb40fa516a71662a4c61b80c94d25336b4934b71c0", size = 5055054, upload-time = "2025-09-22T04:02:38.154Z" },
+ { url = "https://files.pythonhosted.org/packages/60/23/6885b451636ae286c34628f70a7ed1fcc759f8d9ad382d132e1c8d3d9bfd/lxml-6.0.2-cp314-cp314-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:a4bf42d2e4cf52c28cc1812d62426b9503cdb0c87a6de81442626aa7d69707ba", size = 5352421, upload-time = "2025-09-22T04:02:40.413Z" },
+ { url = "https://files.pythonhosted.org/packages/48/5b/fc2ddfc94ddbe3eebb8e9af6e3fd65e2feba4967f6a4e9683875c394c2d8/lxml-6.0.2-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2c7fdaa4d7c3d886a42534adec7cfac73860b89b4e5298752f60aa5984641a0", size = 5673684, upload-time = "2025-09-22T04:02:42.288Z" },
+ { url = "https://files.pythonhosted.org/packages/29/9c/47293c58cc91769130fbf85531280e8cc7868f7fbb6d92f4670071b9cb3e/lxml-6.0.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98a5e1660dc7de2200b00d53fa00bcd3c35a3608c305d45a7bbcaf29fa16e83d", size = 5252463, upload-time = "2025-09-22T04:02:44.165Z" },
+ { url = "https://files.pythonhosted.org/packages/9b/da/ba6eceb830c762b48e711ded880d7e3e89fc6c7323e587c36540b6b23c6b/lxml-6.0.2-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:dc051506c30b609238d79eda75ee9cab3e520570ec8219844a72a46020901e37", size = 4698437, upload-time = "2025-09-22T04:02:46.524Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/24/7be3f82cb7990b89118d944b619e53c656c97dc89c28cfb143fdb7cd6f4d/lxml-6.0.2-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8799481bbdd212470d17513a54d568f44416db01250f49449647b5ab5b5dccb9", size = 5269890, upload-time = "2025-09-22T04:02:48.812Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/bd/dcfb9ea1e16c665efd7538fc5d5c34071276ce9220e234217682e7d2c4a5/lxml-6.0.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9261bb77c2dab42f3ecd9103951aeca2c40277701eb7e912c545c1b16e0e4917", size = 5097185, upload-time = "2025-09-22T04:02:50.746Z" },
+ { url = "https://files.pythonhosted.org/packages/21/04/a60b0ff9314736316f28316b694bccbbabe100f8483ad83852d77fc7468e/lxml-6.0.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:65ac4a01aba353cfa6d5725b95d7aed6356ddc0a3cd734de00124d285b04b64f", size = 4745895, upload-time = "2025-09-22T04:02:52.968Z" },
+ { url = "https://files.pythonhosted.org/packages/d6/bd/7d54bd1846e5a310d9c715921c5faa71cf5c0853372adf78aee70c8d7aa2/lxml-6.0.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b22a07cbb82fea98f8a2fd814f3d1811ff9ed76d0fc6abc84eb21527596e7cc8", size = 5695246, upload-time = "2025-09-22T04:02:54.798Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/32/5643d6ab947bc371da21323acb2a6e603cedbe71cb4c99c8254289ab6f4e/lxml-6.0.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d759cdd7f3e055d6bc8d9bec3ad905227b2e4c785dc16c372eb5b5e83123f48a", size = 5260797, upload-time = "2025-09-22T04:02:57.058Z" },
+ { url = "https://files.pythonhosted.org/packages/33/da/34c1ec4cff1eea7d0b4cd44af8411806ed943141804ac9c5d565302afb78/lxml-6.0.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:945da35a48d193d27c188037a05fec5492937f66fb1958c24fc761fb9d40d43c", size = 5277404, upload-time = "2025-09-22T04:02:58.966Z" },
+ { url = "https://files.pythonhosted.org/packages/82/57/4eca3e31e54dc89e2c3507e1cd411074a17565fa5ffc437c4ae0a00d439e/lxml-6.0.2-cp314-cp314-win32.whl", hash = "sha256:be3aaa60da67e6153eb15715cc2e19091af5dc75faef8b8a585aea372507384b", size = 3670072, upload-time = "2025-09-22T04:03:38.05Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/e0/c96cf13eccd20c9421ba910304dae0f619724dcf1702864fd59dd386404d/lxml-6.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:fa25afbadead523f7001caf0c2382afd272c315a033a7b06336da2637d92d6ed", size = 4080617, upload-time = "2025-09-22T04:03:39.835Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/5d/b3f03e22b3d38d6f188ef044900a9b29b2fe0aebb94625ce9fe244011d34/lxml-6.0.2-cp314-cp314-win_arm64.whl", hash = "sha256:063eccf89df5b24e361b123e257e437f9e9878f425ee9aae3144c77faf6da6d8", size = 3754930, upload-time = "2025-09-22T04:03:41.565Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/5c/42c2c4c03554580708fc738d13414801f340c04c3eff90d8d2d227145275/lxml-6.0.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6162a86d86893d63084faaf4ff937b3daea233e3682fb4474db07395794fa80d", size = 8910380, upload-time = "2025-09-22T04:03:01.645Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/4f/12df843e3e10d18d468a7557058f8d3733e8b6e12401f30b1ef29360740f/lxml-6.0.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:414aaa94e974e23a3e92e7ca5b97d10c0cf37b6481f50911032c69eeb3991bba", size = 4775632, upload-time = "2025-09-22T04:03:03.814Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/0c/9dc31e6c2d0d418483cbcb469d1f5a582a1cd00a1f4081953d44051f3c50/lxml-6.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48461bd21625458dd01e14e2c38dd0aea69addc3c4f960c30d9f59d7f93be601", size = 4975171, upload-time = "2025-09-22T04:03:05.651Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/2b/9b870c6ca24c841bdd887504808f0417aa9d8d564114689266f19ddf29c8/lxml-6.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:25fcc59afc57d527cfc78a58f40ab4c9b8fd096a9a3f964d2781ffb6eb33f4ed", size = 5110109, upload-time = "2025-09-22T04:03:07.452Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/0c/4f5f2a4dd319a178912751564471355d9019e220c20d7db3fb8307ed8582/lxml-6.0.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5179c60288204e6ddde3f774a93350177e08876eaf3ab78aa3a3649d43eb7d37", size = 5041061, upload-time = "2025-09-22T04:03:09.297Z" },
+ { url = "https://files.pythonhosted.org/packages/12/64/554eed290365267671fe001a20d72d14f468ae4e6acef1e179b039436967/lxml-6.0.2-cp314-cp314t-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:967aab75434de148ec80597b75062d8123cadf2943fb4281f385141e18b21338", size = 5306233, upload-time = "2025-09-22T04:03:11.651Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/31/1d748aa275e71802ad9722df32a7a35034246b42c0ecdd8235412c3396ef/lxml-6.0.2-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d100fcc8930d697c6561156c6810ab4a508fb264c8b6779e6e61e2ed5e7558f9", size = 5604739, upload-time = "2025-09-22T04:03:13.592Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/41/2c11916bcac09ed561adccacceaedd2bf0e0b25b297ea92aab99fd03d0fa/lxml-6.0.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ca59e7e13e5981175b8b3e4ab84d7da57993eeff53c07764dcebda0d0e64ecd", size = 5225119, upload-time = "2025-09-22T04:03:15.408Z" },
+ { url = "https://files.pythonhosted.org/packages/99/05/4e5c2873d8f17aa018e6afde417c80cc5d0c33be4854cce3ef5670c49367/lxml-6.0.2-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:957448ac63a42e2e49531b9d6c0fa449a1970dbc32467aaad46f11545be9af1d", size = 4633665, upload-time = "2025-09-22T04:03:17.262Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/c9/dcc2da1bebd6275cdc723b515f93edf548b82f36a5458cca3578bc899332/lxml-6.0.2-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b7fc49c37f1786284b12af63152fe1d0990722497e2d5817acfe7a877522f9a9", size = 5234997, upload-time = "2025-09-22T04:03:19.14Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/e2/5172e4e7468afca64a37b81dba152fc5d90e30f9c83c7c3213d6a02a5ce4/lxml-6.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e19e0643cc936a22e837f79d01a550678da8377d7d801a14487c10c34ee49c7e", size = 5090957, upload-time = "2025-09-22T04:03:21.436Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/b3/15461fd3e5cd4ddcb7938b87fc20b14ab113b92312fc97afe65cd7c85de1/lxml-6.0.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:1db01e5cf14345628e0cbe71067204db658e2fb8e51e7f33631f5f4735fefd8d", size = 4764372, upload-time = "2025-09-22T04:03:23.27Z" },
+ { url = "https://files.pythonhosted.org/packages/05/33/f310b987c8bf9e61c4dd8e8035c416bd3230098f5e3cfa69fc4232de7059/lxml-6.0.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:875c6b5ab39ad5291588aed6925fac99d0097af0dd62f33c7b43736043d4a2ec", size = 5634653, upload-time = "2025-09-22T04:03:25.767Z" },
+ { url = "https://files.pythonhosted.org/packages/70/ff/51c80e75e0bc9382158133bdcf4e339b5886c6ee2418b5199b3f1a61ed6d/lxml-6.0.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:cdcbed9ad19da81c480dfd6dd161886db6096083c9938ead313d94b30aadf272", size = 5233795, upload-time = "2025-09-22T04:03:27.62Z" },
+ { url = "https://files.pythonhosted.org/packages/56/4d/4856e897df0d588789dd844dbed9d91782c4ef0b327f96ce53c807e13128/lxml-6.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80dadc234ebc532e09be1975ff538d154a7fa61ea5031c03d25178855544728f", size = 5257023, upload-time = "2025-09-22T04:03:30.056Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/85/86766dfebfa87bea0ab78e9ff7a4b4b45225df4b4d3b8cc3c03c5cd68464/lxml-6.0.2-cp314-cp314t-win32.whl", hash = "sha256:da08e7bb297b04e893d91087df19638dc7a6bb858a954b0cc2b9f5053c922312", size = 3911420, upload-time = "2025-09-22T04:03:32.198Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/1a/b248b355834c8e32614650b8008c69ffeb0ceb149c793961dd8c0b991bb3/lxml-6.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:252a22982dca42f6155125ac76d3432e548a7625d56f5a273ee78a5057216eca", size = 4406837, upload-time = "2025-09-22T04:03:34.027Z" },
+ { url = "https://files.pythonhosted.org/packages/92/aa/df863bcc39c5e0946263454aba394de8a9084dbaff8ad143846b0d844739/lxml-6.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:bb4c1847b303835d89d785a18801a883436cdfd5dc3d62947f9c49e24f0f5a2c", size = 3822205, upload-time = "2025-09-22T04:03:36.249Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/11/29d08bc103a62c0eba8016e7ed5aeebbf1e4312e83b0b1648dd203b0e87d/lxml-6.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1c06035eafa8404b5cf475bb37a9f6088b0aca288d4ccc9d69389750d5543700", size = 3949829, upload-time = "2025-09-22T04:04:45.608Z" },
+ { url = "https://files.pythonhosted.org/packages/12/b3/52ab9a3b31e5ab8238da241baa19eec44d2ab426532441ee607165aebb52/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c7d13103045de1bdd6fe5d61802565f1a3537d70cd3abf596aa0af62761921ee", size = 4226277, upload-time = "2025-09-22T04:04:47.754Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/33/1eaf780c1baad88224611df13b1c2a9dfa460b526cacfe769103ff50d845/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a3c150a95fbe5ac91de323aa756219ef9cf7fde5a3f00e2281e30f33fa5fa4f", size = 4330433, upload-time = "2025-09-22T04:04:49.907Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/c1/27428a2ff348e994ab4f8777d3a0ad510b6b92d37718e5887d2da99952a2/lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60fa43be34f78bebb27812ed90f1925ec99560b0fa1decdb7d12b84d857d31e9", size = 4272119, upload-time = "2025-09-22T04:04:51.801Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/d0/3020fa12bcec4ab62f97aab026d57c2f0cfd480a558758d9ca233bb6a79d/lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21c73b476d3cfe836be731225ec3421fa2f048d84f6df6a8e70433dff1376d5a", size = 4417314, upload-time = "2025-09-22T04:04:55.024Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/77/d7f491cbc05303ac6801651aabeb262d43f319288c1ea96c66b1d2692ff3/lxml-6.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:27220da5be049e936c3aca06f174e8827ca6445a4353a1995584311487fc4e3e", size = 3518768, upload-time = "2025-09-22T04:04:57.097Z" },
+]
+
+[[package]]
+name = "markdown"
+version = "3.8"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/2f/15/222b423b0b88689c266d9eac4e61396fe2cc53464459d6a37618ac863b24/markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f", size = 360906, upload-time = "2025-04-11T14:42:50.928Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/3f/afe76f8e2246ffbc867440cbcf90525264df0e658f8a5ca1f872b3f6192a/markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc", size = 106210, upload-time = "2025-04-11T14:42:49.178Z" },
+]
+
[[package]]
name = "markdown-it-py"
version = "3.0.0"
@@ -909,6 +1232,30 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
]
+[[package]]
+name = "mergedeep"
+version = "1.3.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661, upload-time = "2021-02-05T18:55:30.623Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" },
+]
+
+[[package]]
+name = "mike"
+version = "1.1.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jinja2" },
+ { name = "mkdocs" },
+ { name = "pyyaml" },
+ { name = "verspec" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/2d/76/2d89ba71dcf8e7a74b5e152fc8e86fe7c1f37bd86563fa8dea927f521425/mike-1.1.2.tar.gz", hash = "sha256:56c3f1794c2d0b5fdccfa9b9487beb013ca813de2e3ad0744724e9d34d40b77b", size = 28626, upload-time = "2021-10-04T05:23:46.59Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl", hash = "sha256:4c307c28769834d78df10f834f57f810f04ca27d248f80a75f49c6fa2d1527ca", size = 26933, upload-time = "2021-10-04T05:23:44.604Z" },
+]
+
[[package]]
name = "mistletoe"
version = "1.4.0"
@@ -918,6 +1265,181 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2a/0f/b5e545f0c7962be90366af3418989b12cf441d9da1e5d89d88f2f3e5cf8f/mistletoe-1.4.0-py3-none-any.whl", hash = "sha256:44a477803861de1237ba22e375c6b617690a31d2902b47279d1f8f7ed498a794", size = 51304, upload-time = "2024-07-14T10:17:33.243Z" },
]
+[[package]]
+name = "mkdocs"
+version = "1.6.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "ghp-import" },
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "markupsafe" },
+ { name = "mergedeep" },
+ { name = "mkdocs-get-deps" },
+ { name = "packaging" },
+ { name = "pathspec" },
+ { name = "pyyaml" },
+ { name = "pyyaml-env-tag" },
+ { name = "watchdog" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159, upload-time = "2024-08-30T12:24:06.899Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451, upload-time = "2024-08-30T12:24:05.054Z" },
+]
+
+[[package]]
+name = "mkdocs-autorefs"
+version = "1.4.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown" },
+ { name = "markupsafe" },
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/51/fa/9124cd63d822e2bcbea1450ae68cdc3faf3655c69b455f3a7ed36ce6c628/mkdocs_autorefs-1.4.3.tar.gz", hash = "sha256:beee715b254455c4aa93b6ef3c67579c399ca092259cc41b7d9342573ff1fc75", size = 55425, upload-time = "2025-08-26T14:23:17.223Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9f/4d/7123b6fa2278000688ebd338e2a06d16870aaf9eceae6ba047ea05f92df1/mkdocs_autorefs-1.4.3-py3-none-any.whl", hash = "sha256:469d85eb3114801d08e9cc55d102b3ba65917a869b893403b8987b601cf55dc9", size = 25034, upload-time = "2025-08-26T14:23:15.906Z" },
+]
+
+[[package]]
+name = "mkdocs-click"
+version = "0.9.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "markdown" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a1/c7/8c25f3a3b379def41e6d0bb5c4beeab7aa8a394b17e749f498504102cfa5/mkdocs_click-0.9.0.tar.gz", hash = "sha256:6050917628d4740517541422b607404d044117bc31b770c4f9e9e1939a50c908", size = 18720, upload-time = "2025-04-07T16:59:36.387Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e9/fc/9124ab36e2341e78d8d9c669511bd70f52ea0de8105760c31fabec1f9396/mkdocs_click-0.9.0-py3-none-any.whl", hash = "sha256:5208e828f4f68f63c847c1ef7be48edee9964090390afc8f5b3d4cbe5ea9bbed", size = 15104, upload-time = "2025-04-07T16:59:34.807Z" },
+]
+
+[[package]]
+name = "mkdocs-gen-files"
+version = "0.5.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/48/85/2d634462fd59136197d3126ca431ffb666f412e3db38fd5ce3a60566303e/mkdocs_gen_files-0.5.0.tar.gz", hash = "sha256:4c7cf256b5d67062a788f6b1d035e157fc1a9498c2399be9af5257d4ff4d19bc", size = 7539, upload-time = "2023-04-27T19:48:04.894Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl", hash = "sha256:7ac060096f3f40bd19039e7277dd3050be9a453c8ac578645844d4d91d7978ea", size = 8380, upload-time = "2023-04-27T19:48:07.059Z" },
+]
+
+[[package]]
+name = "mkdocs-get-deps"
+version = "0.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mergedeep" },
+ { name = "platformdirs" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239, upload-time = "2023-11-20T17:51:09.981Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" },
+]
+
+[[package]]
+name = "mkdocs-git-authors-plugin"
+version = "0.10.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/64/f1/b784c631b812aab80030db80127a576b68a84caac5229836fb7fcc00e055/mkdocs_git_authors_plugin-0.10.0.tar.gz", hash = "sha256:29d1973b2835663d79986fb756e02f1f0ff3fe35c278e993206bd3c550c205e4", size = 23432, upload-time = "2025-06-10T05:42:40.94Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/41/bc/a4166201c2789657c4d370bfcd71a5107edec185ae245675c8b9a6719243/mkdocs_git_authors_plugin-0.10.0-py3-none-any.whl", hash = "sha256:28421a99c3e872a8e205674bb80ec48524838243e5f59eaf9bd97df103e38901", size = 21899, upload-time = "2025-06-10T05:42:39.244Z" },
+]
+
+[[package]]
+name = "mkdocs-glightbox"
+version = "0.5.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "selectolax" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/8b/72/c03e9d8d2dbe098d7ce5d51309933a1d3aea268965ed097ab16f4b54de15/mkdocs_glightbox-0.5.1.tar.gz", hash = "sha256:7d78a5b045f2479f61b0bbb17742ba701755c56b013e70ac189c9d87a91e80bf", size = 480028, upload-time = "2025-09-04T13:10:29.679Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/30/cf/e9a0ce9da269746906fdc595c030f6df66793dad1487abd1699af2ba44f1/mkdocs_glightbox-0.5.1-py3-none-any.whl", hash = "sha256:f47af0daff164edf8d36e553338425be3aab6e34b987d9cbbc2ae7819a98cb01", size = 26431, upload-time = "2025-09-04T13:10:27.933Z" },
+]
+
+[[package]]
+name = "mkdocs-literate-nav"
+version = "0.6.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f6/5f/99aa379b305cd1c2084d42db3d26f6de0ea9bf2cc1d10ed17f61aff35b9a/mkdocs_literate_nav-0.6.2.tar.gz", hash = "sha256:760e1708aa4be86af81a2b56e82c739d5a8388a0eab1517ecfd8e5aa40810a75", size = 17419, upload-time = "2025-03-18T21:53:09.711Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/84/b5b14d2745e4dd1a90115186284e9ee1b4d0863104011ab46abb7355a1c3/mkdocs_literate_nav-0.6.2-py3-none-any.whl", hash = "sha256:0a6489a26ec7598477b56fa112056a5e3a6c15729f0214bea8a4dbc55bd5f630", size = 13261, upload-time = "2025-03-18T21:53:08.1Z" },
+]
+
+[[package]]
+name = "mkdocs-material"
+version = "9.6.21"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "babel" },
+ { name = "backrefs" },
+ { name = "colorama" },
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "mkdocs" },
+ { name = "mkdocs-material-extensions" },
+ { name = "paginate" },
+ { name = "pygments" },
+ { name = "pymdown-extensions" },
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ff/d5/ab83ca9aa314954b0a9e8849780bdd01866a3cfcb15ffb7e3a61ca06ff0b/mkdocs_material-9.6.21.tar.gz", hash = "sha256:b01aa6d2731322438056f360f0e623d3faae981f8f2d8c68b1b973f4f2657870", size = 4043097, upload-time = "2025-09-30T19:11:27.517Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cf/4f/98681c2030375fe9b057dbfb9008b68f46c07dddf583f4df09bf8075e37f/mkdocs_material-9.6.21-py3-none-any.whl", hash = "sha256:aa6a5ab6fb4f6d381588ac51da8782a4d3757cb3d1b174f81a2ec126e1f22c92", size = 9203097, upload-time = "2025-09-30T19:11:24.063Z" },
+]
+
+[[package]]
+name = "mkdocs-material-extensions"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847, upload-time = "2023-11-22T19:09:45.208Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" },
+]
+
+[[package]]
+name = "mkdocstrings"
+version = "0.30.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "markupsafe" },
+ { name = "mkdocs" },
+ { name = "mkdocs-autorefs" },
+ { name = "pymdown-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c5/33/2fa3243439f794e685d3e694590d28469a9b8ea733af4b48c250a3ffc9a0/mkdocstrings-0.30.1.tar.gz", hash = "sha256:84a007aae9b707fb0aebfc9da23db4b26fc9ab562eb56e335e9ec480cb19744f", size = 106350, upload-time = "2025-09-19T10:49:26.446Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/2c/f0dc4e1ee7f618f5bff7e05898d20bf8b6e7fa612038f768bfa295f136a4/mkdocstrings-0.30.1-py3-none-any.whl", hash = "sha256:41bd71f284ca4d44a668816193e4025c950b002252081e387433656ae9a70a82", size = 36704, upload-time = "2025-09-19T10:49:24.805Z" },
+]
+
+[[package]]
+name = "mkdocstrings-python"
+version = "1.18.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "griffe" },
+ { name = "mkdocs-autorefs" },
+ { name = "mkdocstrings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/95/ae/58ab2bfbee2792e92a98b97e872f7c003deb903071f75d8d83aa55db28fa/mkdocstrings_python-1.18.2.tar.gz", hash = "sha256:4ad536920a07b6336f50d4c6d5603316fafb1172c5c882370cbbc954770ad323", size = 207972, upload-time = "2025-08-28T16:11:19.847Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d5/8f/ce008599d9adebf33ed144e7736914385e8537f5fc686fdb7cceb8c22431/mkdocstrings_python-1.18.2-py3-none-any.whl", hash = "sha256:944fe6deb8f08f33fa936d538233c4036e9f53e840994f6146e8e94eb71b600d", size = 138215, upload-time = "2025-08-28T16:11:18.176Z" },
+]
+
[[package]]
name = "mypy"
version = "1.17.0"
@@ -968,6 +1490,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
]
+[[package]]
+name = "paginate"
+version = "0.5.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252, upload-time = "2024-08-25T14:17:24.139Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" },
+]
+
[[package]]
name = "parsimonious"
version = "0.10.0"
@@ -989,6 +1520,47 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
]
+[[package]]
+name = "pillow"
+version = "10.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059, upload-time = "2024-07-01T09:48:43.583Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", size = 3509265, upload-time = "2024-07-01T09:45:49.812Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", size = 3375655, upload-time = "2024-07-01T09:45:52.462Z" },
+ { url = "https://files.pythonhosted.org/packages/73/d5/c4011a76f4207a3c151134cd22a1415741e42fa5ddecec7c0182887deb3d/pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", size = 4340304, upload-time = "2024-07-01T09:45:55.006Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/10/c67e20445a707f7a610699bba4fe050583b688d8cd2d202572b257f46600/pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", size = 4452804, upload-time = "2024-07-01T09:45:58.437Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", size = 4365126, upload-time = "2024-07-01T09:46:00.713Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", size = 4533541, upload-time = "2024-07-01T09:46:03.235Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/7c/01b8dbdca5bc6785573f4cee96e2358b0918b7b2c7b60d8b6f3abf87a070/pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", size = 4471616, upload-time = "2024-07-01T09:46:05.356Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/57/2899b82394a35a0fbfd352e290945440e3b3785655a03365c0ca8279f351/pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", size = 4600802, upload-time = "2024-07-01T09:46:08.145Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/d7/a44f193d4c26e58ee5d2d9db3d4854b2cfb5b5e08d360a5e03fe987c0086/pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", size = 2235213, upload-time = "2024-07-01T09:46:10.211Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", size = 2554498, upload-time = "2024-07-01T09:46:12.685Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/c8/310ac16ac2b97e902d9eb438688de0d961660a87703ad1561fd3dfbd2aa0/pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", size = 2243219, upload-time = "2024-07-01T09:46:14.83Z" },
+ { url = "https://files.pythonhosted.org/packages/05/cb/0353013dc30c02a8be34eb91d25e4e4cf594b59e5a55ea1128fde1e5f8ea/pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", size = 3509350, upload-time = "2024-07-01T09:46:17.177Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/cf/5c558a0f247e0bf9cec92bff9b46ae6474dd736f6d906315e60e4075f737/pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", size = 3374980, upload-time = "2024-07-01T09:46:19.169Z" },
+ { url = "https://files.pythonhosted.org/packages/84/48/6e394b86369a4eb68b8a1382c78dc092245af517385c086c5094e3b34428/pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", size = 4343799, upload-time = "2024-07-01T09:46:21.883Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/f3/a8c6c11fa84b59b9df0cd5694492da8c039a24cd159f0f6918690105c3be/pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", size = 4459973, upload-time = "2024-07-01T09:46:24.321Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/1b/c14b4197b80150fb64453585247e6fb2e1d93761fa0fa9cf63b102fde822/pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", size = 4370054, upload-time = "2024-07-01T09:46:26.825Z" },
+ { url = "https://files.pythonhosted.org/packages/55/77/40daddf677897a923d5d33329acd52a2144d54a9644f2a5422c028c6bf2d/pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", size = 4539484, upload-time = "2024-07-01T09:46:29.355Z" },
+ { url = "https://files.pythonhosted.org/packages/40/54/90de3e4256b1207300fb2b1d7168dd912a2fb4b2401e439ba23c2b2cabde/pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", size = 4477375, upload-time = "2024-07-01T09:46:31.756Z" },
+ { url = "https://files.pythonhosted.org/packages/13/24/1bfba52f44193860918ff7c93d03d95e3f8748ca1de3ceaf11157a14cf16/pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", size = 4608773, upload-time = "2024-07-01T09:46:33.73Z" },
+ { url = "https://files.pythonhosted.org/packages/55/04/5e6de6e6120451ec0c24516c41dbaf80cce1b6451f96561235ef2429da2e/pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", size = 2235690, upload-time = "2024-07-01T09:46:36.587Z" },
+ { url = "https://files.pythonhosted.org/packages/74/0a/d4ce3c44bca8635bd29a2eab5aa181b654a734a29b263ca8efe013beea98/pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", size = 2554951, upload-time = "2024-07-01T09:46:38.777Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/ca/184349ee40f2e92439be9b3502ae6cfc43ac4b50bc4fc6b3de7957563894/pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", size = 2243427, upload-time = "2024-07-01T09:46:43.15Z" },
+ { url = "https://files.pythonhosted.org/packages/c3/00/706cebe7c2c12a6318aabe5d354836f54adff7156fd9e1bd6c89f4ba0e98/pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", size = 3525685, upload-time = "2024-07-01T09:46:45.194Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/76/f658cbfa49405e5ecbfb9ba42d07074ad9792031267e782d409fd8fe7c69/pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", size = 3374883, upload-time = "2024-07-01T09:46:47.331Z" },
+ { url = "https://files.pythonhosted.org/packages/46/2b/99c28c4379a85e65378211971c0b430d9c7234b1ec4d59b2668f6299e011/pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", size = 4339837, upload-time = "2024-07-01T09:46:49.647Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/74/b1ec314f624c0c43711fdf0d8076f82d9d802afd58f1d62c2a86878e8615/pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", size = 4455562, upload-time = "2024-07-01T09:46:51.811Z" },
+ { url = "https://files.pythonhosted.org/packages/4a/2a/4b04157cb7b9c74372fa867096a1607e6fedad93a44deeff553ccd307868/pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", size = 4366761, upload-time = "2024-07-01T09:46:53.961Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/7b/8f1d815c1a6a268fe90481232c98dd0e5fa8c75e341a75f060037bd5ceae/pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", size = 4536767, upload-time = "2024-07-01T09:46:56.664Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/77/05fa64d1f45d12c22c314e7b97398ffb28ef2813a485465017b7978b3ce7/pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", size = 4477989, upload-time = "2024-07-01T09:46:58.977Z" },
+ { url = "https://files.pythonhosted.org/packages/12/63/b0397cfc2caae05c3fb2f4ed1b4fc4fc878f0243510a7a6034ca59726494/pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", size = 4610255, upload-time = "2024-07-01T09:47:01.189Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603, upload-time = "2024-07-01T09:47:03.918Z" },
+ { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972, upload-time = "2024-07-01T09:47:06.152Z" },
+ { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375, upload-time = "2024-07-01T09:47:09.065Z" },
+]
+
[[package]]
name = "platformdirs"
version = "4.3.8"
@@ -1169,6 +1741,37 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" },
]
+[[package]]
+name = "pymdown-extensions"
+version = "10.16.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/55/b3/6d2b3f149bc5413b0a29761c2c5832d8ce904a1d7f621e86616d96f505cc/pymdown_extensions-10.16.1.tar.gz", hash = "sha256:aace82bcccba3efc03e25d584e6a22d27a8e17caa3f4dd9f207e49b787aa9a91", size = 853277, upload-time = "2025-07-28T16:19:34.167Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl", hash = "sha256:d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d", size = 266178, upload-time = "2025-07-28T16:19:31.401Z" },
+]
+
+[[package]]
+name = "pyspelling"
+version = "2.11"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "beautifulsoup4" },
+ { name = "html5lib" },
+ { name = "lxml" },
+ { name = "markdown" },
+ { name = "pyyaml" },
+ { name = "soupsieve" },
+ { name = "wcmatch" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/67/94/7975a04dd17c815b45f5f75fa07a49770b5f230320672dea155ea0a3ca14/pyspelling-2.11.tar.gz", hash = "sha256:94cc6efa979c26779601ad666f8d986adf52d247b313337ad67aac7163749d0e", size = 149444, upload-time = "2025-08-27T15:37:59.626Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/53/3d/8e0b77306de02d45ce8dec40fc999c8723e4c9735c5576db0f2026c63bab/pyspelling-2.11-py3-none-any.whl", hash = "sha256:2690a233131e7d6c3a3d47b15beb1452826b3b0702d5f241a2bcbec0102f3893", size = 45362, upload-time = "2025-08-27T15:37:58.054Z" },
+]
+
[[package]]
name = "pytest"
version = "8.4.1"
@@ -1273,6 +1876,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" },
]
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
+]
+
[[package]]
name = "pyyaml"
version = "6.0.2"
@@ -1308,6 +1923,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" },
]
+[[package]]
+name = "pyyaml-env-tag"
+version = "1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/eb/2e/79c822141bfd05a853236b504869ebc6b70159afc570e1d5a20641782eaa/pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff", size = 5737, upload-time = "2025-05-13T15:24:01.64Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" },
+]
+
[[package]]
name = "pyyaml-ft"
version = "8.0.0"
@@ -1516,6 +2143,44 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/75/5f/786896acb270b7d418a62d1b639341527cfe48049f35093343b6011e992c/rust_pyspec_glue-0.0.9-py3-none-manylinux_2_34_x86_64.whl", hash = "sha256:8c059a4a35229abf4ea719e35894b7d490dfdb0f26790d2a3608511e0861c2c6", size = 493646, upload-time = "2025-01-17T16:14:31.374Z" },
]
+[[package]]
+name = "selectolax"
+version = "0.3.29"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/df/b9/b5a23e29d5e54c590eaad18bdbb1ced13b869b111e03d12ee0ae9eecf9b8/selectolax-0.3.29.tar.gz", hash = "sha256:28696fa4581765c705e15d05dfba464334f5f9bcb3eac9f25045f815aec6fbc1", size = 4691626, upload-time = "2025-04-30T15:17:37.98Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/5d/ca72f7adddae4b2b128394a7559739a6a12c156d29b55968cfcfe07fac4d/selectolax-0.3.29-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d6a1cd0518fa7656ea1683c4b2d3b5a98306753f364da9f673517847e1680a3e", size = 3649215, upload-time = "2025-04-30T15:15:59.57Z" },
+ { url = "https://files.pythonhosted.org/packages/08/c6/ca984f90b12fb10790cc56c2670f1b5f09884ed2f2012a219094b38cbcb4/selectolax-0.3.29-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e5354d805dd76b4b38002f58e6ae2e7b429ac311bf3601992a6662d2bc86911", size = 2091848, upload-time = "2025-04-30T15:16:01.73Z" },
+ { url = "https://files.pythonhosted.org/packages/98/7f/c999ae6d9bfbaac3e8dea3dbb5ca6bdf61c220828e80a6c339e89f9db777/selectolax-0.3.29-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7073e3bcdc60ebdb5f8777c79b465471ec000ab556134da4e00f037d3321a2ec", size = 5638593, upload-time = "2025-04-30T15:16:03.594Z" },
+ { url = "https://files.pythonhosted.org/packages/d6/32/ffd89376a888c24ecaf01fcffc5fe97b82ae03ab163158f51a559f1ebad5/selectolax-0.3.29-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47587db7cef411d22f8224cf2926aacdb326c4c838d386035229f16ccc2d8d26", size = 5668207, upload-time = "2025-04-30T15:16:05.564Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/5c/2de0c7b8be75ad52d44706c67946181b972f27641ab4f6a1f27f46d2a603/selectolax-0.3.29-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21de62b5093b1cb6c5d4cab0bef5f708b9ee1483b640d42be9d955becfcd287a", size = 5276654, upload-time = "2025-04-30T15:16:07.143Z" },
+ { url = "https://files.pythonhosted.org/packages/29/29/152bb745b24072d3eecd3b395c756e74763111b9bbd265604f5b96b9a1aa/selectolax-0.3.29-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:af5cd03298cd75cb0fbf712d6ae4f8aca9c13a226d2821ca82f51cc9b33b032f", size = 5543731, upload-time = "2025-04-30T15:16:09.733Z" },
+ { url = "https://files.pythonhosted.org/packages/04/1d/df65baaf16ece393f9f1a7c55f015510634adbb163ce72adcafaddf5cf9c/selectolax-0.3.29-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3f58dca53d2d3dc18dfd2cb9210a5625f32598db24e3f857f5be58f21a8f3b88", size = 5275005, upload-time = "2025-04-30T15:16:11.958Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/74/e56fd6f9b3087947b812f3862df3265bf5e21396d9673d076e999b1086cf/selectolax-0.3.29-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a6d8e02c6b9ba951d7b5a5dd2788a1d4bbdedc89782a4de165f1a87c4168ac", size = 5617441, upload-time = "2025-04-30T15:16:14.15Z" },
+ { url = "https://files.pythonhosted.org/packages/63/d6/243049029bfc937b9f02faf4a4494e693575046414a475bf28ed9632b768/selectolax-0.3.29-cp311-cp311-win32.whl", hash = "sha256:912a1fc03157ebd066d8f59ae9ca2412ef95c7101a51590327c23071b02c97c7", size = 1701370, upload-time = "2025-04-30T15:16:16.339Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/7f/baba8c5ce941c8cbd2dfb0c9f2253ba2d8c2d5d0fddda4f5a87eceb2484f/selectolax-0.3.29-cp311-cp311-win_amd64.whl", hash = "sha256:a3d44a295416b79815d2858ed4ccb71bf3b63087483a5d3705daa837c9dcf44d", size = 1808251, upload-time = "2025-04-30T15:16:18.289Z" },
+ { url = "https://files.pythonhosted.org/packages/30/ac/ca4332eecc19124782f6f0d7cb28c331da2e9d9cf25287ba2b3b6a00cea1/selectolax-0.3.29-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:6d3f373efd1db18ac9b2222de2668aaa366a1f0b560241eab128f3ca68e8add1", size = 3656166, upload-time = "2025-04-30T15:16:19.907Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/46/2dcae03a94f80f3e0d339c149de8110b5abe1230668b015fd338d9e71a27/selectolax-0.3.29-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:97b9971bb37b54ef4440134f22792d15c9ee12d890a526a7fe0b376502240143", size = 2095991, upload-time = "2025-04-30T15:16:21.654Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/bd/95f15396e5f30898227d84a7ec6a39d9a9b34005f0e9f8f38e7fee21ab66/selectolax-0.3.29-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd99ff0f5a6c017c471635d4ee45b61d25f24689331e407147b2cf5e36892480", size = 5844493, upload-time = "2025-04-30T15:16:23.268Z" },
+ { url = "https://files.pythonhosted.org/packages/36/25/64c60da9aec81f2992355b0a3ce00ea1ed99e6f5499868016d6972bd4948/selectolax-0.3.29-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8377c317bf1d5fd6ccc56dfb5a0928bbcbea3e800b7af54761cfbbb99dc94cb9", size = 5881062, upload-time = "2025-04-30T15:16:24.891Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/81/94105217f91f7c6a98ac3164210cba0c6aa8da91cb85405292a6d70e39c3/selectolax-0.3.29-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5388c56456272b2c241fc1906db9cc993984cafdad936cb5e061e3af0c44144e", size = 5470368, upload-time = "2025-04-30T15:16:26.457Z" },
+ { url = "https://files.pythonhosted.org/packages/51/6e/40bc259f13e5d3dd0bb8ddd1d55ef099244db2568ffb82fd9d489984d61a/selectolax-0.3.29-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9e4690894f406863e25ba49da27e1a6fda9bfc21b0b315c399d3093be080e81", size = 5693476, upload-time = "2025-04-30T15:16:28.386Z" },
+ { url = "https://files.pythonhosted.org/packages/58/bd/2668ee1d5471ad88daf83ca484515ba46774fc9c951d6c4c0beffea89952/selectolax-0.3.29-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:deeab93386b6c9a75052515f5b9e7e3dd623c585871c0c2b3126970ff902603b", size = 5449747, upload-time = "2025-04-30T15:16:30.626Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/b5/1c61839ae5af70a8291c643982a99f051b543df90b220b98db1b26bd4899/selectolax-0.3.29-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6abdd8357f1c105c1add01a9f0373511fa832548b2e2778b00a8ba2a4508d6ed", size = 5786843, upload-time = "2025-04-30T15:16:32.231Z" },
+ { url = "https://files.pythonhosted.org/packages/67/08/ca42c100ab90168c123e6b521e38cb7618b697a693fdb77e42dabb0670fd/selectolax-0.3.29-cp312-cp312-win32.whl", hash = "sha256:9c969626b2295702076f50aac91e44c3bba639fa2e1a612bf6ae254bf29b4d57", size = 1697859, upload-time = "2025-04-30T15:16:33.659Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/22/9524af51d950cc718bd4406f3bed05acbfcb321a4a308ec85b96ccdaa1ef/selectolax-0.3.29-cp312-cp312-win_amd64.whl", hash = "sha256:e7f4cc1b7ce9691559decfd5db7cc500e71a9f6ccfe76c054f284c184a1d1dc9", size = 1804145, upload-time = "2025-04-30T15:16:35.12Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/a7/083a00aa9cb6bef0317baba4269841c366652558d77189275bed2da6aa81/selectolax-0.3.29-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e3112f05a34bf36d36ecc51520b1d98c4667b54a3f123dffef5072273e89a360", size = 3651407, upload-time = "2025-04-30T15:16:37.282Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/cd/6c89ac27961ef5f5e9b40eda0d0653b9c95c93485fb8a554bf093eac1c77/selectolax-0.3.29-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:38462ae369897f71da287f1282079c11f1b878b99a4d1d509d1116ce05226d88", size = 2092649, upload-time = "2025-04-30T15:16:38.817Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/12/82710124b7b52613fdb9d5c14494a41785eb83e1c93ec7e1d1814c2ce292/selectolax-0.3.29-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdd1e63735f2fb8485fb6b9f4fe30d6c030930f438f46a4a62bd9886ab3c7fd9", size = 5821738, upload-time = "2025-04-30T15:16:40.747Z" },
+ { url = "https://files.pythonhosted.org/packages/8b/08/8ceb3eb7fee9743026a4481fccb771f257c82b2c853a1a30271902234eab/selectolax-0.3.29-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea52e0c128e8e89f98ab0ccaabbc853677de5730729a3351da595976131b66e0", size = 5856069, upload-time = "2025-04-30T15:16:42.496Z" },
+ { url = "https://files.pythonhosted.org/packages/47/6c/ec2b7aff0f6202e4157415d76bd588108cc518374bf53afa81c122691780/selectolax-0.3.29-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0933659b4250b91317ccd78167e6804389cdaf7ed86c5d034b058a550d23110f", size = 5443255, upload-time = "2025-04-30T15:16:44.083Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/90/d5fea46ff191d02c2380a779b119ea6799751b79fcddb2bb230b21b38fc5/selectolax-0.3.29-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0c9005e9089a6b0c6fb6a9f691ddbbb10a3a23ebeff54393980340f3dbcdb99", size = 5637529, upload-time = "2025-04-30T15:16:46.175Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/83/7f876a515f5af31f7b948cf10951be896fe6deeff2b9b713640c8ec82fd3/selectolax-0.3.29-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac940963c52f13cdf5d7266a979744949b660d367ce669efa073b557f6e09a18", size = 5379121, upload-time = "2025-04-30T15:16:47.909Z" },
+ { url = "https://files.pythonhosted.org/packages/57/cb/7dc739a484b1a17ccf92a23dfe558ae615c232bd81e78a72049c25d1ff66/selectolax-0.3.29-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:484274f73839f9a143f4c13ce1b0a0123b5d64be22f967a1dc202a9a78687d67", size = 5727944, upload-time = "2025-04-30T15:16:49.52Z" },
+ { url = "https://files.pythonhosted.org/packages/b7/09/95da4d2919d99a6090327390b84bc5440133196351e5e04c24cccda06cbb/selectolax-0.3.29-cp313-cp313-win32.whl", hash = "sha256:29e71fbd58b90d2920ef91a940680cb5331710fe397925ce9d10c3f2f086bf27", size = 1697529, upload-time = "2025-04-30T15:16:51.123Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/17/5a3951da22a4ad8f959088ddc370c68b28dad03190d91fcd137a52410fb9/selectolax-0.3.29-cp313-cp313-win_amd64.whl", hash = "sha256:e13befacff5f78102aa11465055ecb6d4b35f89663e36f271f2b506bcab14112", size = 1803334, upload-time = "2025-04-30T15:16:53.775Z" },
+]
+
[[package]]
name = "semver"
version = "3.0.4"
@@ -1525,6 +2190,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746", size = 17912, upload-time = "2025-01-24T13:19:24.949Z" },
]
+[[package]]
+name = "setuptools"
+version = "78.0.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4c/f4/aa8d364f0dc1f33b2718938648c31202e2db5cd6479a73f0a9ca5a88372d/setuptools-78.0.2.tar.gz", hash = "sha256:137525e6afb9022f019d6e884a319017f9bf879a0d8783985d32cbc8683cab93", size = 1367747, upload-time = "2025-03-24T19:50:41.896Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/aa/db/2fd473dfe436ad19fda190f4079162d400402aedfcc41e048d38c0a375c6/setuptools-78.0.2-py3-none-any.whl", hash = "sha256:4a612c80e1f1d71b80e4906ce730152e8dec23df439f82731d9d0b608d7b700d", size = 1255965, upload-time = "2025-03-24T19:50:39.943Z" },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
+]
+
[[package]]
name = "smmap"
version = "5.0.2"
@@ -1543,13 +2226,34 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" },
]
+[[package]]
+name = "soupsieve"
+version = "2.8"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6d/e6/21ccce3262dd4889aa3332e5a119a3491a95e8f60939870a3a035aabac0d/soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f", size = 103472, upload-time = "2025-08-27T15:39:51.78Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679, upload-time = "2025-08-27T15:39:50.179Z" },
+]
+
[[package]]
name = "tenacity"
-version = "8.5.0"
+version = "9.1.2"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/a3/4d/6a19536c50b849338fcbe9290d562b52cbdcf30d8963d3588a68a4107df1/tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78", size = 47309, upload-time = "2024-07-05T07:25:31.836Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687", size = 28165, upload-time = "2024-07-05T07:25:29.591Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" },
+]
+
+[[package]]
+name = "tinycss2"
+version = "1.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "webencodings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" },
]
[[package]]
@@ -1625,6 +2329,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/35/3e/0346d09d6e338401ebf406f12eaf9d0b54b315b86f1ec29e34f1a0aedae9/types_pyyaml-6.0.12.20250809-py3-none-any.whl", hash = "sha256:032b6003b798e7de1a1ddfeefee32fac6486bdfe4845e0ae0e7fb3ee4512b52f", size = 20277, upload-time = "2025-08-09T03:14:34.055Z" },
]
+[[package]]
+name = "types-requests"
+version = "2.32.4.20250913"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/36/27/489922f4505975b11de2b5ad07b4fe1dca0bca9be81a703f26c5f3acfce5/types_requests-2.32.4.20250913.tar.gz", hash = "sha256:abd6d4f9ce3a9383f269775a9835a4c24e5cd6b9f647d64f88aa4613c33def5d", size = 23113, upload-time = "2025-09-13T02:40:02.309Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658, upload-time = "2025-09-13T02:40:01.115Z" },
+]
+
[[package]]
name = "typing-extensions"
version = "4.14.1"
@@ -1660,11 +2376,20 @@ wheels = [
[[package]]
name = "urllib3"
-version = "1.26.20"
+version = "2.5.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380, upload-time = "2024-08-29T15:43:11.37Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225, upload-time = "2024-08-29T15:43:08.921Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
+]
+
+[[package]]
+name = "verspec"
+version = "0.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e7/44/8126f9f0c44319b2efc65feaad589cadef4d77ece200ae3c9133d58464d0/verspec-0.1.0.tar.gz", hash = "sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e", size = 27123, upload-time = "2020-11-30T02:24:09.646Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl", hash = "sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31", size = 19640, upload-time = "2020-11-30T02:24:08.387Z" },
]
[[package]]
@@ -1676,6 +2401,45 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a0/56/0cc15b8ff2613c1d5c3dc1f3f576ede1c43868c1bc2e5ccaa2d4bcd7974d/vulture-2.14-py2.py3-none-any.whl", hash = "sha256:d9a90dba89607489548a49d557f8bac8112bd25d3cbc8aeef23e860811bd5ed9", size = 28915, upload-time = "2024-12-08T17:39:40.573Z" },
]
+[[package]]
+name = "watchdog"
+version = "6.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" },
+ { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" },
+ { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" },
+ { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" },
+ { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" },
+ { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" },
+ { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" },
+ { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" },
+ { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" },
+ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" },
+]
+
+[[package]]
+name = "wcmatch"
+version = "10.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "bracex" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/79/3e/c0bdc27cf06f4e47680bd5803a07cb3dfd17de84cde92dd217dcb9e05253/wcmatch-10.1.tar.gz", hash = "sha256:f11f94208c8c8484a16f4f48638a85d771d9513f4ab3f37595978801cb9465af", size = 117421, upload-time = "2025-06-22T19:14:02.49Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl", hash = "sha256:5848ace7dbb0476e5e55ab63c6bbd529745089343427caa5537f230cc01beb8a", size = 39854, upload-time = "2025-06-22T19:14:00.978Z" },
+]
+
[[package]]
name = "wcwidth"
version = "0.2.13"
@@ -1684,3 +2448,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc
wheels = [
{ url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" },
]
+
+[[package]]
+name = "webencodings"
+version = "0.5.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" },
+]