From 65b0701f8c68ef9416a5ebbb889c04c0de52fd73 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 20 May 2019 18:14:37 +0200 Subject: [PATCH] Helpers depend on spec version and p1 tests work --- Makefile | 2 +- test_libs/pyspec/tests/phase0/conftest.py | 5 +- .../test_process_crosslinks.py | 4 +- test_libs/pyspec/tests/phase0/helpers.py | 148 +++++++----------- .../pyspec/tests/phase0/test_finality.py | 2 +- test_libs/pyspec/tests/phase1/conftest.py | 18 ++- test_libs/pyspec/tests/phase1/helpers.py | 31 ++-- 7 files changed, 83 insertions(+), 127 deletions(-) diff --git a/Makefile b/Makefile index a262ac5e1..f8682734d 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ PY_SPEC_PHASE_1_DEPS = $(SPEC_DIR)/core/1_*.md PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) $(PY_SPEC_PHASE_1_TARGETS) -.PHONY: clean all test citest gen_yaml_tests pyspec phase0 install_test +.PHONY: clean all test citest gen_yaml_tests pyspec phase0 phase1 install_test all: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_DIR) $(YAML_TEST_TARGETS) diff --git a/test_libs/pyspec/tests/phase0/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py index 4db8f3919..0549a1422 100644 --- a/test_libs/pyspec/tests/phase0/conftest.py +++ b/test_libs/pyspec/tests/phase0/conftest.py @@ -13,11 +13,12 @@ def pytest_addoption(parser): @pytest.fixture(autouse=True) def config(request): - request.function.__globals__['spec'] = spec - request.function.__globals__['helpers'] = helpers config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) spec.apply_constants_preset(presets) + helpers.spec = spec + request.function.__globals__['spec'] = spec + request.function.__globals__['helpers'] = helpers @pytest.fixture def num_validators(config): diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py index a3ec38989..19c668e74 100644 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py @@ -67,7 +67,7 @@ def test_single_crosslink_update_from_previous_epoch(state): assert post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard] assert pre_state.current_crosslinks[shard] != post_state.current_crosslinks[shard] # ensure rewarded - for index in helpers.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): + for index in spec.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): assert crosslink_deltas[0][index] > 0 assert crosslink_deltas[1][index] == 0 @@ -108,7 +108,7 @@ def test_double_late_crosslink(state): # ensure that the current crosslinks were not updated by the second attestation assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard] # ensure no reward, only penalties for the failed crosslink - for index in helpers.get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): + for index in spec.get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[1][index] > 0 diff --git a/test_libs/pyspec/tests/phase0/helpers.py b/test_libs/pyspec/tests/phase0/helpers.py index e8b4f789e..82851c1cc 100644 --- a/test_libs/pyspec/tests/phase0/helpers.py +++ b/test_libs/pyspec/tests/phase0/helpers.py @@ -2,58 +2,18 @@ from copy import deepcopy from py_ecc import bls -import eth2spec.phase0.spec as spec - from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase0.spec import ( - # constants - ZERO_HASH, - MAX_EPOCHS_PER_CROSSLINK, - # SSZ - Attestation, - AttestationData, - AttestationDataAndCustodyBit, - AttesterSlashing, - BeaconBlock, - BeaconBlockHeader, - Crosslink, - Deposit, - DepositData, - Eth1Data, - ProposerSlashing, - Transfer, - VoluntaryExit, - # functions - convert_to_indexed, - get_active_validator_indices, - get_attesting_indices, - get_block_root, - get_block_root_at_slot, - get_crosslink_committee, - get_current_epoch, - get_domain, - get_epoch_start_slot, - get_genesis_beacon_state, - get_previous_epoch, - get_shard_delta, - hash_tree_root, - slot_to_epoch, - state_transition, - verify_merkle_branch, - hash, -) + from eth2spec.utils.merkle_minimal import ( calc_merkle_tree_from_leaves, get_merkle_proof, get_merkle_root, ) - privkeys = [i + 1 for i in range(1024)] pubkeys = [bls.privtopub(privkey) for privkey in privkeys] pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)} - def advance_slot(state) -> None: state.slot += 1 @@ -83,10 +43,10 @@ def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=N deposit_data_list = [] for i in range(num_validators): pubkey = pubkeys[i] - deposit_data = DepositData( + deposit_data = spec.DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well - withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], + withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:], amount=spec.MAX_EFFECTIVE_BALANCE, signature=signature, ) @@ -95,12 +55,12 @@ def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=N tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves)) root = get_merkle_root((tuple(deposit_data_leaves))) proof = list(get_merkle_proof(tree, item_index=i)) - assert verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, i, root) + assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, i, root) deposit_data_list.append(deposit_data) genesis_validator_deposits = [] for i in range(num_validators): - genesis_validator_deposits.append(Deposit( + genesis_validator_deposits.append(spec.Deposit( proof=list(get_merkle_proof(tree, item_index=i)), index=i, data=deposit_data_list[i] @@ -113,10 +73,10 @@ def create_genesis_state(num_validators, deposit_data_leaves=None): num_validators, deposit_data_leaves, ) - return get_genesis_beacon_state( + return spec.get_genesis_beacon_state( initial_deposits, genesis_time=0, - genesis_eth1_data=Eth1Data( + genesis_eth1_data=spec.Eth1Data( deposit_root=deposit_root, deposit_count=len(initial_deposits), block_hash=spec.ZERO_HASH, @@ -125,7 +85,7 @@ def create_genesis_state(num_validators, deposit_data_leaves=None): def build_empty_block_for_next_slot(state): - empty_block = BeaconBlock() + empty_block = spec.BeaconBlock() empty_block.slot = state.slot + 1 empty_block.body.eth1_data.deposit_count = state.deposit_index previous_block_header = deepcopy(state.latest_block_header) @@ -136,16 +96,16 @@ def build_empty_block_for_next_slot(state): def build_deposit_data(state, pubkey, privkey, amount): - deposit_data = DepositData( + deposit_data = spec.DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well - withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], + withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:], amount=amount, ) signature = bls.sign( message_hash=signing_root(deposit_data), privkey=privkey, - domain=get_domain( + domain=spec.get_domain( state, spec.DOMAIN_DEPOSIT, ) @@ -160,15 +120,15 @@ def build_attestation_data(state, slot, shard): if slot == state.slot: block_root = build_empty_block_for_next_slot(state).parent_root else: - block_root = get_block_root_at_slot(state, slot) + block_root = spec.get_block_root_at_slot(state, slot) - current_epoch_start_slot = get_epoch_start_slot(get_current_epoch(state)) + current_epoch_start_slot = spec.get_epoch_start_slot(spec.get_current_epoch(state)) if slot < current_epoch_start_slot: - epoch_boundary_root = get_block_root(state, get_previous_epoch(state)) + epoch_boundary_root = spec.get_block_root(state, spec.get_previous_epoch(state)) elif slot == current_epoch_start_slot: epoch_boundary_root = block_root else: - epoch_boundary_root = get_block_root(state, get_current_epoch(state)) + epoch_boundary_root = spec.get_block_root(state, spec.get_current_epoch(state)) if slot < current_epoch_start_slot: justified_epoch = state.previous_justified_epoch @@ -177,31 +137,31 @@ def build_attestation_data(state, slot, shard): justified_epoch = state.current_justified_epoch justified_block_root = state.current_justified_root - crosslinks = state.current_crosslinks if slot_to_epoch(slot) == get_current_epoch(state) else state.previous_crosslinks - return AttestationData( + crosslinks = state.current_crosslinks if spec.slot_to_epoch(slot) == spec.get_current_epoch(state) else state.previous_crosslinks + return spec.AttestationData( beacon_block_root=block_root, source_epoch=justified_epoch, source_root=justified_block_root, - target_epoch=slot_to_epoch(slot), + target_epoch=spec.slot_to_epoch(slot), target_root=epoch_boundary_root, - crosslink=Crosslink( + crosslink=spec.Crosslink( shard=shard, - epoch=min(slot_to_epoch(slot), crosslinks[shard].epoch + MAX_EPOCHS_PER_CROSSLINK), + epoch=min(spec.slot_to_epoch(slot), crosslinks[shard].epoch + spec.MAX_EPOCHS_PER_CROSSLINK), data_root=spec.ZERO_HASH, - parent_root=hash_tree_root(crosslinks[shard]), + parent_root=spec.hash_tree_root(crosslinks[shard]), ), ) def build_voluntary_exit(state, epoch, validator_index, privkey): - voluntary_exit = VoluntaryExit( + voluntary_exit = spec.VoluntaryExit( epoch=epoch, validator_index=validator_index, ) voluntary_exit.signature = bls.sign( message_hash=signing_root(voluntary_exit), privkey=privkey, - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_VOLUNTARY_EXIT, message_epoch=epoch, @@ -224,9 +184,9 @@ def build_deposit(state, tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves)) root = get_merkle_root((tuple(deposit_data_leaves))) proof = list(get_merkle_proof(tree, item_index=index)) - assert verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) + assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) - deposit = Deposit( + deposit = spec.Deposit( proof=list(proof), index=index, data=deposit_data, @@ -236,22 +196,22 @@ def build_deposit(state, def get_valid_proposer_slashing(state): - current_epoch = get_current_epoch(state) - validator_index = get_active_validator_indices(state, current_epoch)[-1] + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] slot = state.slot - header_1 = BeaconBlockHeader( + header_1 = spec.BeaconBlockHeader( slot=slot, - parent_root=ZERO_HASH, - state_root=ZERO_HASH, - body_root=ZERO_HASH, + parent_root=spec.ZERO_HASH, + state_root=spec.ZERO_HASH, + body_root=spec.ZERO_HASH, ) header_2 = deepcopy(header_1) header_2.parent_root = b'\x02' * 32 header_2.slot = slot + 1 - domain = get_domain( + domain = spec.get_domain( state=state, domain_type=spec.DOMAIN_BEACON_PROPOSER, ) @@ -266,7 +226,7 @@ def get_valid_proposer_slashing(state): domain=domain, ) - return ProposerSlashing( + return spec.ProposerSlashing( proposer_index=validator_index, header_1=header_1, header_2=header_2, @@ -278,9 +238,9 @@ def get_valid_attester_slashing(state): attestation_2 = deepcopy(attestation_1) attestation_2.data.target_root = b'\x01' * 32 - return AttesterSlashing( - attestation_1=convert_to_indexed(state, attestation_1), - attestation_2=convert_to_indexed(state, attestation_2), + return spec.AttesterSlashing( + attestation_1=spec.convert_to_indexed(state, attestation_1), + attestation_2=spec.convert_to_indexed(state, attestation_2), ) @@ -288,26 +248,26 @@ def get_valid_attestation(state, slot=None): if slot is None: slot = state.slot - if slot_to_epoch(slot) == get_current_epoch(state): + if spec.slot_to_epoch(slot) == spec.get_current_epoch(state): shard = (state.latest_start_shard + slot) % spec.SLOTS_PER_EPOCH else: - previous_shard_delta = get_shard_delta(state, get_previous_epoch(state)) + previous_shard_delta = spec.get_shard_delta(state, spec.get_previous_epoch(state)) shard = (state.latest_start_shard - previous_shard_delta + slot) % spec.SHARD_COUNT attestation_data = build_attestation_data(state, slot, shard) - crosslink_committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) + crosslink_committee = spec.get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) committee_size = len(crosslink_committee) bitfield_length = (committee_size + 7) // 8 aggregation_bitfield = b'\xC0' + b'\x00' * (bitfield_length - 1) custody_bitfield = b'\x00' * bitfield_length - attestation = Attestation( + attestation = spec.Attestation( aggregation_bitfield=aggregation_bitfield, data=attestation_data, custody_bitfield=custody_bitfield, ) - participants = get_attesting_indices( + participants = spec.get_attesting_indices( state, attestation.data, attestation.aggregation_bitfield, @@ -332,10 +292,10 @@ def get_valid_attestation(state, slot=None): def get_valid_transfer(state, slot=None, sender_index=None, amount=None, fee=None): if slot is None: slot = state.slot - current_epoch = get_current_epoch(state) + current_epoch = spec.get_current_epoch(state) if sender_index is None: - sender_index = get_active_validator_indices(state, current_epoch)[-1] - recipient_index = get_active_validator_indices(state, current_epoch)[0] + sender_index = spec.get_active_validator_indices(state, current_epoch)[-1] + recipient_index = spec.get_active_validator_indices(state, current_epoch)[0] transfer_pubkey = pubkeys[-1] transfer_privkey = privkeys[-1] @@ -344,22 +304,22 @@ def get_valid_transfer(state, slot=None, sender_index=None, amount=None, fee=Non if amount is None: amount = get_balance(state, sender_index) - fee - transfer = Transfer( + transfer = spec.Transfer( sender=sender_index, recipient=recipient_index, amount=amount, fee=fee, slot=slot, pubkey=transfer_pubkey, - signature=ZERO_HASH, + signature=spec.ZERO_HASH, ) transfer.signature = bls.sign( message_hash=signing_root(transfer), privkey=transfer_privkey, - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_TRANSFER, - message_epoch=get_current_epoch(state), + message_epoch=spec.get_current_epoch(state), ) ) @@ -372,7 +332,7 @@ def get_valid_transfer(state, slot=None, sender_index=None, amount=None, fee=Non def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0): - message_hash = AttestationDataAndCustodyBit( + message_hash = spec.AttestationDataAndCustodyBit( data=attestation_data, custody_bit=custody_bit, ).hash_tree_root() @@ -380,7 +340,7 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) return bls.sign( message_hash=message_hash, privkey=privkey, - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_ATTESTATION, message_epoch=attestation_data.target_epoch, @@ -389,7 +349,7 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) def fill_aggregate_attestation(state, attestation): - crosslink_committee = get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard) + crosslink_committee = spec.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard) for i in range(len(crosslink_committee)): attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i) @@ -398,7 +358,7 @@ def add_attestation_to_state(state, attestation, slot): block = build_empty_block_for_next_slot(state) block.slot = slot block.body.attestations.append(attestation) - state_transition(state, block) + spec.state_transition(state, block) def next_slot(state): @@ -407,7 +367,7 @@ def next_slot(state): Return the empty block that triggered the transition. """ block = build_empty_block_for_next_slot(state) - state_transition(state, block) + spec.state_transition(state, block) return block @@ -418,7 +378,7 @@ def next_epoch(state): """ block = build_empty_block_for_next_slot(state) block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) - state_transition(state, block) + spec.state_transition(state, block) return block diff --git a/test_libs/pyspec/tests/phase0/test_finality.py b/test_libs/pyspec/tests/phase0/test_finality.py index be8ecaa1d..9e2fc361b 100644 --- a/test_libs/pyspec/tests/phase0/test_finality.py +++ b/test_libs/pyspec/tests/phase0/test_finality.py @@ -42,7 +42,7 @@ def next_epoch_with_attestations(state, block = helpers.build_empty_block_for_next_slot(post_state) if fill_cur_epoch: slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1 - if slot_to_attest >= helpers.get_epoch_start_slot(helpers.get_current_epoch(post_state)): + if slot_to_attest >= spec.get_epoch_start_slot(spec.get_current_epoch(post_state)): cur_attestation = helpers.get_valid_attestation(post_state, slot_to_attest) helpers.fill_aggregate_attestation(post_state, cur_attestation) block.body.attestations.append(cur_attestation) diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py index 62dd2be38..53976aeeb 100644 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -3,27 +3,35 @@ import pytest from eth2spec.phase1 import spec from preset_loader import loader +from tests.phase0 import helpers as phase1_helpers from tests.phase1 import helpers as helpers from tests.phase0.conftest import ( - pytest_addoption, deposit_data_leaves, ) -# This is redfined so that the constants are re-applied +def pytest_addoption(parser): + parser.addoption( + "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" + ) + + @pytest.fixture(autouse=True) def config(request): - request.function.__globals__['spec'] = spec - request.function.__globals__['helpers'] = helpers config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) spec.apply_constants_preset(presets) + helpers.spec = spec + phase1_helpers.spec = spec + request.function.__globals__['spec'] = spec + request.function.__globals__['helpers'] = helpers + @pytest.fixture def num_validators(config): return spec.SLOTS_PER_EPOCH * 8 -#This is redefined so that the BeaconState is the new SSZ Object + @pytest.fixture def state(num_validators, deposit_data_leaves): return helpers.create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py index b56266617..5962e45d1 100644 --- a/test_libs/pyspec/tests/phase1/helpers.py +++ b/test_libs/pyspec/tests/phase1/helpers.py @@ -1,48 +1,35 @@ from py_ecc import bls -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( - # constants - CUSTODY_PERIOD_TO_RANDAO_PADDING, - # SSZ - EarlyDerivedSecretReveal, - # functions - get_active_validator_indices, - get_current_epoch, - get_domain, - hash_tree_root, -) - from tests.phase0.helpers import * def get_valid_early_derived_secret_reveal(state, epoch=None): - current_epoch = get_current_epoch(state) - revealed_index = get_active_validator_indices(state, current_epoch)[-1] - masker_index = get_active_validator_indices(state, current_epoch)[0] + current_epoch = spec.get_current_epoch(state) + revealed_index = spec.get_active_validator_indices(state, current_epoch)[-1] + masker_index = spec.get_active_validator_indices(state, current_epoch)[0] if epoch is None: - epoch = current_epoch + CUSTODY_PERIOD_TO_RANDAO_PADDING + epoch = current_epoch + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING reveal = bls.sign( - message_hash=hash_tree_root(epoch), + message_hash=spec.hash_tree_root(epoch), privkey=privkeys[revealed_index], - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_RANDAO, message_epoch=epoch, ), ) mask = bls.sign( - message_hash=hash_tree_root(epoch), + message_hash=spec.hash_tree_root(epoch), privkey=privkeys[masker_index], - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_RANDAO, message_epoch=epoch, ), ) - return EarlyDerivedSecretReveal( + return spec.EarlyDerivedSecretReveal( revealed_index=revealed_index, epoch=epoch, reveal=reveal,