@pytest.mark.parametrize(
"input_data,expected_output,vector_gas_value",
# 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.
pytest.param(
Spec.G1 + Spec.INF_G1,
Spec.G1,
None,
id="generator_plus_inf",
),
pytest.param(
Spec.INF_G1 + Spec.G1,
Spec.G1,
None,
id="inf_plus_generator",
),
pytest.param(
Spec.INF_G1 + Spec.INF_G1,
Spec.INF_G1,
None,
id="inf_plus_inf",
),
pytest.param(
Spec.INF_G1 + Spec.P1,
Spec.P1,
None,
id="inf_plus_point",
),
# Basic arithmetic properties test cases.
# Checks fundamental properties of the BLS12-381 curve.
pytest.param(
Spec.P1 + (-Spec.P1),
Spec.INF_G1,
None,
id="point_plus_neg_point",
),
pytest.param(
Spec.G1 + (-Spec.G1),
Spec.INF_G1,
None,
id="generator_plus_neg_point",
),
pytest.param(
Spec.P1 + Spec.G1,
add_points_g1(Spec.G1, Spec.P1),
None,
id="commutative_check_a",
),
pytest.param(
Spec.G1 + Spec.P1,
add_points_g1(Spec.P1, Spec.G1),
None,
id="commutative_check_b",
),
pytest.param(
Spec.P1 + Spec.P1,
add_points_g1(Spec.P1, Spec.P1),
None,
id="point_doubling",
),
pytest.param( # (P + G) + P = P + (G + P)
add_points_g1(Spec.P1, Spec.G1) + Spec.P1,
add_points_g1(Spec.P1, add_points_g1(Spec.G1, Spec.P1)),
None,
id="associativity_check",
),
pytest.param( # -(P+G) = (-P)+(-G)
(-(add_points_g1(Spec.P1, Spec.G1))) + Spec.INF_G1,
add_points_g1((-Spec.P1), (-Spec.G1)),
None,
id="negation_of_sum",
),
pytest.param(
add_points_g1(Spec.G1, Spec.G1) + add_points_g1(Spec.P1, Spec.P1),
add_points_g1(
add_points_g1(Spec.G1, Spec.G1),
add_points_g1(Spec.P1, Spec.P1),
),
None,
id="double_generator_plus_double_point",
),
pytest.param(
add_points_g1(Spec.G1, Spec.G1) + add_points_g1(Spec.G1, Spec.G1),
add_points_g1(
add_points_g1(Spec.G1, Spec.G1),
add_points_g1(Spec.G1, Spec.G1),
),
None,
id="double_generator_plus_double_generator",
),
pytest.param( # (x,y) + (x,-y) = INF
PointG1(Spec.P1.x, Spec.P1.y)
+ PointG1(Spec.P1.x, Spec.P - Spec.P1.y),
Spec.INF_G1,
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.
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.
Spec.P1_NOT_IN_SUBGROUP + Spec.P1_NOT_IN_SUBGROUP_TIMES_2,
Spec.INF_G1,
None,
id="non_sub_order_3_to_inf",
),
pytest.param(
Spec.P1_NOT_IN_SUBGROUP + Spec.INF_G1,
Spec.P1_NOT_IN_SUBGROUP,
None,
id="non_sub_plus_inf",
),
pytest.param(
Spec.G1 + Spec.P1_NOT_IN_SUBGROUP,
add_points_g1(Spec.G1, Spec.P1_NOT_IN_SUBGROUP),
None,
id="generator_plus_non_sub",
),
pytest.param(
Spec.P1_NOT_IN_SUBGROUP + (-Spec.P1_NOT_IN_SUBGROUP),
Spec.INF_G1,
None,
id="non_sub_plus_neg_non_sub",
),
pytest.param(
Spec.P1 + Spec.P1_NOT_IN_SUBGROUP,
add_points_g1(Spec.P1, Spec.P1_NOT_IN_SUBGROUP),
None,
id="in_sub_plus_non_sub",
),
pytest.param(
Spec.P1_NOT_IN_SUBGROUP_TIMES_2 + Spec.P1,
add_points_g1(Spec.P1_NOT_IN_SUBGROUP_TIMES_2, Spec.P1),
None,
id="doubled_non_sub_plus_in_sub",
),
pytest.param(
Spec.P1_NOT_IN_SUBGROUP_TIMES_2 + (-Spec.P1_NOT_IN_SUBGROUP),
Spec.P1_NOT_IN_SUBGROUP,
None,
id="doubled_non_sub_plus_neg",
),
# 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),
None,
id="rand_not_in_subgroup_0_plus_point",
),
pytest.param(
G1_POINTS_NOT_IN_SUBGROUP[1] + Spec.G1,
add_points_g1(G1_POINTS_NOT_IN_SUBGROUP[1], Spec.G1),
None,
id="rand_not_in_subgroup_1_plus_generator",
),
pytest.param(
G1_POINTS_NOT_IN_SUBGROUP[2] + Spec.INF_G1,
G1_POINTS_NOT_IN_SUBGROUP[2],
None,
id="rand_not_in_subgroup_2_plus_inf",
),
pytest.param(
G1_POINTS_NOT_IN_SUBGROUP[3] + (-G1_POINTS_NOT_IN_SUBGROUP[3]),
Spec.INF_G1,
None,
id="rand_not_in_subgroup_3_plus_neg_self",
),
pytest.param(
G1_POINTS_NOT_IN_SUBGROUP[4] + G1_POINTS_NOT_IN_SUBGROUP[0],
add_points_g1(
G1_POINTS_NOT_IN_SUBGROUP[4], G1_POINTS_NOT_IN_SUBGROUP[0]
),
None,
id="rand_not_in_subgroup_4_plus_0",
),
],
)
def test_valid(
state_test: StateTestFiller,
pre: Alloc,
post: dict,
tx: Transaction,
) -> None:
"""Test the BLS12_G1ADD precompile."""
state_test(
env=Environment(),
pre=pre,
tx=tx,
post=post,
)