diff --git a/.gitignore b/.gitignore index dfb38d170..f33dd5256 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /.pytest_cache build/ +output/ diff --git a/tests/phase0/__init__.py b/tests/phase0/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/phase0/block_processing/test_process_deposit.py b/tests/phase0/block_processing/test_process_deposit.py index 297ad37f1..0c5770195 100644 --- a/tests/phase0/block_processing/test_process_deposit.py +++ b/tests/phase0/block_processing/test_process_deposit.py @@ -4,11 +4,13 @@ import pytest import build.phase0.spec as spec from build.phase0.spec import ( - Deposit, + ZERO_HASH, process_deposit, ) from tests.phase0.helpers import ( build_deposit, + privkeys, + pubkeys, ) @@ -16,8 +18,10 @@ from tests.phase0.helpers import ( pytestmark = pytest.mark.voluntary_exits -def test_success(state, deposit_data_leaves, pubkeys, privkeys): +def test_success(state): pre_state = deepcopy(state) + # fill previous deposits with zero-hash + deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) index = len(deposit_data_leaves) pubkey = pubkeys[index] @@ -45,8 +49,9 @@ def test_success(state, deposit_data_leaves, pubkeys, privkeys): return pre_state, deposit, post_state -def test_success_top_up(state, deposit_data_leaves, pubkeys, privkeys): +def test_success_top_up(state): pre_state = deepcopy(state) + deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) validator_index = 0 amount = spec.MAX_DEPOSIT_AMOUNT // 4 @@ -76,8 +81,10 @@ def test_success_top_up(state, deposit_data_leaves, pubkeys, privkeys): return pre_state, deposit, post_state -def test_wrong_index(state, deposit_data_leaves, pubkeys, privkeys): +def test_wrong_index(state): pre_state = deepcopy(state) + deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) + index = len(deposit_data_leaves) pubkey = pubkeys[index] @@ -104,8 +111,9 @@ def test_wrong_index(state, deposit_data_leaves, pubkeys, privkeys): return pre_state, deposit, None -def test_bad_merkle_proof(state, deposit_data_leaves, pubkeys, privkeys): +def test_bad_merkle_proof(state): pre_state = deepcopy(state) + deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) index = len(deposit_data_leaves) pubkey = pubkeys[index] diff --git a/tests/phase0/block_processing/test_voluntary_exit.py b/tests/phase0/block_processing/test_voluntary_exit.py index 0801e4292..6adc81464 100644 --- a/tests/phase0/block_processing/test_voluntary_exit.py +++ b/tests/phase0/block_processing/test_voluntary_exit.py @@ -10,6 +10,7 @@ from build.phase0.spec import ( ) from tests.phase0.helpers import ( build_voluntary_exit, + pubkey_to_privkey, ) @@ -17,7 +18,7 @@ from tests.phase0.helpers import ( pytestmark = pytest.mark.voluntary_exits -def test_success(state, pub_to_priv): +def test_success(state): pre_state = deepcopy(state) # # setup pre_state @@ -30,7 +31,7 @@ def test_success(state, pub_to_priv): # current_epoch = get_current_epoch(pre_state) validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0] - privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey] + privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey] voluntary_exit = build_voluntary_exit( pre_state, @@ -52,11 +53,11 @@ def test_success(state, pub_to_priv): return pre_state, voluntary_exit, post_state -def test_validator_not_active(state, pub_to_priv): +def test_validator_not_active(state): pre_state = deepcopy(state) current_epoch = get_current_epoch(pre_state) validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0] - privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey] + privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey] # # setup pre_state @@ -79,7 +80,7 @@ def test_validator_not_active(state, pub_to_priv): return pre_state, voluntary_exit, None -def test_validator_already_exited(state, pub_to_priv): +def test_validator_already_exited(state): pre_state = deepcopy(state) # # setup pre_state @@ -89,7 +90,7 @@ def test_validator_already_exited(state, pub_to_priv): current_epoch = get_current_epoch(pre_state) validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0] - privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey] + privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey] # but validator already has exited pre_state.validator_registry[validator_index].exit_epoch = current_epoch + 2 @@ -110,7 +111,7 @@ def test_validator_already_exited(state, pub_to_priv): return pre_state, voluntary_exit, None -def test_validator_already_initiated_exit(state, pub_to_priv): +def test_validator_already_initiated_exit(state): pre_state = deepcopy(state) # # setup pre_state @@ -120,7 +121,7 @@ def test_validator_already_initiated_exit(state, pub_to_priv): current_epoch = get_current_epoch(pre_state) validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0] - privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey] + privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey] # but validator already has initiated exit pre_state.validator_registry[validator_index].initiated_exit = True @@ -141,14 +142,14 @@ def test_validator_already_initiated_exit(state, pub_to_priv): return pre_state, voluntary_exit, None -def test_validator_not_active_long_enough(state, pub_to_priv): +def test_validator_not_active_long_enough(state): pre_state = deepcopy(state) # # setup pre_state # current_epoch = get_current_epoch(pre_state) validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0] - privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey] + privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey] # but validator already has initiated exit pre_state.validator_registry[validator_index].initiated_exit = True diff --git a/tests/phase0/conftest.py b/tests/phase0/conftest.py index 395929028..36a087941 100644 --- a/tests/phase0/conftest.py +++ b/tests/phase0/conftest.py @@ -3,9 +3,6 @@ import pytest from build.phase0 import spec from tests.phase0.helpers import ( - privkeys_list, - pubkeys_list, - pubkey_to_privkey, create_genesis_state, ) @@ -25,21 +22,6 @@ MINIMAL_CONFIG = { } -@pytest.fixture -def privkeys(): - return privkeys_list - - -@pytest.fixture -def pubkeys(): - return pubkeys_list - - -@pytest.fixture -def pub_to_priv(): - return pubkey_to_privkey - - def overwrite_spec_config(config): for field in config: setattr(spec, field, config[field]) diff --git a/tests/phase0/helpers.py b/tests/phase0/helpers.py index 134fa797d..20054b821 100644 --- a/tests/phase0/helpers.py +++ b/tests/phase0/helpers.py @@ -31,18 +31,20 @@ from build.phase0.utils.merkle_minimal import ( ) -privkeys_list = [i + 1 for i in range(1000)] -pubkeys_list = [bls.privtopub(privkey) for privkey in privkeys_list] -pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys_list, pubkeys_list)} +privkeys = [i + 1 for i in range(1000)] +pubkeys = [bls.privtopub(privkey) for privkey in privkeys] +pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)} -def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves): +def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=None): + if not deposit_data_leaves: + deposit_data_leaves = [] deposit_timestamp = 0 proof_of_possession = b'\x33' * 96 deposit_data_list = [] for i in range(num_validators): - pubkey = pubkeys_list[i] + pubkey = pubkeys[i] deposit_data = DepositData( amount=spec.MAX_DEPOSIT_AMOUNT, timestamp=deposit_timestamp, @@ -71,7 +73,7 @@ def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves): return genesis_validator_deposits, root -def create_genesis_state(num_validators, deposit_data_leaves): +def create_genesis_state(num_validators, deposit_data_leaves=None): initial_deposits, deposit_root = create_mock_genesis_validator_deposits( num_validators, deposit_data_leaves, diff --git a/tests/phase0/test_sanity.py b/tests/phase0/test_sanity.py index 8f04f316c..6de6dfb45 100644 --- a/tests/phase0/test_sanity.py +++ b/tests/phase0/test_sanity.py @@ -43,6 +43,8 @@ from tests.phase0.helpers import ( build_attestation_data, build_deposit_data, build_empty_block_for_next_slot, + privkeys, + pubkeys, ) @@ -112,7 +114,7 @@ def test_empty_epoch_transition_not_finalizing(state): return state, [block], test_state -def test_proposer_slashing(state, pubkeys, privkeys): +def test_proposer_slashing(state): test_state = deepcopy(state) current_epoch = get_current_epoch(test_state) validator_index = get_active_validator_indices(test_state.validator_registry, current_epoch)[-1] @@ -172,9 +174,9 @@ def test_proposer_slashing(state, pubkeys, privkeys): return state, [block], test_state -def test_deposit_in_block(state, deposit_data_leaves, pubkeys, privkeys): +def test_deposit_in_block(state): pre_state = deepcopy(state) - test_deposit_data_leaves = deepcopy(deposit_data_leaves) + test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) index = len(test_deposit_data_leaves) pubkey = pubkeys[index] @@ -207,9 +209,9 @@ def test_deposit_in_block(state, deposit_data_leaves, pubkeys, privkeys): return pre_state, [block], post_state -def test_deposit_top_up(state, pubkeys, privkeys, deposit_data_leaves): +def test_deposit_top_up(state): pre_state = deepcopy(state) - test_deposit_data_leaves = deepcopy(deposit_data_leaves) + test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) validator_index = 0 amount = spec.MAX_DEPOSIT_AMOUNT // 4 @@ -245,7 +247,7 @@ def test_deposit_top_up(state, pubkeys, privkeys, deposit_data_leaves): return pre_state, [block], post_state -def test_attestation(state, pubkeys, privkeys): +def test_attestation(state): test_state = deepcopy(state) slot = state.slot shard = state.current_shuffling_start_shard @@ -314,7 +316,7 @@ def test_attestation(state, pubkeys, privkeys): return state, [attestation_block, epoch_block], test_state -def test_voluntary_exit(state, pubkeys, privkeys): +def test_voluntary_exit(state): pre_state = deepcopy(state) validator_index = get_active_validator_indices(pre_state.validator_registry, get_current_epoch(pre_state))[-1] @@ -363,7 +365,7 @@ def test_voluntary_exit(state, pubkeys, privkeys): return pre_state, [initiate_exit_block, exit_block], post_state -def test_transfer(state, pubkeys, privkeys): +def test_transfer(state): pre_state = deepcopy(state) current_epoch = get_current_epoch(pre_state) sender_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[-1] diff --git a/utils/phase0/jsonize.py b/utils/phase0/jsonize.py new file mode 100644 index 000000000..816192ec6 --- /dev/null +++ b/utils/phase0/jsonize.py @@ -0,0 +1,52 @@ +from .minimal_ssz import hash_tree_root + + +def jsonize(value, typ, include_hash_tree_roots=False): + if isinstance(typ, str) and typ[:4] == 'uint': + return value + elif typ == 'bool': + assert value in (True, False) + return value + elif isinstance(typ, list): + return [jsonize(element, typ[0], include_hash_tree_roots) for element in value] + elif isinstance(typ, str) and typ[:4] == 'byte': + return '0x' + value.hex() + elif hasattr(typ, 'fields'): + ret = {} + for field, subtype in typ.fields.items(): + ret[field] = jsonize(getattr(value, field), subtype, include_hash_tree_roots) + if include_hash_tree_roots: + ret[field + "_hash_tree_root"] = '0x' + hash_tree_root(getattr(value, field), subtype).hex() + if include_hash_tree_roots: + ret["hash_tree_root"] = '0x' + hash_tree_root(value, typ).hex() + return ret + else: + print(value, typ) + raise Exception("Type not recognized") + + +def dejsonize(json, typ): + if isinstance(typ, str) and typ[:4] == 'uint': + return json + elif typ == 'bool': + assert json in (True, False) + return json + elif isinstance(typ, list): + return [dejsonize(element, typ[0]) for element in json] + elif isinstance(typ, str) and typ[:4] == 'byte': + return bytes.fromhex(json[2:]) + elif hasattr(typ, 'fields'): + temp = {} + for field, subtype in typ.fields.items(): + temp[field] = dejsonize(json[field], subtype) + if field + "_hash_tree_root" in json: + assert(json[field + "_hash_tree_root"][2:] == + hash_tree_root(temp[field], subtype).hex()) + ret = typ(**temp) + if "hash_tree_root" in json: + assert(json["hash_tree_root"][2:] == + hash_tree_root(ret, typ).hex()) + return ret + else: + print(json, typ) + raise Exception("Type not recognized")