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
Empty file.
38 changes: 38 additions & 0 deletions tests/core/pyspec/eth2spec/test/altair/bls/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
###############################################################################
# Precomputed constants
###############################################################################


def _hex_to_int(x: str) -> int:
return int(x, 16)


MESSAGES = [
bytes(b"\x00" * 32),
bytes(b"\x56" * 32),
bytes(b"\xab" * 32),
]
SAMPLE_MESSAGE = b"\x12" * 32

PRIVKEYS = [
# Curve order is 256, so private keys use 32 bytes at most.
# Also, not all integers are valid private keys. Therefore, using pre-generated keys.
_hex_to_int(
"0x00000000000000000000000000000000263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3"
),
_hex_to_int(
"0x0000000000000000000000000000000047b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138"
),
_hex_to_int(
"0x00000000000000000000000000000000328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216"
),
]

ZERO_PUBKEY = b"\x00" * 48
G1_POINT_AT_INFINITY = b"\xc0" + b"\x00" * 47

ZERO_SIGNATURE = b"\x00" * 96
G2_POINT_AT_INFINITY = b"\xc0" + b"\x00" * 95

ZERO_PRIVKEY = 0
ZERO_PRIVKEY_BYTES = b"\x00" * 32
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import milagro_bls_binding as milagro_bls
import pytest
from eth_utils import encode_hex

from eth2spec.test.context import only_generator, single_phase, spec_test, with_phases
from eth2spec.test.helpers.constants import ALTAIR
from eth2spec.utils import bls
from tests.infra.manifest import manifest
from tests.infra.template_test import template_test

from .constants import G1_POINT_AT_INFINITY, PRIVKEYS, ZERO_PUBKEY


def _run_eth_aggregate_pubkeys_valid(spec, pubkeys):
aggregate_pubkey = spec.eth_aggregate_pubkeys(pubkeys)

assert aggregate_pubkey == milagro_bls._AggregatePKs(pubkeys)

yield (
"data",
"data",
{
"input": [encode_hex(pubkey) for pubkey in pubkeys],
"output": (encode_hex(aggregate_pubkey)),
},
)


def _run_eth_aggregate_pubkeys_invalid(spec, pubkeys):
with pytest.raises(Exception):
spec.eth_aggregate_pubkeys(pubkeys)

with pytest.raises(Exception):
milagro_bls._AggregatePKs(pubkeys)

yield (
"data",
"data",
{
"input": [encode_hex(pubkey) for pubkey in pubkeys],
"output": (None),
},
)


@template_test
def _template_eth_aggregate_pubkeys_valid(privkey_index: int):
privkey = PRIVKEYS[privkey_index]

@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def the_test(spec):
yield from _run_eth_aggregate_pubkeys_valid(spec, [bls.SkToPk(privkey)])

return (the_test, f"test_eth_aggregate_pubkeys_valid_{privkey_index}")


for privkey_index in range(len(PRIVKEYS)):
_template_eth_aggregate_pubkeys_valid(privkey_index)


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_aggregate_pubkeys_valid_pubkeys(spec):
pubkeys = [bls.SkToPk(privkey) for privkey in PRIVKEYS]
yield from _run_eth_aggregate_pubkeys_valid(spec, pubkeys)


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_aggregate_pubkeys_empty_list(spec):
yield from _run_eth_aggregate_pubkeys_invalid(spec, [])


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_aggregate_pubkeys_zero_pubkey(spec):
yield from _run_eth_aggregate_pubkeys_invalid(spec, [ZERO_PUBKEY])


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_aggregate_pubkeys_infinity_pubkey(spec):
yield from _run_eth_aggregate_pubkeys_invalid(spec, [G1_POINT_AT_INFINITY])


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_aggregate_pubkeys_x40_pubkey(spec):
yield from _run_eth_aggregate_pubkeys_invalid(spec, [b"\x40" + b"\x00" * 47])
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
from eth_utils import encode_hex

from eth2spec.test.context import only_generator, single_phase, spec_test, with_phases
from eth2spec.test.helpers.constants import ALTAIR
from eth2spec.utils import bls
from tests.infra.manifest import manifest
from tests.infra.template_test import template_test

from .constants import (
G1_POINT_AT_INFINITY,
G2_POINT_AT_INFINITY,
MESSAGES,
PRIVKEYS,
SAMPLE_MESSAGE,
ZERO_SIGNATURE,
)


