Merge pull request #1803 from ethereum/fast-bls-option

BLS options for pyspec
This commit is contained in:
Danny Ryan 2020-05-20 14:39:49 -06:00 committed by GitHub
commit 7770accf96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 106 additions and 33 deletions

View File

@ -75,15 +75,15 @@ install_test:
test: pyspec test: pyspec
. venv/bin/activate; cd $(PY_SPEC_DIR); \ . venv/bin/activate; cd $(PY_SPEC_DIR); \
python -m pytest -n 4 --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec python -m pytest -n 4 --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
find_test: pyspec find_test: pyspec
. venv/bin/activate; cd $(PY_SPEC_DIR); \ . venv/bin/activate; cd $(PY_SPEC_DIR); \
python -m pytest -k=$(K) --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec python -m pytest -k=$(K) --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
citest: pyspec citest: pyspec
mkdir -p tests/core/pyspec/test-reports/eth2spec; . venv/bin/activate; cd $(PY_SPEC_DIR); \ mkdir -p tests/core/pyspec/test-reports/eth2spec; . venv/bin/activate; cd $(PY_SPEC_DIR); \
python -m pytest -n 4 --junitxml=eth2spec/test_results.xml eth2spec python -m pytest -n 4 --disable-bls --junitxml=eth2spec/test_results.xml eth2spec
open_cov: open_cov:
((open "$(COV_INDEX_FILE)" || xdg-open "$(COV_INDEX_FILE)") &> /dev/null) & ((open "$(COV_INDEX_FILE)" || xdg-open "$(COV_INDEX_FILE)") &> /dev/null) &

View File

