From cfcb7b2f015ddf637dae03b7bf262a6d8349a9e0 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 18 Feb 2020 16:12:43 +0300 Subject: [PATCH 1/3] Measure eth1 voting period in epochs instead of slots --- specs/phase0/beacon-chain.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/phase0/beacon-chain.md b/specs/phase0/beacon-chain.md index acf098663..0bf953c43 100644 --- a/specs/phase0/beacon-chain.md +++ b/specs/phase0/beacon-chain.md @@ -213,7 +213,7 @@ The following values are (non-configurable) constants used throughout the specif | `MIN_SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes | | `MAX_SEED_LOOKAHEAD` | `2**2` (= 4) | epochs | 25.6 minutes | | `MIN_EPOCHS_TO_INACTIVITY_PENALTY` | `2**2` (= 4) | epochs | 25.6 minutes | -| `SLOTS_PER_ETH1_VOTING_PERIOD` | `2**10` (= 1,024) | slots | ~3.4 hours | +| `EPOCHS_PER_ETH1_VOTING_PERIOD` | `2**5` (= 32) | epochs | ~3.4 hours | | `SLOTS_PER_HISTORICAL_ROOT` | `2**13` (= 8,192) | slots | ~27 hours | | `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `2**8` (= 256) | epochs | ~27 hours | | `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | 9 days | @@ -478,7 +478,7 @@ class BeaconState(Container): historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] # Eth1 eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, SLOTS_PER_ETH1_VOTING_PERIOD] + eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] eth1_deposit_index: uint64 # Registry validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] @@ -1397,7 +1397,7 @@ def process_final_updates(state: BeaconState) -> None: current_epoch = get_current_epoch(state) next_epoch = Epoch(current_epoch + 1) # Reset eth1 data votes - if (state.slot + 1) % SLOTS_PER_ETH1_VOTING_PERIOD == 0: + if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0: state.eth1_data_votes = [] # Update effective balances with hysteresis for index, validator in enumerate(state.validators): @@ -1468,7 +1468,7 @@ def process_randao(state: BeaconState, body: BeaconBlockBody) -> None: ```python def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None: state.eth1_data_votes.append(body.eth1_data) - if state.eth1_data_votes.count(body.eth1_data) * 2 > SLOTS_PER_ETH1_VOTING_PERIOD: + if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH: state.eth1_data = body.eth1_data ``` From 2d7a292d3663b398ecb222b873ac700726ddf57a Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 Mar 2020 18:36:53 +0100 Subject: [PATCH 2/3] eth1 vote period constant in epochs: update configs, phase1, tests --- configs/mainnet.yaml | 4 +-- configs/minimal.yaml | 2 +- specs/phase0/validator.md | 4 +-- specs/phase1/beacon-chain.md | 2 +- .../test_process_final_updates.py | 4 +-- .../eth2spec/test/sanity/test_blocks.py | 26 +++++++++++-------- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 74f062d9b..69bbbff22 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -82,8 +82,8 @@ SLOTS_PER_EPOCH: 32 MIN_SEED_LOOKAHEAD: 1 # 2**2 (= 4) epochs 25.6 minutes MAX_SEED_LOOKAHEAD: 4 -# 2**10 (= 1,024) slots ~1.7 hours -SLOTS_PER_ETH1_VOTING_PERIOD: 1024 +# 2**5 (= 32) epochs ~3.4 hours +EPOCHS_PER_ETH1_VOTING_PERIOD: 32 # 2**13 (= 8,192) slots ~13 hours SLOTS_PER_HISTORICAL_ROOT: 8192 # 2**8 (= 256) epochs ~27 hours diff --git a/configs/minimal.yaml b/configs/minimal.yaml index 42c63e301..23ebbfbbc 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -82,7 +82,7 @@ MIN_SEED_LOOKAHEAD: 1 # 2**2 (= 4) epochs MAX_SEED_LOOKAHEAD: 4 # [customized] higher frequency new deposits from eth1 for testing -SLOTS_PER_ETH1_VOTING_PERIOD: 16 +EPOCHS_PER_ETH1_VOTING_PERIOD: 2 # [customized] smaller state SLOTS_PER_HISTORICAL_ROOT: 64 # 2**8 (= 256) epochs diff --git a/specs/phase0/validator.md b/specs/phase0/validator.md index 0bde81e60..7865e3921 100644 --- a/specs/phase0/validator.md +++ b/specs/phase0/validator.md @@ -129,7 +129,7 @@ To submit a deposit: ### Process deposit -Deposits cannot be processed into the beacon chain until the Eth1 block in which they were deposited or any of its descendants is added to the beacon chain `state.eth1_data`. This takes _a minimum_ of `ETH1_FOLLOW_DISTANCE` Eth1 blocks (~4 hours) plus `SLOTS_PER_ETH1_VOTING_PERIOD` slots (~3.4 hours). Once the requisite Eth1 data is added, the deposit will normally be added to a beacon chain block and processed into the `state.validators` within an epoch or two. The validator is then in a queue to be activated. +Deposits cannot be processed into the beacon chain until the Eth1 block in which they were deposited or any of its descendants is added to the beacon chain `state.eth1_data`. This takes _a minimum_ of `ETH1_FOLLOW_DISTANCE` Eth1 blocks (~4 hours) plus `EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH` slots (~3.4 hours). Once the requisite Eth1 data is added, the deposit will normally be added to a beacon chain block and processed into the `state.validators` within an epoch or two. The validator is then in a queue to be activated. ### Validator index @@ -269,7 +269,7 @@ def compute_time_at_slot(state: BeaconState, slot: Slot) -> uint64: ```python def voting_period_start_time(state: BeaconState) -> uint64: - eth1_voting_period_start_slot = Slot(state.slot - state.slot % SLOTS_PER_ETH1_VOTING_PERIOD) + eth1_voting_period_start_slot = Slot(state.slot - state.slot % (EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH)) return compute_time_at_slot(state, eth1_voting_period_start_slot) ``` diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index 78b3b3d25..259d18601 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -253,7 +253,7 @@ class BeaconState(Container): historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] # Eth1 eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, SLOTS_PER_ETH1_VOTING_PERIOD] + eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] eth1_deposit_index: uint64 # Registry validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] diff --git a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py b/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py index 58882a44f..110bd35a7 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py @@ -11,7 +11,7 @@ def run_process_final_updates(spec, state): @with_all_phases @spec_state_test def test_eth1_vote_no_reset(spec, state): - assert spec.SLOTS_PER_ETH1_VOTING_PERIOD > spec.SLOTS_PER_EPOCH + assert spec.EPOCHS_PER_ETH1_VOTING_PERIOD > 1 # skip ahead to the end of the epoch state.slot = spec.SLOTS_PER_EPOCH - 1 for i in range(state.slot + 1): # add a vote for each skipped slot. @@ -29,7 +29,7 @@ def test_eth1_vote_no_reset(spec, state): @spec_state_test def test_eth1_vote_reset(spec, state): # skip ahead to the end of the voting period - state.slot = spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1 + state.slot = (spec.EPOCHS_PER_ETH1_VOTING_PERIOD * spec.SLOTS_PER_EPOCH) - 1 for i in range(state.slot + 1): # add a vote for each skipped slot. state.eth1_data_votes.append( spec.Eth1Data(deposit_root=b'\xaa' * 32, diff --git a/tests/core/pyspec/eth2spec/test/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/sanity/test_blocks.py index 9027660ab..c6f9d8576 100644 --- a/tests/core/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/sanity/test_blocks.py @@ -486,10 +486,12 @@ def test_historical_batch(spec, state): @spec_state_test def test_eth1_data_votes_consensus(spec, state): # Don't run when it will take very, very long to simulate. Minimal configuration suffices. - if spec.SLOTS_PER_ETH1_VOTING_PERIOD > 16: + if spec.EPOCHS_PER_ETH1_VOTING_PERIOD > 2: return - offset_block = build_empty_block(spec, state, slot=spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1) + voting_period_slots = spec.EPOCHS_PER_ETH1_VOTING_PERIOD * spec.SLOTS_PER_EPOCH + + offset_block = build_empty_block(spec, state, slot=voting_period_slots - 1) state_transition_and_sign_block(spec, state, offset_block) yield 'pre', state @@ -499,14 +501,14 @@ def test_eth1_data_votes_consensus(spec, state): blocks = [] - for i in range(0, spec.SLOTS_PER_ETH1_VOTING_PERIOD): + for i in range(0, voting_period_slots): block = build_empty_block_for_next_slot(spec, state) # wait for over 50% for A, then start voting B - block.body.eth1_data.block_hash = b if i * 2 > spec.SLOTS_PER_ETH1_VOTING_PERIOD else a + block.body.eth1_data.block_hash = b if i * 2 > voting_period_slots else a signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(signed_block) - assert len(state.eth1_data_votes) == spec.SLOTS_PER_ETH1_VOTING_PERIOD + assert len(state.eth1_data_votes) == voting_period_slots assert state.eth1_data.block_hash == a # transition to next eth1 voting period @@ -519,7 +521,7 @@ def test_eth1_data_votes_consensus(spec, state): yield 'post', state assert state.eth1_data.block_hash == a - assert state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 + assert state.slot % voting_period_slots == 0 assert len(state.eth1_data_votes) == 1 assert state.eth1_data_votes[0].block_hash == c @@ -528,12 +530,14 @@ def test_eth1_data_votes_consensus(spec, state): @spec_state_test def test_eth1_data_votes_no_consensus(spec, state): # Don't run when it will take very, very long to simulate. Minimal configuration suffices. - if spec.SLOTS_PER_ETH1_VOTING_PERIOD > 16: + if spec.EPOCHS_PER_ETH1_VOTING_PERIOD > 2: return + voting_period_slots = spec.EPOCHS_PER_ETH1_VOTING_PERIOD * spec.SLOTS_PER_EPOCH + pre_eth1_hash = state.eth1_data.block_hash - offset_block = build_empty_block(spec, state, slot=spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1) + offset_block = build_empty_block(spec, state, slot=voting_period_slots - 1) state_transition_and_sign_block(spec, state, offset_block) yield 'pre', state @@ -542,14 +546,14 @@ def test_eth1_data_votes_no_consensus(spec, state): blocks = [] - for i in range(0, spec.SLOTS_PER_ETH1_VOTING_PERIOD): + for i in range(0, voting_period_slots): block = build_empty_block_for_next_slot(spec, state) # wait for precisely 50% for A, then start voting B for other 50% - block.body.eth1_data.block_hash = b if i * 2 >= spec.SLOTS_PER_ETH1_VOTING_PERIOD else a + block.body.eth1_data.block_hash = b if i * 2 >= voting_period_slots else a signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(signed_block) - assert len(state.eth1_data_votes) == spec.SLOTS_PER_ETH1_VOTING_PERIOD + assert len(state.eth1_data_votes) == voting_period_slots assert state.eth1_data.block_hash == pre_eth1_hash yield 'blocks', blocks From 55d436db517f95fa39dd202619c02adf92b61c8a Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 Mar 2020 18:55:59 +0100 Subject: [PATCH 3/3] simplify description of voting period time --- specs/phase0/validator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/phase0/validator.md b/specs/phase0/validator.md index 7865e3921..009816c2e 100644 --- a/specs/phase0/validator.md +++ b/specs/phase0/validator.md @@ -129,7 +129,7 @@ To submit a deposit: ### Process deposit -Deposits cannot be processed into the beacon chain until the Eth1 block in which they were deposited or any of its descendants is added to the beacon chain `state.eth1_data`. This takes _a minimum_ of `ETH1_FOLLOW_DISTANCE` Eth1 blocks (~4 hours) plus `EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH` slots (~3.4 hours). Once the requisite Eth1 data is added, the deposit will normally be added to a beacon chain block and processed into the `state.validators` within an epoch or two. The validator is then in a queue to be activated. +Deposits cannot be processed into the beacon chain until the Eth1 block in which they were deposited or any of its descendants is added to the beacon chain `state.eth1_data`. This takes _a minimum_ of `ETH1_FOLLOW_DISTANCE` Eth1 blocks (~4 hours) plus `EPOCHS_PER_ETH1_VOTING_PERIOD` epochs (~3.4 hours). Once the requisite Eth1 data is added, the deposit will normally be added to a beacon chain block and processed into the `state.validators` within an epoch or two. The validator is then in a queue to be activated. ### Validator index