Merge pull request #2083 from ethereum/init-tests

additional genesis init tests
This commit is contained in:
Danny Ryan 2020-09-29 12:27:56 -06:00 committed by GitHub
commit 122d34a41e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 195 additions and 22 deletions

View File

@ -1,3 +1,5 @@
from random import Random
from eth2spec.test.helpers.keys import pubkeys, privkeys from eth2spec.test.helpers.keys import pubkeys, privkeys
from eth2spec.utils import bls from eth2spec.utils import bls
from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof
@ -62,29 +64,69 @@ def deposit_from_context(spec, deposit_data_list, index):
return deposit, root, deposit_data_list return deposit, root, deposit_data_list
def prepare_genesis_deposits(spec, genesis_validator_count, amount, signed=False, deposit_data_list=None): def prepare_full_genesis_deposits(spec,
amount,
deposit_count,
min_pubkey_index=0,
signed=False,
deposit_data_list=None):
if deposit_data_list is None: if deposit_data_list is None:
deposit_data_list = [] deposit_data_list = []
genesis_deposits = [] genesis_deposits = []
for validator_index in range(genesis_validator_count): for pubkey_index in range(min_pubkey_index, min_pubkey_index + deposit_count):
pubkey = pubkeys[validator_index] pubkey = pubkeys[pubkey_index]
privkey = privkeys[validator_index] privkey = privkeys[pubkey_index]
# insecurely use pubkey as withdrawal key if no credentials provided # insecurely use pubkey as withdrawal key if no credentials provided
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkey)[1:] withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkey)[1:]
deposit, root, deposit_data_list = build_deposit( deposit, root, deposit_data_list = build_deposit(
spec, spec,
deposit_data_list, deposit_data_list=deposit_data_list,
pubkey, pubkey=pubkey,
privkey, privkey=privkey,
amount, amount=amount,
withdrawal_credentials, withdrawal_credentials=withdrawal_credentials,
signed, signed=signed,
) )
genesis_deposits.append(deposit) genesis_deposits.append(deposit)
return genesis_deposits, root, deposit_data_list return genesis_deposits, root, deposit_data_list
def prepare_random_genesis_deposits(spec,
deposit_count,
max_pubkey_index,
min_pubkey_index=0,
max_amount=None,
min_amount=None,
deposit_data_list=None,
rng=Random(3131)):
if max_amount is None:
max_amount = spec.MAX_EFFECTIVE_BALANCE
if min_amount is None:
min_amount = spec.MIN_DEPOSIT_AMOUNT
if deposit_data_list is None:
deposit_data_list = []
deposits = []
for _ in range(deposit_count):
pubkey_index = rng.randint(min_pubkey_index, max_pubkey_index)
pubkey = pubkeys[pubkey_index]
privkey = privkeys[pubkey_index]
amount = rng.randint(min_amount, max_amount)
random_byte = bytes([rng.randint(0, 255)])
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(random_byte)[1:]
deposit, root, deposit_data_list = build_deposit(
spec,
deposit_data_list=deposit_data_list,
pubkey=pubkey,
privkey=privkey,
amount=amount,
withdrawal_credentials=withdrawal_credentials,
signed=True,
)
deposits.append(deposit)
return deposits, root, deposit_data_list
def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_credentials=None, signed=False): def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_credentials=None, signed=False):
""" """
Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount. Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount.

View File