def _run_eth_fast_aggregate_verify(spec, pubkeys, message, aggregate_signature, expected_result):
result = spec.eth_fast_aggregate_verify(pubkeys, message, aggregate_signature)

assert result == expected_result

yield (
"data",
"data",
{
"input": {
"pubkeys": [encode_hex(pubkey) for pubkey in pubkeys],
"message": encode_hex(message),
"signature": encode_hex(aggregate_signature),
},
"output": result,
},
)


@template_test
def _template_eth_fast_aggregate_verify_valid(message_index: int):
message = MESSAGES[message_index]
privkeys = PRIVKEYS[: message_index + 1]

@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def the_test(spec):
sigs = [bls.Sign(privkey, message) for privkey in privkeys]
aggregate_signature = bls.Aggregate(sigs)
pubkeys = [bls.SkToPk(privkey) for privkey in privkeys]
yield from _run_eth_fast_aggregate_verify(
spec, pubkeys, message, aggregate_signature, expected_result=True
)

return (the_test, f"test_eth_fast_aggregate_verify_valid_{message_index}")


for message_index in range(len(MESSAGES)):
_template_eth_fast_aggregate_verify_valid(message_index)


@template_test
def _template_eth_fast_aggregate_verify_extra_pubkey(message_index: int):
message = MESSAGES[message_index]
privkeys = PRIVKEYS[: message_index + 1]

@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def the_test(spec):
sigs = [bls.Sign(privkey, message) for privkey in privkeys]
aggregate_signature = bls.Aggregate(sigs)
# Add an extra pubkey to the end
pubkeys = [bls.SkToPk(privkey) for privkey in privkeys] + [bls.SkToPk(PRIVKEYS[-1])]
yield from _run_eth_fast_aggregate_verify(
spec, pubkeys, message, aggregate_signature, expected_result=False
)

return (the_test, f"test_eth_fast_aggregate_verify_extra_pubkey_{message_index}")


for message_index in range(len(MESSAGES)):
_template_eth_fast_aggregate_verify_extra_pubkey(message_index)


@template_test
def _template_eth_fast_aggregate_verify_tampered_signature(message_index: int):
message = MESSAGES[message_index]
privkeys = PRIVKEYS[: message_index + 1]

@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def the_test(spec):
sigs = [bls.Sign(privkey, message) for privkey in privkeys]
aggregate_signature = bls.Aggregate(sigs)
pubkeys = [bls.SkToPk(privkey) for privkey in privkeys]
# Tamper with the signature
tampered_signature = aggregate_signature[:-4] + b"\xff\xff\xff\xff"
yield from _run_eth_fast_aggregate_verify(
spec, pubkeys, message, tampered_signature, expected_result=False
)

return (the_test, f"test_eth_fast_aggregate_verify_tampered_signature_{message_index}")


for message_index in range(len(MESSAGES)):
_template_eth_fast_aggregate_verify_tampered_signature(message_index)


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_fast_aggregate_verify_na_pubkeys_and_infinity_signature(spec):
# NOTE: Unlike `FastAggregateVerify`, len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY is VALID
yield from _run_eth_fast_aggregate_verify(
spec, [], MESSAGES[-1], G2_POINT_AT_INFINITY, expected_result=True
)


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_fast_aggregate_verify_na_pubkeys_and_zero_signature(spec):
yield from _run_eth_fast_aggregate_verify(
spec, [], MESSAGES[-1], ZERO_SIGNATURE, expected_result=False
)


@manifest(preset_name="general", suite_name="bls")
@only_generator("too slow")
@with_phases([ALTAIR])
@spec_test
@single_phase
def test_eth_fast_aggregate_verify_infinity_pubkey(spec):
pubkeys = [bls.SkToPk(privkey) for privkey in PRIVKEYS]
pubkeys_with_infinity = pubkeys + [G1_POINT_AT_INFINITY]
signatures = [bls.Sign(privkey, SAMPLE_MESSAGE) for privkey in PRIVKEYS]
aggregate_signature = bls.Aggregate(signatures)
yield from _run_eth_fast_aggregate_verify(
spec, pubkeys_with_infinity, SAMPLE_MESSAGE, aggregate_signature, expected_result=False
)
Loading