Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
63 changes: 63 additions & 0 deletions tests/osaka/eip7883_modexp_gas_increase/test_eip_mainnet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
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).
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we make it clear in the docstring that these are specifically for mainnet execute use only (fill is a sanity check).

Suggested change
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).
Mainnet Marked Checklist Tests for ModExp gas cost increase in
[EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883).

"""

from typing import Dict

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

from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput
from .spec import ref_spec_7883

REFERENCE_SPEC_GIT_PATH = ref_spec_7883.git_path
REFERENCE_SPEC_VERSION = ref_spec_7883.version


@pytest.mark.parametrize(
"modexp_input,modexp_expected",
[
pytest.param(
ModExpInput(
base="ff" * 31 + "fc",
exponent="02",
modulus="05",
declared_base_length=32,
declared_exponent_length=1,
declared_modulus_length=1,
),
bytes([4]),
id="32-bytes-long-base",
),
pytest.param(
ModExpInput(
base="ff" * 32 + "fb",
exponent="02",
modulus="05",
declared_base_length=33,
declared_exponent_length=1,
declared_modulus_length=1,
),
bytes([1]),
id="33-bytes-long-base", # higher cost than 32 bytes
Comment on lines 42 to 53
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should remove this test and add 1/2 extras. These both currently test the minimum gas cost increase of 200 to 500 from the EIP.

  1. If we add nagydani-1-pow0x10001 from here we additionally check that the 2x complexity multiplier works, if max_length > 32: multiplication_complexity = 2 * words**2, from the spec.

  2. If we add zero-exponent-64bytes from here we additionally test the 16x exponent multiplaction works, iteration_count = (16 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1), from the spec.

Please see below for modexp equation snippets:
https://eips.ethereum.org/EIPS/eip-7883#specification

They shouldn't cost too much more.

Copy link
Contributor Author

@felix314159 felix314159 Nov 25, 2025

Choose a reason for hiding this comment

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

The link you have put shows that these two test do NOT both test the same thing. The 32 bytes base test is cheaper than the 33 bytes test. If you remove one of them you lose coverage of that case. But I agree that we can add another test we an even larger number, e.g. the two cases u mentioned

),
],
)
@pytest.mark.valid_at("Osaka")
Copy link
Contributor

Choose a reason for hiding this comment

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

We should mark these tests as mainnet only like we do in: https://github.com/ethereum/execution-spec-tests/pull/1511/files#diff-a9add5727efb38c476ff59942c2a0732eb1f9dde4958dd3b573a36fe3444bf05R15

Suggested change
@pytest.mark.valid_at("Osaka")
@pytest.mark.valid_at("Osaka")
@pytest.mark.mainnet

We only want to fill/execute these specifically for mainnet validation.

def test_modexp_different_base_lengths(
state_test: StateTestFiller,
pre: Alloc,
tx: Transaction,
post: Dict,
modexp_input: ModExpInput,
modexp_expected: ModExpInput,
) -> None:
"""Mainnet test for triggering gas cost increase."""
state_test(pre=pre, tx=tx, post=post)
91 changes: 91 additions & 0 deletions tests/osaka/eip7951_p256verify_precompiles/test_eip_mainnet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"""
Tests for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951).
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar here:

Suggested change
Tests for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951).
Mainnet Marked Checklist Tests for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951).

"""

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

from .spec import H, R, S, Spec, X, Y, ref_spec_7951

REFERENCE_SPEC_GIT_PATH = ref_spec_7951.git_path
REFERENCE_SPEC_VERSION = ref_spec_7951.version


Copy link
Contributor

Choose a reason for hiding this comment

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

If we add this here we can remove Osaka mark's below.

Suggested change
pytestmark = [pytest.mark.valid_at("Osaka"), pytest.mark.mainnet]

@pytest.mark.parametrize(
"expected_output", [Spec.SUCCESS_RETURN_VALUE], ids=[""]
)
@pytest.mark.parametrize(
"input_data",
[
pytest.param(
H( # 'hello world' r1 signed with privkey 0xd946578401d1980aba1fc85df2a1ddc0d2d618aadd37b213f7f7f91a553b1499 # noqa: E501
0xB94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9
)
+ R(
0x434287FA699FF2BE2A4475CCD9C063D1A22A424B6AB357D9BB0B31F7A71307B9
)
+ S(
0xBE6AF716032D408183C53F6F76945363144555FAD2A5FF7854159166E52FC1D0
)
+ X(
0xDA3C553A4215893E6D95D5818DF2519E13233A1E0E56E0EA7B4817A92A6973F9
)
+ Y(
0xD8C8877A49383E20C3FDC21D4E8E280EF1FEEB72C333036770369A4387168D33
),
id="valid_r1_sig",
),
],
)
@pytest.mark.valid_at("Osaka")
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
@pytest.mark.valid_at("Osaka")

@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""])
def test_valid(
state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction
) -> None:
"""Positive mainnet test for the P256VERIFY precompile."""
state_test(env=Environment(), pre=pre, post=post, tx=tx)


@pytest.mark.parametrize(
"expected_output", [Spec.INVALID_RETURN_VALUE], ids=[""]
)
@pytest.mark.parametrize(
"input_data",
[
pytest.param(
H( # 'hello world' k1 signed (with eth prefix) with privkey 0xd946578401d1980aba1fc85df2a1ddc0d2d618aadd37b213f7f7f91a553b1499 # noqa: E501
0xD9EBA16ED0ECAE432B71FE008C98CC872BB4CC214D3220A36F365326CF807D68
)
+ R(
0x69CCCD84CA870C08D49D596342F464017F2A05B0BE539682EAA7529E4BE2DE36
)
+ S(
0x2CDB85FE13CB7DE39C1C7385BE9F38E8BDE9963CCBECD96281C4DF3ACA38F537
)
+ X(
0x82AE98A95AE76E389354F0EC660CF071309EA2D2CB14ADB6543106B790BE27FD
)
+ Y(
0x77B2CDC82C3AA8F2CF21E6257C197D75F84DCD0BC2FF8875C3E245C0E0874751
),
id="invalid_r1_sig_but_valid_k1_sig",
),
],
)
@pytest.mark.valid_at("Osaka")
@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""])
def test_invalid(
state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction
) -> None:
"""
Negative mainnet test for the P256VERIFY precompile.

The signature actually is a valid secp256k1 signature,
so this is an interesting test case.
"""
state_test(env=Environment(), pre=pre, post=post, tx=tx)
Comment on lines +82 to +91
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice. My understanding is that this is a valid tx but with an invalid signature?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it is a valid ecdsa signature over a different curve, so the signature verification is expected to fail (but this is a good test because the other curve is also used by clients)

Loading