@ -1,6 +1,7 @@
from eth2spec.test.context import PHASE0, spec_test, with_phases, single_phase from eth2spec.test.context import PHASE0, spec_test, with_phases, single_phase
from eth2spec.test.helpers.deposits import ( from eth2spec.test.helpers.deposits import (
prepare_genesis_deposits, prepare_full_genesis_deposits,
prepare_random_genesis_deposits,
) )
@ -9,7 +10,12 @@ from eth2spec.test.helpers.deposits import (
@single_phase @single_phase
def test_initialize_beacon_state_from_eth1(spec): def test_initialize_beacon_state_from_eth1(spec):
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
deposits, deposit_root, _ = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE, signed=True) deposits, deposit_root, _ = prepare_full_genesis_deposits(
spec,
spec.MAX_EFFECTIVE_BALANCE,
deposit_count,
signed=True,
)
eth1_block_hash = b'\x12' * 32 eth1_block_hash = b'\x12' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME eth1_timestamp = spec.MIN_GENESIS_TIME
@ -37,14 +43,18 @@ def test_initialize_beacon_state_from_eth1(spec):
@single_phase @single_phase
def test_initialize_beacon_state_some_small_balances(spec): def test_initialize_beacon_state_some_small_balances(spec):
main_deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT main_deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
main_deposits, _, deposit_data_list = prepare_genesis_deposits(spec, main_deposit_count, main_deposits, _, deposit_data_list = prepare_full_genesis_deposits(
spec.MAX_EFFECTIVE_BALANCE, signed=True) spec, spec.MAX_EFFECTIVE_BALANCE,
deposit_count=main_deposit_count, signed=True,
)
# For deposits above, and for another deposit_count, add a balance of EFFECTIVE_BALANCE_INCREMENT # For deposits above, and for another deposit_count, add a balance of EFFECTIVE_BALANCE_INCREMENT
small_deposit_count = main_deposit_count * 2 small_deposit_count = main_deposit_count * 2
small_deposits, deposit_root, _ = prepare_genesis_deposits(spec, small_deposit_count, small_deposits, deposit_root, _ = prepare_full_genesis_deposits(
spec.MIN_DEPOSIT_AMOUNT, spec, spec.MIN_DEPOSIT_AMOUNT,
deposit_count=small_deposit_count,
signed=True, signed=True,
deposit_data_list=deposit_data_list) deposit_data_list=deposit_data_list,
)
deposits = main_deposits + small_deposits deposits = main_deposits + small_deposits
eth1_block_hash = b'\x12' * 32 eth1_block_hash = b'\x12' * 32
@ -67,3 +77,109 @@ def test_initialize_beacon_state_some_small_balances(spec):
# yield state # yield state
yield 'state', state yield 'state', state
@with_phases([PHASE0])
@spec_test
@single_phase
def test_initialize_beacon_state_one_topup_activation(spec):
# Submit all but one deposit as MAX_EFFECTIVE_BALANCE
main_deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 1
main_deposits, _, deposit_data_list = prepare_full_genesis_deposits(
spec, spec.MAX_EFFECTIVE_BALANCE,
deposit_count=main_deposit_count, signed=True,
)
# Submit last pubkey deposit as MAX_EFFECTIVE_BALANCE - MIN_DEPOSIT_AMOUNT
partial_deposits, _, deposit_data_list = prepare_full_genesis_deposits(
spec, spec.MAX_EFFECTIVE_BALANCE - spec.MIN_DEPOSIT_AMOUNT,
deposit_count=1,
min_pubkey_index=main_deposit_count,
signed=True,
deposit_data_list=deposit_data_list,
)
# Top up thelast pubkey deposit as MIN_DEPOSIT_AMOUNT to complete the deposit
top_up_deposits, _, _ = prepare_full_genesis_deposits(
spec, spec.MIN_DEPOSIT_AMOUNT,
deposit_count=1,
min_pubkey_index=main_deposit_count,
signed=True,
deposit_data_list=deposit_data_list,
)
deposits = main_deposits + partial_deposits + top_up_deposits
eth1_block_hash = b'\x13' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME
yield 'eth1_block_hash', eth1_block_hash
yield 'eth1_timestamp', eth1_timestamp
yield 'deposits', deposits
# initialize beacon_state
state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
assert spec.is_valid_genesis_state(state)
# yield state
yield 'state', state
@with_phases([PHASE0])
@spec_test
@single_phase
def test_initialize_beacon_state_random_invalid_genesis(spec):
# Make a bunch of random deposits
deposits, _, deposit_data_list = prepare_random_genesis_deposits(
spec,
deposit_count=20,
max_pubkey_index=10,
)
eth1_block_hash = b'\x14' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME + 1
yield 'eth1_block_hash', eth1_block_hash
yield 'eth1_timestamp', eth1_timestamp
yield 'deposits', deposits
# initialize beacon_state
state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
assert not spec.is_valid_genesis_state(state)
yield 'state', state
@with_phases([PHASE0])
@spec_test
@single_phase
def test_initialize_beacon_state_random_valid_genesis(spec):
# Make a bunch of random deposits
random_deposits, _, deposit_data_list = prepare_random_genesis_deposits(
spec,
deposit_count=20,
min_pubkey_index=spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 5,
max_pubkey_index=spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT + 5,
)
# Then make spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT full deposits
full_deposits, _, _ = prepare_full_genesis_deposits(
spec,
spec.MAX_EFFECTIVE_BALANCE,
deposit_count=spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT,
signed=True,
deposit_data_list=deposit_data_list
)
deposits = random_deposits + full_deposits
eth1_block_hash = b'\x15' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME + 2
yield 'eth1_block_hash', eth1_block_hash
yield 'eth1_timestamp', eth1_timestamp
yield 'deposits', deposits
# initialize beacon_state
state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
assert spec.is_valid_genesis_state(state)
yield 'state', state

View File

@ -1,12 +1,17 @@
from eth2spec.test.context import PHASE0, spec_test, with_phases, single_phase from eth2spec.test.context import PHASE0, spec_test, with_phases, single_phase
from eth2spec.test.helpers.deposits import ( from eth2spec.test.helpers.deposits import (
prepare_genesis_deposits, prepare_full_genesis_deposits,
) )
def create_valid_beacon_state(spec): def create_valid_beacon_state(spec):
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
deposits, _, _ = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE, signed=True) deposits, _, _ = prepare_full_genesis_deposits(
spec,
amount=spec.MAX_EFFECTIVE_BALANCE,
deposit_count=deposit_count,
signed=True,
)
eth1_block_hash = b'\x12' * 32 eth1_block_hash = b'\x12' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME eth1_timestamp = spec.MIN_GENESIS_TIME
@ -69,7 +74,12 @@ def test_is_valid_genesis_state_true_more_balance(spec):
@single_phase @single_phase
def test_is_valid_genesis_state_true_one_more_validator(spec): def test_is_valid_genesis_state_true_one_more_validator(spec):
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT + 1 deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT + 1
deposits, _, _ = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE, signed=True) deposits, _, _ = prepare_full_genesis_deposits(
spec,
amount=spec.MAX_EFFECTIVE_BALANCE,
deposit_count=deposit_count,
signed=True,
)
eth1_block_hash = b'\x12' * 32 eth1_block_hash = b'\x12' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME eth1_timestamp = spec.MIN_GENESIS_TIME
@ -83,7 +93,12 @@ def test_is_valid_genesis_state_true_one_more_validator(spec):
@single_phase @single_phase
def test_is_valid_genesis_state_false_not_enough_validator(spec): def test_is_valid_genesis_state_false_not_enough_validator(spec):
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 1 deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 1
deposits, _, _ = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE, signed=True) deposits, _, _ = prepare_full_genesis_deposits(
spec,
amount=spec.MAX_EFFECTIVE_BALANCE,
deposit_count=deposit_count,
signed=True,
)
eth1_block_hash = b'\x12' * 32 eth1_block_hash = b'\x12' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME eth1_timestamp = spec.MIN_GENESIS_TIME