diff --git a/test_libs/pyspec/eth2spec/test/helpers/block.py b/test_libs/pyspec/eth2spec/test/helpers/block.py index 094423ab3..81c5e9ef5 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/block.py +++ b/test_libs/pyspec/eth2spec/test/helpers/block.py @@ -4,16 +4,15 @@ from eth2spec.phase0 import spec from eth2spec.phase0.spec import get_beacon_proposer_index, slot_to_epoch, get_domain, BeaconBlock from eth2spec.phase0.state_transition import state_transition, state_transition_to from eth2spec.test.helpers.keys import privkeys -from eth2spec.utils import bls +from eth2spec.utils.bls import bls_sign, only_with_bls from eth2spec.utils.minimal_ssz import signing_root, hash_tree_root +# Fully ignore the function if BLS is off, beacon-proposer index calculation is slow. +@only_with_bls() def sign_block(state, block, proposer_index=None): assert state.slot <= block.slot - if not bls.bls_active: - return - if proposer_index is None: if block.slot == state.slot: proposer_index = get_beacon_proposer_index(state) @@ -28,7 +27,7 @@ def sign_block(state, block, proposer_index=None): privkey = privkeys[proposer_index] - block.body.randao_reveal = bls.bls_sign( + block.body.randao_reveal = bls_sign( privkey=privkey, message_hash=hash_tree_root(slot_to_epoch(block.slot)), domain=get_domain( @@ -37,14 +36,13 @@ def sign_block(state, block, proposer_index=None): domain_type=spec.DOMAIN_RANDAO, ) ) - block.signature = bls.bls_sign( + block.signature = bls_sign( message_hash=signing_root(block), privkey=privkey, domain=get_domain( state, spec.DOMAIN_BEACON_PROPOSER, slot_to_epoch(block.slot))) - return block def apply_empty_block(state): diff --git a/test_libs/pyspec/eth2spec/test/utils.py b/test_libs/pyspec/eth2spec/test/utils.py index 1c157bcee..c1d424109 100644 --- a/test_libs/pyspec/eth2spec/test/utils.py +++ b/test_libs/pyspec/eth2spec/test/utils.py @@ -1,5 +1,5 @@ +from typing import Dict, Any, Callable, Iterable from eth2spec.debug.encode import encode -from eth2spec.utils import bls def spectest(description: str = None): @@ -19,9 +19,6 @@ def spectest(description: str = None): else: # description can be explicit out['description'] = description - # If BLS is not active, mark the test as BLS-ignorant. - if not bls.bls_active: - out['stub_bls'] = True # put all generated data into a dict. for data in fn(*args, **kw): # If there is a type argument, encode it as that type. @@ -44,10 +41,34 @@ def spectest(description: str = None): return runner -def with_args(create_args): +def with_tags(tags: Dict[str, Any]): + """ + Decorator factory, adds tags (key, value) pairs to the output of the function. + Useful to build test-vector annotations with. + This decorator is applied after the ``spectest`` decorator is applied. + :param tags: dict of tags + :return: Decorator. + """ + def runner(fn): + def entry(*args, **kw): + fn_out = fn(*args, **kw) + # do not add tags if the function is not returning a dict at all (i.e. not in generator mode) + if fn_out is None: + return fn_out + return {**tags, **fn_out} + return entry + return runner + + +def with_args(create_args: Callable[[], Iterable[Any]]): + """ + Decorator factory, adds given extra arguments to the decorated function. + :param create_args: function to create arguments with. + :return: Decorator. + """ def runner(fn): # this wraps the function, to hide that the function actually yielding data. def entry(*args, **kw): - return fn(*(create_args() + list(args)), **kw) + return fn(*(list(create_args()) + list(args)), **kw) return entry return runner diff --git a/test_libs/pyspec/eth2spec/utils/bls.py b/test_libs/pyspec/eth2spec/utils/bls.py index 23a9a7529..52f1fed63 100644 --- a/test_libs/pyspec/eth2spec/utils/bls.py +++ b/test_libs/pyspec/eth2spec/utils/bls.py @@ -3,37 +3,44 @@ from py_ecc import bls # 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 +STUB_SIGNATURE = b'\x11' * 96 +STUB_PUBKEY = b'\x22' * 48 + +def only_with_bls(alt_return=None): + """ + Decorator factory to make a function only run when BLS is active. Otherwise return the default. + """ + def runner(fn): + def entry(*args, **kw): + if bls_active: + return fn(*args, **kw) + else: + return alt_return + return entry + return runner + + +@only_with_bls(alt_return=True) def bls_verify(pubkey, message_hash, signature, domain): - if bls_active: - return bls.verify(message_hash=message_hash, pubkey=pubkey, signature=signature, domain=domain) - else: - return True + return bls.verify(message_hash=message_hash, pubkey=pubkey, signature=signature, domain=domain) +@only_with_bls(alt_return=True) def bls_verify_multiple(pubkeys, message_hashes, signature, domain): - if bls_active: - return bls.verify_multiple(pubkeys, message_hashes, signature, domain) - else: - return True + return bls.verify_multiple(pubkeys, message_hashes, signature, domain) +@only_with_bls(alt_return=STUB_PUBKEY) def bls_aggregate_pubkeys(pubkeys): - if bls_active: - return bls.aggregate_pubkeys(pubkeys) - else: - return b'\xaa' * 48 + return bls.aggregate_pubkeys(pubkeys) +@only_with_bls(alt_return=STUB_SIGNATURE) def bls_aggregate_signatures(signatures): - if bls_active: - return bls.aggregate_signatures(signatures) - else: - return b'\x22' * 96 + return bls.aggregate_signatures(signatures) +@only_with_bls(alt_return=STUB_SIGNATURE) def bls_sign(message_hash, privkey, domain): - if bls_active: - return bls.sign(message_hash=message_hash, privkey=privkey, domain=domain) - else: - return b'\x11' * 96 + return bls.sign(message_hash=message_hash, privkey=privkey, domain=domain)