diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index 4858f2575..3cba3188d 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -47,6 +47,7 @@ - [`compute_updated_gasprice`](#compute_updated_gasprice) - [`compute_committee_source_epoch`](#compute_committee_source_epoch) - [Beacon state accessors](#beacon-state-accessors) + - [New `get_committee_count_per_slot`](#new-get_committee_count_per_slot) - [`get_active_shard_count`](#get_active_shard_count) - [`get_online_validator_indices`](#get_online_validator_indices) - [`get_shard_committee`](#get_shard_committee) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 68696ea0a..69be2fd0a 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -151,6 +151,15 @@ def low_single_balance(spec): return [1] +def large_validator_set(spec): + """ + Helper method to create a series of default balances. + Usage: `@with_custom_state(balances_fn=default_balances, ...)` + """ + num_validators = 2 * spec.SLOTS_PER_EPOCH * spec.MAX_COMMITTEES_PER_SLOT * spec.TARGET_COMMITTEE_SIZE + return [spec.MAX_EFFECTIVE_BALANCE] * num_validators + + def single_phase(fn): """ Decorator that filters out the phases data. diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py index 6d7ff096a..3ec76e8b8 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -22,7 +22,10 @@ from eth2spec.test.helpers.shard_transitions import get_shard_transition_of_comm from eth2spec.test.context import ( PHASE0, PHASE1, + spec_test, spec_state_test, with_all_phases, expect_assertion_error, always_bls, with_phases, + with_custom_state, single_phase, + large_validator_set, ) @@ -85,6 +88,28 @@ def test_empty_block_transition(spec, state): assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.Bytes32() +@with_all_phases +@spec_test +@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.EJECTION_BALANCE) +@single_phase +def test_empty_block_transition_large_validator_set(spec, state): + pre_slot = state.slot + pre_eth1_votes = len(state.eth1_data_votes) + + yield 'pre', state + + block = build_empty_block_for_next_slot(spec, state) + + signed_block = state_transition_and_sign_block(spec, state, block) + + yield 'blocks', [signed_block] + yield 'post', state + + assert len(state.eth1_data_votes) == pre_eth1_votes + 1 + assert spec.get_block_root_at_slot(state, pre_slot) == signed_block.message.parent_root + assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.Bytes32() + + def process_and_sign_block_without_header_validations(spec, state, block): """ Artificially bypass the restrictions in the state transition to transition and sign block @@ -288,6 +313,26 @@ def test_empty_epoch_transition(spec, state): assert spec.get_block_root_at_slot(state, slot) == block.parent_root +@with_all_phases +@spec_test +@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.EJECTION_BALANCE) +@single_phase +def test_empty_epoch_transition_large_validator_set(spec, state): + pre_slot = state.slot + yield 'pre', state + + block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH) + + signed_block = state_transition_and_sign_block(spec, state, block) + + yield 'blocks', [signed_block] + yield 'post', state + + assert state.slot == block.slot + for slot in range(pre_slot, state.slot): + assert spec.get_block_root_at_slot(state, slot) == block.parent_root + + @with_all_phases @spec_state_test def test_empty_epoch_transition_not_finalizing(spec, state):