From 9004bcf1a51ce11dfacfb044c4351a12165edfc7 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 25 Nov 2019 15:06:33 -0700 Subject: [PATCH 01/56] WIP filter block tree --- specs/core/0_fork-choice.md | 49 +++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 099843067..86afdb7d5 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -136,17 +136,62 @@ def get_latest_attesting_balance(store: Store, root: Root) -> Gwei: )) ``` +#### `filter_block_tree` + +```python +def filter_block_tree(store, block_root, blocks): + block = store.blocks[block_root] + children = [ + root for root in store.blocks.keys() + if store.blocks[root].parent_root == block + ] + + # If any children branches contain expected finalized/justified checkpoints, + # add to filtered block-tree and signal viability to parent. + if any(children): + if True in [filter_block_tree(child, blocks) for child in children]: + blocks[block_root] = block + return True + return False + + # If leaf block, check finalized/justified checkpoints as matching latest. + # If matching, add to viable block-tree and signal viability to parent. + head_state = store.block_states[block_root] + is_viable_branch = ( + head_state.finalized_checkpoint == store.finalized_checkpoint + and head_state.current_justified_checkpoint == store.justified_checkpoint + ) + if is_viable_branch: + blocks[block_root] = block + return True + + # Otherwise, not viable + return False +``` + +#### `get_filtered_block_tree` + +```python +def get_filtered_block_tree(store: Store) -> Dict[Root, BeaconBlock]: + head = store.justified_checkpoint.root + blocks = {} + filter_block_tree(head, blocks) + return blocks +``` + #### `get_head` ```python def get_head(store: Store) -> Root: + # Get filtered block tree that includes viable branches + blocks = get_filtered_block_tree(store) # Execute the LMD-GHOST fork choice head = store.justified_checkpoint.root justified_slot = compute_start_slot_at_epoch(store.justified_checkpoint.epoch) while True: children = [ - root for root in store.blocks.keys() - if store.blocks[root].parent_root == head and store.blocks[root].slot > justified_slot + root for root in blocks.keys() + if blocks[root].parent_root == head and blocks[root].slot > justified_slot ] if len(children) == 0: return head From 8021f34c0682a639830f4a60a5f39c6b347e1280 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 25 Nov 2019 15:44:22 -0700 Subject: [PATCH 02/56] fix existing fork choce tests with new filter --- specs/core/0_fork-choice.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 86afdb7d5..d62b04169 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -139,17 +139,17 @@ def get_latest_attesting_balance(store: Store, root: Root) -> Gwei: #### `filter_block_tree` ```python -def filter_block_tree(store, block_root, blocks): +def filter_block_tree(store: Store, block_root: Root, blocks: Dict[Root, BeaconBlock]) -> bool: block = store.blocks[block_root] children = [ root for root in store.blocks.keys() - if store.blocks[root].parent_root == block + if store.blocks[root].parent_root == block_root ] # If any children branches contain expected finalized/justified checkpoints, # add to filtered block-tree and signal viability to parent. if any(children): - if True in [filter_block_tree(child, blocks) for child in children]: + if True in [filter_block_tree(store, child, blocks) for child in children]: blocks[block_root] = block return True return False @@ -157,10 +157,15 @@ def filter_block_tree(store, block_root, blocks): # If leaf block, check finalized/justified checkpoints as matching latest. # If matching, add to viable block-tree and signal viability to parent. head_state = store.block_states[block_root] - is_viable_branch = ( - head_state.finalized_checkpoint == store.finalized_checkpoint - and head_state.current_justified_checkpoint == store.justified_checkpoint - ) + + # Handle base case where justified hasn't updated yet + if head_state.current_justified_checkpoint.epoch == GENESIS_EPOCH: + is_viable_branch = True + else: + is_viable_branch = ( + head_state.finalized_checkpoint == store.finalized_checkpoint + and head_state.current_justified_checkpoint == store.justified_checkpoint + ) if is_viable_branch: blocks[block_root] = block return True @@ -174,8 +179,8 @@ def filter_block_tree(store, block_root, blocks): ```python def get_filtered_block_tree(store: Store) -> Dict[Root, BeaconBlock]: head = store.justified_checkpoint.root - blocks = {} - filter_block_tree(head, blocks) + blocks: Dict[Root, BeaconBlock] = {} + filter_block_tree(store, head, blocks) return blocks ``` @@ -185,6 +190,8 @@ def get_filtered_block_tree(store: Store) -> Dict[Root, BeaconBlock]: def get_head(store: Store) -> Root: # Get filtered block tree that includes viable branches blocks = get_filtered_block_tree(store) + print(len(blocks)) + print(len(store.blocks)) # Execute the LMD-GHOST fork choice head = store.justified_checkpoint.root justified_slot = compute_start_slot_at_epoch(store.justified_checkpoint.epoch) From 5aa9f9655871b2f86ac06bed676b0bf752ad851b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 27 Nov 2019 13:11:30 -0700 Subject: [PATCH 03/56] Update specs/core/0_fork-choice.md Co-Authored-By: Diederik Loerakker --- specs/core/0_fork-choice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index d62b04169..c9a5c90d6 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -149,7 +149,7 @@ def filter_block_tree(store: Store, block_root: Root, blocks: Dict[Root, BeaconB # If any children branches contain expected finalized/justified checkpoints, # add to filtered block-tree and signal viability to parent. if any(children): - if True in [filter_block_tree(store, child, blocks) for child in children]: + if any(filter_block_tree(store, child, blocks) for child in children): blocks[block_root] = block return True return False From 2275cdfeb8e8d823fcf1af2f67884695c475e4a7 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 27 Nov 2019 13:26:44 -0700 Subject: [PATCH 04/56] fix child filter in get_head --- specs/core/0_fork-choice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index c9a5c90d6..d62b04169 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -149,7 +149,7 @@ def filter_block_tree(store: Store, block_root: Root, blocks: Dict[Root, BeaconB # If any children branches contain expected finalized/justified checkpoints, # add to filtered block-tree and signal viability to parent. if any(children): - if any(filter_block_tree(store, child, blocks) for child in children): + if True in [filter_block_tree(store, child, blocks) for child in children]: blocks[block_root] = block return True return False From dfcd6f6402be7d5d660f9aa91ebf72ebff0f01a6 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 4 Dec 2019 16:50:48 -0700 Subject: [PATCH 05/56] add tests for block filter in get_head --- specs/core/0_fork-choice.md | 38 ++++----- .../test/fork_choice/test_get_head.py | 80 ++++++++++++++++++- 2 files changed, 99 insertions(+), 19 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index d62b04169..3cdbcbc5a 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -155,22 +155,22 @@ def filter_block_tree(store: Store, block_root: Root, blocks: Dict[Root, BeaconB return False # If leaf block, check finalized/justified checkpoints as matching latest. - # If matching, add to viable block-tree and signal viability to parent. head_state = store.block_states[block_root] - # Handle base case where justified hasn't updated yet - if head_state.current_justified_checkpoint.epoch == GENESIS_EPOCH: - is_viable_branch = True - else: - is_viable_branch = ( - head_state.finalized_checkpoint == store.finalized_checkpoint - and head_state.current_justified_checkpoint == store.justified_checkpoint - ) - if is_viable_branch: + correct_justified = ( + store.justified_checkpoint.epoch == GENESIS_EPOCH + or head_state.current_justified_checkpoint == store.justified_checkpoint + ) + correct_finalized = ( + store.finalized_checkpoint.epoch == GENESIS_EPOCH + or head_state.finalized_checkpoint == store.finalized_checkpoint + ) + # If expected finalized/justified, add to viable block-tree and signal viability to parent. + if correct_justified and correct_finalized: blocks[block_root] = block return True - # Otherwise, not viable + # Otherwise, branch not viable return False ``` @@ -178,9 +178,13 @@ def filter_block_tree(store: Store, block_root: Root, blocks: Dict[Root, BeaconB ```python def get_filtered_block_tree(store: Store) -> Dict[Root, BeaconBlock]: - head = store.justified_checkpoint.root + """ + Retrieve a filtered block true from ``store``, only returning branches + whose leaf state's justified/finalized info agrees with that in ``store``. + """ + base = store.justified_checkpoint.root blocks: Dict[Root, BeaconBlock] = {} - filter_block_tree(store, head, blocks) + filter_block_tree(store, base, blocks) return blocks ``` @@ -188,10 +192,8 @@ def get_filtered_block_tree(store: Store) -> Dict[Root, BeaconBlock]: ```python def get_head(store: Store) -> Root: - # Get filtered block tree that includes viable branches + # Get filtered block tree that only includes viable branches blocks = get_filtered_block_tree(store) - print(len(blocks)) - print(len(store.blocks)) # Execute the LMD-GHOST fork choice head = store.justified_checkpoint.root justified_slot = compute_start_slot_at_epoch(store.justified_checkpoint.epoch) @@ -224,8 +226,8 @@ def should_update_justified_checkpoint(store: Store, new_justified_checkpoint: C if new_justified_block.slot <= compute_start_slot_at_epoch(store.justified_checkpoint.epoch): return False if not ( - get_ancestor(store, new_justified_checkpoint.root, store.blocks[store.justified_checkpoint.root].slot) == - store.justified_checkpoint.root + get_ancestor(store, new_justified_checkpoint.root, store.blocks[store.justified_checkpoint.root].slot) + == store.justified_checkpoint.root ): return False diff --git a/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py b/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py index ff5a822fb..f0098bb98 100644 --- a/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py +++ b/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py @@ -1,7 +1,12 @@ from eth2spec.test.context import with_all_phases, spec_state_test from eth2spec.test.helpers.attestations import get_valid_attestation from eth2spec.test.helpers.block import build_empty_block_for_next_slot -from eth2spec.test.helpers.state import state_transition_and_sign_block +from eth2spec.test.helpers.state import ( + next_epoch, + next_epoch_with_attestations, + state_transition_and_sign_block, +) +from eth2spec.utils.ssz.ssz_impl import signing_root def add_block_to_store(spec, store, block): @@ -112,3 +117,76 @@ def test_shorter_chain_but_heavier_weight(spec, state): add_attestation_to_store(spec, store, short_attestation) assert spec.get_head(store) == spec.signing_root(short_block) + + +@with_all_phases +@spec_state_test +def test_filtered_block_tree(spec, state): + genesis_state = state.copy() + + # transition state past initial couple of epochs + next_epoch(spec, state) + next_epoch(spec, state) + + # Initialization + store = spec.get_genesis_store(genesis_state) + genesis_block = spec.BeaconBlock(state_root=genesis_state.hash_tree_root()) + assert spec.get_head(store) == spec.signing_root(genesis_block) + + # fill in attestations for entire epoch, justifying the recent epoch + prev_state, blocks, state = next_epoch_with_attestations(spec, state, True, False) + attestations = [attestation for block in blocks for attestation in block.body.attestations] + assert state.current_justified_checkpoint.epoch > prev_state.current_justified_checkpoint.epoch + + # tick time forward and add blocks and attestations to store + current_time = state.slot * spec.SECONDS_PER_SLOT + store.genesis_time + spec.on_tick(store, current_time) + for block in blocks: + spec.on_block(store, block) + for attestation in attestations: + spec.on_attestation(store, attestation) + + assert store.justified_checkpoint == state.current_justified_checkpoint + + # the last block in the branch should be the head + expected_head_root = signing_root(blocks[-1]) + assert spec.get_head(store) == expected_head_root + + # + # create branch containing the justified block but not containing enough on + # chain votes to justify that block + # + + # build a chain without attestations off of previous justified block + non_viable_state = store.block_states[store.justified_checkpoint.root].copy() + + # ensure that next wave of votes are for future epoch + next_epoch(spec, non_viable_state) + next_epoch(spec, non_viable_state) + next_epoch(spec, non_viable_state) + assert spec.get_current_epoch(non_viable_state) > store.justified_checkpoint.epoch + + # create rogue block that will be attested to in this non-viable branch + rogue_block = build_empty_block_for_next_slot(spec, non_viable_state, True) + state_transition_and_sign_block(spec, non_viable_state, rogue_block) + + # create an epoch's worth of attestations for the rogue block + next_epoch(spec, non_viable_state) + attestations = [] + for i in range(spec.SLOTS_PER_EPOCH): + slot = rogue_block.slot + i + for index in range(spec.get_committee_count_at_slot(non_viable_state, slot)): + attestation = get_valid_attestation(spec, non_viable_state, rogue_block.slot + i, index) + attestations.append(attestation) + + # tick time forward to be able to include up to the latest attestation + current_time = (attestations[-1].data.slot + 1) * spec.SECONDS_PER_SLOT + store.genesis_time + spec.on_tick(store, current_time) + + # include rogue block and associated attestations in the store + spec.on_block(store, rogue_block) + for attestation in attestations: + spec.on_attestation(store, attestation) + + # ensure that get_head still returns the head from the previous branch + assert spec.get_head(store) == expected_head_root From 7baf81e4c2991d31982bf252562d4cfe3d7428e9 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 5 Dec 2019 18:47:41 +0100 Subject: [PATCH 06/56] minor test style change, avoid state copy --- .../pyspec/eth2spec/test/fork_choice/test_get_head.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py b/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py index f0098bb98..c40864c81 100644 --- a/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py +++ b/test_libs/pyspec/eth2spec/test/fork_choice/test_get_head.py @@ -122,15 +122,15 @@ def test_shorter_chain_but_heavier_weight(spec, state): @with_all_phases @spec_state_test def test_filtered_block_tree(spec, state): - genesis_state = state.copy() + # Initialization + genesis_state_root = state.hash_tree_root() + store = spec.get_genesis_store(state) + genesis_block = spec.BeaconBlock(state_root=genesis_state_root) # transition state past initial couple of epochs next_epoch(spec, state) next_epoch(spec, state) - # Initialization - store = spec.get_genesis_store(genesis_state) - genesis_block = spec.BeaconBlock(state_root=genesis_state.hash_tree_root()) assert spec.get_head(store) == spec.signing_root(genesis_block) # fill in attestations for entire epoch, justifying the recent epoch From e53a6daecc179f50cf9d3877483d568127a98d20 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 8 Dec 2019 11:50:04 -0700 Subject: [PATCH 07/56] clarify fliter block tree through two line usage Co-Authored-By: Hsiao-Wei Wang --- specs/core/0_fork-choice.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 3cdbcbc5a..95e8ee7a2 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -149,7 +149,8 @@ def filter_block_tree(store: Store, block_root: Root, blocks: Dict[Root, BeaconB # If any children branches contain expected finalized/justified checkpoints, # add to filtered block-tree and signal viability to parent. if any(children): - if True in [filter_block_tree(store, child, blocks) for child in children]: + filter_block_tree_result = [filter_block_tree(store, child, blocks) for child in children] + if any(filter_block_tree_result): blocks[block_root] = block return True return False From d4d17ecc4e06b92852b8b4592895bcc1d253d087 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 9 Dec 2019 16:47:43 -0700 Subject: [PATCH 08/56] ensure the best better-justification is stored in fork choice --- specs/core/0_fork-choice.md | 3 +- .../test/fork_choice/test_on_block.py | 40 ++++++++++++------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 6a5afdf5b..b957d65c1 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -281,7 +281,8 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: # Update justified checkpoint if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch: - store.best_justified_checkpoint = state.current_justified_checkpoint + if state.current_justified_checkpoint.epoch > store.best_justified_checkpoint.epoch: + store.best_justified_checkpoint = state.current_justified_checkpoint if should_update_justified_checkpoint(store, state.current_justified_checkpoint): store.justified_checkpoint = state.current_justified_checkpoint diff --git a/test_libs/pyspec/eth2spec/test/fork_choice/test_on_block.py b/test_libs/pyspec/eth2spec/test/fork_choice/test_on_block.py index 4fda49664..10d1c0011 100644 --- a/test_libs/pyspec/eth2spec/test/fork_choice/test_on_block.py +++ b/test_libs/pyspec/eth2spec/test/fork_choice/test_on_block.py @@ -168,7 +168,7 @@ def test_on_block_update_justified_checkpoint_within_safe_slots(spec, state): @with_all_phases @spec_state_test -def test_on_block_outside_safe_slots_and_old_block(spec, state): +def test_on_block_outside_safe_slots_and_multiple_better_justified(spec, state): # Initialization store = spec.get_genesis_store(state) time = 100 @@ -187,20 +187,30 @@ def test_on_block_outside_safe_slots_and_old_block(spec, state): just_block.slot = spec.compute_start_slot_at_epoch(store.justified_checkpoint.epoch) store.blocks[just_block.hash_tree_root()] = just_block - # Mock the justified checkpoint - just_state = store.block_states[last_block_root] - new_justified = spec.Checkpoint( - epoch=just_state.current_justified_checkpoint.epoch + 1, - root=just_block.hash_tree_root(), - ) - just_state.current_justified_checkpoint = new_justified - - block = build_empty_block_for_next_slot(spec, just_state) - signed_block = state_transition_and_sign_block(spec, deepcopy(just_state), block) - + # Step time past safe slots spec.on_tick(store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.SECONDS_PER_SLOT) assert spec.get_current_slot(store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED - run_on_block(spec, store, signed_block) - assert store.justified_checkpoint != new_justified - assert store.best_justified_checkpoint == new_justified + previously_justified = store.justified_checkpoint + + # Add a series of new blocks with "better" justifications + best_justified_checkpoint = spec.Checkpoint(epoch=0) + for i in range(3, 0, -1): + just_state = store.block_states[last_block_root] + new_justified = spec.Checkpoint( + epoch=previously_justified.epoch + i, + root=just_block.hash_tree_root(), + ) + if new_justified.epoch > best_justified_checkpoint.epoch: + best_justified_checkpoint = new_justified + + just_state.current_justified_checkpoint = new_justified + + block = build_empty_block_for_next_slot(spec, just_state) + signed_block = state_transition_and_sign_block(spec, deepcopy(just_state), block) + + run_on_block(spec, store, signed_block) + + assert store.justified_checkpoint == previously_justified + # ensure the best from the series was stored + assert store.best_justified_checkpoint == best_justified_checkpoint From 432257659e46754dc93ca41f8cf29c44a7eb4cc8 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 9 Dec 2019 17:31:43 -0700 Subject: [PATCH 09/56] add asserts to ensure that attestation slot must match the target epoch --- specs/core/0_beacon-chain.md | 1 + specs/core/0_fork-choice.md | 1 + .../test/fork_choice/test_on_attestation.py | 23 +++++++++++++++++++ .../test_process_attestation.py | 14 +++++++++++ 4 files changed, 39 insertions(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fca21994f..1655d57d9 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1482,6 +1482,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: data = attestation.data assert data.index < get_committee_count_at_slot(state, data.slot) assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) + assert data.target.epoch == compute_epoch_at_slot(data.slot) assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH committee = get_beacon_committee(state, data.slot, data.index) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 6a5afdf5b..f7d863614 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -307,6 +307,7 @@ def on_attestation(store: Store, attestation: Attestation) -> None: # Use GENESIS_EPOCH for previous when genesis to avoid underflow previous_epoch = current_epoch - 1 if current_epoch > GENESIS_EPOCH else GENESIS_EPOCH assert target.epoch in [current_epoch, previous_epoch] + assert target.epoch == compute_epoch_at_slot(attestation.data.slot) # Attestations target be for a known block. If target block is unknown, delay consideration until the block is found assert target.root in store.blocks diff --git a/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py b/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py index 8f1d6f74f..d7fbc4777 100644 --- a/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py +++ b/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py @@ -84,6 +84,29 @@ def test_on_attestation_past_epoch(spec, state): run_on_attestation(spec, state, store, attestation, False) +@with_all_phases +@spec_state_test +def test_on_attestation_mismatched_target_and_slot(spec, state): + store = spec.get_genesis_store(state) + spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH) + + block = build_empty_block_for_next_slot(spec, state) + signed_block = state_transition_and_sign_block(spec, state, block) + + # store block in store + spec.on_block(store, signed_block) + + attestation = get_valid_attestation(spec, state, slot=block.slot) + attestation.data.target.epoch += 1 + sign_attestation(spec, state, attestation) + + assert attestation.data.target.epoch == spec.GENESIS_EPOCH + 1 + assert spec.compute_epoch_at_slot(attestation.data.slot) == spec.GENESIS_EPOCH + assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == spec.GENESIS_EPOCH + 1 + + run_on_attestation(spec, state, store, attestation, False) + + @with_all_phases @spec_state_test def test_on_attestation_target_not_in_store(spec, state): diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index f19bc66d3..d48386fd4 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -177,6 +177,20 @@ def test_invalid_index(spec, state): yield from run_attestation_processing(spec, state, attestation, False) +@with_all_phases +@spec_state_test +def test_mismatched_target_and_slot(spec, state): + next_epoch(spec, state) + next_epoch(spec, state) + + attestation = get_valid_attestation(spec, state) + attestation.data.slot = attestation.data.slot - spec.SLOTS_PER_EPOCH + + sign_attestation(spec, state, attestation) + + yield from run_attestation_processing(spec, state, attestation, False) + + @with_all_phases @spec_state_test def test_old_target_epoch(spec, state): From 9989f3ea9d3ad72507ceb409b051dcef312bc134 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 9 Dec 2019 19:02:16 -0700 Subject: [PATCH 10/56] ensure fork choice functions when GENESIS_SLOT != 0 --- specs/core/0_fork-choice.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 6a5afdf5b..56fe7fef6 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -13,9 +13,15 @@ - [`LatestMessage`](#latestmessage) - [`Store`](#store) - [`get_genesis_store`](#get_genesis_store) + - [`get_slots_since_genesis`](#get_slots_since_genesis) + - [`get_current_slot`](#get_current_slot) + - [`compute_slots_since_epoch_start`](#compute_slots_since_epoch_start) - [`get_ancestor`](#get_ancestor) - [`get_latest_attesting_balance`](#get_latest_attesting_balance) + - [`filter_block_tree`](#filter_block_tree) + - [`get_filtered_block_tree`](#get_filtered_block_tree) - [`get_head`](#get_head) + - [`should_update_justified_checkpoint`](#should_update_justified_checkpoint) - [Handlers](#handlers) - [`on_tick`](#on_tick) - [`on_block`](#on_block) @@ -96,11 +102,18 @@ def get_genesis_store(genesis_state: BeaconState) -> Store: ) ``` +#### `get_slots_since_genesis` + +```python +def get_slots_since_genesis(store: Store) -> Slot: + return Slot((store.time - store.genesis_time) // SECONDS_PER_SLOT) +``` + #### `get_current_slot` ```python def get_current_slot(store: Store) -> Slot: - return Slot((store.time - store.genesis_time) // SECONDS_PER_SLOT) + return GENESIS_SLOT + get_slots_since_genesis(store) ``` #### `compute_slots_since_epoch_start` @@ -327,7 +340,7 @@ def on_attestation(store: Store, attestation: Attestation) -> None: # Attestations can only affect the fork choice of subsequent slots. # Delay consideration in the fork choice until their slot is in the past. - assert store.time >= (attestation.data.slot + 1) * SECONDS_PER_SLOT + assert get_current_slot(store) >= attestation.data.slot + 1 # Get state at the `target` to validate attestation and calculate the committees indexed_attestation = get_indexed_attestation(target_state, attestation) From 8861ca02824a7d439b94176e4676935ffb34a5b4 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 10 Dec 2019 10:05:19 -0700 Subject: [PATCH 11/56] minor typo Co-Authored-By: MrChico --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fca21994f..9c7248c56 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -484,7 +484,7 @@ class BeaconState(Container): ### Signed envelopes -Some messages in the protocol are wrapped in an envelop to better facilitate adding/pruning the signature and to `hash_tree_root` the `message` separate from the signature. +Some messages in the protocol are wrapped in an envelope to better facilitate adding/pruning the signature and to `hash_tree_root` the `message` separate from the signature. #### `SignedVoluntaryExit` From 2c5c9cb71a21c1907c9ad226efe9d25c0ea97c8c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 10 Dec 2019 10:12:51 -0700 Subject: [PATCH 12/56] feedback from mikhail --- specs/core/0_fork-choice.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 56fe7fef6..0aaa7d953 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -105,15 +105,15 @@ def get_genesis_store(genesis_state: BeaconState) -> Store: #### `get_slots_since_genesis` ```python -def get_slots_since_genesis(store: Store) -> Slot: - return Slot((store.time - store.genesis_time) // SECONDS_PER_SLOT) +def get_slots_since_genesis(store: Store) -> int: + return (store.time - store.genesis_time) // SECONDS_PER_SLOT ``` #### `get_current_slot` ```python def get_current_slot(store: Store) -> Slot: - return GENESIS_SLOT + get_slots_since_genesis(store) + return Slot(GENESIS_SLOT + get_slots_since_genesis(store)) ``` #### `compute_slots_since_epoch_start` @@ -277,7 +277,7 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: assert block.parent_root in store.block_states pre_state = store.block_states[block.parent_root].copy() # Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past. - assert store.time >= pre_state.genesis_time + block.slot * SECONDS_PER_SLOT + assert get_current_slot(store) >= block.slot # Add new block to the store store.blocks[hash_tree_root(block)] = block # Check block is a descendant of the finalized block @@ -325,7 +325,7 @@ def on_attestation(store: Store, attestation: Attestation) -> None: assert target.root in store.blocks # Attestations cannot be from future epochs. If they are, delay consideration until the epoch arrives base_state = store.block_states[target.root].copy() - assert store.time >= base_state.genesis_time + compute_start_slot_at_epoch(target.epoch) * SECONDS_PER_SLOT + assert get_current_slot(store) >= compute_start_slot_at_epoch(target.epoch) # Attestations must be for a known block. If block is unknown, delay consideration until the block is found assert attestation.data.beacon_block_root in store.blocks From 12ff64ea1a55d6a8e91b58d0216a4f5b787766f7 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Tue, 10 Dec 2019 15:17:06 +0100 Subject: [PATCH 13/56] Update ToC of specs to consistent use of doctoc --- specs/bls_signature.md | 32 +-- specs/core/0_beacon-chain.md | 224 ++++++++++---------- specs/core/0_deposit-contract.md | 24 ++- specs/core/0_fork-choice.md | 38 ++-- specs/core/1_beacon-chain-misc.md | 44 ++-- specs/core/1_custody-game.md | 94 ++++---- specs/core/1_shard-data-chains.md | 76 +++---- specs/light_client/merkle_proofs.md | 28 +-- specs/light_client/sync_protocol.md | 26 +-- specs/networking/p2p-interface.md | 6 +- specs/simple-serialize.md | 46 ++-- specs/validator/0_beacon-chain-validator.md | 109 +++++----- 12 files changed, 388 insertions(+), 359 deletions(-) diff --git a/specs/bls_signature.md b/specs/bls_signature.md index 652279cd7..284485afb 100644 --- a/specs/bls_signature.md +++ b/specs/bls_signature.md @@ -6,23 +6,25 @@ ## Table of contents + + -- [BLS signature verification](#bls-signature-verification) - - [Table of contents](#table-of-contents) - - [Curve parameters](#curve-parameters) - - [Point representations](#point-representations) - - [G1 points](#g1-points) - - [G2 points](#g2-points) - - [Helpers](#helpers) - - [`hash_to_G2`](#hash_to_g2) - - [`modular_squareroot`](#modular_squareroot) - - [Aggregation operations](#aggregation-operations) - - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys) - - [`bls_aggregate_signatures`](#bls_aggregate_signatures) - - [Signature verification](#signature-verification) - - [`bls_verify`](#bls_verify) - - [`bls_verify_multiple`](#bls_verify_multiple) +- [Curve parameters](#curve-parameters) +- [Point representations](#point-representations) + - [G1 points](#g1-points) + - [G2 points](#g2-points) +- [Helpers](#helpers) + - [`hash_to_G2`](#hash_to_g2) + - [`modular_squareroot`](#modular_squareroot) +- [Aggregation operations](#aggregation-operations) + - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys) + - [`bls_aggregate_signatures`](#bls_aggregate_signatures) +- [Signature verification](#signature-verification) + - [`bls_verify`](#bls_verify) + - [`bls_verify_multiple`](#bls_verify_multiple) + + ## Curve parameters diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 9c7248c56..1c4a4eae9 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -4,119 +4,121 @@ ## Table of contents + + -- [Ethereum 2.0 Phase 0 -- The Beacon Chain](#ethereum-20-phase-0----the-beacon-chain) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Notation](#notation) - - [Custom types](#custom-types) - - [Constants](#constants) - - [Configuration](#configuration) - - [Misc](#misc) - - [Gwei values](#gwei-values) - - [Initial values](#initial-values) - - [Time parameters](#time-parameters) - - [State list lengths](#state-list-lengths) - - [Rewards and penalties](#rewards-and-penalties) - - [Max operations per block](#max-operations-per-block) - - [Domain types](#domain-types) - - [Containers](#containers) - - [Misc dependencies](#misc-dependencies) - - [`Fork`](#fork) - - [`Checkpoint`](#checkpoint) - - [`Validator`](#validator) - - [`AttestationData`](#attestationdata) - - [`IndexedAttestation`](#indexedattestation) - - [`PendingAttestation`](#pendingattestation) - - [`Eth1Data`](#eth1data) - - [`HistoricalBatch`](#historicalbatch) - - [`DepositMessage`](#depositmessage) - - [`DepositData`](#depositdata) - - [`BeaconBlockHeader`](#beaconblockheader) - - [Beacon operations](#beacon-operations) - - [`ProposerSlashing`](#proposerslashing) - - [`AttesterSlashing`](#attesterslashing) - - [`Attestation`](#attestation) - - [`Deposit`](#deposit) - - [`VoluntaryExit`](#voluntaryexit) - - [Beacon blocks](#beacon-blocks) - - [`BeaconBlockBody`](#beaconblockbody) - - [`BeaconBlock`](#beaconblock) - - [Beacon state](#beacon-state) - - [`BeaconState`](#beaconstate) - - [Signed envelopes](#signed-envelopes) - - [`SignedVoluntaryExit`](#signedvoluntaryexit) - - [`SignedBeaconBlock`](#signedbeaconblock) - - [`SignedBeaconBlockHeader`](#signedbeaconblockheader) - - [Helper functions](#helper-functions) - - [Math](#math) - - [`integer_squareroot`](#integer_squareroot) - - [`xor`](#xor) - - [`int_to_bytes`](#int_to_bytes) - - [`bytes_to_int`](#bytes_to_int) - - [Crypto](#crypto) - - [`hash`](#hash) - - [`hash_tree_root`](#hash_tree_root) - - [`bls_verify`](#bls_verify) - - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys) - - [Predicates](#predicates) - - [`is_active_validator`](#is_active_validator) - - [`is_slashable_validator`](#is_slashable_validator) - - [`is_slashable_attestation_data`](#is_slashable_attestation_data) - - [`is_valid_indexed_attestation`](#is_valid_indexed_attestation) - - [`is_valid_merkle_branch`](#is_valid_merkle_branch) - - [Misc](#misc-1) - - [`compute_shuffled_index`](#compute_shuffled_index) - - [`compute_proposer_index`](#compute_proposer_index) - - [`compute_committee`](#compute_committee) - - [`compute_epoch_at_slot`](#compute_epoch_at_slot) - - [`compute_start_slot_at_epoch`](#compute_start_slot_at_epoch) - - [`compute_activation_exit_epoch`](#compute_activation_exit_epoch) - - [`compute_domain`](#compute_domain) - - [Beacon state accessors](#beacon-state-accessors) - - [`get_current_epoch`](#get_current_epoch) - - [`get_previous_epoch`](#get_previous_epoch) - - [`get_block_root`](#get_block_root) - - [`get_block_root_at_slot`](#get_block_root_at_slot) - - [`get_randao_mix`](#get_randao_mix) - - [`get_active_validator_indices`](#get_active_validator_indices) - - [`get_validator_churn_limit`](#get_validator_churn_limit) - - [`get_seed`](#get_seed) - - [`get_committee_count_at_slot`](#get_committee_count_at_slot) - - [`get_beacon_committee`](#get_beacon_committee) - - [`get_beacon_proposer_index`](#get_beacon_proposer_index) - - [`get_total_balance`](#get_total_balance) - - [`get_total_active_balance`](#get_total_active_balance) - - [`get_domain`](#get_domain) - - [`get_indexed_attestation`](#get_indexed_attestation) - - [`get_attesting_indices`](#get_attesting_indices) - - [Beacon state mutators](#beacon-state-mutators) - - [`increase_balance`](#increase_balance) - - [`decrease_balance`](#decrease_balance) - - [`initiate_validator_exit`](#initiate_validator_exit) - - [`slash_validator`](#slash_validator) - - [Genesis](#genesis) - - [Genesis state](#genesis-state) - - [Genesis block](#genesis-block) - - [Beacon chain state transition function](#beacon-chain-state-transition-function) - - [Epoch processing](#epoch-processing) - - [Helper functions](#helper-functions-1) - - [Justification and finalization](#justification-and-finalization) - - [Rewards and penalties](#rewards-and-penalties-1) - - [Registry updates](#registry-updates) - - [Slashings](#slashings) - - [Final updates](#final-updates) - - [Block processing](#block-processing) - - [Block header](#block-header) - - [RANDAO](#randao) - - [Eth1 data](#eth1-data) - - [Operations](#operations) - - [Proposer slashings](#proposer-slashings) - - [Attester slashings](#attester-slashings) - - [Attestations](#attestations) - - [Deposits](#deposits) - - [Voluntary exits](#voluntary-exits) +- [Introduction](#introduction) +- [Notation](#notation) +- [Custom types](#custom-types) +- [Constants](#constants) +- [Configuration](#configuration) + - [Misc](#misc) + - [Gwei values](#gwei-values) + - [Initial values](#initial-values) + - [Time parameters](#time-parameters) + - [State list lengths](#state-list-lengths) + - [Rewards and penalties](#rewards-and-penalties) + - [Max operations per block](#max-operations-per-block) + - [Domain types](#domain-types) +- [Containers](#containers) + - [Misc dependencies](#misc-dependencies) + - [`Fork`](#fork) + - [`Checkpoint`](#checkpoint) + - [`Validator`](#validator) + - [`AttestationData`](#attestationdata) + - [`IndexedAttestation`](#indexedattestation) + - [`PendingAttestation`](#pendingattestation) + - [`Eth1Data`](#eth1data) + - [`HistoricalBatch`](#historicalbatch) + - [`DepositMessage`](#depositmessage) + - [`DepositData`](#depositdata) + - [`BeaconBlockHeader`](#beaconblockheader) + - [Beacon operations](#beacon-operations) + - [`ProposerSlashing`](#proposerslashing) + - [`AttesterSlashing`](#attesterslashing) + - [`Attestation`](#attestation) + - [`Deposit`](#deposit) + - [`VoluntaryExit`](#voluntaryexit) + - [Beacon blocks](#beacon-blocks) + - [`BeaconBlockBody`](#beaconblockbody) + - [`BeaconBlock`](#beaconblock) + - [Beacon state](#beacon-state) + - [`BeaconState`](#beaconstate) + - [Signed envelopes](#signed-envelopes) + - [`SignedVoluntaryExit`](#signedvoluntaryexit) + - [`SignedBeaconBlock`](#signedbeaconblock) + - [`SignedBeaconBlockHeader`](#signedbeaconblockheader) +- [Helper functions](#helper-functions) + - [Math](#math) + - [`integer_squareroot`](#integer_squareroot) + - [`xor`](#xor) + - [`int_to_bytes`](#int_to_bytes) + - [`bytes_to_int`](#bytes_to_int) + - [Crypto](#crypto) + - [`hash`](#hash) + - [`hash_tree_root`](#hash_tree_root) + - [`bls_verify`](#bls_verify) + - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys) + - [Predicates](#predicates) + - [`is_active_validator`](#is_active_validator) + - [`is_slashable_validator`](#is_slashable_validator) + - [`is_slashable_attestation_data`](#is_slashable_attestation_data) + - [`is_valid_indexed_attestation`](#is_valid_indexed_attestation) + - [`is_valid_merkle_branch`](#is_valid_merkle_branch) + - [Misc](#misc-1) + - [`compute_shuffled_index`](#compute_shuffled_index) + - [`compute_proposer_index`](#compute_proposer_index) + - [`compute_committee`](#compute_committee) + - [`compute_epoch_at_slot`](#compute_epoch_at_slot) + - [`compute_start_slot_at_epoch`](#compute_start_slot_at_epoch) + - [`compute_activation_exit_epoch`](#compute_activation_exit_epoch) + - [`compute_domain`](#compute_domain) + - [Beacon state accessors](#beacon-state-accessors) + - [`get_current_epoch`](#get_current_epoch) + - [`get_previous_epoch`](#get_previous_epoch) + - [`get_block_root`](#get_block_root) + - [`get_block_root_at_slot`](#get_block_root_at_slot) + - [`get_randao_mix`](#get_randao_mix) + - [`get_active_validator_indices`](#get_active_validator_indices) + - [`get_validator_churn_limit`](#get_validator_churn_limit) + - [`get_seed`](#get_seed) + - [`get_committee_count_at_slot`](#get_committee_count_at_slot) + - [`get_beacon_committee`](#get_beacon_committee) + - [`get_beacon_proposer_index`](#get_beacon_proposer_index) + - [`get_total_balance`](#get_total_balance) + - [`get_total_active_balance`](#get_total_active_balance) + - [`get_domain`](#get_domain) + - [`get_indexed_attestation`](#get_indexed_attestation) + - [`get_attesting_indices`](#get_attesting_indices) + - [Beacon state mutators](#beacon-state-mutators) + - [`increase_balance`](#increase_balance) + - [`decrease_balance`](#decrease_balance) + - [`initiate_validator_exit`](#initiate_validator_exit) + - [`slash_validator`](#slash_validator) +- [Genesis](#genesis) + - [Genesis state](#genesis-state) + - [Genesis block](#genesis-block) +- [Beacon chain state transition function](#beacon-chain-state-transition-function) + - [Epoch processing](#epoch-processing) + - [Helper functions](#helper-functions-1) + - [Justification and finalization](#justification-and-finalization) + - [Rewards and penalties](#rewards-and-penalties-1) + - [Registry updates](#registry-updates) + - [Slashings](#slashings) + - [Final updates](#final-updates) + - [Block processing](#block-processing) + - [Block header](#block-header) + - [RANDAO](#randao) + - [Eth1 data](#eth1-data) + - [Operations](#operations) + - [Proposer slashings](#proposer-slashings) + - [Attester slashings](#attester-slashings) + - [Attestations](#attestations) + - [Deposits](#deposits) + - [Voluntary exits](#voluntary-exits) + + ## Introduction diff --git a/specs/core/0_deposit-contract.md b/specs/core/0_deposit-contract.md index 06962594e..c9f366330 100644 --- a/specs/core/0_deposit-contract.md +++ b/specs/core/0_deposit-contract.md @@ -4,19 +4,21 @@ ## Table of contents + + -- [Ethereum 2.0 Phase 0 -- Deposit Contract](#ethereum-20-phase-0----deposit-contract) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Constants](#constants) - - [Contract](#contract) - - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - - [`deposit` function](#deposit-function) - - [Deposit amount](#deposit-amount) - - [Withdrawal credentials](#withdrawal-credentials) - - [`DepositEvent` log](#depositevent-log) - - [Vyper code](#vyper-code) +- [Introduction](#introduction) +- [Constants](#constants) + - [Contract](#contract) +- [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) + - [`deposit` function](#deposit-function) + - [Deposit amount](#deposit-amount) + - [Withdrawal credentials](#withdrawal-credentials) + - [`DepositEvent` log](#depositevent-log) +- [Vyper code](#vyper-code) + + ## Introduction diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 6a5afdf5b..ae150de00 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -4,23 +4,31 @@ ## Table of contents + + -- [Ethereum 2.0 Phase 0 -- Beacon Chain Fork Choice](#ethereum-20-phase-0----beacon-chain-fork-choice) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Fork choice](#fork-choice) - - [Helpers](#helpers) - - [`LatestMessage`](#latestmessage) - - [`Store`](#store) - - [`get_genesis_store`](#get_genesis_store) - - [`get_ancestor`](#get_ancestor) - - [`get_latest_attesting_balance`](#get_latest_attesting_balance) - - [`get_head`](#get_head) - - [Handlers](#handlers) - - [`on_tick`](#on_tick) - - [`on_block`](#on_block) - - [`on_attestation`](#on_attestation) +- [Introduction](#introduction) +- [Fork choice](#fork-choice) + - [Configuration](#configuration) + - [Helpers](#helpers) + - [`LatestMessage`](#latestmessage) + - [`Store`](#store) + - [`get_genesis_store`](#get_genesis_store) + - [`get_current_slot`](#get_current_slot) + - [`compute_slots_since_epoch_start`](#compute_slots_since_epoch_start) + - [`get_ancestor`](#get_ancestor) + - [`get_latest_attesting_balance`](#get_latest_attesting_balance) + - [`filter_block_tree`](#filter_block_tree) + - [`get_filtered_block_tree`](#get_filtered_block_tree) + - [`get_head`](#get_head) + - [`should_update_justified_checkpoint`](#should_update_justified_checkpoint) + - [Handlers](#handlers) + - [`on_tick`](#on_tick) + - [`on_block`](#on_block) + - [`on_attestation`](#on_attestation) + + ## Introduction diff --git a/specs/core/1_beacon-chain-misc.md b/specs/core/1_beacon-chain-misc.md index d99aca0ef..b27c72b34 100644 --- a/specs/core/1_beacon-chain-misc.md +++ b/specs/core/1_beacon-chain-misc.md @@ -3,29 +3,31 @@ ## Table of contents + + -- [Phase 1 miscellaneous beacon chain changes](#phase-1-miscellaneous-beacon-chain-changes) - - [Table of contents](#table-of-contents) - - [Configuration](#configuration) - - [Containers](#containers) - - [`CompactCommittee`](#compactcommittee) - - [`ShardReceiptDelta`](#shardreceiptdelta) - - [`ShardReceiptProof`](#shardreceiptproof) - - [Helper functions](#helper-functions) - - [`pack_compact_validator`](#pack_compact_validator) - - [`unpack_compact_validator`](#unpack_compact_validator) - - [`committee_to_compact_committee`](#committee_to_compact_committee) - - [`verify_merkle_proof`](#verify_merkle_proof) - - [`compute_historical_state_generalized_index`](#compute_historical_state_generalized_index) - - [`get_generalized_index_of_crosslink_header`](#get_generalized_index_of_crosslink_header) - - [`process_shard_receipt_proof`](#process_shard_receipt_proof) - - [Changes](#changes) - - [Phase 0 container updates](#phase-0-container-updates) - - [`BeaconState`](#beaconstate) - - [`BeaconBlockBody`](#beaconblockbody) - - [Persistent committees](#persistent-committees) - - [Shard receipt processing](#shard-receipt-processing) +- [Configuration](#configuration) +- [Containers](#containers) + - [`CompactCommittee`](#compactcommittee) + - [`ShardReceiptDelta`](#shardreceiptdelta) + - [`ShardReceiptProof`](#shardreceiptproof) +- [Helper functions](#helper-functions) + - [`pack_compact_validator`](#pack_compact_validator) + - [`unpack_compact_validator`](#unpack_compact_validator) + - [`committee_to_compact_committee`](#committee_to_compact_committee) + - [`verify_merkle_proof`](#verify_merkle_proof) + - [`compute_historical_state_generalized_index`](#compute_historical_state_generalized_index) + - [`get_generalized_index_of_crosslink_header`](#get_generalized_index_of_crosslink_header) + - [`process_shard_receipt_proof`](#process_shard_receipt_proof) +- [Changes](#changes) + - [Phase 0 container updates](#phase-0-container-updates) + - [`BeaconState`](#beaconstate) + - [`BeaconBlockBody`](#beaconblockbody) + - [Persistent committees](#persistent-committees) + - [Shard receipt processing](#shard-receipt-processing) + + ## Configuration diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 946165bb7..7eb9e2526 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -5,54 +5,56 @@ ## Table of contents + + -- [Ethereum 2.0 Phase 1 -- Custody Game](#ethereum-20-phase-1----custody-game) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Terminology](#terminology) - - [Constants](#constants) - - [Misc](#misc) - - [Custody game parameters](#custody-game-parameters) - - [Time parameters](#time-parameters) - - [Max operations per block](#max-operations-per-block) - - [Reward and penalty quotients](#reward-and-penalty-quotients) - - [Signature domain types](#signature-domain-types) - - [TODO PLACEHOLDER](#todo-placeholder) - - [Data structures](#data-structures) - - [Custody objects](#custody-objects) - - [`CustodyChunkChallenge`](#custodychunkchallenge) - - [`CustodyBitChallenge`](#custodybitchallenge) - - [`CustodyChunkChallengeRecord`](#custodychunkchallengerecord) - - [`CustodyBitChallengeRecord`](#custodybitchallengerecord) - - [`CustodyResponse`](#custodyresponse) - - [New beacon operations](#new-beacon-operations) - - [`CustodyKeyReveal`](#custodykeyreveal) - - [`EarlyDerivedSecretReveal`](#earlyderivedsecretreveal) - - [Phase 0 container updates](#phase-0-container-updates) - - [`Validator`](#validator) - - [`BeaconState`](#beaconstate) - - [`BeaconBlockBody`](#beaconblockbody) - - [Helpers](#helpers) - - [`ceillog2`](#ceillog2) - - [`is_valid_merkle_branch_with_mixin`](#is_valid_merkle_branch_with_mixin) - - [`get_crosslink_chunk_count`](#get_crosslink_chunk_count) - - [`legendre_bit`](#legendre_bit) - - [`custody_subchunkify`](#custody_subchunkify) - - [`get_custody_chunk_bit`](#get_custody_chunk_bit) - - [`get_chunk_bits_root`](#get_chunk_bits_root) - - [`get_randao_epoch_for_custody_period`](#get_randao_epoch_for_custody_period) - - [`get_custody_period_for_validator`](#get_custody_period_for_validator) - - [`replace_empty_or_append`](#replace_empty_or_append) - - [Per-block processing](#per-block-processing) - - [Operations](#operations) - - [Custody key reveals](#custody-key-reveals) - - [Early derived secret reveals](#early-derived-secret-reveals) - - [Chunk challenges](#chunk-challenges) - - [Bit challenges](#bit-challenges) - - [Custody responses](#custody-responses) - - [Per-epoch processing](#per-epoch-processing) - - [Handling of custody-related deadlines](#handling-of-custody-related-deadlines) +- [Introduction](#introduction) +- [Terminology](#terminology) +- [Constants](#constants) + - [Misc](#misc) + - [Custody game parameters](#custody-game-parameters) + - [Time parameters](#time-parameters) + - [Max operations per block](#max-operations-per-block) + - [Reward and penalty quotients](#reward-and-penalty-quotients) + - [Signature domain types](#signature-domain-types) + - [TODO PLACEHOLDER](#todo-placeholder) +- [Data structures](#data-structures) + - [Custody objects](#custody-objects) + - [`CustodyChunkChallenge`](#custodychunkchallenge) + - [`CustodyBitChallenge`](#custodybitchallenge) + - [`CustodyChunkChallengeRecord`](#custodychunkchallengerecord) + - [`CustodyBitChallengeRecord`](#custodybitchallengerecord) + - [`CustodyResponse`](#custodyresponse) + - [New beacon operations](#new-beacon-operations) + - [`CustodyKeyReveal`](#custodykeyreveal) + - [`EarlyDerivedSecretReveal`](#earlyderivedsecretreveal) + - [Phase 0 container updates](#phase-0-container-updates) + - [`Validator`](#validator) + - [`BeaconState`](#beaconstate) + - [`BeaconBlockBody`](#beaconblockbody) +- [Helpers](#helpers) + - [`ceillog2`](#ceillog2) + - [`is_valid_merkle_branch_with_mixin`](#is_valid_merkle_branch_with_mixin) + - [`get_crosslink_chunk_count`](#get_crosslink_chunk_count) + - [`legendre_bit`](#legendre_bit) + - [`custody_subchunkify`](#custody_subchunkify) + - [`get_custody_chunk_bit`](#get_custody_chunk_bit) + - [`get_chunk_bits_root`](#get_chunk_bits_root) + - [`get_randao_epoch_for_custody_period`](#get_randao_epoch_for_custody_period) + - [`get_custody_period_for_validator`](#get_custody_period_for_validator) + - [`replace_empty_or_append`](#replace_empty_or_append) +- [Per-block processing](#per-block-processing) + - [Operations](#operations) + - [Custody key reveals](#custody-key-reveals) + - [Early derived secret reveals](#early-derived-secret-reveals) + - [Chunk challenges](#chunk-challenges) + - [Bit challenges](#bit-challenges) + - [Custody responses](#custody-responses) +- [Per-epoch processing](#per-epoch-processing) + - [Handling of custody-related deadlines](#handling-of-custody-related-deadlines) + + ## Introduction diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 6fce90626..d5964fe7d 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -5,45 +5,47 @@ ## Table of contents + + -- [Ethereum 2.0 Phase 1 -- Shard Data Chains](#ethereum-20-phase-1----shard-data-chains) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Custom types](#custom-types) - - [Configuration](#configuration) - - [Misc](#misc) - - [Initial values](#initial-values) - - [Time parameters](#time-parameters) - - [State list lengths](#state-list-lengths) - - [Rewards and penalties](#rewards-and-penalties) - - [Signature domain types](#signature-domain-types) - - [Containers](#containers) - - [`Crosslink`](#crosslink) - - [`ShardBlock`](#shardblock) - - [`ShardBlockHeader`](#shardblockheader) - - [`ShardState`](#shardstate) - - [`ShardAttestationData`](#shardattestationdata) - - [Helper functions](#helper-functions) - - [Misc](#misc-1) - - [`compute_epoch_of_shard_slot`](#compute_epoch_of_shard_slot) - - [`compute_shard_period_start_epoch`](#compute_shard_period_start_epoch) - - [Beacon state accessors](#beacon-state-accessors) - - [`get_period_committee`](#get_period_committee) - - [`get_shard_committee`](#get_shard_committee) - - [`get_shard_proposer_index`](#get_shard_proposer_index) - - [Shard state mutators](#shard-state-mutators) - - [`process_delta`](#process_delta) - - [Genesis](#genesis) - - [`get_genesis_shard_state`](#get_genesis_shard_state) - - [`get_genesis_shard_block`](#get_genesis_shard_block) - - [Shard state transition function](#shard-state-transition-function) - - [Period processing](#period-processing) - - [Block processing](#block-processing) - - [Block header](#block-header) - - [Attestations](#attestations) - - [Block body](#block-body) - - [Shard fork choice rule](#shard-fork-choice-rule) +- [Introduction](#introduction) +- [Custom types](#custom-types) +- [Configuration](#configuration) + - [Misc](#misc) + - [Initial values](#initial-values) + - [Time parameters](#time-parameters) + - [State list lengths](#state-list-lengths) + - [Rewards and penalties](#rewards-and-penalties) + - [Signature domain types](#signature-domain-types) +- [Containers](#containers) + - [`Crosslink`](#crosslink) + - [`ShardBlock`](#shardblock) + - [`ShardBlockHeader`](#shardblockheader) + - [`ShardState`](#shardstate) + - [`ShardAttestationData`](#shardattestationdata) +- [Helper functions](#helper-functions) + - [Misc](#misc-1) + - [`compute_epoch_of_shard_slot`](#compute_epoch_of_shard_slot) + - [`compute_shard_period_start_epoch`](#compute_shard_period_start_epoch) + - [Beacon state accessors](#beacon-state-accessors) + - [`get_period_committee`](#get_period_committee) + - [`get_shard_committee`](#get_shard_committee) + - [`get_shard_proposer_index`](#get_shard_proposer_index) + - [Shard state mutators](#shard-state-mutators) + - [`process_delta`](#process_delta) +- [Genesis](#genesis) + - [`get_genesis_shard_state`](#get_genesis_shard_state) + - [`get_genesis_shard_block`](#get_genesis_shard_block) +- [Shard state transition function](#shard-state-transition-function) + - [Period processing](#period-processing) + - [Block processing](#block-processing) + - [Block header](#block-header) + - [Attestations](#attestations) + - [Block body](#block-body) +- [Shard fork choice rule](#shard-fork-choice-rule) + + ## Introduction diff --git a/specs/light_client/merkle_proofs.md b/specs/light_client/merkle_proofs.md index c89235cb5..3e176f2aa 100644 --- a/specs/light_client/merkle_proofs.md +++ b/specs/light_client/merkle_proofs.md @@ -4,21 +4,23 @@ ## Table of contents + + -- [Merkle proof formats](#merkle-proof-formats) - - [Table of contents](#table-of-contents) - - [Helper functions](#helper-functions) - - [Generalized Merkle tree index](#generalized-merkle-tree-index) - - [SSZ object to index](#ssz-object-to-index) - - [Helpers for generalized indices](#helpers-for-generalized-indices) - - [`concat_generalized_indices`](#concat_generalized_indices) - - [`get_generalized_index_length`](#get_generalized_index_length) - - [`get_generalized_index_bit`](#get_generalized_index_bit) - - [`generalized_index_sibling`](#generalized_index_sibling) - - [`generalized_index_child`](#generalized_index_child) - - [`generalized_index_parent`](#generalized_index_parent) - - [Merkle multiproofs](#merkle-multiproofs) +- [Helper functions](#helper-functions) +- [Generalized Merkle tree index](#generalized-merkle-tree-index) +- [SSZ object to index](#ssz-object-to-index) + - [Helpers for generalized indices](#helpers-for-generalized-indices) + - [`concat_generalized_indices`](#concat_generalized_indices) + - [`get_generalized_index_length`](#get_generalized_index_length) + - [`get_generalized_index_bit`](#get_generalized_index_bit) + - [`generalized_index_sibling`](#generalized_index_sibling) + - [`generalized_index_child`](#generalized_index_child) + - [`generalized_index_parent`](#generalized_index_parent) +- [Merkle multiproofs](#merkle-multiproofs) + + ## Helper functions diff --git a/specs/light_client/sync_protocol.md b/specs/light_client/sync_protocol.md index 00edb990d..05180516b 100644 --- a/specs/light_client/sync_protocol.md +++ b/specs/light_client/sync_protocol.md @@ -5,20 +5,22 @@ ## Table of contents + + -- [Minimal Light Client Design](#minimal-light-client-design) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Custom types](#custom-types) - - [Constants](#constants) - - [Containers](#containers) - - [`LightClientUpdate`](#lightclientupdate) - - [Helpers](#helpers) - - [`LightClientMemory`](#lightclientmemory) - - [`get_persistent_committee_pubkeys_and_balances`](#get_persistent_committee_pubkeys_and_balances) - - [Light client state updates](#light-client-state-updates) - - [Data overhead](#data-overhead) +- [Introduction](#introduction) +- [Custom types](#custom-types) +- [Constants](#constants) +- [Containers](#containers) + - [`LightClientUpdate`](#lightclientupdate) +- [Helpers](#helpers) + - [`LightClientMemory`](#lightclientmemory) + - [`get_persistent_committee_pubkeys_and_balances`](#get_persistent_committee_pubkeys_and_balances) +- [Light client state updates](#light-client-state-updates) +- [Data overhead](#data-overhead) + + ## Introduction diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 414dc8cde..71a7088fa 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -19,7 +19,7 @@ It consists of four main sections: - [Network fundamentals](#network-fundamentals) - [Transport](#transport) - [Encryption and identification](#encryption-and-identification) - - [Protocol negotiation](#protocol-negotiation) + - [Protocol Negotiation](#protocol-negotiation) - [Multiplexing](#multiplexing) - [Eth2 network interaction domains](#eth2-network-interaction-domains) - [Configuration](#configuration) @@ -29,7 +29,7 @@ It consists of four main sections: - [Design decision rationale](#design-decision-rationale) - [Transport](#transport-1) - [Multiplexing](#multiplexing-1) - - [Protocol negotiation](#protocol-negotiation-1) + - [Protocol Negotiation](#protocol-negotiation-1) - [Encryption](#encryption) - [Gossipsub](#gossipsub) - [Req/Resp](#reqresp) @@ -567,7 +567,7 @@ Conscious of that, the libp2p community conceptualized [mplex](https://github.co Overlay multiplexers are not necessary with QUIC since the protocol provides native multiplexing, but they need to be layered atop TCP, WebSockets, and other transports that lack such support. -## Protocol negotiation +## Protocol Negotiation ### When is multiselect 2.0 due and why are we using it for mainnet? diff --git a/specs/simple-serialize.md b/specs/simple-serialize.md index 556c31b27..860a27f01 100644 --- a/specs/simple-serialize.md +++ b/specs/simple-serialize.md @@ -4,30 +4,32 @@ ## Table of contents + + -- [SimpleSerialize (SSZ)](#simpleserialize-ssz) - - [Table of contents](#table-of-contents) - - [Constants](#constants) - - [Typing](#typing) - - [Basic types](#basic-types) - - [Composite types](#composite-types) - - [Variable-size and fixed-size](#variable-size-and-fixed-size) - - [Aliases](#aliases) - - [Default values](#default-values) - - [`is_zero`](#is_zero) - - [Illegal types](#illegal-types) - - [Serialization](#serialization) - - [`uintN`](#uintn) - - [`boolean`](#boolean) - - [`null`](#null) - - [`Bitvector[N]`](#bitvectorn) - - [`Bitlist[N]`](#bitlistn) - - [Vectors, containers, lists, unions](#vectors-containers-lists-unions) - - [Deserialization](#deserialization) - - [Merkleization](#merkleization) - - [Summaries and expansions](#summaries-and-expansions) - - [Implementations](#implementations) +- [Constants](#constants) +- [Typing](#typing) + - [Basic types](#basic-types) + - [Composite types](#composite-types) + - [Variable-size and fixed-size](#variable-size-and-fixed-size) + - [Aliases](#aliases) + - [Default values](#default-values) + - [`is_zero`](#is_zero) + - [Illegal types](#illegal-types) +- [Serialization](#serialization) + - [`uintN`](#uintn) + - [`boolean`](#boolean) + - [`null`](#null) + - [`Bitvector[N]`](#bitvectorn) + - [`Bitlist[N]`](#bitlistn) + - [Vectors, containers, lists, unions](#vectors-containers-lists-unions) +- [Deserialization](#deserialization) +- [Merkleization](#merkleization) +- [Summaries and expansions](#summaries-and-expansions) +- [Implementations](#implementations) + + ## Constants diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 3b90350e3..76bcc3b7d 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -5,61 +5,64 @@ ## Table of contents + + -- [Ethereum 2.0 Phase 0 -- Honest Validator](#ethereum-20-phase-0----honest-validator) - - [Table of contents](#table-of-contents) - - [Introduction](#introduction) - - [Prerequisites](#prerequisites) - - [Constants](#constants) - - [Misc](#misc) - - [Becoming a validator](#becoming-a-validator) - - [Initialization](#initialization) - - [BLS public key](#bls-public-key) - - [BLS withdrawal key](#bls-withdrawal-key) - - [Submit deposit](#submit-deposit) - - [Process deposit](#process-deposit) - - [Validator index](#validator-index) - - [Activation](#activation) - - [Validator assignments](#validator-assignments) - - [Lookahead](#lookahead) - - [Beacon chain responsibilities](#beacon-chain-responsibilities) - - [Block proposal](#block-proposal) - - [Block header](#block-header) - - [Slot](#slot) - - [Parent root](#parent-root) - - [State root](#state-root) - - [Randao reveal](#randao-reveal) - - [Eth1 Data](#eth1-data) - - [Signature](#signature) - - [Block body](#block-body) - - [Proposer slashings](#proposer-slashings) - - [Attester slashings](#attester-slashings) - - [Attestations](#attestations) - - [Deposits](#deposits) - - [Voluntary exits](#voluntary-exits) - - [Attesting](#attesting) - - [Attestation data](#attestation-data) - - [General](#general) - - [LMD GHOST vote](#lmd-ghost-vote) - - [FFG vote](#ffg-vote) - - [Construct attestation](#construct-attestation) - - [Data](#data) - - [Aggregation bits](#aggregation-bits) - - [Aggregate signature](#aggregate-signature) - - [Broadcast attestation](#broadcast-attestation) - - [Attestation aggregation](#attestation-aggregation) - - [Aggregation selection](#aggregation-selection) - - [Construct aggregate](#construct-aggregate) - - [Data](#data-1) - - [Aggregation bits](#aggregation-bits-1) - - [Aggregate signature](#aggregate-signature-1) - - [Broadcast aggregate](#broadcast-aggregate) - - [`AggregateAndProof`](#aggregateandproof) - - [Phase 0 attestation subnet stability](#phase-0-attestation-subnet-stability) - - [How to avoid slashing](#how-to-avoid-slashing) - - [Proposer slashing](#proposer-slashing) - - [Attester slashing](#attester-slashing) +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) +- [Constants](#constants) + - [Misc](#misc) +- [Becoming a validator](#becoming-a-validator) + - [Initialization](#initialization) + - [BLS public key](#bls-public-key) + - [BLS withdrawal key](#bls-withdrawal-key) + - [Submit deposit](#submit-deposit) + - [Process deposit](#process-deposit) + - [Validator index](#validator-index) + - [Activation](#activation) +- [Validator assignments](#validator-assignments) + - [Lookahead](#lookahead) +- [Beacon chain responsibilities](#beacon-chain-responsibilities) + - [Block proposal](#block-proposal) + - [Preparing for a `BeaconBlock`](#preparing-for-a-beaconblock) + - [Slot](#slot) + - [Parent root](#parent-root) + - [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody) + - [Randao reveal](#randao-reveal) + - [Eth1 Data](#eth1-data) + - [Proposer slashings](#proposer-slashings) + - [Attester slashings](#attester-slashings) + - [Attestations](#attestations) + - [Deposits](#deposits) + - [Voluntary exits](#voluntary-exits) + - [Packaging into a `SignedBeaconBlock`](#packaging-into-a-signedbeaconblock) + - [State root](#state-root) + - [Signature](#signature) + - [Attesting](#attesting) + - [Attestation data](#attestation-data) + - [General](#general) + - [LMD GHOST vote](#lmd-ghost-vote) + - [FFG vote](#ffg-vote) + - [Construct attestation](#construct-attestation) + - [Data](#data) + - [Aggregation bits](#aggregation-bits) + - [Aggregate signature](#aggregate-signature) + - [Broadcast attestation](#broadcast-attestation) + - [Attestation aggregation](#attestation-aggregation) + - [Aggregation selection](#aggregation-selection) + - [Construct aggregate](#construct-aggregate) + - [Data](#data-1) + - [Aggregation bits](#aggregation-bits-1) + - [Aggregate signature](#aggregate-signature-1) + - [Broadcast aggregate](#broadcast-aggregate) + - [`AggregateAndProof`](#aggregateandproof) +- [Phase 0 attestation subnet stability](#phase-0-attestation-subnet-stability) +- [How to avoid slashing](#how-to-avoid-slashing) + - [Proposer slashing](#proposer-slashing) + - [Attester slashing](#attester-slashing) + + ## Introduction From ca2b6a0e52454ca8466caf80b5760e17205948f1 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Tue, 10 Dec 2019 15:17:42 +0100 Subject: [PATCH 14/56] Use consistent header level for TOC generation --- specs/networking/p2p-interface.md | 65 +++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 71a7088fa..dfddbb3f7 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -18,23 +18,88 @@ It consists of four main sections: - [Network fundamentals](#network-fundamentals) - [Transport](#transport) + - [Interop](#interop) + - [Mainnet](#mainnet) - [Encryption and identification](#encryption-and-identification) + - [Interop](#interop-1) + - [Mainnet](#mainnet-1) - [Protocol Negotiation](#protocol-negotiation) + - [Interop](#interop-2) + - [Mainnet](#mainnet-2) - [Multiplexing](#multiplexing) - [Eth2 network interaction domains](#eth2-network-interaction-domains) - [Configuration](#configuration) - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) + - [Topics and messages](#topics-and-messages) + - [Global topics](#global-topics) + - [Attestation subnets](#attestation-subnets) + - [Interop](#interop-3) + - [Mainnet](#mainnet-3) + - [Encodings](#encodings) + - [Interop](#interop-4) + - [Mainnet](#mainnet-4) - [The Req/Resp domain](#the-reqresp-domain) + - [Protocol identification](#protocol-identification) + - [Req/Resp interaction](#reqresp-interaction) + - [Requesting side](#requesting-side) + - [Responding side](#responding-side) + - [Encoding strategies](#encoding-strategies) + - [SSZ-encoding strategy (with or without Snappy)](#ssz-encoding-strategy-with-or-without-snappy) + - [Messages](#messages) + - [Status](#status) + - [Goodbye](#goodbye) + - [BeaconBlocksByRange](#beaconblocksbyrange) + - [BeaconBlocksByRoot](#beaconblocksbyroot) - [The discovery domain: discv5](#the-discovery-domain-discv5) + - [Integration into libp2p stacks](#integration-into-libp2p-stacks) + - [ENR structure](#enr-structure) + - [Interop](#interop-5) + - [Mainnet](#mainnet-5) + - [Topic advertisement](#topic-advertisement) + - [Interop](#interop-6) + - [Mainnet](#mainnet-6) - [Design decision rationale](#design-decision-rationale) - [Transport](#transport-1) + - [Why are we defining specific transports?](#why-are-we-defining-specific-transports) + - [Can clients support other transports/handshakes than the ones mandated by the spec?](#can-clients-support-other-transportshandshakes-than-the-ones-mandated-by-the-spec) + - [What are the advantages of using TCP/QUIC/Websockets?](#what-are-the-advantages-of-using-tcpquicwebsockets) + - [Why do we not just support a single transport?](#why-do-we-not-just-support-a-single-transport) + - [Why are we not using QUIC for mainnet from the start?](#why-are-we-not-using-quic-for-mainnet-from-the-start) - [Multiplexing](#multiplexing-1) + - [Why are we using mplex/yamux?](#why-are-we-using-mplexyamux) - [Protocol Negotiation](#protocol-negotiation-1) + - [When is multiselect 2.0 due and why are we using it for mainnet?](#when-is-multiselect-20-due-and-why-are-we-using-it-for-mainnet) + - [What is the difference between connection-level and stream-level protocol negotiation?](#what-is-the-difference-between-connection-level-and-stream-level-protocol-negotiation) - [Encryption](#encryption) + - [Why are we using SecIO for interop? Why not for mainnet?](#why-are-we-using-secio-for-interop-why-not-for-mainnet) + - [Why are we using Noise/TLS 1.3 for mainnet?](#why-are-we-using-noisetls-13-for-mainnet) + - [Why are we using encryption at all?](#why-are-we-using-encryption-at-all) + - [Will mainnnet networking be untested when it launches?](#will-mainnnet-networking-be-untested-when-it-launches) - [Gossipsub](#gossipsub) + - [Why are we using a pub/sub algorithm for block and attestation propagation?](#why-are-we-using-a-pubsub-algorithm-for-block-and-attestation-propagation) + - [Why are we using topics to segregate encodings, yet only support one encoding?](#why-are-we-using-topics-to-segregate-encodings-yet-only-support-one-encoding) + - [How do we upgrade gossip channels (e.g. changes in encoding, compression)?](#how-do-we-upgrade-gossip-channels-eg-changes-in-encoding-compression) + - [Why must all clients use the same gossip topic instead of one negotiated between each peer pair?](#why-must-all-clients-use-the-same-gossip-topic-instead-of-one-negotiated-between-each-peer-pair) + - [Why are the topics strings and not hashes?](#why-are-the-topics-strings-and-not-hashes) + - [Why are there `ATTESTATION_SUBNET_COUNT` attestation subnets?](#why-are-there-attestation_subnet_count-attestation-subnets) + - [Why are attestations limited to be broadcast on gossip channels within `SLOTS_PER_EPOCH` slots?](#why-are-attestations-limited-to-be-broadcast-on-gossip-channels-within-slots_per_epoch-slots) + - [Why are aggregate attestations broadcast to the global topic as `AggregateAndProof`s rather than just as `Attestation`s?](#why-are-aggregate-attestations-broadcast-to-the-global-topic-as-aggregateandproofs-rather-than-just-as-attestations) + - [Why are we sending entire objects in the pubsub and not just hashes?](#why-are-we-sending-entire-objects-in-the-pubsub-and-not-just-hashes) + - [Should clients gossip blocks if they *cannot* validate the proposer signature due to not yet being synced, not knowing the head block, etc?](#should-clients-gossip-blocks-if-they-cannot-validate-the-proposer-signature-due-to-not-yet-being-synced-not-knowing-the-head-block-etc) + - [How are we going to discover peers in a gossipsub topic?](#how-are-we-going-to-discover-peers-in-a-gossipsub-topic) - [Req/Resp](#reqresp) + - [Why segregate requests into dedicated protocol IDs?](#why-segregate-requests-into-dedicated-protocol-ids) + - [Why are messages length-prefixed with a protobuf varint in the SSZ-encoding?](#why-are-messages-length-prefixed-with-a-protobuf-varint-in-the-ssz-encoding) + - [Why do we version protocol strings with ordinals instead of semver?](#why-do-we-version-protocol-strings-with-ordinals-instead-of-semver) + - [Why is it called Req/Resp and not RPC?](#why-is-it-called-reqresp-and-not-rpc) - [Discovery](#discovery) + - [Why are we using discv5 and not libp2p Kademlia DHT?](#why-are-we-using-discv5-and-not-libp2p-kademlia-dht) + - [What is the difference between an ENR and a multiaddr, and why are we using ENRs?](#what-is-the-difference-between-an-enr-and-a-multiaddr-and-why-are-we-using-enrs) - [Compression/Encoding](#compressionencoding) + - [Why are we using SSZ for encoding?](#why-are-we-using-ssz-for-encoding) + - [Why are we compressing, and at which layers?](#why-are-we-compressing-and-at-which-layers) + - [Why are using Snappy for compression?](#why-are-using-snappy-for-compression) + - [Can I get access to unencrypted bytes on the wire for debugging purposes?](#can-i-get-access-to-unencrypted-bytes-on-the-wire-for-debugging-purposes) - [libp2p implementations matrix](#libp2p-implementations-matrix) From aa0c9f89c337e2b0221f36f59c7fbaa33455869d Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Tue, 10 Dec 2019 17:07:30 +0100 Subject: [PATCH 15/56] Add check_toc rule to makefile, which fails if table of contents of any of the MARKDOWN_FILES are out of sync --- Makefile | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index bfbc28070..2cdb1021f 100644 --- a/Makefile +++ b/Makefile @@ -17,18 +17,22 @@ GENERATOR_VENVS = $(patsubst $(GENERATOR_DIR)/%, $(GENERATOR_DIR)/%venv, $(GENER #$(info $$GENERATOR_TARGETS is [${GENERATOR_TARGETS}]) PY_SPEC_PHASE_0_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase0/spec.py -PY_SPEC_PHASE_0_DEPS = $(SPEC_DIR)/core/0_*.md +PY_SPEC_PHASE_0_DEPS = $(wildcard $(SPEC_DIR)/core/0_*.md) PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/spec.py -PY_SPEC_PHASE_1_DEPS = $(SPEC_DIR)/core/1_*.md +PY_SPEC_PHASE_1_DEPS = $(wildcard $(SPEC_DIR)/core/1_*.md) + +PY_SPEC_ALL_DEPS = $(PY_SPEC_PHASE_0_DEPS) $(PY_SPEC_PHASE_1_DEPS) PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) $(PY_SPEC_PHASE_1_TARGETS) +MARKDOWN_FILES = $(PY_SPEC_ALL_DEPS) $(wildcard $(SPEC_DIR)/*.md) $(wildcard $(SPEC_DIR)/light_client/*.md) $(wildcard $(SPEC_DIR)/networking/*.md) $(wildcard $(SPEC_DIR)/validator/*.md) + COV_HTML_OUT=.htmlcov COV_INDEX_FILE=$(PY_SPEC_DIR)/$(COV_HTML_OUT)/index.html .PHONY: clean partial_clean all test citest lint generate_tests pyspec phase0 phase1 install_test open_cov \ - install_deposit_contract_test test_deposit_contract compile_deposit_contract + install_deposit_contract_test test_deposit_contract compile_deposit_contract check_toc all: $(PY_SPEC_ALL_TARGETS) @@ -65,6 +69,14 @@ citest: $(PY_SPEC_ALL_TARGETS) open_cov: ((open "$(COV_INDEX_FILE)" || xdg-open "$(COV_INDEX_FILE)") &> /dev/null) & +check_toc: $(MARKDOWN_FILES:=.toc) + +%.toc: + cp $* $*.tmp && \ + doctoc $* && \ + diff -q $* $*.tmp && \ + rm $*.tmp + lint: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; \ flake8 --ignore=E252,W504,W503 --max-line-length=120 ./eth2spec \ From 8408ec6311697f594ff3bd372e1fc11a7dcc1522 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Tue, 10 Dec 2019 17:38:37 +0100 Subject: [PATCH 16/56] check table of contents in circleci --- .circleci/config.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index b612378e2..410763f95 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -103,6 +103,14 @@ jobs: command: make citest - store_test_results: path: test_libs/pyspec/test-reports + table_of_contents: + docker: + - image: circleci/node:10.16.3 + working_directory: ~/specs-repo + steps: + - run: + name: Check table of contents + command: npm install -g doctoc && make check_toc lint: docker: - image: circleci/python:3.6 @@ -148,6 +156,7 @@ workflows: - test: requires: - install_pyspec_test + - table_of_contents - lint: requires: - test From 3190f58a15e970e48af2a40b7977411151bfdb46 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Tue, 10 Dec 2019 18:20:55 +0100 Subject: [PATCH 17/56] ci: try with sudo --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 410763f95..884454788 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -110,7 +110,7 @@ jobs: steps: - run: name: Check table of contents - command: npm install -g doctoc && make check_toc + command: sudo npm install -g doctoc && make check_toc lint: docker: - image: circleci/python:3.6 From e090174d77e8ca17891ad452cf65234225da482b Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Tue, 10 Dec 2019 18:32:04 +0100 Subject: [PATCH 18/56] checkout specs before checking toc --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 884454788..03db9d614 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -156,7 +156,9 @@ workflows: - test: requires: - install_pyspec_test - - table_of_contents + - table_of_contents: + requires: + - checkout_specs - lint: requires: - test From c761feafdcba696b88e1420f7df3facff511a809 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Tue, 10 Dec 2019 18:57:19 +0100 Subject: [PATCH 19/56] checkout in same job --- .circleci/config.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 03db9d614..19ab1543a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -108,6 +108,7 @@ jobs: - image: circleci/node:10.16.3 working_directory: ~/specs-repo steps: + - checkout - run: name: Check table of contents command: sudo npm install -g doctoc && make check_toc @@ -156,9 +157,7 @@ workflows: - test: requires: - install_pyspec_test - - table_of_contents: - requires: - - checkout_specs + - table_of_contents - lint: requires: - test From d126162ca8e687e0a687754b8e389f9cf68955b8 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 10 Dec 2019 11:25:55 -0700 Subject: [PATCH 20/56] fix activation queue efficiency --- specs/core/0_beacon-chain.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 9c7248c56..4caf8a862 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1311,17 +1311,16 @@ def process_registry_updates(state: BeaconState) -> None: if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE: initiate_validator_exit(state, ValidatorIndex(index)) - # Queue validators eligible for activation and not dequeued for activation prior to finalized epoch + # Queue validators eligible for activation and not yet dequeued for activation prior activation_queue = sorted([ index for index, validator in enumerate(state.validators) if validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH - and validator.activation_epoch >= compute_activation_exit_epoch(state.finalized_checkpoint.epoch) + and validator.activation_epoch == FAR_FUTURE_EPOCH ], key=lambda index: state.validators[index].activation_eligibility_epoch) - # Dequeued validators for activation up to churn limit (without resetting activation epoch) + # Dequeued validators for activation up to churn limit for index in activation_queue[:get_validator_churn_limit(state)]: validator = state.validators[index] - if validator.activation_epoch == FAR_FUTURE_EPOCH: - validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) + validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) ``` #### Slashings From e4d710590a1b9421b4701eb0626f892fc8679e21 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 10 Dec 2019 11:49:26 -0700 Subject: [PATCH 21/56] add test for queue efficiency --- specs/core/0_beacon-chain.md | 2 +- .../test_process_registry_updates.py | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 4caf8a862..35fd439c1 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1311,7 +1311,7 @@ def process_registry_updates(state: BeaconState) -> None: if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE: initiate_validator_exit(state, ValidatorIndex(index)) - # Queue validators eligible for activation and not yet dequeued for activation prior + # Queue validators eligible for activation and not yet dequeued for activation activation_queue = sorted([ index for index, validator in enumerate(state.validators) if validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index bfd992ffa..26eb26104 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -63,6 +63,34 @@ def test_activation_queue_sorting(spec, state): assert state.validators[churn_limit - 2].activation_epoch != spec.FAR_FUTURE_EPOCH +@with_all_phases +@spec_state_test +def test_activation_queue_efficiency(spec, state): + churn_limit = spec.get_validator_churn_limit(state) + mock_activations = churn_limit * 2 + + epoch = spec.get_current_epoch(state) + for i in range(mock_activations): + mock_deposit(spec, state, i) + state.validators[i].activation_eligibility_epoch = epoch + 1 + + # Run first registry update. Do not yield test vectors + for _ in run_process_registry_updates(spec, state): + pass + + # Half should churn in first run of registry update + for i in range(mock_activations): + if i < mock_activations // 2: + assert state.validators[i].activation_epoch < spec.FAR_FUTURE_EPOCH + else: + assert state.validators[i].activation_epoch == spec.FAR_FUTURE_EPOCH + + # Second half should churn in second run of registry update + yield from run_process_registry_updates(spec, state) + for i in range(mock_activations): + assert state.validators[i].activation_epoch < spec.FAR_FUTURE_EPOCH + + @with_all_phases @spec_state_test def test_ejection(spec, state): From 6610aeea2fabea028180b2123e8b93ed800554d9 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 11 Dec 2019 16:00:46 -0700 Subject: [PATCH 22/56] fix activation queue to finality --- specs/core/0_beacon-chain.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 35fd439c1..5f8b84376 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -601,6 +601,21 @@ def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool: return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch) ``` +#### `is_eligible_for_activation` + +```python +def is_eligible_for_activation(state: BeaconState, validator: Validator) -> bool: + """ + Check if ``validator`` is eligible for activation. + """ + return ( + # Was placed in activation queue prior to most recent finalized epoch + validator.activation_eligibility_epoch < state.finalized_checkpoint.epoch + # Has not yet been activated + and validator.activation_epoch == FAR_FUTURE_EPOCH + ) +``` + #### `is_slashable_attestation_data` ```python @@ -1314,8 +1329,7 @@ def process_registry_updates(state: BeaconState) -> None: # Queue validators eligible for activation and not yet dequeued for activation activation_queue = sorted([ index for index, validator in enumerate(state.validators) - if validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH - and validator.activation_epoch == FAR_FUTURE_EPOCH + if is_eligible_for_activation(state, validator) ], key=lambda index: state.validators[index].activation_eligibility_epoch) # Dequeued validators for activation up to churn limit for index in activation_queue[:get_validator_churn_limit(state)]: From e117b58ae2269afc56d2ce2dce397cfbe21f8954 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 11 Dec 2019 16:10:18 -0700 Subject: [PATCH 23/56] add queue eligibility helper --- specs/core/0_beacon-chain.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 5f8b84376..210e1797f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -601,6 +601,20 @@ def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool: return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch) ``` +#### `is_eligible_for_activation_queue` + +```python +def is_eligible_for_activation_queue(validator: Validator) -> bool: + """ + Check if ``validator`` is eligible to be placed into the activation queue. + """ + return ( + validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH + and validator.effective_balance == MAX_EFFECTIVE_BALANCE + ) +``` + + #### `is_eligible_for_activation` ```python @@ -1317,10 +1331,7 @@ def process_rewards_and_penalties(state: BeaconState) -> None: def process_registry_updates(state: BeaconState) -> None: # Process activation eligibility and ejections for index, validator in enumerate(state.validators): - if ( - validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH - and validator.effective_balance == MAX_EFFECTIVE_BALANCE - ): + if is_eligible_for_activation_queue(validator): validator.activation_eligibility_epoch = get_current_epoch(state) if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE: From e8d079b366ed4d1a81b9a5e5c9d503338d1d8721 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 11 Dec 2019 17:06:14 -0700 Subject: [PATCH 24/56] fix and add tests for activation queue --- .../test_process_registry_updates.py | 80 ++++++++++++++++--- 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index 26eb26104..b6bd47204 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -1,4 +1,7 @@ -from eth2spec.test.helpers.state import next_epoch +from eth2spec.test.helpers.state import ( + next_epoch, + next_epoch_with_attestations, +) from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with @@ -17,18 +20,71 @@ def mock_deposit(spec, state, index): @with_all_phases @spec_state_test -def test_activation(spec, state): +def test_add_to_activation_queue(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + index = 0 mock_deposit(spec, state, index) - for _ in range(spec.MAX_SEED_LOOKAHEAD + 1): - next_epoch(spec, state) + yield from run_process_registry_updates(spec, state) + + # validator moved into queue + assert state.validators[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH + assert state.validators[index].activation_epoch == spec.FAR_FUTURE_EPOCH + assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) + + +@with_all_phases +@spec_state_test +def test_activation_queue_to_activated_if_finalized(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + index = 0 + mock_deposit(spec, state, index) + + # mock validator as having been in queue since before latest finalized + state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1 + state.validators[index].activation_eligibility_epoch = state.finalized_checkpoint.epoch - 1 + + assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) yield from run_process_registry_updates(spec, state) + # validator activated for future epoch assert state.validators[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH assert state.validators[index].activation_epoch != spec.FAR_FUTURE_EPOCH - assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) + assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) + assert spec.is_active_validator( + state.validators[index], + spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) + ) + + +@with_all_phases +@spec_state_test +def test_activation_queue_no_activation_no_finality(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + index = 0 + mock_deposit(spec, state, index) + + # mock validator as having been in queue only since latest finalized (not before) + state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1 + state.validators[index].activation_eligibility_epoch = state.finalized_checkpoint.epoch + + assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) + + yield from run_process_registry_updates(spec, state) + + # validator not activated + assert state.validators[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH + assert state.validators[index].activation_epoch == spec.FAR_FUTURE_EPOCH @with_all_phases @@ -44,6 +100,10 @@ def test_activation_queue_sorting(spec, state): # give the last priority over the others state.validators[mock_activations - 1].activation_eligibility_epoch = epoch + # move state forward and finalize to allow for activations + state.slot += spec.SLOTS_PER_EPOCH * 3 + state.finalized_checkpoint.epoch = epoch + 2 + # make sure we are hitting the churn churn_limit = spec.get_validator_churn_limit(state) assert mock_activations > churn_limit @@ -74,6 +134,10 @@ def test_activation_queue_efficiency(spec, state): mock_deposit(spec, state, i) state.validators[i].activation_eligibility_epoch = epoch + 1 + # move state forward and finalize to allow for activations + state.slot += spec.SLOTS_PER_EPOCH * 3 + state.finalized_checkpoint.epoch = epoch + 2 + # Run first registry update. Do not yield test vectors for _ in run_process_registry_updates(spec, state): pass @@ -101,13 +165,11 @@ def test_ejection(spec, state): # Mock an ejection state.validators[index].effective_balance = spec.EJECTION_BALANCE - for _ in range(spec.MAX_SEED_LOOKAHEAD + 1): - next_epoch(spec, state) - yield from run_process_registry_updates(spec, state) assert state.validators[index].exit_epoch != spec.FAR_FUTURE_EPOCH + assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) assert not spec.is_active_validator( state.validators[index], - spec.get_current_epoch(state), + spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) ) From b6d7cd93e9706702490d87cdf2d9dd202c392a45 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 11 Dec 2019 17:20:35 -0700 Subject: [PATCH 25/56] Add ejection/exit queue test --- .../test_process_registry_updates.py | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index b6bd47204..26a1a5a94 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -1,7 +1,4 @@ -from eth2spec.test.helpers.state import ( - next_epoch, - next_epoch_with_attestations, -) +from eth2spec.test.helpers.state import next_epoch from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with @@ -90,7 +87,10 @@ def test_activation_queue_no_activation_no_finality(spec, state): @with_all_phases @spec_state_test def test_activation_queue_sorting(spec, state): - mock_activations = 10 + churn_limit = spec.get_validator_churn_limit(state) + + # try to activate more than the per-epoch churn linmit + mock_activations = churn_limit * 2 epoch = spec.get_current_epoch(state) for i in range(mock_activations): @@ -104,10 +104,6 @@ def test_activation_queue_sorting(spec, state): state.slot += spec.SLOTS_PER_EPOCH * 3 state.finalized_checkpoint.epoch = epoch + 2 - # make sure we are hitting the churn - churn_limit = spec.get_validator_churn_limit(state) - assert mock_activations > churn_limit - yield from run_process_registry_updates(spec, state) # the first got in as second @@ -173,3 +169,30 @@ def test_ejection(spec, state): state.validators[index], spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) ) + + +@with_all_phases +@spec_state_test +def test_ejection_past_churn_limit(spec, state): + churn_limit = spec.get_validator_churn_limit(state) + + # try to eject more than per-epoch churn limit + mock_ejections = churn_limit * 3 + + for i in range(mock_ejections): + state.validators[i].effective_balance = spec.EJECTION_BALANCE + + expected_ejection_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) + + yield from run_process_registry_updates(spec, state) + + for i in range(mock_ejections): + # first third ejected in normal speed + if i < mock_ejections // 3: + assert state.validators[i].exit_epoch == expected_ejection_epoch + # second thirdgets delayed by 1 epoch + elif mock_ejections // 3 <= i < mock_ejections * 2 // 3: + assert state.validators[i].exit_epoch == expected_ejection_epoch + 1 + # second thirdgets delayed by 2 epochs + else: + assert state.validators[i].exit_epoch == expected_ejection_epoch + 2 From 45620e345d1daf6146efa39d212869e9acb9db1e Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 11 Dec 2019 17:31:05 -0700 Subject: [PATCH 26/56] add test for activation_queue, activation, and ejection all in one --- .../test_process_registry_updates.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index 26a1a5a94..a4655b33e 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -196,3 +196,52 @@ def test_ejection_past_churn_limit(spec, state): # second thirdgets delayed by 2 epochs else: assert state.validators[i].exit_epoch == expected_ejection_epoch + 2 + + +@with_all_phases +@spec_state_test +def test_activation_queue_activation_and_ejection(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + # ready for entrance into activation queue + activation_queue_index = 0 + mock_deposit(spec, state, activation_queue_index) + + # ready for activation + activation_index = 1 + mock_deposit(spec, state, activation_index) + state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1 + state.validators[activation_index].activation_eligibility_epoch = state.finalized_checkpoint.epoch - 1 + + # ready for ejection + ejection_index = 2 + state.validators[ejection_index].effective_balance = spec.EJECTION_BALANCE + + yield from run_process_registry_updates(spec, state) + + # validator moved into activation queue + validator = state.validators[activation_queue_index] + assert validator.activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH + assert validator.activation_epoch == spec.FAR_FUTURE_EPOCH + assert not spec.is_active_validator(validator, spec.get_current_epoch(state)) + + # validator activated for future epoch + validator = state.validators[activation_index] + assert validator.activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH + assert validator.activation_epoch != spec.FAR_FUTURE_EPOCH + assert not spec.is_active_validator(validator, spec.get_current_epoch(state)) + assert spec.is_active_validator( + validator, + spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) + ) + + # validator ejected for future epoch + validator = state.validators[ejection_index] + assert validator.exit_epoch != spec.FAR_FUTURE_EPOCH + assert spec.is_active_validator(validator, spec.get_current_epoch(state)) + assert not spec.is_active_validator( + validator, + spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) + ) From 2405060a7e07c7a7141ba6f45da54eb9d9c21fa4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 12 Dec 2019 01:45:59 +0100 Subject: [PATCH 27/56] Fixes #1486: disallow duplicate indices in indexed attestation --- specs/core/0_beacon-chain.md | 4 +- .../test_process_attester_slashing.py | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 7ce93eb6f..8234c9324 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -628,8 +628,8 @@ def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: Indexe # Verify max number of indices if not len(indices) <= MAX_VALIDATORS_PER_COMMITTEE: return False - # Verify indices are sorted - if not indices == sorted(indices): + # Verify indices are sorted and unique + if not indices == sorted(set(indices)): return False # Verify aggregate signature if not bls_verify( diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py index 85e807ec0..3fc2f8a38 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py @@ -252,6 +252,66 @@ def test_att2_bad_replaced_index(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) +@with_all_phases +@spec_state_test +@always_bls +def test_att1_duplicate_index_normal_signed(spec, state): + attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) + + indices = attester_slashing.attestation_1.attesting_indices + indices.pop(1) # remove an index, make room for the additional duplicate index. + indices.append(indices[0]) # add one of the indices a second time + attester_slashing.attestation_1.attesting_indices = sorted(indices) + sign_indexed_attestation(spec, state, attester_slashing.attestation_1) + # it will just appear normal, unless the double index is spotted + yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + + +@with_all_phases +@spec_state_test +@always_bls +def test_att2_duplicate_index_normal_signed(spec, state): + attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) + + indices = attester_slashing.attestation_2.attesting_indices + indices.pop(2) # remove an index, make room for the additional duplicate index. + indices.append(indices[1]) # add one of the indices a second time + attester_slashing.attestation_2.attesting_indices = sorted(indices) + sign_indexed_attestation(spec, state, attester_slashing.attestation_2) + # it will just appear normal, unless the double index is spotted + yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + + +@with_all_phases +@spec_state_test +@always_bls +def test_att1_duplicate_index_double_signed(spec, state): + attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) + + indices = attester_slashing.attestation_1.attesting_indices + indices.pop(1) # remove an index, make room for the additional duplicate index. + indices.append(indices[2]) # add one of the indices a second time + attester_slashing.attestation_1.attesting_indices = sorted(indices) + sign_indexed_attestation(spec, state, attester_slashing.attestation_1) # will have one attester signing it double + + yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + + +@with_all_phases +@spec_state_test +@always_bls +def test_att2_duplicate_index_double_signed(spec, state): + attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) + + indices = attester_slashing.attestation_2.attesting_indices + indices.pop(1) # remove an index, make room for the additional duplicate index. + indices.append(indices[2]) # add one of the indices a second time + attester_slashing.attestation_2.attesting_indices = sorted(indices) + sign_indexed_attestation(spec, state, attester_slashing.attestation_2) # will have one attester signing it double + + yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + + @with_all_phases @spec_state_test def test_unsorted_att_1(spec, state): From 7691e312c7d9a34dcf213faaf7ec2404b01c90b8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 12 Dec 2019 01:48:03 +0100 Subject: [PATCH 28/56] update mypy to compile pyspec well with py 3.8.0, and minor mypy fix --- scripts/build_spec.py | 2 +- test_libs/pyspec/requirements-testing.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index c38d0bd65..cca5a1bf9 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -82,7 +82,7 @@ def get_eth1_data(distance: uint64) -> Bytes32: return hash(distance) -def hash(x: bytes) -> Bytes32: +def hash(x: bytes) -> Bytes32: # type: ignore if x not in hash_cache: hash_cache[x] = Bytes32(_hash(x)) return hash_cache[x] diff --git a/test_libs/pyspec/requirements-testing.txt b/test_libs/pyspec/requirements-testing.txt index b5229ae20..e8ecd12a6 100644 --- a/test_libs/pyspec/requirements-testing.txt +++ b/test_libs/pyspec/requirements-testing.txt @@ -2,6 +2,6 @@ pytest>=4.4 ../config_helpers flake8==3.7.7 -mypy==0.701 +mypy==0.750 pytest-cov pytest-xdist From 8d5d7387f959e6393da5b29684d52ae04e64722f Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 12 Dec 2019 02:36:20 +0100 Subject: [PATCH 29/56] Two tests for proposer indices being off because of active validators status, fixes #1515 --- .../eth2spec/test/sanity/test_blocks.py | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index 41316e92d..3c42446cb 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -3,7 +3,7 @@ from copy import deepcopy from eth2spec.utils.ssz.ssz_impl import hash_tree_root from eth2spec.utils.bls import bls_sign -from eth2spec.test.helpers.state import get_balance, state_transition_and_sign_block +from eth2spec.test.helpers.state import get_balance, state_transition_and_sign_block, next_slot from eth2spec.test.helpers.block import build_empty_block_for_next_slot, build_empty_block, sign_block, \ transition_unsigned_block from eth2spec.test.helpers.keys import privkeys, pubkeys @@ -253,6 +253,56 @@ def test_attester_slashing(spec, state): ) +@with_all_phases +@spec_state_test +def test_proposer_after_inactive_index(spec, state): + # disable some low validator index to check after for + inactive_index = 10 + state.validators[inactive_index].exit_epoch = spec.get_current_epoch(state) + + # skip forward, get brand new proposers + state.slot = spec.SLOTS_PER_EPOCH * 2 + + while True: + proposer_index = spec.get_beacon_proposer_index(state) + if proposer_index > inactive_index: + # found a proposer that has a higher index than a disabled validator + yield 'pre', state + # test if the proposer can be recognized correctly after the inactive validator + signed_block = sign_block(spec, state, build_empty_block(spec, state), proposer_index=proposer_index) + yield 'blocks', [signed_block] + yield 'post', state + break + else: + next_slot(spec, state) + + +@with_all_phases +@spec_state_test +def test_high_proposer_index(spec, state): + # disable a good amount of validators to make the active count lower, for a faster test + current_epoch = spec.get_current_epoch(state) + for i in range(len(state.validators) // 3): + state.validators[i].exit_epoch = current_epoch + + # skip forward, get brand new proposers + state.slot = spec.SLOTS_PER_EPOCH * 2 + + active_count = len(spec.get_active_validator_indices(state, current_epoch)) + while True: + proposer_index = spec.get_beacon_proposer_index(state) + if proposer_index >= active_count: + # found a proposer that has a higher index than the active validator count + yield 'pre', state + # test if the proposer can be recognized correctly, even while it has a high index. + signed_block = sign_block(spec, state, build_empty_block(spec, state), proposer_index=proposer_index) + yield 'blocks', [signed_block] + yield 'post', state + break + else: + next_slot(spec, state) + + @with_all_phases @spec_state_test def test_expected_deposit_in_block(spec, state): From 3d48a3e9eb6174e53c3bb672e1cdf77c47268eb1 Mon Sep 17 00:00:00 2001 From: ethers <6937903+ethers@users.noreply.github.com> Date: Wed, 11 Dec 2019 18:17:20 -0800 Subject: [PATCH 30/56] Fix dead link to use Internet Archive --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fca21994f..8cfcd622e 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -178,7 +178,7 @@ The following values are (non-configurable) constants used throughout the specif | `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT` | `2**14` (= 16,384) | | `MIN_GENESIS_TIME` | `1578009600` (Jan 3, 2020) | -- For the safety of committees, `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) +- For the safety of committees, `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](http://web.archive.org/web/20190504131341/https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) ### Gwei values From 19ec01e4e919252108876168b116f3e511784854 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 12 Dec 2019 06:43:37 -0700 Subject: [PATCH 31/56] add comment about activation queue sort order Co-Authored-By: Hsiao-Wei Wang --- specs/core/0_beacon-chain.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 210e1797f..ff0d42634 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1341,7 +1341,8 @@ def process_registry_updates(state: BeaconState) -> None: activation_queue = sorted([ index for index, validator in enumerate(state.validators) if is_eligible_for_activation(state, validator) - ], key=lambda index: state.validators[index].activation_eligibility_epoch) + # Order by the sequence of activation_eligibility_epoch setting and then index. + ], key=lambda index: (state.validators[index].activation_eligibility_epoch, index)) # Dequeued validators for activation up to churn limit for index in activation_queue[:get_validator_churn_limit(state)]: validator = state.validators[index] From 86fb3acd59a51be40c04e7a56e50d3ea51c43d71 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 12 Dec 2019 06:53:56 -0700 Subject: [PATCH 32/56] minor changes to finality in activation queue --- specs/core/0_beacon-chain.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index ff0d42634..f9a726ff4 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -623,8 +623,8 @@ def is_eligible_for_activation(state: BeaconState, validator: Validator) -> bool Check if ``validator`` is eligible for activation. """ return ( - # Was placed in activation queue prior to most recent finalized epoch - validator.activation_eligibility_epoch < state.finalized_checkpoint.epoch + # Placement in queue is finalized + validator.activation_eligibility_epoch <= state.finalized_checkpoint.epoch # Has not yet been activated and validator.activation_epoch == FAR_FUTURE_EPOCH ) @@ -1332,7 +1332,7 @@ def process_registry_updates(state: BeaconState) -> None: # Process activation eligibility and ejections for index, validator in enumerate(state.validators): if is_eligible_for_activation_queue(validator): - validator.activation_eligibility_epoch = get_current_epoch(state) + validator.activation_eligibility_epoch = get_current_epoch(state) + 1 if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE: initiate_validator_exit(state, ValidatorIndex(index)) @@ -1341,7 +1341,7 @@ def process_registry_updates(state: BeaconState) -> None: activation_queue = sorted([ index for index, validator in enumerate(state.validators) if is_eligible_for_activation(state, validator) - # Order by the sequence of activation_eligibility_epoch setting and then index. + # Order by the sequence of activation_eligibility_epoch setting and then index ], key=lambda index: (state.validators[index].activation_eligibility_epoch, index)) # Dequeued validators for activation up to churn limit for index in activation_queue[:get_validator_churn_limit(state)]: From 199933cb2664061e0ebff273ef9bf0c5f4b024a8 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 12 Dec 2019 06:57:11 -0700 Subject: [PATCH 33/56] fix tocs --- specs/core/0_beacon-chain.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index f9a726ff4..b74a29e9d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -61,6 +61,8 @@ - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys) - [Predicates](#predicates) - [`is_active_validator`](#is_active_validator) + - [`is_eligible_for_activation_queue`](#is_eligible_for_activation_queue) + - [`is_eligible_for_activation`](#is_eligible_for_activation) - [`is_slashable_validator`](#is_slashable_validator) - [`is_slashable_attestation_data`](#is_slashable_attestation_data) - [`is_valid_indexed_attestation`](#is_valid_indexed_attestation) @@ -591,16 +593,6 @@ def is_active_validator(validator: Validator, epoch: Epoch) -> bool: return validator.activation_epoch <= epoch < validator.exit_epoch ``` -#### `is_slashable_validator` - -```python -def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool: - """ - Check if ``validator`` is slashable. - """ - return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch) -``` - #### `is_eligible_for_activation_queue` ```python @@ -614,7 +606,6 @@ def is_eligible_for_activation_queue(validator: Validator) -> bool: ) ``` - #### `is_eligible_for_activation` ```python @@ -630,6 +621,16 @@ def is_eligible_for_activation(state: BeaconState, validator: Validator) -> bool ) ``` +#### `is_slashable_validator` + +```python +def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool: + """ + Check if ``validator`` is slashable. + """ + return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch) +``` + #### `is_slashable_attestation_data` ```python From ba8a67ccd89fa068dd4ba4d88ac788d095deba21 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 12 Dec 2019 07:31:51 -0700 Subject: [PATCH 34/56] update registry tests to modified finality condition --- .../test_process_registry_updates.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index a4655b33e..526aba277 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -43,9 +43,9 @@ def test_activation_queue_to_activated_if_finalized(spec, state): index = 0 mock_deposit(spec, state, index) - # mock validator as having been in queue since before latest finalized + # mock validator as having been in queue since latest finalized state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1 - state.validators[index].activation_eligibility_epoch = state.finalized_checkpoint.epoch - 1 + state.validators[index].activation_eligibility_epoch = state.finalized_checkpoint.epoch assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) @@ -71,9 +71,9 @@ def test_activation_queue_no_activation_no_finality(spec, state): index = 0 mock_deposit(spec, state, index) - # mock validator as having been in queue only since latest finalized (not before) + # mock validator as having been in queue only after latest finalized state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1 - state.validators[index].activation_eligibility_epoch = state.finalized_checkpoint.epoch + state.validators[index].activation_eligibility_epoch = state.finalized_checkpoint.epoch + 1 assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) @@ -102,7 +102,7 @@ def test_activation_queue_sorting(spec, state): # move state forward and finalize to allow for activations state.slot += spec.SLOTS_PER_EPOCH * 3 - state.finalized_checkpoint.epoch = epoch + 2 + state.finalized_checkpoint.epoch = epoch + 1 yield from run_process_registry_updates(spec, state) @@ -132,7 +132,7 @@ def test_activation_queue_efficiency(spec, state): # move state forward and finalize to allow for activations state.slot += spec.SLOTS_PER_EPOCH * 3 - state.finalized_checkpoint.epoch = epoch + 2 + state.finalized_checkpoint.epoch = epoch + 1 # Run first registry update. Do not yield test vectors for _ in run_process_registry_updates(spec, state): @@ -213,7 +213,7 @@ def test_activation_queue_activation_and_ejection(spec, state): activation_index = 1 mock_deposit(spec, state, activation_index) state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1 - state.validators[activation_index].activation_eligibility_epoch = state.finalized_checkpoint.epoch - 1 + state.validators[activation_index].activation_eligibility_epoch = state.finalized_checkpoint.epoch # ready for ejection ejection_index = 2 From 020dbb1ecd3ac29f7e8e0a0beae304f5769c4304 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 12 Dec 2019 16:16:52 +0100 Subject: [PATCH 35/56] fix missing transition --- test_libs/pyspec/eth2spec/test/sanity/test_blocks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index 3c42446cb..2c08a88fe 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -269,7 +269,7 @@ def test_proposer_after_inactive_index(spec, state): # found a proposer that has a higher index than a disabled validator yield 'pre', state # test if the proposer can be recognized correctly after the inactive validator - signed_block = sign_block(spec, state, build_empty_block(spec, state), proposer_index=proposer_index) + signed_block = state_transition_and_sign_block(spec, state, build_empty_block(spec, state)) yield 'blocks', [signed_block] yield 'post', state break @@ -295,7 +295,7 @@ def test_high_proposer_index(spec, state): # found a proposer that has a higher index than the active validator count yield 'pre', state # test if the proposer can be recognized correctly, even while it has a high index. - signed_block = sign_block(spec, state, build_empty_block(spec, state), proposer_index=proposer_index) + signed_block = state_transition_and_sign_block(spec, state, build_empty_block(spec, state)) yield 'blocks', [signed_block] yield 'post', state break From 5c26d8e52fd48833ed22e4773915cc9b2a3b248b Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 12 Dec 2019 16:29:30 +0100 Subject: [PATCH 36/56] fix normal signed case; only sign for 1 of the duplicate indices --- .../test_process_attester_slashing.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py index 3fc2f8a38..98a6e25e5 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py @@ -260,9 +260,14 @@ def test_att1_duplicate_index_normal_signed(spec, state): indices = attester_slashing.attestation_1.attesting_indices indices.pop(1) # remove an index, make room for the additional duplicate index. + attester_slashing.attestation_1.attesting_indices = sorted(indices) + + # sign it, the signature will be valid for a single occurence. If the transition accidentally ignores the duplicate. + sign_indexed_attestation(spec, state, attester_slashing.attestation_1) + indices.append(indices[0]) # add one of the indices a second time attester_slashing.attestation_1.attesting_indices = sorted(indices) - sign_indexed_attestation(spec, state, attester_slashing.attestation_1) + # it will just appear normal, unless the double index is spotted yield from run_attester_slashing_processing(spec, state, attester_slashing, False) @@ -275,9 +280,14 @@ def test_att2_duplicate_index_normal_signed(spec, state): indices = attester_slashing.attestation_2.attesting_indices indices.pop(2) # remove an index, make room for the additional duplicate index. + attester_slashing.attestation_2.attesting_indices = sorted(indices) + + # sign it, the signature will be valid for a single occurence. If the transition accidentally ignores the duplicate. + sign_indexed_attestation(spec, state, attester_slashing.attestation_2) + indices.append(indices[1]) # add one of the indices a second time attester_slashing.attestation_2.attesting_indices = sorted(indices) - sign_indexed_attestation(spec, state, attester_slashing.attestation_2) + # it will just appear normal, unless the double index is spotted yield from run_attester_slashing_processing(spec, state, attester_slashing, False) From 020af2707ac5c26e2753cc69f8a02af5086543eb Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 12 Dec 2019 16:40:57 +0100 Subject: [PATCH 37/56] fix: don't get stuck in same slot doing a transition, and clean up latest-block-header with starting block for pre-state --- test_libs/pyspec/eth2spec/test/sanity/test_blocks.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index 2c08a88fe..c2f980ba0 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -262,8 +262,11 @@ def test_proposer_after_inactive_index(spec, state): # skip forward, get brand new proposers state.slot = spec.SLOTS_PER_EPOCH * 2 + block = build_empty_block_for_next_slot(spec, state) + state_transition_and_sign_block(spec, state, block) while True: + next_slot(spec, state) proposer_index = spec.get_beacon_proposer_index(state) if proposer_index > inactive_index: # found a proposer that has a higher index than a disabled validator @@ -273,8 +276,6 @@ def test_proposer_after_inactive_index(spec, state): yield 'blocks', [signed_block] yield 'post', state break - else: - next_slot(spec, state) @with_all_phases @@ -287,9 +288,12 @@ def test_high_proposer_index(spec, state): # skip forward, get brand new proposers state.slot = spec.SLOTS_PER_EPOCH * 2 + block = build_empty_block_for_next_slot(spec, state) + state_transition_and_sign_block(spec, state, block) active_count = len(spec.get_active_validator_indices(state, current_epoch)) while True: + next_slot(spec, state) proposer_index = spec.get_beacon_proposer_index(state) if proposer_index >= active_count: # found a proposer that has a higher index than the active validator count @@ -299,8 +303,6 @@ def test_high_proposer_index(spec, state): yield 'blocks', [signed_block] yield 'post', state break - else: - next_slot(spec, state) @with_all_phases From 47ecedb81d34df345b856d7d52e37fa0cf182dee Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 12 Dec 2019 09:48:53 -0700 Subject: [PATCH 38/56] update tocs --- specs/core/0_beacon-chain.md | 2 ++ specs/core/0_fork-choice.md | 1 + 2 files changed, 3 insertions(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 22522b3bd..e7c62d342 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -62,6 +62,8 @@ - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys) - [Predicates](#predicates) - [`is_active_validator`](#is_active_validator) + - [`is_eligible_for_activation_queue`](#is_eligible_for_activation_queue) + - [`is_eligible_for_activation`](#is_eligible_for_activation) - [`is_slashable_validator`](#is_slashable_validator) - [`is_slashable_attestation_data`](#is_slashable_attestation_data) - [`is_valid_indexed_attestation`](#is_valid_indexed_attestation) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 2191c24a2..34430d092 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -15,6 +15,7 @@ - [`LatestMessage`](#latestmessage) - [`Store`](#store) - [`get_genesis_store`](#get_genesis_store) + - [`get_slots_since_genesis`](#get_slots_since_genesis) - [`get_current_slot`](#get_current_slot) - [`compute_slots_since_epoch_start`](#compute_slots_since_epoch_start) - [`get_ancestor`](#get_ancestor) From b09c45ffd210c3d28caf3e64ede61ee0ce17146c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 12 Dec 2019 12:34:02 -0700 Subject: [PATCH 39/56] remove last two references to signing root --- specs/networking/p2p-interface.md | 2 +- specs/test_formats/ssz_generic/README.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index dfddbb3f7..84539713d 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -421,7 +421,7 @@ The fields are, as seen by the client at the time of sending the message: - `head_fork_version`: The beacon_state `Fork` version. - `finalized_root`: `state.finalized_checkpoint.root` for the state corresponding to the head block. - `finalized_epoch`: `state.finalized_checkpoint.epoch` for the state corresponding to the head block. -- `head_root`: The signing root of the current head block. +- `head_root`: The hash_tree_root root of the current head block. - `head_slot`: The slot of the block corresponding to the `head_root`. The dialing client MUST send a `Status` request upon connection. diff --git a/specs/test_formats/ssz_generic/README.md b/specs/test_formats/ssz_generic/README.md index ce0f709dd..b6faa04af 100644 --- a/specs/test_formats/ssz_generic/README.md +++ b/specs/test_formats/ssz_generic/README.md @@ -37,7 +37,7 @@ Valid has 3 parts: `meta.yaml`, `serialized.ssz`, `value.yaml` ### `meta.yaml` -Valid ssz objects can have a hash-tree-root, and for some types also a signing-root. +Valid ssz objects can have a hash-tree-root. The expected roots are encoded into the metadata yaml: ```yaml @@ -61,7 +61,6 @@ The conditions are the same for each type: - Encoding: After encoding the given `value` object, the output should match `serialized`. - Decoding: After decoding the given `serialized` bytes, it should match the `value` object. - Hash-tree-root: the root should match the root declared in the metadata. -- Signing-root: if present in metadata, the signing root of the object should match the container. ## `invalid` From a4f8a77c027766af6cbc12f9f5cddc08fe0b85bc Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Mon, 16 Dec 2019 12:55:18 +0100 Subject: [PATCH 40/56] Fix spelling errors found by codespell --- Makefile | 3 +++ scripts/build_spec.py | 2 +- specs/core/0_beacon-chain.md | 2 +- specs/test_formats/ssz_generic/README.md | 2 +- .../block_processing/test_process_attester_slashing.py | 4 ++-- .../epoch_processing/test_process_rewards_and_penalties.py | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 2cdb1021f..2bd87aed8 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,9 @@ check_toc: $(MARKDOWN_FILES:=.toc) diff -q $* $*.tmp && \ rm $*.tmp +codespell: + ! codespell . --skip ./.git | grep -v 'disabled' + lint: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; \ flake8 --ignore=E252,W504,W503 --max-line-length=120 ./eth2spec \ diff --git a/scripts/build_spec.py b/scripts/build_spec.py index cca5a1bf9..d5689b082 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -252,7 +252,7 @@ def combine_ssz_objects(old_objects: Dict[str, str], new_objects: Dict[str, str] return old_objects -# inserts are handeled the same way as functions +# inserts are handled the same way as functions combine_inserts = combine_functions diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index e7c62d342..ab1ea2c08 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -560,7 +560,7 @@ def int_to_bytes(n: uint64, length: uint64) -> bytes: ```python def bytes_to_int(data: bytes) -> uint64: """ - Return the integer deserialization of ``data`` intepreted as ``ENDIANNESS``-endian. + Return the integer deserialization of ``data`` interpreted as ``ENDIANNESS``-endian. """ return int.from_bytes(data, ENDIANNESS) ``` diff --git a/specs/test_formats/ssz_generic/README.md b/specs/test_formats/ssz_generic/README.md index b6faa04af..68bdbc15f 100644 --- a/specs/test_formats/ssz_generic/README.md +++ b/specs/test_formats/ssz_generic/README.md @@ -150,7 +150,7 @@ Template: Data: -{container name}: Any of the container names listed below (exluding the `(Container)` python super type) +{container name}: Any of the container names listed below (excluding the `(Container)` python super type) ``` ```python diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py index 98a6e25e5..19fdd04a2 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py @@ -262,7 +262,7 @@ def test_att1_duplicate_index_normal_signed(spec, state): indices.pop(1) # remove an index, make room for the additional duplicate index. attester_slashing.attestation_1.attesting_indices = sorted(indices) - # sign it, the signature will be valid for a single occurence. If the transition accidentally ignores the duplicate. + # sign it, the signature will be valid for a single occurrence. If the transition accidentally ignores the duplicate. sign_indexed_attestation(spec, state, attester_slashing.attestation_1) indices.append(indices[0]) # add one of the indices a second time @@ -282,7 +282,7 @@ def test_att2_duplicate_index_normal_signed(spec, state): indices.pop(2) # remove an index, make room for the additional duplicate index. attester_slashing.attestation_2.attesting_indices = sorted(indices) - # sign it, the signature will be valid for a single occurence. If the transition accidentally ignores the duplicate. + # sign it, the signature will be valid for a single occurrence. If the transition accidentally ignores the duplicate. sign_indexed_attestation(spec, state, attester_slashing.attestation_2) indices.append(indices[1]) # add one of the indices a second time diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_rewards_and_penalties.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_rewards_and_penalties.py index 7d844b63b..b4fc46b7d 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_rewards_and_penalties.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_rewards_and_penalties.py @@ -155,7 +155,7 @@ def test_duplicate_attestation(spec, state): next_epoch(spec, single_state) next_epoch(spec, dup_state) - # Run non-duplicate inclusion rewards for comparision. Do not yield test vectors + # Run non-duplicate inclusion rewards for comparison. Do not yield test vectors for _ in run_process_rewards_and_penalties(spec, single_state): pass From 5234e431ec71643e57da90825728d9a5db963054 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Mon, 16 Dec 2019 12:55:51 +0100 Subject: [PATCH 41/56] Add codespell to ci --- .circleci/config.yml | 10 ++++++++++ Makefile | 1 + 2 files changed, 11 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 19ab1543a..60d26e896 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -112,6 +112,15 @@ jobs: - run: name: Check table of contents command: sudo npm install -g doctoc && make check_toc + codespell: + docker: + - image: circleci/python:3.6 + working_directory: ~/specs-repo + steps: + - checkout + - run: + name: Check codespell + command: pip install codespell --user && make codespell lint: docker: - image: circleci/python:3.6 @@ -158,6 +167,7 @@ workflows: requires: - install_pyspec_test - table_of_contents + - codespell - lint: requires: - test diff --git a/Makefile b/Makefile index 2bd87aed8..61fc34a52 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,7 @@ check_toc: $(MARKDOWN_FILES:=.toc) rm $*.tmp codespell: + # Check codespell for errors, but disregard entries in .codespell-whitelist ! codespell . --skip ./.git | grep -v 'disabled' lint: $(PY_SPEC_ALL_TARGETS) From 21c8c58cb18c717b59b715c089a588501b27a5d4 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Mon, 16 Dec 2019 13:22:08 +0100 Subject: [PATCH 42/56] edit comment to make line shorter --- .../block_processing/test_process_attester_slashing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py index 19fdd04a2..dba48ca64 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py @@ -262,7 +262,7 @@ def test_att1_duplicate_index_normal_signed(spec, state): indices.pop(1) # remove an index, make room for the additional duplicate index. attester_slashing.attestation_1.attesting_indices = sorted(indices) - # sign it, the signature will be valid for a single occurrence. If the transition accidentally ignores the duplicate. + # The signature will be valid for a single occurrence. If the transition accidentally ignores the duplicate. sign_indexed_attestation(spec, state, attester_slashing.attestation_1) indices.append(indices[0]) # add one of the indices a second time @@ -282,7 +282,7 @@ def test_att2_duplicate_index_normal_signed(spec, state): indices.pop(2) # remove an index, make room for the additional duplicate index. attester_slashing.attestation_2.attesting_indices = sorted(indices) - # sign it, the signature will be valid for a single occurrence. If the transition accidentally ignores the duplicate. + # The signature will be valid for a single occurrence. If the transition accidentally ignores the duplicate. sign_indexed_attestation(spec, state, attester_slashing.attestation_2) indices.append(indices[1]) # add one of the indices a second time From 798fadc3cb432ac6c260ecf456e58d3ca6ebbbe4 Mon Sep 17 00:00:00 2001 From: Martin Lundfall Date: Mon, 16 Dec 2019 14:11:05 +0100 Subject: [PATCH 43/56] Makefile: Use codespell as intended --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 61fc34a52..2b165ad7d 100644 --- a/Makefile +++ b/Makefile @@ -78,8 +78,7 @@ check_toc: $(MARKDOWN_FILES:=.toc) rm $*.tmp codespell: - # Check codespell for errors, but disregard entries in .codespell-whitelist - ! codespell . --skip ./.git | grep -v 'disabled' + codespell . --skip ./.git -I .codespell-whitelist lint: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; \ From fa916323f0e520208d0f51f5153d73482904c763 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 17 Dec 2019 10:56:52 -0700 Subject: [PATCH 44/56] add basics for ENR bitfield --- specs/networking/p2p-interface.md | 9 +++++++++ specs/validator/0_beacon-chain-validator.md | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 84539713d..8487bd3ba 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -53,6 +53,7 @@ It consists of four main sections: - [The discovery domain: discv5](#the-discovery-domain-discv5) - [Integration into libp2p stacks](#integration-into-libp2p-stacks) - [ENR structure](#enr-structure) + - [Shard bitfield](#shard-bitfield) - [Interop](#interop-5) - [Mainnet](#mainnet-5) - [Topic advertisement](#topic-advertisement) @@ -557,6 +558,14 @@ The Ethereum Node Record (ENR) for an Ethereum 2.0 client MUST contain the follo Specifications of these parameters can be found in the [ENR Specification](http://eips.ethereum.org/EIPS/eip-778). +#### Shard bitfield + +The ENR MAY contain an entry signifying the shard subnet bitfield with the following form to more easily discover peers participating in particular shard gossip subnets. + +| Key | Value | +|:-------------|:-------------------------------------------------| +| `shards` | SSZ `Bitvector[MAX_COMMITTEES_PER_SLOT]` | + #### Interop In the interoperability testnet, all peers will support all capabilities defined in this document (gossip, full Req/Resp suite, discovery protocol), therefore the ENR record does not need to carry Eth2 capability information, as it would be superfluous. diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 76bcc3b7d..f2a666dce 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -198,7 +198,7 @@ Specifically a validator should: * Call `get_committee_assignment(state, next_epoch, validator_index)` when checking for next epoch assignments. * Join the pubsub topic -- `committee_index{committee_index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. * If any current peers are subscribed to the topic, the validator simply sends `subscribe` messages for the new topic. - * If no current peers are subscribed to the topic, the validator must discover new peers on this topic. If "topic discovery" is available, use topic discovery to find peers that advertise subscription to the topic. If not, "guess and check" by connecting with a number of random new peers, persisting connections with peers subscribed to the topic and (potentially) dropping the new peers otherwise. + * If no current peers are subscribed to the topic, the validator must discover new peers on this topic. Find peers via the discovery protocol with an ENR containing the `shards` entry such that `ENR["shards"][committee_index % ATTESTATION_SUBNET_COUNT] == True`. ## Beacon chain responsibilities @@ -443,7 +443,11 @@ Where ## Phase 0 attestation subnet stability -Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`committee_index{subnet_id}_beacon_attestation`). To provide this stability, each validator must randomly select and remain subscribed to `RANDOM_SUBNETS_PER_VALIDATOR` attestation subnets. The lifetime of each random subscription should be a random number of epochs between `EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION` and `2 * EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION]`. +Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`committee_index{subnet_id}_beacon_attestation`). To provide this stability, each validator must + +* Randomly select and remain subscribed to `RANDOM_SUBNETS_PER_VALIDATOR` attestation subnets +* Maintain advertisement of the randomly selected subnets in their node's ENR `shards` entry by setting the randomly selected `subnet_id` bits to `True` (e.g. `ENR["shards"][subnet_id] = True`) for all persistent attestation subnets +* Set the lifetime of each random subscription to a random number of epochs between `EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION` and `2 * EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION]`. At the end of life for a subscription, select a new random subnet, update subnet subscriptions, and publish an updated ENR ## How to avoid slashing From caffe8d720b5987ac6d794f9b00182a9439666e0 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 17 Dec 2019 16:25:30 -0700 Subject: [PATCH 45/56] update ENR to use attesation subnets instead of shards --- specs/networking/p2p-interface.md | 21 +++++++++------------ specs/validator/0_beacon-chain-validator.md | 8 ++++---- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 8487bd3ba..38e9b366b 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -53,11 +53,10 @@ It consists of four main sections: - [The discovery domain: discv5](#the-discovery-domain-discv5) - [Integration into libp2p stacks](#integration-into-libp2p-stacks) - [ENR structure](#enr-structure) - - [Shard bitfield](#shard-bitfield) + - [Attestation subnet bitfield](#attestation-subnet-bitfield) - [Interop](#interop-5) - [Mainnet](#mainnet-5) - [Topic advertisement](#topic-advertisement) - - [Interop](#interop-6) - [Mainnet](#mainnet-6) - [Design decision rationale](#design-decision-rationale) - [Transport](#transport-1) @@ -558,13 +557,13 @@ The Ethereum Node Record (ENR) for an Ethereum 2.0 client MUST contain the follo Specifications of these parameters can be found in the [ENR Specification](http://eips.ethereum.org/EIPS/eip-778). -#### Shard bitfield +#### Attestation subnet bitfield -The ENR MAY contain an entry signifying the shard subnet bitfield with the following form to more easily discover peers participating in particular shard gossip subnets. +The ENR MAY contain an entry (`attnets`) signifying the attestation subnet bitfield with the following form to more easily discover peers participating in particular attestation gossip subnets. | Key | Value | |:-------------|:-------------------------------------------------| -| `shards` | SSZ `Bitvector[MAX_COMMITTEES_PER_SLOT]` | +| `attnets` | SSZ `Bitvector[ATTESTATION_SUBNET_COUNT]` | #### Interop @@ -578,13 +577,11 @@ On mainnet, ENRs MUST include a structure enumerating the capabilities offered b ### Topic advertisement -#### Interop - -This feature will not be used in the interoperability testnet. - #### Mainnet -In mainnet, we plan to use discv5’s topic advertisement feature as a rendezvous facility for peers on shards (thus subscribing to the relevant gossipsub topics). +discv5's topic advertisement feature is not expected to be ready for mainnet launch of Phase 0. + +Once this feature is built out and stable, we expect to use topic advertisement as a rendezvous facility for peers on shards. Until then, the ENR [attestation subnet bitfield](#attestation-subnet-bitfield) will be used for discovery of peers on particular subnets. # Design decision rationale @@ -773,9 +770,9 @@ The prohibition of unverified-block-gossiping extends to nodes that cannot verif ### How are we going to discover peers in a gossipsub topic? -Via discv5 topics. ENRs should not be used for this purpose, as they store identity, location, and capability information, not volatile [advertisements](#topic-advertisement). +In Phase 0, peers for attestation subnets will be found using the `attnets` entry in the ENR. -In the interoperability testnet, all peers will be subscribed to all global beacon chain topics, so discovering peers in specific shard topics will be unnecessary. +Although this method will be sufficient for early phases of Eth2, we aim to use the more appropriate discv5 topics for this and other similar tasks in the future. ENRs should ultimately not be used for this purpose. They are best suited to store identity, location, and capability information, rather than more volatile advertisements. ## Req/Resp diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index f2a666dce..341fb8e8c 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -197,8 +197,8 @@ The beacon chain shufflings are designed to provide a minimum of 1 epoch lookahe Specifically a validator should: * Call `get_committee_assignment(state, next_epoch, validator_index)` when checking for next epoch assignments. * Join the pubsub topic -- `committee_index{committee_index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. - * If any current peers are subscribed to the topic, the validator simply sends `subscribe` messages for the new topic. - * If no current peers are subscribed to the topic, the validator must discover new peers on this topic. Find peers via the discovery protocol with an ENR containing the `shards` entry such that `ENR["shards"][committee_index % ATTESTATION_SUBNET_COUNT] == True`. + * For any current peer subscribed to the topic, the validator simply sends a `subscribe` message for the new topic. + * If an _insufficient_ number of current peers are subscribed to the topic, the validator must discover new peers on this topic. Via the discovery protocol, find peers with an ENR containing the `attnets` entry such that `ENR["attnets"][committee_index % ATTESTATION_SUBNET_COUNT] == True`. ## Beacon chain responsibilities @@ -443,10 +443,10 @@ Where ## Phase 0 attestation subnet stability -Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`committee_index{subnet_id}_beacon_attestation`). To provide this stability, each validator must +Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`committee_index{subnet_id}_beacon_attestation`). To provide this stability, each validator must: * Randomly select and remain subscribed to `RANDOM_SUBNETS_PER_VALIDATOR` attestation subnets -* Maintain advertisement of the randomly selected subnets in their node's ENR `shards` entry by setting the randomly selected `subnet_id` bits to `True` (e.g. `ENR["shards"][subnet_id] = True`) for all persistent attestation subnets +* Maintain advertisement of the randomly selected subnets in their node's ENR `attnets` entry by setting the randomly selected `subnet_id` bits to `True` (e.g. `ENR["attnets"][subnet_id] = True`) for all persistent attestation subnets * Set the lifetime of each random subscription to a random number of epochs between `EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION` and `2 * EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION]`. At the end of life for a subscription, select a new random subnet, update subnet subscriptions, and publish an updated ENR ## How to avoid slashing From 4290c1dd1b60b4e2144c09d5f8a6385ff8c32b70 Mon Sep 17 00:00:00 2001 From: Daejun Park Date: Tue, 17 Dec 2019 18:58:56 -0600 Subject: [PATCH 46/56] Vyper b13 -> b13.hotfix1761 --- deposit_contract/contracts/validator_registration.json | 2 +- deposit_contract/contracts/validator_registration.v.py | 2 +- deposit_contract/requirements-testing.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deposit_contract/contracts/validator_registration.json b/deposit_contract/contracts/validator_registration.json index cd2004233..12cfd74ac 100644 --- a/deposit_contract/contracts/validator_registration.json +++ b/deposit_contract/contracts/validator_registration.json @@ -1 +1 @@ -{"abi": [{"name": "DepositEvent", "inputs": [{"type": "bytes", "name": "pubkey", "indexed": false}, {"type": "bytes", "name": "withdrawal_credentials", "indexed": false}, {"type": "bytes", "name": "amount", "indexed": false}, {"type": "bytes", "name": "signature", "indexed": false}, {"type": "bytes", "name": "index", "indexed": false}], "anonymous": false, "type": "event"}, {"outputs": [], "inputs": [], "constant": false, "payable": false, "type": "constructor"}, {"name": "get_deposit_root", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 95727}, {"name": "get_deposit_count", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 18283}, {"name": "deposit", "outputs": [], "inputs": [{"type": "bytes", "name": "pubkey"}, {"type": "bytes", "name": "withdrawal_credentials"}, {"type": "bytes", "name": "signature"}, {"type": "bytes32", "name": "deposit_data_root"}], "constant": false, "payable": true, "type": "function", "gas": 1342680}], "bytecode": "0x740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052341561009857600080fd5b6101406000601f818352015b600061014051602081106100b757600080fd5b600260c052602060c020015460208261016001015260208101905061014051602081106100e357600080fd5b600260c052602060c020015460208261016001015260208101905080610160526101609050602060c0825160208401600060025af161012157600080fd5b60c0519050606051600161014051018060405190131561014057600080fd5b809190121561014e57600080fd5b6020811061015b57600080fd5b600260c052602060c02001555b81516001018083528114156100a4575b505061127956600436101561000d576110f4565b600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052600015610286575b6101605261014052600061018052610140516101a0526101c060006008818352015b61018051600860008112156100e8578060000360020a82046100ef565b8060020a82025b905090506101805260ff6101a051166101e052610180516101e0516101805101101561011a57600080fd5b6101e0516101805101610180526101a0517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86000811215610163578060000360020a820461016a565b8060020a82025b905090506101a0525b81516001018083528114156100cb575b5050601860086020820661020001602082840111156101a157600080fd5b60208061022082610180600060046015f15050818152809050905090508051602001806102c0828460006004600a8704601201f16101de57600080fd5b50506102c05160206001820306601f82010390506103206102c0516020818352015b82610320511015156102115761022d565b6000610320516102e001535b8151600101808352811415610200575b50505060206102a05260406102c0510160206001820306601f8201039050610280525b6000610280511115156102625761027e565b602061028051036102a001516020610280510361028052610250565b610160515650005b63c5f2892f600051141561051857341561029f57600080fd5b6000610140526101405161016052600154610180526101a060006020818352015b60016001610180511614156103415760006101a051602081106102e257600080fd5b600060c052602060c02001546020826102400101526020810190506101605160208261024001015260208101905080610240526102409050602060c0825160208401600060025af161033357600080fd5b60c0519050610160526103af565b6000610160516020826101c00101526020810190506101a0516020811061036757600080fd5b600260c052602060c02001546020826101c0010152602081019050806101c0526101c09050602060c0825160208401600060025af16103a557600080fd5b60c0519050610160525b61018060026103bd57600080fd5b60028151048152505b81516001018083528114156102c0575b505060006101605160208261046001015260208101905061014051610160516101805163806732896102e0526001546103005261030051600658016100a9565b506103605260006103c0525b6103605160206001820306601f82010390506103c0511015156104445761045d565b6103c05161038001526103c0516020016103c052610422565b61018052610160526101405261036060088060208461046001018260208501600060046012f150508051820191505060006018602082066103e001602082840111156104a857600080fd5b60208061040082610140600060046015f150508181528090509050905060188060208461046001018260208501600060046014f150508051820191505080610460526104609050602060c0825160208401600060025af161050857600080fd5b60c051905060005260206000f350005b63621fd130600051141561062c57341561053157600080fd5b6380673289610140526001546101605261016051600658016100a9565b506101c0526000610220525b6101c05160206001820306601f82010390506102205110151561057c57610595565b610220516101e00152610220516020016102205261055a565b6101c0805160200180610280828460006004600a8704601201f16105b857600080fd5b50506102805160206001820306601f82010390506102e0610280516020818352015b826102e0511015156105eb57610607565b60006102e0516102a001535b81516001018083528114156105da575b5050506020610260526040610280510160206001820306601f8201039050610260f350005b632289511860005114156110f357605060043560040161014037603060043560040135111561065a57600080fd5b60406024356004016101c037602060243560040135111561067a57600080fd5b608060443560040161022037606060443560040135111561069a57600080fd5b63ffffffff600154106106ac57600080fd5b633b9aca006102e0526102e0516106c257600080fd5b6102e05134046102c052633b9aca006102c05110156106e057600080fd5b603061014051146106f057600080fd5b60206101c0511461070057600080fd5b6060610220511461071057600080fd5b610140610360525b6103605151602061036051016103605261036061036051101561073a57610718565b6380673289610380526102c0516103a0526103a051600658016100a9565b50610400526000610460525b6104005160206001820306601f8201039050610460511015156107865761079f565b6104605161042001526104605160200161046052610764565b610340610360525b61036051526020610360510361036052610140610360511015156107ca576107a7565b610400805160200180610300828460006004600a8704601201f16107ed57600080fd5b5050610140610480525b61048051516020610480510161048052610480610480511015610819576107f7565b63806732896104a0526001546104c0526104c051600658016100a9565b50610520526000610580525b6105205160206001820306601f8201039050610580511015156108645761087d565b6105805161054001526105805160200161058052610842565b610460610480525b61048051526020610480510361048052610140610480511015156108a857610885565b6105208051602001806105a0828460006004600a8704601201f16108cb57600080fd5b505060a06106205261062051610660526101408051602001806106205161066001828460006004600a8704601201f161090357600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516040818352015b826106005110151561094057610961565b600061060051610620516106800101535b815160010180835281141561092f575b505050602061062051610660015160206001820306601f82010390506106205101016106205261062051610680526101c08051602001806106205161066001828460006004600a8704601201f16109b757600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516020818352015b82610600511015156109f457610a15565b600061060051610620516106800101535b81516001018083528114156109e3575b505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106a0526103008051602001806106205161066001828460006004600a8704601201f1610a6b57600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516020818352015b8261060051101515610aa857610ac9565b600061060051610620516106800101535b8151600101808352811415610a97575b505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106c0526102208051602001806106205161066001828460006004600a8704601201f1610b1f57600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516060818352015b8261060051101515610b5c57610b7d565b600061060051610620516106800101535b8151600101808352811415610b4b575b505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106e0526105a08051602001806106205161066001828460006004600a8704601201f1610bd357600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516020818352015b8261060051101515610c1057610c31565b600061060051610620516106800101535b8151600101808352811415610bff575b505050602061062051610660015160206001820306601f8201039050610620510101610620527f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c561062051610660a160006107005260006101406030806020846107c001018260208501600060046016f150508051820191505060006010602082066107400160208284011115610cc757600080fd5b60208061076082610700600060046015f15050818152809050905090506010806020846107c001018260208501600060046013f1505080518201915050806107c0526107c09050602060c0825160208401600060025af1610d2757600080fd5b60c0519050610720526000600060406020820661086001610220518284011115610d5057600080fd5b606080610880826020602088068803016102200160006004601bf1505081815280905090509050602060c0825160208401600060025af1610d9057600080fd5b60c0519050602082610a600101526020810190506000604060206020820661092001610220518284011115610dc457600080fd5b606080610940826020602088068803016102200160006004601bf15050818152809050905090506020806020846109e001018260208501600060046015f1505080518201915050610700516020826109e0010152602081019050806109e0526109e09050602060c0825160208401600060025af1610e4157600080fd5b60c0519050602082610a6001015260208101905080610a6052610a609050602060c0825160208401600060025af1610e7857600080fd5b60c0519050610840526000600061072051602082610b000101526020810190506101c0602080602084610b0001018260208501600060046015f150508051820191505080610b0052610b009050602060c0825160208401600060025af1610ede57600080fd5b60c0519050602082610c800101526020810190506000610300600880602084610c0001018260208501600060046012f15050805182019150506000601860208206610b800160208284011115610f3357600080fd5b602080610ba082610700600060046015f1505081815280905090509050601880602084610c0001018260208501600060046014f150508051820191505061084051602082610c0001015260208101905080610c0052610c009050602060c0825160208401600060025af1610fa657600080fd5b60c0519050602082610c8001015260208101905080610c8052610c809050602060c0825160208401600060025af1610fdd57600080fd5b60c0519050610ae052606435610ae05114610ff757600080fd5b600180546001825401101561100b57600080fd5b6001815401815550600154610d0052610d2060006020818352015b60016001610d005116141561105b57610ae051610d20516020811061104a57600080fd5b600060c052602060c02001556110ef565b6000610d20516020811061106e57600080fd5b600060c052602060c0200154602082610d40010152602081019050610ae051602082610d4001015260208101905080610d4052610d409050602060c0825160208401600060025af16110bf57600080fd5b60c0519050610ae052610d0060026110d657600080fd5b60028151048152505b8151600101808352811415611026575b5050005b5b60006000fd5b61017f6112790361017f60003961017f611279036000f3"} \ No newline at end of file +{"abi": [{"name": "DepositEvent", "inputs": [{"type": "bytes", "name": "pubkey", "indexed": false}, {"type": "bytes", "name": "withdrawal_credentials", "indexed": false}, {"type": "bytes", "name": "amount", "indexed": false}, {"type": "bytes", "name": "signature", "indexed": false}, {"type": "bytes", "name": "index", "indexed": false}], "anonymous": false, "type": "event"}, {"outputs": [], "inputs": [], "constant": false, "payable": false, "type": "constructor"}, {"name": "get_deposit_root", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 95628}, {"name": "get_deposit_count", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 18231}, {"name": "deposit", "outputs": [], "inputs": [{"type": "bytes", "name": "pubkey"}, {"type": "bytes", "name": "withdrawal_credentials"}, {"type": "bytes", "name": "signature"}, {"type": "bytes32", "name": "deposit_data_root"}], "constant": false, "payable": true, "type": "function", "gas": 1342274}], "bytecode": "0x740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052341561009857600080fd5b6101406000601f818352015b600061014051602081106100b757600080fd5b600260c052602060c020015460208261016001015260208101905061014051602081106100e357600080fd5b600260c052602060c020015460208261016001015260208101905080610160526101609050602060c0825160208401600060025af161012157600080fd5b60c0519050606051600161014051018060405190131561014057600080fd5b809190121561014e57600080fd5b6020811061015b57600080fd5b600260c052602060c02001555b81516001018083528114156100a4575b505061123556600436101561000d576110b0565b600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05260001561027f575b6101605261014052600061018052610140516101a0526101c060006008818352015b61018051600860008112156100e8578060000360020a82046100ef565b8060020a82025b905090506101805260ff6101a051166101e052610180516101e0516101805101101561011a57600080fd5b6101e0516101805101610180526101a0517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86000811215610163578060000360020a820461016a565b8060020a82025b905090506101a0525b81516001018083528114156100cb575b5050601860086020820661020001602082840111156101a157600080fd5b60208061022082610180600060045af15050818152809050905090508051602001806102c08284600060045af16101d757600080fd5b50506102c05160206001820306601f82010390506103206102c0516020818352015b826103205110151561020a57610226565b6000610320516102e001535b81516001018083528114156101f9575b50505060206102a05260406102c0510160206001820306601f8201039050610280525b60006102805111151561025b57610277565b602061028051036102a001516020610280510361028052610249565b610160515650005b63c5f2892f600051141561050e57341561029857600080fd5b6000610140526101405161016052600154610180526101a060006020818352015b600160016101805116141561033a5760006101a051602081106102db57600080fd5b600060c052602060c02001546020826102400101526020810190506101605160208261024001015260208101905080610240526102409050602060c0825160208401600060025af161032c57600080fd5b60c0519050610160526103a8565b6000610160516020826101c00101526020810190506101a0516020811061036057600080fd5b600260c052602060c02001546020826101c0010152602081019050806101c0526101c09050602060c0825160208401600060025af161039e57600080fd5b60c0519050610160525b61018060026103b657600080fd5b60028151048152505b81516001018083528114156102b9575b505060006101605160208261046001015260208101905061014051610160516101805163806732896102e0526001546103005261030051600658016100a9565b506103605260006103c0525b6103605160206001820306601f82010390506103c05110151561043d57610456565b6103c05161038001526103c0516020016103c05261041b565b61018052610160526101405261036060088060208461046001018260208501600060045af150508051820191505060006018602082066103e001602082840111156104a057600080fd5b60208061040082610140600060045af150508181528090509050905060188060208461046001018260208501600060045af150508051820191505080610460526104609050602060c0825160208401600060025af16104fe57600080fd5b60c051905060005260206000f350005b63621fd130600051141561061c57341561052757600080fd5b6380673289610140526001546101605261016051600658016100a9565b506101c0526000610220525b6101c05160206001820306601f8201039050610220511015156105725761058b565b610220516101e001526102205160200161022052610550565b6101c08051602001806102808284600060045af16105a857600080fd5b50506102805160206001820306601f82010390506102e0610280516020818352015b826102e0511015156105db576105f7565b60006102e0516102a001535b81516001018083528114156105ca575b5050506020610260526040610280510160206001820306601f8201039050610260f350005b632289511860005114156110af57605060043560040161014037603060043560040135111561064a57600080fd5b60406024356004016101c037602060243560040135111561066a57600080fd5b608060443560040161022037606060443560040135111561068a57600080fd5b63ffffffff6001541061069c57600080fd5b633b9aca006102e0526102e0516106b257600080fd5b6102e05134046102c052633b9aca006102c05110156106d057600080fd5b603061014051146106e057600080fd5b60206101c051146106f057600080fd5b6060610220511461070057600080fd5b610140610360525b6103605151602061036051016103605261036061036051101561072a57610708565b6380673289610380526102c0516103a0526103a051600658016100a9565b50610400526000610460525b6104005160206001820306601f8201039050610460511015156107765761078f565b6104605161042001526104605160200161046052610754565b610340610360525b61036051526020610360510361036052610140610360511015156107ba57610797565b6104008051602001806103008284600060045af16107d757600080fd5b5050610140610480525b61048051516020610480510161048052610480610480511015610803576107e1565b63806732896104a0526001546104c0526104c051600658016100a9565b50610520526000610580525b6105205160206001820306601f82010390506105805110151561084e57610867565b610580516105400152610580516020016105805261082c565b610460610480525b61048051526020610480510361048052610140610480511015156108925761086f565b6105208051602001806105a08284600060045af16108af57600080fd5b505060a061062052610620516106605261014080516020018061062051610660018284600060045af16108e157600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516040818352015b826106005110151561091e5761093f565b600061060051610620516106800101535b815160010180835281141561090d575b505050602061062051610660015160206001820306601f82010390506106205101016106205261062051610680526101c080516020018061062051610660018284600060045af161098f57600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516020818352015b82610600511015156109cc576109ed565b600061060051610620516106800101535b81516001018083528114156109bb575b505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106a05261030080516020018061062051610660018284600060045af1610a3d57600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516020818352015b8261060051101515610a7a57610a9b565b600061060051610620516106800101535b8151600101808352811415610a69575b505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106c05261022080516020018061062051610660018284600060045af1610aeb57600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516060818352015b8261060051101515610b2857610b49565b600061060051610620516106800101535b8151600101808352811415610b17575b505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106e0526105a080516020018061062051610660018284600060045af1610b9957600080fd5b505061062051610660015160206001820306601f82010390506106006106205161066001516020818352015b8261060051101515610bd657610bf7565b600061060051610620516106800101535b8151600101808352811415610bc5575b505050602061062051610660015160206001820306601f8201039050610620510101610620527f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c561062051610660a160006107005260006101406030806020846107c001018260208501600060045af150508051820191505060006010602082066107400160208284011115610c8c57600080fd5b60208061076082610700600060045af15050818152809050905090506010806020846107c001018260208501600060045af1505080518201915050806107c0526107c09050602060c0825160208401600060025af1610cea57600080fd5b60c0519050610720526000600060406020820661086001610220518284011115610d1357600080fd5b6060806108808260206020880688030161022001600060045af1505081815280905090509050602060c0825160208401600060025af1610d5257600080fd5b60c0519050602082610a600101526020810190506000604060206020820661092001610220518284011115610d8657600080fd5b6060806109408260206020880688030161022001600060045af15050818152809050905090506020806020846109e001018260208501600060045af1505080518201915050610700516020826109e0010152602081019050806109e0526109e09050602060c0825160208401600060025af1610e0157600080fd5b60c0519050602082610a6001015260208101905080610a6052610a609050602060c0825160208401600060025af1610e3857600080fd5b60c0519050610840526000600061072051602082610b000101526020810190506101c0602080602084610b0001018260208501600060045af150508051820191505080610b0052610b009050602060c0825160208401600060025af1610e9d57600080fd5b60c0519050602082610c800101526020810190506000610300600880602084610c0001018260208501600060045af15050805182019150506000601860208206610b800160208284011115610ef157600080fd5b602080610ba082610700600060045af1505081815280905090509050601880602084610c0001018260208501600060045af150508051820191505061084051602082610c0001015260208101905080610c0052610c009050602060c0825160208401600060025af1610f6257600080fd5b60c0519050602082610c8001015260208101905080610c8052610c809050602060c0825160208401600060025af1610f9957600080fd5b60c0519050610ae052606435610ae05114610fb357600080fd5b6001805460018254011015610fc757600080fd5b6001815401815550600154610d0052610d2060006020818352015b60016001610d005116141561101757610ae051610d20516020811061100657600080fd5b600060c052602060c02001556110ab565b6000610d20516020811061102a57600080fd5b600060c052602060c0200154602082610d40010152602081019050610ae051602082610d4001015260208101905080610d4052610d409050602060c0825160208401600060025af161107b57600080fd5b60c0519050610ae052610d00600261109257600080fd5b60028151048152505b8151600101808352811415610fe2575b5050005b5b60006000fd5b61017f6112350361017f60003961017f611235036000f3"} \ No newline at end of file diff --git a/deposit_contract/contracts/validator_registration.v.py b/deposit_contract/contracts/validator_registration.v.py index ca18cbdfd..671252e2e 100644 --- a/deposit_contract/contracts/validator_registration.v.py +++ b/deposit_contract/contracts/validator_registration.v.py @@ -1,4 +1,4 @@ -# Vyper target 0.1.0b13 +# Vyper target 0.1.0b13.hotfix1761 MIN_DEPOSIT_AMOUNT: constant(uint256) = 1000000000 # Gwei DEPOSIT_CONTRACT_TREE_DEPTH: constant(uint256) = 32 MAX_DEPOSIT_COUNT: constant(uint256) = 4294967295 # 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1 diff --git a/deposit_contract/requirements-testing.txt b/deposit_contract/requirements-testing.txt index 9b07eae6f..fe4b88a23 100644 --- a/deposit_contract/requirements-testing.txt +++ b/deposit_contract/requirements-testing.txt @@ -1,5 +1,5 @@ eth-tester[py-evm]==0.1.0b39 -vyper==0.1.0b13 +https://github.com/vyperlang/vyper/archive/1761-HOTFIX-v0.1.0-beta.13.tar.gz web3==5.0.0b2 pytest==3.6.1 ../test_libs/pyspec From 331892ad15ac1a97bd64b1fdde432304988d9cdb Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 18 Dec 2019 13:30:02 -0700 Subject: [PATCH 47/56] bump version on despoit cache --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 19ab1543a..9ca22a0e1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,13 +48,13 @@ commands: description: "Restore the cache with deposit_contract keys" steps: - restore_cached_venv: - venv_name: v6-deposit-contract + venv_name: v7-deposit-contract reqs_checksum: cache-{{ checksum "test_libs/pyspec/requirements.txt" }}-{{ checksum "deposit_contract/requirements-testing.txt" }} save_deposit_contract_cached_venv: description: Save a venv into a cache with deposit_contract keys" steps: - save_cached_venv: - venv_name: v6-deposit-contract + venv_name: v7-deposit-contract reqs_checksum: cache-{{ checksum "test_libs/pyspec/requirements.txt" }}-{{ checksum "deposit_contract/requirements-testing.txt" }} venv_path: ./deposit_contract/venv jobs: From 8a03e6d291caad8e4adcd37b4ae2b935768310ba Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 18 Dec 2019 10:08:52 +1100 Subject: [PATCH 48/56] Add gossipsub message-id specification --- specs/networking/p2p-interface.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 38e9b366b..2220740d9 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -212,6 +212,13 @@ Topics are plain UTF-8 strings and are encoded on the wire as determined by prot Each gossipsub [message](https://github.com/libp2p/go-libp2p-pubsub/blob/master/pb/rpc.proto#L17-L24) has a maximum size of `GOSSIP_MAX_SIZE`. Clients MUST reject (fail validation) messages that are over this size limit. Likewise, clients MUST NOT emit or propagate messages larger than this limit. +The message-id of a gossipsub message MUST be: + +```python + message-id: base64(SHA256(message.data)) +``` +where `base64` is the [URL-safe base64 alphabet](https://tools.ietf.org/html/rfc4648#section-3.2) with padding characters omitted. + The payload is carried in the `data` field of a gossipsub message, and varies depending on the topic: | Topic | Message Type | From 31d90ea7990ac90342a83df7b2fe154d57802f40 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 18 Dec 2019 14:43:13 -0700 Subject: [PATCH 49/56] add p2p faq on why message-id override --- specs/networking/p2p-interface.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 2220740d9..7305a8b59 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -81,6 +81,7 @@ It consists of four main sections: - [How do we upgrade gossip channels (e.g. changes in encoding, compression)?](#how-do-we-upgrade-gossip-channels-eg-changes-in-encoding-compression) - [Why must all clients use the same gossip topic instead of one negotiated between each peer pair?](#why-must-all-clients-use-the-same-gossip-topic-instead-of-one-negotiated-between-each-peer-pair) - [Why are the topics strings and not hashes?](#why-are-the-topics-strings-and-not-hashes) + - [Why are we overriding the default libp2p pubsub `message-id`?](#why-are-we-overriding-the-default-libp2p-pubsub-message-id) - [Why are there `ATTESTATION_SUBNET_COUNT` attestation subnets?](#why-are-there-attestation_subnet_count-attestation-subnets) - [Why are attestations limited to be broadcast on gossip channels within `SLOTS_PER_EPOCH` slots?](#why-are-attestations-limited-to-be-broadcast-on-gossip-channels-within-slots_per_epoch-slots) - [Why are aggregate attestations broadcast to the global topic as `AggregateAndProof`s rather than just as `Attestation`s?](#why-are-aggregate-attestations-broadcast-to-the-global-topic-as-aggregateandproofs-rather-than-just-as-attestations) @@ -212,7 +213,7 @@ Topics are plain UTF-8 strings and are encoded on the wire as determined by prot Each gossipsub [message](https://github.com/libp2p/go-libp2p-pubsub/blob/master/pb/rpc.proto#L17-L24) has a maximum size of `GOSSIP_MAX_SIZE`. Clients MUST reject (fail validation) messages that are over this size limit. Likewise, clients MUST NOT emit or propagate messages larger than this limit. -The message-id of a gossipsub message MUST be: +The `message-id` of a gossipsub message MUST be: ```python message-id: base64(SHA256(message.data)) @@ -751,6 +752,16 @@ No security or privacy guarantees are lost as a result of choosing plaintext top Furthermore, the Eth2 topic names are shorter than their digest equivalents (assuming SHA-256 hash), so hashing topics would bloat messages unnecessarily. +## Why are we overriding the default libp2p pubsub `message-id`? + +For our current purposes, there is no need to address messages based on source peer, and it seems likely we might even override the message `from` to obfuscate the peer. By overriding the default `message-id` to use content-addressing we can filter unnecessary duplicates before hitting the application layer. + +Some examples of where messages could be duplicated: + +* A validator client connected to multiple beacon nodes publishing duplicate gossip messages +* Attestation aggregation strategies where clients partially aggregate attestations and propagate them. Partial aggregates could be duplicated +* Clients re-publishing seen messages + ### Why are there `ATTESTATION_SUBNET_COUNT` attestation subnets? Depending on the number of validators, it may be more efficient to group shard subnets and might provide better stability for the gossipsub channel. The exact grouping will be dependent on more involved network tests. This constant allows for more flexibility in setting up the network topology for attestation aggregation (as aggregation should happen on each subnet). The value is currently set to to be equal `MAX_COMMITTEES_PER_SLOT` until network tests indicate otherwise. From 01a2ef8158bbb9de7a849bb61fac3129f61254fd Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 18 Dec 2019 16:36:28 -0700 Subject: [PATCH 50/56] fix vyper custom build link and bump pycryptodome version --- deposit_contract/requirements-testing.txt | 2 +- test_libs/pyspec/requirements.txt | 2 +- test_libs/pyspec/setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deposit_contract/requirements-testing.txt b/deposit_contract/requirements-testing.txt index fe4b88a23..c542121c2 100644 --- a/deposit_contract/requirements-testing.txt +++ b/deposit_contract/requirements-testing.txt @@ -1,5 +1,5 @@ eth-tester[py-evm]==0.1.0b39 -https://github.com/vyperlang/vyper/archive/1761-HOTFIX-v0.1.0-beta.13.tar.gz +git+https://github.com/vyperlang/vyper@1761-HOTFIX-v0.1.0-beta.13 web3==5.0.0b2 pytest==3.6.1 ../test_libs/pyspec diff --git a/test_libs/pyspec/requirements.txt b/test_libs/pyspec/requirements.txt index 480602779..8dfbccf66 100644 --- a/test_libs/pyspec/requirements.txt +++ b/test_libs/pyspec/requirements.txt @@ -1,6 +1,6 @@ eth-utils>=1.3.0,<2 eth-typing>=2.1.0,<3.0.0 -pycryptodome==3.7.3 +pycryptodome==3.9.4 py_ecc==1.7.1 dataclasses==0.6 ssz==0.1.3 diff --git a/test_libs/pyspec/setup.py b/test_libs/pyspec/setup.py index 94575f2a1..d41412eb8 100644 --- a/test_libs/pyspec/setup.py +++ b/test_libs/pyspec/setup.py @@ -7,7 +7,7 @@ setup( install_requires=[ "eth-utils>=1.3.0,<2", "eth-typing>=2.1.0,<3.0.0", - "pycryptodome==3.7.3", + "pycryptodome==3.9.4", "py_ecc==1.7.1", "ssz==0.1.3", "dataclasses==0.6", From c4b23590d402f4e1bae811601a779359cf10e14e Mon Sep 17 00:00:00 2001 From: Chih Cheng Liang Date: Thu, 19 Dec 2019 18:46:15 +0800 Subject: [PATCH 51/56] Add a note on requesting STATUS again --- specs/networking/p2p-interface.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 38e9b366b..9bcfe6aae 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -437,6 +437,8 @@ Clients SHOULD immediately disconnect from one another following the handshake a Once the handshake completes, the client with the lower `finalized_epoch` or `head_slot` (if the clients have equal `finalized_epoch`s) SHOULD request beacon blocks from its counterparty via the `BeaconBlocksByRange` request. +*Note*: Under bad network condition or after some rounds of `BeaconBlocksByRange` requests, the client might need to send `Status` request again to learn if the peer has a higher head. Implementers are free to implement such behavior in their own way. + #### Goodbye **Protocol ID:** ``/eth2/beacon_chain/req/goodbye/1/`` From 2de5119cfe64eacc5310d9c512607c62499ab383 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 19 Dec 2019 17:31:58 +0100 Subject: [PATCH 52/56] fix two missing pre-states, and fix unsigned block --- test_libs/pyspec/eth2spec/test/sanity/test_blocks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index c2f980ba0..c32f4c583 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -83,7 +83,7 @@ def test_invalid_state_root(spec, state): expect_assertion_error(lambda: spec.state_transition(state, signed_block)) - yield 'blocks', [block] + yield 'blocks', [signed_block] yield 'post', None @@ -91,6 +91,8 @@ def test_invalid_state_root(spec, state): @spec_state_test @always_bls def test_zero_block_sig(spec, state): + yield 'pre', state + block = build_empty_block_for_next_slot(spec, state) invalid_signed_block = spec.SignedBeaconBlock(message=block) expect_assertion_error(lambda: spec.state_transition(state, invalid_signed_block)) @@ -103,6 +105,8 @@ def test_zero_block_sig(spec, state): @spec_state_test @always_bls def test_invalid_block_sig(spec, state): + yield 'pre', state + block = build_empty_block_for_next_slot(spec, state) invalid_signed_block = spec.SignedBeaconBlock( message=block, From e34d22e4f81e7dbcdaacebdf25a05e0a691428d6 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 19 Dec 2019 14:04:45 -0700 Subject: [PATCH 53/56] bad -> abnormal --- specs/networking/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 9bcfe6aae..6bdcc1233 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -437,7 +437,7 @@ Clients SHOULD immediately disconnect from one another following the handshake a Once the handshake completes, the client with the lower `finalized_epoch` or `head_slot` (if the clients have equal `finalized_epoch`s) SHOULD request beacon blocks from its counterparty via the `BeaconBlocksByRange` request. -*Note*: Under bad network condition or after some rounds of `BeaconBlocksByRange` requests, the client might need to send `Status` request again to learn if the peer has a higher head. Implementers are free to implement such behavior in their own way. +*Note*: Under abnormal network condition or after some rounds of `BeaconBlocksByRange` requests, the client might need to send `Status` request again to learn if the peer has a higher head. Implementers are free to implement such behavior in their own way. #### Goodbye From 662a986d042164077fde259247ad99d2fc32e16c Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 25 Dec 2019 09:51:29 -0800 Subject: [PATCH 54/56] Update 0_fork-choice.md --- specs/core/0_fork-choice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 34430d092..b286654af 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -196,7 +196,7 @@ def filter_block_tree(store: Store, block_root: Root, blocks: Dict[Root, BeaconB ```python def get_filtered_block_tree(store: Store) -> Dict[Root, BeaconBlock]: """ - Retrieve a filtered block true from ``store``, only returning branches + Retrieve a filtered block tree from ``store``, only returning branches whose leaf state's justified/finalized info agrees with that in ``store``. """ base = store.justified_checkpoint.root From 765176ec8ca1dda29a7534d44afb962eb3502fd7 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 27 Dec 2019 09:37:26 +0100 Subject: [PATCH 55/56] PySpec SSZ Bytes instantiated from hex --- scripts/build_spec.py | 2 -- specs/core/0_beacon-chain.md | 14 ++++++-------- specs/core/1_custody-game.md | 2 +- specs/core/1_shard-data-chains.md | 4 ++-- test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py | 7 ++++++- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 67c9a547c..1a719cb29 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -163,8 +163,6 @@ def objects_to_spec(functions: Dict[str, str], del functions[k] functions_spec = '\n\n'.join(functions.values()) for k in list(constants.keys()): - if k.startswith('DOMAIN_'): - constants[k] = f"DomainType(({constants[k]}).to_bytes(length=4, byteorder='little'))" if k == "BLS12_381_Q": constants[k] += " # noqa: E501" constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants)) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 9c0b9fe66..0c9f49b74 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -199,7 +199,7 @@ The following values are (non-configurable) constants used throughout the specif | - | - | | `GENESIS_SLOT` | `Slot(0)` | | `GENESIS_EPOCH` | `Epoch(0)` | -| `BLS_WITHDRAWAL_PREFIX` | `Bytes1(b'\x00')` | +| `BLS_WITHDRAWAL_PREFIX` | `Bytes1('0x00')` | ### Time parameters @@ -249,15 +249,13 @@ The following values are (non-configurable) constants used throughout the specif ### Domain types -The following types are defined, mapping into `DomainType` (little endian): - | Name | Value | | - | - | -| `DOMAIN_BEACON_PROPOSER` | `0` | -| `DOMAIN_BEACON_ATTESTER` | `1` | -| `DOMAIN_RANDAO` | `2` | -| `DOMAIN_DEPOSIT` | `3` | -| `DOMAIN_VOLUNTARY_EXIT` | `4` | +| `DOMAIN_BEACON_PROPOSER` | `Bytes4('0x00000000')` | +| `DOMAIN_BEACON_ATTESTER` | `Bytes4('0x01000000')` | +| `DOMAIN_RANDAO` | `Bytes4('0x02000000')` | +| `DOMAIN_DEPOSIT` | `Bytes4('0x03000000')` | +| `DOMAIN_VOLUNTARY_EXIT` | `Bytes4('0x04000000')` | ## Containers diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 017e2a22a..829c68ac1 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -131,7 +131,7 @@ The following types are defined, mapping into `DomainType` (little endian): | Name | Value | | - | - | -| `DOMAIN_CUSTODY_BIT_CHALLENGE` | `6` | +| `DOMAIN_CUSTODY_BIT_CHALLENGE` | `Bytes4('0x06000000')` | ### TODO PLACEHOLDER diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index d5964fe7d..408c9b2a8 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -101,8 +101,8 @@ This document describes the shard transition function (data layer only) and the | Name | Value | | - | - | -| `DOMAIN_SHARD_PROPOSER` | `128` | -| `DOMAIN_SHARD_ATTESTER` | `129` | +| `DOMAIN_SHARD_PROPOSER` | `Bytes4('0x80000000')` | +| `DOMAIN_SHARD_ATTESTER` | `Bytes4('0x81000000')` | ## Containers diff --git a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py index 4bda43360..4ddff1b5e 100644 --- a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py +++ b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py @@ -451,10 +451,15 @@ class BaseBytes(bytes, Elements, metaclass=BytesType): @classmethod def extract_args(cls, *args): x = args - if len(x) == 1 and isinstance(x[0], (GeneratorType, bytes)): + if len(x) == 1 and isinstance(x[0], (GeneratorType, bytes, str)): x = x[0] if isinstance(x, bytes): # Includes BytesLike return x + if isinstance(x, str): + if x[:2] == '0x': + return bytes.fromhex(x[2:]) + else: + return bytes.fromhex(x) else: return bytes(x) # E.g. GeneratorType put into bytes. From e70863ca936a63b792f690d951eb757576f872cf Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 30 Dec 2019 06:52:00 +0100 Subject: [PATCH 56/56] Bytes4 -> DomainType --- specs/core/0_beacon-chain.md | 10 +++++----- specs/core/1_custody-game.md | 2 +- specs/core/1_shard-data-chains.md | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 0c9f49b74..647d1c9bd 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -251,11 +251,11 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | -| `DOMAIN_BEACON_PROPOSER` | `Bytes4('0x00000000')` | -| `DOMAIN_BEACON_ATTESTER` | `Bytes4('0x01000000')` | -| `DOMAIN_RANDAO` | `Bytes4('0x02000000')` | -| `DOMAIN_DEPOSIT` | `Bytes4('0x03000000')` | -| `DOMAIN_VOLUNTARY_EXIT` | `Bytes4('0x04000000')` | +| `DOMAIN_BEACON_PROPOSER` | `DomainType('0x00000000')` | +| `DOMAIN_BEACON_ATTESTER` | `DomainType('0x01000000')` | +| `DOMAIN_RANDAO` | `DomainType('0x02000000')` | +| `DOMAIN_DEPOSIT` | `DomainType('0x03000000')` | +| `DOMAIN_VOLUNTARY_EXIT` | `DomainType('0x04000000')` | ## Containers diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 829c68ac1..b1f61de2f 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -131,7 +131,7 @@ The following types are defined, mapping into `DomainType` (little endian): | Name | Value | | - | - | -| `DOMAIN_CUSTODY_BIT_CHALLENGE` | `Bytes4('0x06000000')` | +| `DOMAIN_CUSTODY_BIT_CHALLENGE` | `DomainType('0x06000000')` | ### TODO PLACEHOLDER diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 408c9b2a8..93570dbee 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -101,8 +101,8 @@ This document describes the shard transition function (data layer only) and the | Name | Value | | - | - | -| `DOMAIN_SHARD_PROPOSER` | `Bytes4('0x80000000')` | -| `DOMAIN_SHARD_ATTESTER` | `Bytes4('0x81000000')` | +| `DOMAIN_SHARD_PROPOSER` | `DomainType('0x80000000')` | +| `DOMAIN_SHARD_ATTESTER` | `DomainType('0x81000000')` | ## Containers