Skip to content

test_modular_comparison()

Documentation for tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py::test_modular_comparison@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py::test_modular_comparison --fork Bogota

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.

Source code in tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py
@pytest.mark.parametrize(
    "input_data,expected_output",
    [
        # Test case where computed x-coordinate exceeds curve order N
        # 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(
                0x000000000000000000000000000000004319055358E8617B0C46353D039CDAAB
            )
            + S(
                0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E
            )
            # X, Y: Public key coordinates that will produce x-coordinate > N
            # during verification
            + X(
                0x0AD99500288D466940031D72A9F5445A4D43784640855BF0A69874D2DE5FE103
            )
            + Y(
                0xC5011E6EF2C42DCD50D5D3D29F99AE6EBA2C80C9244F4C5422F0979FF0C3BA5E
            ),
            Spec.SUCCESS_RETURN_VALUE,
            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
            + R(Spec.N + 1)  # R = N + 1 ≡ 1 (mod N)
            + Spec.S0
            + Spec.X0
            + Spec.Y0,
            Spec.INVALID_RETURN_VALUE,  # Should fail because R = 1 is not a
            # valid signature
            id="r_equals_n_plus_one",
        ),
        pytest.param(
            Spec.H0
            + R(Spec.N + 2)  # R = N + 2 ≡ 2 (mod N)
            + Spec.S0
            + Spec.X0
            + Spec.Y0,
            Spec.INVALID_RETURN_VALUE,  # Should fail because R = 2 is not a
            # valid signature
            id="r_equals_n_plus_two",
        ),
    ],
)
@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""])
@EIPChecklist.Precompile.Test.Inputs.Valid()
@EIPChecklist.Precompile.Test.Inputs.Invalid.Crypto()
def test_modular_comparison(
    state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction
) -> None:
    """
    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.
    """
    state_test(env=Environment(), pre=pre, post=post, tx=tx)

Parametrized Test Cases

This test generates 5 parametrized test cases across 3 forks.