From 8c32128ffbda5c7e056c218cdb78ab76d856c5f5 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 11 Apr 2019 22:28:42 +1000 Subject: [PATCH 01/11] initial pass on genesis slot == 0 --- specs/core/0_beacon-chain.md | 20 ++++++++++++------- .../test_process_attester_slashing.py | 3 +++ tests/phase0/helpers.py | 13 ++++++++++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 185b07443e..ad7efc6483 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -216,8 +216,8 @@ These configurations are updated for releases, but may be out of sync during `de | Name | Value | | - | - | | `GENESIS_FORK_VERSION` | `int_to_bytes4(0)` | -| `GENESIS_SLOT` | `2**32` | -| `GENESIS_EPOCH` | `slot_to_epoch(GENESIS_SLOT)` | +| `GENESIS_SLOT` | `0` | +| `GENESIS_EPOCH` | `0` | | `GENESIS_START_SHARD` | `0` | | `FAR_FUTURE_EPOCH` | `2**64 - 1` | | `ZERO_HASH` | `int_to_bytes32(0)` | @@ -1044,12 +1044,12 @@ def verify_merkle_branch(leaf: Bytes32, proof: List[Bytes32], depth: int, index: ```python def get_crosslink_committee_for_attestation(state: BeaconState, - attestation_data: AttestationData) -> List[ValidatorIndex]: + attestation_data: AttestationData) -> List[ValidatorIndex]: """ Return the crosslink committee corresponding to ``attestation_data``. - """ + """ crosslink_committees = get_crosslink_committees_at_slot(state, attestation_data.slot) - + # Find the committee in the list with the desired shard assert attestation_data.shard in [shard for _, shard in crosslink_committees] crosslink_committee = [committee for committee, shard in crosslink_committees if shard == attestation_data.shard][0] @@ -1554,7 +1554,7 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit], # Finality previous_epoch_attestations=[], current_epoch_attestations=[], - previous_justified_epoch=GENESIS_EPOCH - 1, + previous_justified_epoch=GENESIS_EPOCH, current_justified_epoch=GENESIS_EPOCH, previous_justified_root=ZERO_HASH, current_justified_root=ZERO_HASH, @@ -1814,6 +1814,9 @@ Run the following function: ```python def update_justification_and_finalization(state: BeaconState) -> None: + if get_current_epoch(state) == GENESIS_EPOCH: + return + new_justified_epoch = state.current_justified_epoch new_finalized_epoch = state.finalized_epoch @@ -1864,7 +1867,7 @@ Run the following function: ```python def process_crosslinks(state: BeaconState) -> None: current_epoch = get_current_epoch(state) - previous_epoch = max(current_epoch - 1, GENESIS_EPOCH) + previous_epoch = current_epoch if current_epoch == GENESIS_EPOCH else get_previous_epoch(state) next_epoch = current_epoch + 1 for slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch)): for crosslink_committee, shard in get_crosslink_committees_at_slot(state, slot): @@ -1999,6 +2002,9 @@ Run the following: ```python def apply_rewards(state: BeaconState) -> None: + if get_current_epoch(state) == GENESIS_EPOCH: + return + rewards1, penalties1 = get_justification_and_finalization_deltas(state) rewards2, penalties2 = get_crosslink_deltas(state) for i in range(len(state.validator_registry)): diff --git a/tests/phase0/block_processing/test_process_attester_slashing.py b/tests/phase0/block_processing/test_process_attester_slashing.py index 06f214c4b8..8b73342945 100644 --- a/tests/phase0/block_processing/test_process_attester_slashing.py +++ b/tests/phase0/block_processing/test_process_attester_slashing.py @@ -9,6 +9,7 @@ ) from tests.phase0.helpers import ( get_valid_attester_slashing, + next_epoch, ) # mark entire file as 'attester_slashing' @@ -59,6 +60,8 @@ def test_success_double(state): def test_success_surround(state): + next_epoch(state) + state.current_justified_epoch += 1 attester_slashing = get_valid_attester_slashing(state) # set attestion1 to surround attestation 2 diff --git a/tests/phase0/helpers.py b/tests/phase0/helpers.py index 61f02ea8c0..020e518312 100644 --- a/tests/phase0/helpers.py +++ b/tests/phase0/helpers.py @@ -4,6 +4,9 @@ import build.phase0.spec as spec from build.phase0.utils.minimal_ssz import signing_root +from build.phase0.state_transition import ( + state_transition, +) from build.phase0.spec import ( # constants EMPTY_SIGNATURE, @@ -144,7 +147,7 @@ def build_attestation_data(state, slot, shard): if epoch_start_slot == slot: epoch_boundary_root = block_root else: - get_block_root(state, epoch_start_slot) + epoch_boundary_root = get_block_root(state, epoch_start_slot) if slot < epoch_start_slot: justified_block_root = state.previous_justified_root @@ -260,7 +263,7 @@ def get_valid_attester_slashing(state): def get_valid_attestation(state, slot=None): if slot is None: slot = state.slot - shard = state.latest_start_shard + shard = state.latest_start_shard + slot % spec.SLOTS_PER_EPOCH attestation_data = build_attestation_data(state, slot, shard) crosslink_committee = get_crosslink_committee_for_attestation(state, attestation_data) @@ -312,3 +315,9 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) domain_type=spec.DOMAIN_ATTESTATION, ) ) + + +def next_epoch(state): + block = build_empty_block_for_next_slot(state) + block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) + state_transition(state, block) From 6ca550489ed23c53d58e61c071236400d6ba433f Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 11 Apr 2019 22:48:27 +1000 Subject: [PATCH 02/11] prevent underflow of previous epoch in all cases --- specs/core/0_beacon-chain.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index ad7efc6483..394b26ee18 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -702,7 +702,8 @@ def get_previous_epoch(state: BeaconState) -> Epoch: """` Return the previous epoch of the given ``state``. """ - return get_current_epoch(state) - 1 + current_epoch = get_current_epoch(state) + return (current_epoch - 1) if current_epoch > GENESIS_EPOCH else current_epoch ``` ### `get_current_epoch` @@ -2338,6 +2339,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: # Check target epoch, source epoch, and source root target_epoch = slot_to_epoch(attestation.data.slot) + assert (target_epoch, attestation.data.source_epoch, attestation.data.source_root) in { (get_current_epoch(state), state.current_justified_epoch, state.current_justified_root), (get_previous_epoch(state), state.previous_justified_epoch, state.previous_justified_root), From 47b9cdbb367b5227eb8a17ea625accec9bbc2f2f Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 12 Apr 2019 13:18:10 +1000 Subject: [PATCH 03/11] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 394b26ee18..0cf1a59c01 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -224,8 +224,6 @@ These configurations are updated for releases, but may be out of sync during `de | `EMPTY_SIGNATURE` | `int_to_bytes96(0)` | | `BLS_WITHDRAWAL_PREFIX_BYTE` | `int_to_bytes1(0)` | -* `GENESIS_SLOT` should be at least as large in terms of time as the largest of the time parameters or state list lengths below (ie. it should be at least as large as any value measured in slots, and at least `SLOTS_PER_EPOCH` times as large as any value measured in epochs). - ### Time parameters | Name | Value | Unit | Duration | @@ -1608,7 +1606,7 @@ For a beacon chain block, `block`, to be processed by a node, the following cond * The parent block with root `block.previous_block_root` has been processed and accepted. * An Ethereum 1.0 block pointed to by the `state.latest_eth1_data.block_hash` has been processed and accepted. -* The node's Unix time is greater than or equal to `state.genesis_time + (block.slot - GENESIS_SLOT) * SECONDS_PER_SLOT`. (Note that leap seconds mean that slots will occasionally last `SECONDS_PER_SLOT + 1` or `SECONDS_PER_SLOT - 1` seconds, possibly several times a year.) +* The node's Unix time is greater than or equal to `state.genesis_time + block.slot * SECONDS_PER_SLOT`. (Note that leap seconds mean that slots will occasionally last `SECONDS_PER_SLOT + 1` or `SECONDS_PER_SLOT - 1` seconds, possibly several times a year.) If these conditions are not met, the client should delay processing the beacon block until the conditions are all satisfied. @@ -2334,8 +2332,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: Process ``Attestation`` operation. Note that this function mutates ``state``. """ - assert max(GENESIS_SLOT, state.slot - SLOTS_PER_EPOCH) <= attestation.data.slot - assert attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY + assert attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation.data.slot + SLOTS_PER_EPOCH # Check target epoch, source epoch, and source root target_epoch = slot_to_epoch(attestation.data.slot) From e9a44545be522f7fa55d73840fa582df6d739226 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 12 Apr 2019 13:38:58 +1000 Subject: [PATCH 04/11] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 0cf1a59c01..07dc5be6f7 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1366,14 +1366,16 @@ Note: All functions in this section mutate `state`. #### `activate_validator` ```python -def activate_validator(state: BeaconState, index: ValidatorIndex, is_genesis: bool) -> None: +def activate_validator(state: BeaconState, index: ValidatorIndex) -> None: """ Activate the validator of the given ``index``. Note that this function mutates ``state``. """ validator = state.validator_registry[index] - - validator.activation_epoch = GENESIS_EPOCH if is_genesis else get_delayed_activation_exit_epoch(get_current_epoch(state)) + if state.slot == GENESIS_SLOT: + validator.activation_epoch = GENESIS_EPOCH + else: + validator.activation_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state)) ``` #### `initiate_validator_exit` @@ -1583,7 +1585,7 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit], # Process genesis activations for validator_index, _ in enumerate(state.validator_registry): if get_effective_balance(state, validator_index) >= MAX_DEPOSIT_AMOUNT: - activate_validator(state, validator_index, is_genesis=True) + activate_validator(state, validator_index) genesis_active_index_root = hash_tree_root(get_active_validator_indices(state.validator_registry, GENESIS_EPOCH)) for index in range(LATEST_ACTIVE_INDEX_ROOTS_LENGTH): @@ -1865,9 +1867,8 @@ Run the following function: ```python def process_crosslinks(state: BeaconState) -> None: - current_epoch = get_current_epoch(state) - previous_epoch = current_epoch if current_epoch == GENESIS_EPOCH else get_previous_epoch(state) - next_epoch = current_epoch + 1 + previous_epoch = get_previous_epoch(state) + next_epoch = get_current_epoch(state) + 1 for slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch)): for crosslink_committee, shard in get_crosslink_committees_at_slot(state, slot): winning_root, participants = get_winning_root_and_participants(state, shard) @@ -2062,7 +2063,7 @@ def update_validator_registry(state: BeaconState) -> None: break # Activate validator - activate_validator(state, index, is_genesis=False) + activate_validator(state, index) # Exit validators within the allowable balance churn if current_epoch < state.validator_registry_update_epoch + LATEST_SLASHED_EXIT_LENGTH: From 3c55854072465787ccdd64d31a251553710fa5cb Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 12 Apr 2019 21:16:34 +1000 Subject: [PATCH 05/11] clean up --- specs/core/0_beacon-chain.md | 5 ++--- tests/phase0/conftest.py | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 07dc5be6f7..a45e0565be 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1867,9 +1867,9 @@ Run the following function: ```python def process_crosslinks(state: BeaconState) -> None: - previous_epoch = get_previous_epoch(state) + start_epoch = get_previous_epoch(state) next_epoch = get_current_epoch(state) + 1 - for slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch)): + for slot in range(get_epoch_start_slot(start_epoch), get_epoch_start_slot(next_epoch)): for crosslink_committee, shard in get_crosslink_committees_at_slot(state, slot): winning_root, participants = get_winning_root_and_participants(state, shard) participating_balance = get_total_balance(state, participants) @@ -2337,7 +2337,6 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: # Check target epoch, source epoch, and source root target_epoch = slot_to_epoch(attestation.data.slot) - assert (target_epoch, attestation.data.source_epoch, attestation.data.source_root) in { (get_current_epoch(state), state.current_justified_epoch, state.current_justified_root), (get_previous_epoch(state), state.previous_justified_epoch, state.previous_justified_root), diff --git a/tests/phase0/conftest.py b/tests/phase0/conftest.py index 36a0879410..c0461cb67c 100644 --- a/tests/phase0/conftest.py +++ b/tests/phase0/conftest.py @@ -14,7 +14,6 @@ "MIN_ATTESTATION_INCLUSION_DELAY": 2, "TARGET_COMMITTEE_SIZE": 4, "SLOTS_PER_EPOCH": 8, - "GENESIS_EPOCH": spec.GENESIS_SLOT // 8, "SLOTS_PER_HISTORICAL_ROOT": 64, "LATEST_RANDAO_MIXES_LENGTH": 64, "LATEST_ACTIVE_INDEX_ROOTS_LENGTH": 64, From a3b020384ffadcb677ba4374cbfa9d0ff2b73a9b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 12 Apr 2019 23:17:57 +1000 Subject: [PATCH 06/11] add tests for finality through the first few epochs --- specs/core/0_beacon-chain.md | 2 +- tests/phase0/helpers.py | 44 +++++++++++++++++++++++++---- tests/phase0/test_sanity.py | 55 ++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index a45e0565be..dfa26c86d3 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1007,7 +1007,7 @@ def get_beacon_proposer_index(state: BeaconState, the epoch in question, this can only be run for the current epoch. """ current_epoch = get_current_epoch(state) - assert slot_to_epoch(slot) == current_epoch + # assert slot_to_epoch(slot) == current_epoch first_committee, _ = get_crosslink_committees_at_slot(state, slot)[0] i = 0 diff --git a/tests/phase0/helpers.py b/tests/phase0/helpers.py index 020e518312..66ae17f2c4 100644 --- a/tests/phase0/helpers.py +++ b/tests/phase0/helpers.py @@ -34,6 +34,7 @@ get_empty_block, get_epoch_start_slot, get_genesis_beacon_state, + get_previous_epoch, slot_to_epoch, verify_merkle_branch, hash, @@ -50,6 +51,19 @@ pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)} +def set_bitfield_bit(bitfield, i): + """ + Set the bit in ``bitfield`` at position ``i`` to ``1``. + """ + byte_index = i // 8 + bit_index = i % 8 + return ( + bitfield[:byte_index] + + bytes([bitfield[byte_index] | (1 << bit_index)]) + + bitfield[byte_index+1:] + ) + + def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=None): if not deposit_data_leaves: deposit_data_leaves = [] @@ -141,24 +155,31 @@ def build_deposit_data(state, pubkey, privkey, amount): def build_attestation_data(state, slot, shard): assert state.slot >= slot - block_root = build_empty_block_for_next_slot(state).previous_block_root + if slot == state.slot: + block_root = build_empty_block_for_next_slot(state).previous_block_root + else: + block_root = get_block_root(state, slot) - epoch_start_slot = get_epoch_start_slot(get_current_epoch(state)) - if epoch_start_slot == slot: + current_epoch_start_slot = get_epoch_start_slot(get_current_epoch(state)) + if slot < current_epoch_start_slot: + epoch_boundary_root = get_block_root(state, get_epoch_start_slot(get_previous_epoch(state))) + elif slot == current_epoch_start_slot: epoch_boundary_root = block_root else: - epoch_boundary_root = get_block_root(state, epoch_start_slot) + epoch_boundary_root = get_block_root(state, current_epoch_start_slot) - if slot < epoch_start_slot: + if slot < current_epoch_start_slot: + justified_epoch = state.previous_justified_epoch justified_block_root = state.previous_justified_root else: + justified_epoch = state.current_justified_epoch justified_block_root = state.current_justified_root return AttestationData( slot=slot, shard=shard, beacon_block_root=block_root, - source_epoch=state.current_justified_epoch, + source_epoch=justified_epoch, source_root=justified_block_root, target_root=epoch_boundary_root, crosslink_data_root=spec.ZERO_HASH, @@ -317,6 +338,17 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) ) +def fill_aggregate_attestation(state, attestation): + crosslink_committee = get_crosslink_committee_for_attestation(state, attestation.data) + for i in range(len(crosslink_committee)): + attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i) + + +def next_slot(state): + block = build_empty_block_for_next_slot(state) + state_transition(state, block) + + def next_epoch(state): block = build_empty_block_for_next_slot(state) block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) diff --git a/tests/phase0/test_sanity.py b/tests/phase0/test_sanity.py index 0930bad072..67a27f3f21 100644 --- a/tests/phase0/test_sanity.py +++ b/tests/phase0/test_sanity.py @@ -39,10 +39,12 @@ from tests.phase0.helpers import ( build_deposit_data, build_empty_block_for_next_slot, + fill_aggregate_attestation, force_registry_change_at_next_epoch, get_valid_attestation, get_valid_attester_slashing, get_valid_proposer_slashing, + next_slot, privkeys, pubkeys, ) @@ -52,6 +54,33 @@ pytestmark = pytest.mark.sanity +def check_finality(state, + prev_state, + current_justified_changed, + previous_justified_changed, + finalized_changed): + if current_justified_changed: + assert state.current_justified_epoch > prev_state.current_justified_epoch + assert state.current_justified_root != prev_state.current_justified_root + else: + assert state.current_justified_epoch == prev_state.current_justified_epoch + assert state.current_justified_root == prev_state.current_justified_root + + if previous_justified_changed: + assert state.previous_justified_epoch > prev_state.previous_justified_epoch + assert state.previous_justified_root != prev_state.previous_justified_root + else: + assert state.previous_justified_epoch == prev_state.previous_justified_epoch + assert state.previous_justified_root == prev_state.previous_justified_root + + if finalized_changed: + assert state.finalized_epoch > prev_state.finalized_epoch + assert state.finalized_root != prev_state.finalized_root + else: + assert state.finalized_epoch == prev_state.finalized_epoch + assert state.finalized_root == prev_state.finalized_root + + def test_slot_transition(state): test_state = deepcopy(state) cache_state(test_state) @@ -116,6 +145,32 @@ def test_empty_epoch_transition_not_finalizing(state): return state, [block], test_state +def test_full_attestations_finalizing(state): + test_state = deepcopy(state) + + for slot in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): + next_slot(test_state) + + for epoch in range(5): + for slot in range(spec.SLOTS_PER_EPOCH): + attestation = get_valid_attestation(test_state, test_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY) + fill_aggregate_attestation(test_state, attestation) + block = build_empty_block_for_next_slot(test_state) + block.body.attestations.append(attestation) + state_transition(test_state, block) + + if epoch == 0: + check_finality(test_state, state, False, False, False) + elif epoch == 1: + check_finality(test_state, state, False, False, False) + elif epoch == 2: + check_finality(test_state, state, True, False, False) + elif epoch == 3: + check_finality(test_state, state, True, True, False) + elif epoch == 4: + check_finality(test_state, state, True, True, True) + + def test_proposer_slashing(state): test_state = deepcopy(state) proposer_slashing = get_valid_proposer_slashing(state) From 30fe6f5657715f71510707f987d74078436a971c Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 14 Apr 2019 00:47:14 +1000 Subject: [PATCH 07/11] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index dfa26c86d3..2737d3055f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1867,9 +1867,9 @@ Run the following function: ```python def process_crosslinks(state: BeaconState) -> None: - start_epoch = get_previous_epoch(state) + previous_epoch = get_previous_epoch(state) next_epoch = get_current_epoch(state) + 1 - for slot in range(get_epoch_start_slot(start_epoch), get_epoch_start_slot(next_epoch)): + for slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch)): for crosslink_committee, shard in get_crosslink_committees_at_slot(state, slot): winning_root, participants = get_winning_root_and_participants(state, shard) participating_balance = get_total_balance(state, participants) From 3c8d1b23a52c8be12c01628d8546a4443a217ca7 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Sun, 14 Apr 2019 22:12:39 +1000 Subject: [PATCH 08/11] Update specs/core/0_beacon-chain.md Co-Authored-By: djrtwo --- specs/core/0_beacon-chain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 3be5deda5e..accade5999 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -691,6 +691,7 @@ def slot_to_epoch(slot: Slot) -> Epoch: def get_previous_epoch(state: BeaconState) -> Epoch: """` Return the previous epoch of the given ``state``. + Return the current epoch if it's genesis epoch. """ current_epoch = get_current_epoch(state) return (current_epoch - 1) if current_epoch > GENESIS_EPOCH else current_epoch From af4d06c8bf89acb2f55f5ef73f08b304018d4019 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 17 Apr 2019 09:38:10 -0600 Subject: [PATCH 09/11] only run justification/finalization after 2 epochs --- specs/core/0_beacon-chain.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 83f4ec9268..86623dff5d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1588,7 +1588,8 @@ def cache_state(state: BeaconState) -> None: state.latest_block_header.state_root = previous_slot_state_root # store latest known block for previous slot - state.latest_block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = signing_root(state.latest_block_header) + latest_block_root = signing_root(state.latest_block_header) + state.latest_block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = latest_block_root ``` ### Per-epoch processing @@ -1683,7 +1684,7 @@ Run the following function: ```python def update_justification_and_finalization(state: BeaconState) -> None: - if get_current_epoch(state) == GENESIS_EPOCH: + if get_current_epoch(state) <= GENESIS_EPOCH + 1: return antepenultimate_justified_epoch = state.previous_justified_epoch From 5531adcdd152b91f20edc3ce81e7b0d87a5865e2 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 17 Apr 2019 09:41:23 -0600 Subject: [PATCH 10/11] remove old assertion in get_beacon_proposer_index --- specs/core/0_beacon-chain.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 86623dff5d..14f2536fcb 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -976,7 +976,6 @@ def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex: Return the beacon proposer index at ``state.slot``. """ current_epoch = get_current_epoch(state) - # assert slot_to_epoch(slot) == current_epoch first_committee, _ = get_crosslink_committees_at_slot(state, state.slot)[0] i = 0 From 71e1a598d283d94242b579e931c57ed58e52fe73 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 18 Apr 2019 11:09:30 +1000 Subject: [PATCH 11/11] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index b98d531544..e0556a7f3a 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1575,16 +1575,15 @@ At every `slot > GENESIS_SLOT` run the following function: ```python def cache_state(state: BeaconState) -> None: - previous_slot_state_root = hash_tree_root(state) + # Cache latest known state root (for previous slot) + latest_state_root = hash_tree_root(state) + state.latest_state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = latest_state_root - # store the previous slot's post state transition root - state.latest_state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_slot_state_root - - # cache state root in stored latest_block_header if empty + # Store latest known state root (for previous slot) in latest_block_header if it is empty if state.latest_block_header.state_root == ZERO_HASH: - state.latest_block_header.state_root = previous_slot_state_root + state.latest_block_header.state_root = latest_state_root - # store latest known block for previous slot + # Cache latest known block root (for previous slot) latest_block_root = signing_root(state.latest_block_header) state.latest_block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = latest_block_root ```