Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions tests/byzantium/eip196_ec_add_mul/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Shared pytest definitions local to EIP-196 tests."""

import pytest
from execution_testing import (
Address,
Fork,
)

from ...common.precompile_fixtures import (
call_contract_address, # noqa: F401
call_contract_code, # noqa: F401
call_contract_post_storage, # noqa: F401
call_opcode, # noqa: F401
call_succeeds, # noqa: F401
post, # noqa: F401
precompile_gas_modifier, # noqa: F401
sender, # noqa: F401
tx, # noqa: F401
tx_gas_limit, # noqa: F401
)
from .spec import Spec


@pytest.fixture
def precompile_gas(precompile_address: Address, fork: Fork) -> int:
"""Gas cost for the precompile."""
gas_costs = fork.gas_costs()
match precompile_address:
case Spec.ECADD:
return gas_costs.G_PRECOMPILE_ECADD
case Spec.ECMUL:
return gas_costs.G_PRECOMPILE_ECMUL
case _:
raise ValueError(
f"Unexpected precompile address: {precompile_address}"
)
52 changes: 52 additions & 0 deletions tests/byzantium/eip196_ec_add_mul/spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Defines EIP-196 specification constants and functions."""

from dataclasses import dataclass

from execution_testing import Address, BytesConcatenation

from ...constantinople.eip145_bitwise_shift.spec import ReferenceSpec

ref_spec_196 = ReferenceSpec(
"EIPS/eip-196.md", "6538d198b1db10784ddccd6931888d7ae718de75"
)


@dataclass(frozen=True)
class FP(BytesConcatenation):
"""Dataclass that defines an element of the BN254 Prime Field (Fp)."""

x: int = 0

def __bytes__(self) -> bytes:
"""Convert field element to bytes."""
return self.x.to_bytes(32, byteorder="big")


@dataclass(frozen=True)
class PointG1(BytesConcatenation):
"""Dataclass that defines an affine point in the BN254 E(Fp) group (G1)."""

x: int = 0
y: int = 0

def __bytes__(self) -> bytes:
"""Convert point to bytes."""
return FP(self.x) + FP(self.y)


@dataclass(frozen=True)
class Spec:
"""
Parameters from the EIP-196 specification (https://eips.ethereum.org/EIPS/eip-196)
with some modifications for readability.
"""

# Addresses
ECADD = Address(0x06)
ECMUL = Address(0x07)

# G1 generator point
G1 = PointG1(1, 2)

# The point at infinity in G1
INF_G1 = PointG1()
69 changes: 69 additions & 0 deletions tests/byzantium/eip196_ec_add_mul/test_ecadd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Tests the ecadd precompiled contract."""

import pytest
from execution_testing import (
Alloc,
Environment,
StateTestFiller,
Transaction,
)

from .spec import PointG1, Spec, ref_spec_196

REFERENCE_SPEC_GIT_PATH = ref_spec_196.git_path
REFERENCE_SPEC_VERSION = ref_spec_196.version

pytestmark = [
pytest.mark.valid_from("Byzantium"),
pytest.mark.parametrize("precompile_address", [Spec.ECADD], ids=["ecadd"]),
]


@pytest.mark.parametrize(
"input_data, expected_output",
[
pytest.param(
Spec.G1 + Spec.INF_G1,
Spec.G1,
id="generator_plus_inf",
),
],
)
def test_valid(
state_test: StateTestFiller,
pre: Alloc,
post: dict,
tx: Transaction,
) -> None:
"""Test the valid inputs to the ECADD precompile."""
state_test(
env=Environment(),
pre=pre,
tx=tx,
post=post,
)


@pytest.mark.parametrize(
"input_data, expected_output",
[
pytest.param(
PointG1(1, 1) + Spec.INF_G1,
b"",
id="pt_1_1_plus_inf",
),
],
)
def test_invalid(
state_test: StateTestFiller,
pre: Alloc,
post: dict,
tx: Transaction,
) -> None:
"""Test the invalid inputs to the ECADD precompile."""
state_test(
env=Environment(),
pre=pre,
tx=tx,
post=post,
)
15 changes: 7 additions & 8 deletions tests/byzantium/eip196_ec_add_mul/test_gas.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,27 @@
import pytest
from execution_testing import (
Account,
Address,
Alloc,
StateTestFiller,
Transaction,
)
from execution_testing.base_types.base_types import Address
from execution_testing.forks import Byzantium
from execution_testing.forks.helpers import Fork
from execution_testing.vm import Opcodes as Op

REFERENCE_SPEC_GIT_PATH = "EIPS/eip-196.md"
REFERENCE_SPEC_VERSION = "6538d198b1db10784ddccd6931888d7ae718de75"
from .spec import Spec, ref_spec_196

EC_ADD_ADDRESS = Address(0x06)
EC_MUL_ADDRESS = Address(0x07)
REFERENCE_SPEC_GIT_PATH = ref_spec_196.git_path
REFERENCE_SPEC_VERSION = ref_spec_196.version


@pytest.mark.valid_from("Byzantium")
@pytest.mark.parametrize(
"address",
[
pytest.param(EC_ADD_ADDRESS, id="ecadd"),
pytest.param(EC_MUL_ADDRESS, id="ecmul"),
pytest.param(Spec.ECADD, id="ecadd"),
pytest.param(Spec.ECMUL, id="ecmul"),
],
)
@pytest.mark.parametrize("enough_gas", [True, False])
Expand All @@ -42,7 +41,7 @@ def test_gas_costs(
gas_costs = fork.gas_costs()
gas = (
gas_costs.G_PRECOMPILE_ECADD
if address == EC_ADD_ADDRESS
if address == Spec.ECADD
else gas_costs.G_PRECOMPILE_ECMUL
)
if not enough_gas:
Expand Down
Loading
Loading