@ -485,6 +485,7 @@ setup(
url="https://github.com/ethereum/eth2.0-specs", url="https://github.com/ethereum/eth2.0-specs",
include_package_data=False, include_package_data=False,
package_data={'configs': ['*.yaml'], package_data={'configs': ['*.yaml'],
'specs': ['**/*.md'], 'specs': ['**/*.md'],
'eth2spec': ['VERSION.txt']}, 'eth2spec': ['VERSION.txt']},
package_dir={ package_dir={
@ -505,6 +506,7 @@ setup(
"eth-typing>=2.1.0,<3.0.0", "eth-typing>=2.1.0,<3.0.0",
"pycryptodome==3.9.4", "pycryptodome==3.9.4",
"py_ecc==4.0.0", "py_ecc==4.0.0",
"milagro_bls_binding==1.3.0",
"dataclasses==0.6", "dataclasses==0.6",
"remerkleable==0.1.16", "remerkleable==0.1.16",
"ruamel.yaml==0.16.5", "ruamel.yaml==0.16.5",

View File

@ -55,6 +55,11 @@ Run the test command from the `tests/core/pyspec` directory:
pytest --config=minimal eth2spec pytest --config=minimal eth2spec
``` ```
Options:
- `--config`, to change the config. Defaults to `minimal`, can be set to `mainnet`, or other configs from the configs directory.
- `--disable-bls`, to disable BLS (only for tests that can run without)
- `--bls-type`, `milagro` or `py_ecc` (default)
### How to view code coverage report ### How to view code coverage report
Run `make open_cov` from the root of the specs repository after running `make test` to open the html code coverage report. Run `make open_cov` from the root of the specs repository after running `make test` to open the html code coverage report.

View File

@ -1,6 +1,6 @@
from eth2spec.config import config_util from eth2spec.config import config_util
from eth2spec.test.context import reload_specs from eth2spec.test import context
from eth2spec.utils import bls as bls_utils
# We import pytest only when it's present, i.e. when we are running tests. # We import pytest only when it's present, i.e. when we are running tests.
# The test-cases themselves can be generated without installing pytest. # The test-cases themselves can be generated without installing pytest.
@ -27,7 +27,16 @@ def fixture(*args, **kwargs):
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addoption( parser.addoption(
"--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" "--config", action="store", type=str, default="minimal",
help="config: make the pyspec use the specified configuration"
)
parser.addoption(
"--disable-bls", action="store_true",
help="bls-default: make tests that are not dependent on BLS run without BLS"
)
parser.addoption(
"--bls-type", action="store", type=str, default="py_ecc", choices=["py_ecc", "milagro"],
help="bls-type: use 'pyecc' or 'milagro' implementation for BLS"
) )
@ -36,4 +45,22 @@ def config(request):
config_name = request.config.getoption("--config") config_name = request.config.getoption("--config")
config_util.prepare_config('../../../configs/', config_name) config_util.prepare_config('../../../configs/', config_name)
# now that the presets are loaded, reload the specs to apply them # now that the presets are loaded, reload the specs to apply them
reload_specs() context.reload_specs()
@fixture(autouse=True)
def bls_default(request):
disable_bls = request.config.getoption("--disable-bls")
if disable_bls:
context.DEFAULT_BLS_ACTIVE = False
@fixture(autouse=True)
def bls_type(request):
bls_type = request.config.getoption("--bls-type")
if bls_type == "py_ecc":
bls_utils.bls = bls_utils.py_ecc_bls
elif bls_type == "milagro":
bls_utils.bls = bls_utils.milagro_bls
else:
raise Exception(f"unrecognized bls type: {bls_type}")

View File

@ -167,14 +167,15 @@ def single_phase(fn):
return entry return entry
# BLS is turned off by default *for performance purposes during TESTING*. # BLS is turned on by default, it can be disabled in tests by overriding this, or using `--disable-bls`.
# *This is for performance purposes during TESTING, DO NOT DISABLE IN PRODUCTION*.
# The runner of the test can indicate the preferred setting (test generators prefer BLS to be ON). # The runner of the test can indicate the preferred setting (test generators prefer BLS to be ON).
# - Some tests are marked as BLS-requiring, and ignore this setting. # - Some tests are marked as BLS-requiring, and ignore this setting.
# (tests that express differences caused by BLS, e.g. invalid signatures being rejected) # (tests that express differences caused by BLS, e.g. invalid signatures being rejected)
# - Some other tests are marked as BLS-ignoring, and ignore this setting. # - Some other tests are marked as BLS-ignoring, and ignore this setting.
# (tests that are heavily performance impacted / require unsigned state transitions) # (tests that are heavily performance impacted / require unsigned state transitions)
# - Most tests respect the BLS setting. # - Most tests respect the BLS setting.
DEFAULT_BLS_ACTIVE = False DEFAULT_BLS_ACTIVE = True
def spec_test(fn): def spec_test(fn):

View File

@ -183,7 +183,7 @@ def test_filtered_block_tree(spec, state):
for i in range(spec.SLOTS_PER_EPOCH): for i in range(spec.SLOTS_PER_EPOCH):
slot = rogue_block.slot + i slot = rogue_block.slot + i
for index in range(spec.get_committee_count_at_slot(non_viable_state, slot)): for index in range(spec.get_committee_count_at_slot(non_viable_state, slot)):
attestation = get_valid_attestation(spec, non_viable_state, rogue_block.slot + i, index) attestation = get_valid_attestation(spec, non_viable_state, slot, index, signed=True)
attestations.append(attestation) attestations.append(attestation)
# tick time forward to be able to include up to the latest attestation # tick time forward to be able to include up to the latest attestation

View File

@ -1,6 +1,6 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE1, PHASE0, PHASE1,
spec_state_test, expect_assertion_error, always_bls, with_all_phases, with_phases spec_state_test, expect_assertion_error, always_bls, never_bls, with_all_phases, with_phases
) )
from eth2spec.test.helpers.attestations import sign_indexed_attestation from eth2spec.test.helpers.attestations import sign_indexed_attestation
from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing, \ from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing, \
@ -89,6 +89,7 @@ def test_success_double(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@never_bls
def test_success_surround(spec, state): def test_success_surround(spec, state):
next_epoch_via_block(spec, state) next_epoch_via_block(spec, state)

View File

@ -1,4 +1,4 @@
from eth2spec.test.context import spec_state_test, never_bls, with_all_phases from eth2spec.test.context import spec_state_test, always_bls, with_all_phases
from eth2spec.test.helpers.attestations import build_attestation_data from eth2spec.test.helpers.attestations import build_attestation_data
from eth2spec.test.helpers.block import build_empty_block from eth2spec.test.helpers.block import build_empty_block
from eth2spec.test.helpers.deposits import prepare_state_and_deposit from eth2spec.test.helpers.deposits import prepare_state_and_deposit
@ -8,9 +8,11 @@ from eth2spec.utils import bls
from eth2spec.utils.ssz.ssz_typing import Bitlist from eth2spec.utils.ssz.ssz_typing import Bitlist
def run_get_signature_test(spec, state, obj, domain, get_signature_fn, privkey, pubkey): def run_get_signature_test(spec, state, obj, domain, get_signature_fn, privkey, pubkey, signing_ssz_object=None):
if signing_ssz_object is None:
signing_ssz_object = obj
signature = get_signature_fn(state, obj, privkey) signature = get_signature_fn(state, obj, privkey)
signing_root = spec.compute_signing_root(obj, domain) signing_root = spec.compute_signing_root(signing_ssz_object, domain)
assert bls.Verify(pubkey, signing_root, signature) assert bls.Verify(pubkey, signing_root, signature)
@ -55,7 +57,6 @@ def get_mock_aggregate(spec):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@never_bls
def test_check_if_validator_active(spec, state): def test_check_if_validator_active(spec, state):
active_validator_index = len(state.validators) - 1 active_validator_index = len(state.validators) - 1
assert spec.check_if_validator_active(state, active_validator_index) assert spec.check_if_validator_active(state, active_validator_index)
@ -73,7 +74,6 @@ def test_check_if_validator_active(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@never_bls
def test_get_committee_assignment_current_epoch(spec, state): def test_get_committee_assignment_current_epoch(spec, state):
epoch = spec.get_current_epoch(state) epoch = spec.get_current_epoch(state)
validator_index = len(state.validators) - 1 validator_index = len(state.validators) - 1
@ -82,7 +82,6 @@ def test_get_committee_assignment_current_epoch(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@never_bls
def test_get_committee_assignment_next_epoch(spec, state): def test_get_committee_assignment_next_epoch(spec, state):
epoch = spec.get_current_epoch(state) + 1 epoch = spec.get_current_epoch(state) + 1
validator_index = len(state.validators) - 1 validator_index = len(state.validators) - 1
@ -91,7 +90,6 @@ def test_get_committee_assignment_next_epoch(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@never_bls
def test_get_committee_assignment_out_bound_epoch(spec, state): def test_get_committee_assignment_out_bound_epoch(spec, state):
epoch = spec.get_current_epoch(state) + 2 epoch = spec.get_current_epoch(state) + 2
validator_index = len(state.validators) - 1 validator_index = len(state.validators) - 1
@ -100,7 +98,6 @@ def test_get_committee_assignment_out_bound_epoch(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@never_bls
def test_is_proposer(spec, state): def test_is_proposer(spec, state):
proposer_index = spec.get_beacon_proposer_index(state) proposer_index = spec.get_beacon_proposer_index(state)
assert spec.is_proposer(state, proposer_index) assert spec.is_proposer(state, proposer_index)
@ -132,6 +129,7 @@ def test_get_epoch_signature(spec, state):
get_signature_fn=spec.get_epoch_signature, get_signature_fn=spec.get_epoch_signature,
privkey=privkey, privkey=privkey,
pubkey=pubkey, pubkey=pubkey,
signing_ssz_object=spec.compute_epoch_at_slot(block.slot),
) )
@ -299,6 +297,7 @@ def test_compute_new_state_root(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@always_bls
def test_get_block_signature(spec, state): def test_get_block_signature(spec, state):
privkey = privkeys[0] privkey = privkeys[0]
pubkey = pubkeys[0] pubkey = pubkeys[0]
@ -320,6 +319,7 @@ def test_get_block_signature(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@always_bls
def test_get_attestation_signature(spec, state): def test_get_attestation_signature(spec, state):
privkey = privkeys[0] privkey = privkeys[0]
pubkey = pubkeys[0] pubkey = pubkeys[0]
@ -341,6 +341,7 @@ def test_get_attestation_signature(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@always_bls
def test_get_slot_signature(spec, state): def test_get_slot_signature(spec, state):
privkey = privkeys[0] privkey = privkeys[0]
pubkey = pubkeys[0] pubkey = pubkeys[0]
@ -359,6 +360,7 @@ def test_get_slot_signature(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@always_bls
def test_is_aggregator(spec, state): def test_is_aggregator(spec, state):
# TODO: we can test the probabilistic result against `TARGET_AGGREGATORS_PER_COMMITTEE` # TODO: we can test the probabilistic result against `TARGET_AGGREGATORS_PER_COMMITTEE`
# if we have more validators and larger committeee size # if we have more validators and larger committeee size
@ -377,9 +379,10 @@ def test_is_aggregator(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@always_bls
def test_get_aggregate_signature(spec, state): def test_get_aggregate_signature(spec, state):
attestations = [] attestations = []
pubkeys = [] attesting_pubkeys = []
slot = state.slot slot = state.slot
committee_index = 0 committee_index = 0
attestation_data = build_attestation_data(spec, state, slot=slot, index=committee_index) attestation_data = build_attestation_data(spec, state, slot=slot, index=committee_index)
@ -391,24 +394,26 @@ def test_get_aggregate_signature(spec, state):
committee_size = len(beacon_committee) committee_size = len(beacon_committee)
aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](*([0] * committee_size)) aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](*([0] * committee_size))
for i, validator_index in enumerate(beacon_committee): for i, validator_index in enumerate(beacon_committee):
bits = aggregation_bits bits = aggregation_bits.copy()
bits[i] = True bits[i] = True
attestations.append( attestations.append(
spec.Attestation( spec.Attestation(
data=attestation_data, data=attestation_data,
aggregation_bits=bits, aggregation_bits=bits,
signature=spec.get_attestation_signature(state, attestation_data, privkeys[validator_index]),
) )
) )
pubkeys.append(state.validators[validator_index].pubkey) attesting_pubkeys.append(state.validators[validator_index].pubkey)
pubkey = bls.AggregatePKs(pubkeys) assert len(attestations) > 0
signature = spec.get_aggregate_signature(attestations) signature = spec.get_aggregate_signature(attestations)
domain = spec.get_domain(state, spec.DOMAIN_BEACON_ATTESTER, attestation_data.target.epoch) domain = spec.get_domain(state, spec.DOMAIN_BEACON_ATTESTER, attestation_data.target.epoch)
signing_root = spec.compute_signing_root(attestation_data, domain) signing_root = spec.compute_signing_root(attestation_data, domain)
assert bls.Verify(pubkey, signing_root, signature) assert bls.FastAggregateVerify(attesting_pubkeys, signing_root, signature)
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@always_bls
def test_get_aggregate_and_proof(spec, state): def test_get_aggregate_and_proof(spec, state):
privkey = privkeys[0] privkey = privkeys[0]
aggregator_index = spec.ValidatorIndex(10) aggregator_index = spec.ValidatorIndex(10)
@ -421,6 +426,7 @@ def test_get_aggregate_and_proof(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
@always_bls
def test_get_aggregate_and_proof_signature(spec, state): def test_get_aggregate_and_proof_signature(spec, state):
privkey = privkeys[0] privkey = privkeys[0]
pubkey = pubkeys[0] pubkey = pubkeys[0]

View File

@ -1,12 +1,17 @@
from py_ecc.bls import G2ProofOfPossession as bls from py_ecc.bls import G2ProofOfPossession as py_ecc_bls
from py_ecc.bls.g2_primatives import signature_to_G2 as _signature_to_G2 from py_ecc.bls.g2_primatives import signature_to_G2 as _signature_to_G2
import milagro_bls_binding as milagro_bls # noqa: F401 for BLS switching option
# Flag to make BLS active or not. Used for testing, do not ignore BLS in production unless you know what you are doing. # Flag to make BLS active or not. Used for testing, do not ignore BLS in production unless you know what you are doing.
bls_active = True bls_active = True
# To change bls implementation, default to PyECC for correctness. Milagro is a good faster alternative.
bls = py_ecc_bls
STUB_SIGNATURE = b'\x11' * 96 STUB_SIGNATURE = b'\x11' * 96
STUB_PUBKEY = b'\x22' * 48 STUB_PUBKEY = b'\x22' * 48
STUB_COORDINATES = _signature_to_G2(bls.Sign(0, b"")) Z2_SIGNATURE = b'\xc0' + b'\x00' * 95
STUB_COORDINATES = _signature_to_G2(Z2_SIGNATURE)
def only_with_bls(alt_return=None): def only_with_bls(alt_return=None):
@ -36,7 +41,7 @@ def Verify(PK, message, signature):
@only_with_bls(alt_return=True) @only_with_bls(alt_return=True)
def AggregateVerify(pubkeys, messages, signature): def AggregateVerify(pubkeys, messages, signature):
try: try:
result = bls.AggregateVerify(pubkeys, messages, signature) result = bls.AggregateVerify(list(pubkeys), list(messages), signature)
except Exception: except Exception:
result = False result = False
finally: finally:
@ -46,7 +51,7 @@ def AggregateVerify(pubkeys, messages, signature):
@only_with_bls(alt_return=True) @only_with_bls(alt_return=True)
def FastAggregateVerify(pubkeys, message, signature): def FastAggregateVerify(pubkeys, message, signature):
try: try:
result = bls.FastAggregateVerify(pubkeys, message, signature) result = bls.FastAggregateVerify(list(pubkeys), message, signature)
except Exception: except Exception:
result = False result = False
finally: finally:
@ -60,7 +65,10 @@ def Aggregate(signatures):
@only_with_bls(alt_return=STUB_SIGNATURE) @only_with_bls(alt_return=STUB_SIGNATURE)
def Sign(SK, message): def Sign(SK, message):
return bls.Sign(SK, message) if bls == py_ecc_bls:
return bls.Sign(SK, message)
else:
return bls.Sign(SK.to_bytes(32, 'big'), message)
@only_with_bls(alt_return=STUB_COORDINATES) @only_with_bls(alt_return=STUB_COORDINATES)
@ -70,7 +78,7 @@ def signature_to_G2(signature):
@only_with_bls(alt_return=STUB_PUBKEY) @only_with_bls(alt_return=STUB_PUBKEY)
def AggregatePKs(pubkeys): def AggregatePKs(pubkeys):
return bls._AggregatePKs(pubkeys) return bls._AggregatePKs(list(pubkeys))
@only_with_bls(alt_return=STUB_SIGNATURE) @only_with_bls(alt_return=STUB_SIGNATURE)

View File

@ -2,18 +2,22 @@
BLS test vectors generator BLS test vectors generator
""" """
from hashlib import sha256
from typing import Tuple, Iterable, Any, Callable, Dict from typing import Tuple, Iterable, Any, Callable, Dict
from eth_utils import ( from eth_utils import (
encode_hex, encode_hex,
int_to_big_endian, int_to_big_endian,
) )
from gen_base import gen_runner, gen_typing import milagro_bls_binding as milagro_bls
from eth2spec.utils import bls from eth2spec.utils import bls
from hashlib import sha256
from eth2spec.test.context import PHASE0 from eth2spec.test.context import PHASE0
from gen_base import gen_runner, gen_typing
def to_bytes(i):
return i.to_bytes(32, "big")
def hash(x): def hash(x):
@ -70,8 +74,15 @@ def case02_verify():
# Valid signature # Valid signature
signature = bls.Sign(privkey, message) signature = bls.Sign(privkey, message)
pubkey = bls.SkToPk(privkey) pubkey = bls.SkToPk(privkey)
assert milagro_bls.SkToPk(to_bytes(privkey)) == pubkey
assert milagro_bls.Sign(to_bytes(privkey), message) == signature
identifier = f'{encode_hex(pubkey)}_{encode_hex(message)}' identifier = f'{encode_hex(pubkey)}_{encode_hex(message)}'
assert bls.Verify(pubkey, message, signature) assert bls.Verify(pubkey, message, signature)
assert milagro_bls.Verify(pubkey, message, signature)
yield f'verify_valid_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'verify_valid_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
'pubkey': encode_hex(pubkey), 'pubkey': encode_hex(pubkey),
@ -85,6 +96,7 @@ def case02_verify():
wrong_pubkey = bls.SkToPk(PRIVKEYS[(i + 1) % len(PRIVKEYS)]) wrong_pubkey = bls.SkToPk(PRIVKEYS[(i + 1) % len(PRIVKEYS)])
identifier = f'{encode_hex(wrong_pubkey)}_{encode_hex(message)}' identifier = f'{encode_hex(wrong_pubkey)}_{encode_hex(message)}'
assert not bls.Verify(wrong_pubkey, message, signature) assert not bls.Verify(wrong_pubkey, message, signature)
assert not milagro_bls.Verify(wrong_pubkey, message, signature)
yield f'verify_wrong_pubkey_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'verify_wrong_pubkey_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
'pubkey': encode_hex(wrong_pubkey), 'pubkey': encode_hex(wrong_pubkey),
@ -98,6 +110,7 @@ def case02_verify():
tampered_signature = signature[:-4] + b'\xFF\xFF\xFF\xFF' tampered_signature = signature[:-4] + b'\xFF\xFF\xFF\xFF'
identifier = f'{encode_hex(pubkey)}_{encode_hex(message)}' identifier = f'{encode_hex(pubkey)}_{encode_hex(message)}'
assert not bls.Verify(pubkey, message, tampered_signature) assert not bls.Verify(pubkey, message, tampered_signature)
assert not milagro_bls.Verify(pubkey, message, tampered_signature)
yield f'verify_tampered_signature_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'verify_tampered_signature_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
'pubkey': encode_hex(pubkey), 'pubkey': encode_hex(pubkey),
@ -109,6 +122,7 @@ def case02_verify():
# Valid pubkey and signature with the point at infinity # Valid pubkey and signature with the point at infinity
assert bls.Verify(Z1_PUBKEY, message, Z2_SIGNATURE) assert bls.Verify(Z1_PUBKEY, message, Z2_SIGNATURE)
assert milagro_bls.Verify(Z1_PUBKEY, message, Z2_SIGNATURE)
yield f'verify_infinity_pubkey_and_infinity_signature', { yield f'verify_infinity_pubkey_and_infinity_signature', {
'input': { 'input': {
'pubkey': encode_hex(Z1_PUBKEY), 'pubkey': encode_hex(Z1_PUBKEY),
@ -152,6 +166,7 @@ def case04_fast_aggregate_verify():
# Valid signature # Valid signature
identifier = f'{pubkeys_serial}_{encode_hex(message)}' identifier = f'{pubkeys_serial}_{encode_hex(message)}'
assert bls.FastAggregateVerify(pubkeys, message, aggregate_signature) assert bls.FastAggregateVerify(pubkeys, message, aggregate_signature)
assert milagro_bls.FastAggregateVerify(pubkeys, message, aggregate_signature)
yield f'fast_aggregate_verify_valid_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'fast_aggregate_verify_valid_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
'pubkeys': pubkeys_serial, 'pubkeys': pubkeys_serial,
@ -166,6 +181,7 @@ def case04_fast_aggregate_verify():
pubkeys_extra_serial = [encode_hex(pubkey) for pubkey in pubkeys_extra] pubkeys_extra_serial = [encode_hex(pubkey) for pubkey in pubkeys_extra]
identifier = f'{pubkeys_extra_serial}_{encode_hex(message)}' identifier = f'{pubkeys_extra_serial}_{encode_hex(message)}'
assert not bls.FastAggregateVerify(pubkeys_extra, message, aggregate_signature) assert not bls.FastAggregateVerify(pubkeys_extra, message, aggregate_signature)
assert not milagro_bls.FastAggregateVerify(pubkeys_extra, message, aggregate_signature)
yield f'fast_aggregate_verify_extra_pubkey_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'fast_aggregate_verify_extra_pubkey_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
'pubkeys': pubkeys_extra_serial, 'pubkeys': pubkeys_extra_serial,
@ -179,6 +195,7 @@ def case04_fast_aggregate_verify():
tampered_signature = aggregate_signature[:-4] + b'\xff\xff\xff\xff' tampered_signature = aggregate_signature[:-4] + b'\xff\xff\xff\xff'
identifier = f'{pubkeys_serial}_{encode_hex(message)}' identifier = f'{pubkeys_serial}_{encode_hex(message)}'
assert not bls.FastAggregateVerify(pubkeys, message, tampered_signature) assert not bls.FastAggregateVerify(pubkeys, message, tampered_signature)
assert not milagro_bls.FastAggregateVerify(pubkeys, message, tampered_signature)
yield f'fast_aggregate_verify_tampered_signature_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'fast_aggregate_verify_tampered_signature_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
'pubkeys': pubkeys_serial, 'pubkeys': pubkeys_serial,
@ -190,6 +207,7 @@ def case04_fast_aggregate_verify():
# Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == Z1_SIGNATURE # Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == Z1_SIGNATURE
assert not bls.FastAggregateVerify([], message, Z2_SIGNATURE) assert not bls.FastAggregateVerify([], message, Z2_SIGNATURE)
assert not milagro_bls.FastAggregateVerify([], message, Z2_SIGNATURE)
yield f'fast_aggregate_verify_na_pubkeys_and_infinity_signature', { yield f'fast_aggregate_verify_na_pubkeys_and_infinity_signature', {
'input': { 'input': {
'pubkeys': [], 'pubkeys': [],
@ -201,6 +219,7 @@ def case04_fast_aggregate_verify():
# Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == 0x00... # Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == 0x00...
assert not bls.FastAggregateVerify([], message, NO_SIGNATURE) assert not bls.FastAggregateVerify([], message, NO_SIGNATURE)
assert not milagro_bls.FastAggregateVerify([], message, NO_SIGNATURE)
yield f'fast_aggregate_verify_na_pubkeys_and_na_signature', { yield f'fast_aggregate_verify_na_pubkeys_and_na_signature', {
'input': { 'input': {
'pubkeys': [], 'pubkeys': [],
@ -228,6 +247,7 @@ def case05_aggregate_verify():
aggregate_signature = bls.Aggregate(sigs) aggregate_signature = bls.Aggregate(sigs)
assert bls.AggregateVerify(pubkeys, messages, aggregate_signature) assert bls.AggregateVerify(pubkeys, messages, aggregate_signature)
assert milagro_bls.AggregateVerify(pubkeys, messages, aggregate_signature)
yield f'aggregate_verify_valid', { yield f'aggregate_verify_valid', {
'input': { 'input': {
'pubkeys': pubkeys_serial, 'pubkeys': pubkeys_serial,
@ -239,6 +259,7 @@ def case05_aggregate_verify():
tampered_signature = aggregate_signature[:4] + b'\xff\xff\xff\xff' tampered_signature = aggregate_signature[:4] + b'\xff\xff\xff\xff'
assert not bls.AggregateVerify(pubkey, messages, tampered_signature) assert not bls.AggregateVerify(pubkey, messages, tampered_signature)
assert not milagro_bls.AggregateVerify(pubkeys, messages, tampered_signature)
yield f'aggregate_verify_tampered_signature', { yield f'aggregate_verify_tampered_signature', {
'input': { 'input': {
'pubkeys': pubkeys_serial, 'pubkeys': pubkeys_serial,
@ -250,6 +271,7 @@ def case05_aggregate_verify():
# Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == Z1_SIGNATURE # Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == Z1_SIGNATURE
assert not bls.AggregateVerify([], [], Z2_SIGNATURE) assert not bls.AggregateVerify([], [], Z2_SIGNATURE)
assert not milagro_bls.AggregateVerify([], [], Z2_SIGNATURE)
yield f'aggregate_verify_na_pubkeys_and_infinity_signature', { yield f'aggregate_verify_na_pubkeys_and_infinity_signature', {
'input': { 'input': {
'pubkeys': [], 'pubkeys': [],
@ -261,6 +283,7 @@ def case05_aggregate_verify():
# Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == 0x00... # Invalid pubkeys and signature -- len(pubkeys) == 0 and signature == 0x00...
assert not bls.AggregateVerify([], [], NO_SIGNATURE) assert not bls.AggregateVerify([], [], NO_SIGNATURE)
assert not milagro_bls.AggregateVerify([], [], NO_SIGNATURE)
yield f'aggregate_verify_na_pubkeys_and_na_signature', { yield f'aggregate_verify_na_pubkeys_and_na_signature', {
'input': { 'input': {
'pubkeys': [], 'pubkeys': [],