Skip to content

Commit

Permalink
Add G1 hash to curve precompile
Browse files Browse the repository at this point in the history
  • Loading branch information
petertdavies authored and gurukamath committed Aug 2, 2024
1 parent c127505 commit 3d27159
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 1 deletion.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ install_requires =
pycryptodome>=3,<4
coincurve>=18,<19
typing_extensions>=4
py_ecc>=7,<8
py_ecc @ git+https://github.com/petertdavies/py_ecc.git@127184f4c57b1812da959586d0fe8f43bb1a2389

[options.package_data]
ethereum =
Expand Down
2 changes: 2 additions & 0 deletions src/ethereum/prague/vm/precompiled_contracts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"BLS12_G2_MULTIPLY_ADDRESS",
"BLS12_G2_MSM_ADDRESS",
"BLS12_PAIRING_ADDRESS",
"BLS12_MAP_FP_TO_G1_ADDRESS",
"BLS12_MAP_FP2_TO_G2_ADDRESS",
)

Expand All @@ -53,4 +54,5 @@
BLS12_G2_MULTIPLY_ADDRESS = hex_to_address("0x0f")
BLS12_G2_MSM_ADDRESS = hex_to_address("0x10")
BLS12_PAIRING_ADDRESS = hex_to_address("0x11")
BLS12_MAP_FP_TO_G1_ADDRESS = hex_to_address("0x12")
BLS12_MAP_FP2_TO_G2_ADDRESS = hex_to_address("0x13")
36 changes: 36 additions & 0 deletions src/ethereum/prague/vm/precompiled_contracts/bls12_381/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
is_on_curve,
multiply,
)
from py_ecc.optimized_bls12_381.optimized_curve import FQ as OPTIMIZED_FQ
from py_ecc.optimized_bls12_381.optimized_curve import FQ2 as OPTIMIZED_FQ2
from py_ecc.typing import Point2D

Expand Down Expand Up @@ -262,6 +263,41 @@ def decode_G1_scalar_pair(data: Bytes) -> Tuple[Point2D, int]:
return p, m


def bytes_to_FQ(
data: Bytes, optimized: bool = False
) -> Union[FQ2, OPTIMIZED_FQ2]:
"""
Decode 64 bytes to a FQ2 element.
Parameters
----------
data :
The bytes data to decode.
optimized :
Whether to use the optimized FQ2 implementation.
Returns
-------
fq : FQ
The FQ2 element.
Raises
------
InvalidParameter
If the field element is invalid.
"""
assert len(data) == 64
c = int.from_bytes(data[:64], "big")

if c >= P:
raise InvalidParameter("Invalid field element")

if optimized:
return OPTIMIZED_FQ(c)
else:
return FQ(c)


def bytes_to_FQ2(
data: Bytes, optimized: bool = False
) -> Union[FQ2, OPTIMIZED_FQ2]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
Implementation of pre-compiles in G1 (curve over base prime field).
"""
from py_ecc.bls12_381.bls12_381_curve import add, multiply
from py_ecc.bls.hash_to_curve import clear_cofactor_G1, map_to_curve_G1
from py_ecc.optimized_bls12_381.optimized_curve import FQ as OPTIMIZED_FQ
from py_ecc.optimized_bls12_381.optimized_curve import normalize

from ethereum.base_types import U256, Uint

Expand All @@ -24,6 +27,7 @@
MAX_DISCOUNT,
MULTIPLIER,
G1_to_bytes,
bytes_to_FQ,
bytes_to_G1,
decode_G1_scalar_pair,
)
Expand Down Expand Up @@ -135,3 +139,34 @@ def bls12_g1_msm(evm: Evm) -> None:
result = add(result, product)

evm.output = G1_to_bytes(result)


def bls12_map_fp_to_g1(evm: Evm) -> None:
"""
Precompile to map field element to G1.
Parameters
----------
evm :
The current EVM frame.
Raises
------
InvalidParameter
If the input length is invalid.
"""
data = evm.message.data
if len(data) != 64:
raise InvalidParameter("Invalid Input Length")

# GAS
charge_gas(evm, Uint(5500))

# OPERATION
field_element = bytes_to_FQ(data, True)
assert isinstance(field_element, OPTIMIZED_FQ)

g1_uncompressed = clear_cofactor_G1(map_to_curve_G1(field_element))
g1_normalised = normalize(g1_uncompressed)

evm.output = G1_to_bytes(g1_normalised)
3 changes: 3 additions & 0 deletions src/ethereum/prague/vm/precompiled_contracts/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
BLS12_G2_MSM_ADDRESS,
BLS12_G2_MULTIPLY_ADDRESS,
BLS12_MAP_FP2_TO_G2_ADDRESS,
BLS12_MAP_FP_TO_G1_ADDRESS,
BLS12_PAIRING_ADDRESS,
ECRECOVER_ADDRESS,
IDENTITY_ADDRESS,
Expand All @@ -40,6 +41,7 @@
bls12_g1_add,
bls12_g1_msm,
bls12_g1_multiply,
bls12_map_fp_to_g1,
)
from .bls12_381.bls12_381_g2 import (
bls12_g2_add,
Expand Down Expand Up @@ -73,5 +75,6 @@
BLS12_G2_MULTIPLY_ADDRESS: bls12_g2_multiply,
BLS12_G2_MSM_ADDRESS: bls12_g2_msm,
BLS12_PAIRING_ADDRESS: bls12_pairing,
BLS12_MAP_FP_TO_G1_ADDRESS: bls12_map_fp_to_g1,
BLS12_MAP_FP2_TO_G2_ADDRESS: bls12_map_fp2_to_g2,
}
1 change: 1 addition & 0 deletions tests/prague/test_state_transition.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def test_general_state_tests(test_case: Dict) -> None:
"tests/fixtures/latest_fork_tests/fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/bls12_pairing",
"tests/fixtures/latest_fork_tests/fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/bls12_g1msm",
"tests/fixtures/latest_fork_tests/fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/bls12_g2msm",
"tests/fixtures/latest_fork_tests/fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/bls12_map_fp_to_g1",
"tests/fixtures/latest_fork_tests/fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/bls12_map_fp2_to_g2",
)

Expand Down
1 change: 1 addition & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ coeffs
b2
FQ12

FP
FP2
cofactor

Expand Down

0 comments on commit 3d27159

Please sign in to comment.