add additional genesis initialization tests

This commit is contained in:
Danny Ryan
2020-09-28 17:55:54 -06:00
parent 157f7e8ef4
commit 4e2c7d20b7
3 changed files with 171 additions and 14 deletions

View File

@@ -1,3 +1,5 @@
import random
from eth2spec.test.helpers.keys import pubkeys, privkeys
from eth2spec.utils import bls
from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof
@@ -62,11 +64,16 @@ def deposit_from_context(spec, deposit_data_list, index):
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,
pubkey_max_range,
pubkey_min_range=0,
signed=False,
deposit_data_list=None):
if deposit_data_list is None:
deposit_data_list = []
genesis_deposits = []
for validator_index in range(genesis_validator_count):
for validator_index in range(pubkey_min_range, pubkey_max_range):
pubkey = pubkeys[validator_index]
privkey = privkeys[validator_index]
# insecurely use pubkey as withdrawal key if no credentials provided
@@ -85,6 +92,40 @@ def prepare_genesis_deposits(spec, genesis_validator_count, amount, signed=False
return genesis_deposits, root, deposit_data_list
def prepare_random_genesis_deposits(spec,
num_deposits,
max_pubkey_index,
min_pubkey_index=0,
max_amount=None,
min_amount=None,
deposit_data_list=None):
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(num_deposits):
pubkey_index = random.randint(min_pubkey_index, max_pubkey_index)
pubkey = pubkeys[pubkey_index]
privkey = privkeys[pubkey_index]
amount = random.randint(min_amount, max_amount)
random_byte = bytes([random.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,
pubkey,
privkey,
amount,
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):
"""
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.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
def test_initialize_beacon_state_from_eth1(spec):
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_timestamp = spec.MIN_GENESIS_TIME
@@ -37,14 +43,18 @@ def test_initialize_beacon_state_from_eth1(spec):
@single_phase
def test_initialize_beacon_state_some_small_balances(spec):
main_deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
main_deposits, _, deposit_data_list = prepare_genesis_deposits(spec, main_deposit_count,
spec.MAX_EFFECTIVE_BALANCE, signed=True)
main_deposits, _, deposit_data_list = prepare_full_genesis_deposits(
spec, spec.MAX_EFFECTIVE_BALANCE,
pubkey_max_range=main_deposit_count, signed=True,
)
# For deposits above, and for another deposit_count, add a balance of EFFECTIVE_BALANCE_INCREMENT
small_deposit_count = main_deposit_count * 2
small_deposits, deposit_root, _ = prepare_genesis_deposits(spec, small_deposit_count,
spec.MIN_DEPOSIT_AMOUNT,
signed=True,
deposit_data_list=deposit_data_list)
small_deposits, deposit_root, _ = prepare_full_genesis_deposits(
spec, spec.MIN_DEPOSIT_AMOUNT,
pubkey_max_range=small_deposit_count,
signed=True,
deposit_data_list=deposit_data_list,
)
deposits = main_deposits + small_deposits
eth1_block_hash = b'\x12' * 32
@@ -67,3 +77,109 @@ def test_initialize_beacon_state_some_small_balances(spec):
# yield 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,
pubkey_max_range=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,
pubkey_max_range=main_deposit_count + 1,
pubkey_min_range=main_deposit_count,
signed=True,
deposit_data_list=deposit_data_list,
)
# submit last pubkey deposit as MIN_DEPOSIT_AMOUNT to complete the deposit
completed_deposits, deposit_root, deposit_data_list = prepare_full_genesis_deposits(
spec, spec.MIN_DEPOSIT_AMOUNT,
pubkey_max_range=main_deposit_count + 1,
pubkey_min_range=main_deposit_count,
signed=True,
deposit_data_list=deposit_data_list,
)
deposits = main_deposits + partial_deposits + completed_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,
num_deposits=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,
num_deposits=30,
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,
pubkey_max_range=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,12 @@
from eth2spec.test.context import PHASE0, spec_test, with_phases, single_phase
from eth2spec.test.helpers.deposits import (
prepare_genesis_deposits,
prepare_full_genesis_deposits,
)
def create_valid_beacon_state(spec):
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, deposit_count, spec.MAX_EFFECTIVE_BALANCE, signed=True)
eth1_block_hash = b'\x12' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME
@@ -69,7 +69,7 @@ def test_is_valid_genesis_state_true_more_balance(spec):
@single_phase
def test_is_valid_genesis_state_true_one_more_validator(spec):
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, deposit_count, spec.MAX_EFFECTIVE_BALANCE, signed=True)
eth1_block_hash = b'\x12' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME
@@ -83,7 +83,7 @@ def test_is_valid_genesis_state_true_one_more_validator(spec):
@single_phase
def test_is_valid_genesis_state_false_not_enough_validator(spec):
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, deposit_count, spec.MAX_EFFECTIVE_BALANCE, signed=True)
eth1_block_hash = b'\x12' * 32
eth1_timestamp = spec.MIN_GENESIS_TIME