Add validator guide tests
1. "Becoming a validator" 2. "Validator assignments" 3. "Beacon chain responsibilities: Block proposal"
This commit is contained in:
parent
4d980aec71
commit
303d7d5adb
|
@ -0,0 +1,182 @@
|
||||||
|
from eth2spec.test.context import spec_state_test, never_bls, with_all_phases
|
||||||
|
from eth2spec.test.helpers.block import build_empty_block
|
||||||
|
from eth2spec.test.helpers.deposits import prepare_state_and_deposit
|
||||||
|
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
||||||
|
from eth2spec.test.helpers.state import next_epoch
|
||||||
|
from eth2spec.utils import bls
|
||||||
|
|
||||||
|
|
||||||
|
def run_is_candidate_block(spec, eth1_block, period_start, success):
|
||||||
|
result = spec.is_candidate_block(eth1_block, period_start)
|
||||||
|
if success:
|
||||||
|
assert result
|
||||||
|
else:
|
||||||
|
assert not result
|
||||||
|
|
||||||
|
|
||||||
|
def get_min_new_period_epochs(spec):
|
||||||
|
return int(
|
||||||
|
spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2 # to seconds
|
||||||
|
/ spec.SECONDS_PER_SLOT / spec.SLOTS_PER_EPOCH
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Becoming a validator
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
@never_bls
|
||||||
|
def test_check_if_validator_active(spec, state):
|
||||||
|
active_validator_index = len(state.validators) - 1
|
||||||
|
assert spec.check_if_validator_active(state, active_validator_index)
|
||||||
|
new_validator_index = len(state.validators)
|
||||||
|
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||||
|
deposit = prepare_state_and_deposit(spec, state, new_validator_index, amount, signed=True)
|
||||||
|
spec.process_deposit(state, deposit)
|
||||||
|
assert not spec.check_if_validator_active(state, new_validator_index)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Validator assignments
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
@never_bls
|
||||||
|
def test_get_committee_assignment(spec, state):
|
||||||
|
epoch = spec.get_current_epoch(state)
|
||||||
|
validator_index = len(state.validators) - 1
|
||||||
|
assignment = spec.get_committee_assignment(state, epoch, validator_index)
|
||||||
|
committee, committee_index, slot = assignment
|
||||||
|
assert spec.compute_epoch_at_slot(slot) == epoch
|
||||||
|
assert committee == spec.get_beacon_committee(state, slot, committee_index)
|
||||||
|
assert committee_index < spec.get_committee_count_at_slot(state, slot)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
@never_bls
|
||||||
|
def test_is_proposer(spec, state):
|
||||||
|
proposer_index = spec.get_beacon_proposer_index(state)
|
||||||
|
assert spec.is_proposer(state, proposer_index)
|
||||||
|
|
||||||
|
proposer_index = proposer_index + 1 % len(state.validators)
|
||||||
|
assert not spec.is_proposer(state, proposer_index)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Beacon chain responsibilities
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# Block proposal
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_get_epoch_signature(spec, state):
|
||||||
|
block = spec.BeaconBlock()
|
||||||
|
privkey = privkeys[0]
|
||||||
|
pubkey = pubkeys[0]
|
||||||
|
signature = spec.get_epoch_signature(state, block, privkey)
|
||||||
|
domain = spec.get_domain(state, spec.DOMAIN_RANDAO, spec.compute_epoch_at_slot(block.slot))
|
||||||
|
signing_root = spec.compute_signing_root(spec.compute_epoch_at_slot(block.slot), domain)
|
||||||
|
assert bls.Verify(pubkey, signing_root, signature)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_is_candidate_block(spec, state):
|
||||||
|
period_start = spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2 + 1000
|
||||||
|
run_is_candidate_block(
|
||||||
|
spec,
|
||||||
|
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE),
|
||||||
|
period_start,
|
||||||
|
success=True,
|
||||||
|
)
|
||||||
|
run_is_candidate_block(
|
||||||
|
spec,
|
||||||
|
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE + 1),
|
||||||
|
period_start,
|
||||||
|
success=False,
|
||||||
|
)
|
||||||
|
run_is_candidate_block(
|
||||||
|
spec,
|
||||||
|
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2),
|
||||||
|
period_start,
|
||||||
|
success=True,
|
||||||
|
)
|
||||||
|
run_is_candidate_block(
|
||||||
|
spec,
|
||||||
|
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2 - 1),
|
||||||
|
period_start,
|
||||||
|
success=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_get_eth1_data_default_vote(spec, state):
|
||||||
|
min_new_period_epochs = get_min_new_period_epochs(spec)
|
||||||
|
for _ in range(min_new_period_epochs):
|
||||||
|
next_epoch(spec, state)
|
||||||
|
|
||||||
|
state.eth1_data_votes = ()
|
||||||
|
eth1_chain = []
|
||||||
|
eth1_data = spec.get_eth1_vote(state, eth1_chain)
|
||||||
|
assert eth1_data == state.eth1_data
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_get_eth1_data_consensus_vote(spec, state):
|
||||||
|
min_new_period_epochs = get_min_new_period_epochs(spec)
|
||||||
|
for _ in range(min_new_period_epochs):
|
||||||
|
next_epoch(spec, state)
|
||||||
|
|
||||||
|
period_start = spec.voting_period_start_time(state)
|
||||||
|
votes_length = spec.get_current_epoch(state) % spec.EPOCHS_PER_ETH1_VOTING_PERIOD
|
||||||
|
state.eth1_data_votes = ()
|
||||||
|
eth1_chain = []
|
||||||
|
eth1_data_votes = []
|
||||||
|
block = spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE)
|
||||||
|
for i in range(votes_length):
|
||||||
|
eth1_chain.append(block)
|
||||||
|
eth1_data_votes.append(spec.get_eth1_data(block))
|
||||||
|
|
||||||
|
state.eth1_data_votes = eth1_data_votes
|
||||||
|
eth1_data = spec.get_eth1_vote(state, eth1_chain)
|
||||||
|
print(state.eth1_data_votes)
|
||||||
|
assert eth1_data.block_hash == block.hash_tree_root()
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_compute_new_state_root(spec, state):
|
||||||
|
pre_state = state.copy()
|
||||||
|
post_state = state.copy()
|
||||||
|
block = build_empty_block(spec, state, state.slot + 1)
|
||||||
|
state_root = spec.compute_new_state_root(state, block)
|
||||||
|
|
||||||
|
assert state_root != pre_state.hash_tree_root()
|
||||||
|
|
||||||
|
# dumb verification
|
||||||
|
spec.process_slots(post_state, block.slot)
|
||||||
|
spec.process_block(post_state, block)
|
||||||
|
assert state_root == post_state.hash_tree_root()
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_get_block_signature(spec, state):
|
||||||
|
privkey = privkeys[0]
|
||||||
|
pubkey = pubkeys[0]
|
||||||
|
block = build_empty_block(spec, state)
|
||||||
|
signature = spec.get_block_signature(state, block, privkey)
|
||||||
|
domain = spec.get_domain(state, spec.DOMAIN_BEACON_PROPOSER, spec.compute_epoch_at_slot(block.slot))
|
||||||
|
signing_root = spec.compute_signing_root(block, domain)
|
||||||
|
assert bls.Verify(pubkey, signing_root, signature)
|
Loading…
Reference in New Issue