From e1a1f936feb7ed253d77a034ae8404c3a74630d2 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 18:22:25 -0800 Subject: [PATCH 01/11] penalized -> slashed, SEED_LOOKAHEAD -> MIN_SEED_LOOKAHED --- specs/core/0_beacon-chain.md | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 7baca73e6..02e76fa58 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -216,7 +216,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be | `SLOT_DURATION` | `6` | seconds | 6 seconds | | `MIN_ATTESTATION_INCLUSION_DELAY` | `2**2` (= 4) | slots | 24 seconds | | `EPOCH_LENGTH` | `2**6` (= 64) | slots | 6.4 minutes | -| `SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes | +| `MIN_SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes | | `ENTRY_EXIT_DELAY` | `2**2` (= 4) | epochs | 25.6 minutes | | `ETH1_DATA_VOTING_PERIOD` | `2**4` (= 16) | epochs | ~1.7 hours | | `MIN_VALIDATOR_WITHDRAWAL_EPOCHS` | `2**8` (= 256) | epochs | ~27 hours | @@ -228,7 +228,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be | `LATEST_BLOCK_ROOTS_LENGTH` | `2**13` (= 8,192) | slots | ~13 hours | | `LATEST_RANDAO_MIXES_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | | `LATEST_INDEX_ROOTS_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | -| `LATEST_PENALIZED_EXIT_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | +| `LATEST_SLASHED_EXIT_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | ### Reward and penalty quotients @@ -508,7 +508,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git 'latest_crosslinks': [Crosslink], 'latest_block_roots': ['bytes32'], 'latest_index_roots': ['bytes32'], - 'latest_penalized_balances': ['uint64'], # Balances penalized at every withdrawal period + 'latest_slashed_balances': ['uint64'], # Balances slashed at every withdrawal period 'latest_attestations': [PendingAttestation], 'batched_block_roots': ['bytes32'], @@ -532,8 +532,8 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git 'exit_epoch': 'uint64', # Epoch when validator withdrew 'withdrawal_epoch': 'uint64', - # Epoch when validator was penalized - 'penalized_epoch': 'uint64', + # Epoch when validator was slashed + 'slashed_epoch': 'uint64', # Status flags 'status_flags': 'uint64', } @@ -942,7 +942,7 @@ def generate_seed(state: BeaconState, """ return hash( - get_randao_mix(state, epoch - SEED_LOOKAHEAD) + + get_randao_mix(state, epoch - MIN_SEED_LOOKAHEAD) + get_active_index_root(state, epoch) ) ``` @@ -1256,7 +1256,7 @@ def process_deposit(state: BeaconState, activation_epoch=FAR_FUTURE_EPOCH, exit_epoch=FAR_FUTURE_EPOCH, withdrawal_epoch=FAR_FUTURE_EPOCH, - penalized_epoch=FAR_FUTURE_EPOCH, + slashed_epoch=FAR_FUTURE_EPOCH, status_flags=0, ) @@ -1327,13 +1327,13 @@ def penalize_validator(state: BeaconState, index: ValidatorIndex) -> None: """ exit_validator(state, index) validator = state.validator_registry[index] - state.latest_penalized_balances[get_current_epoch(state) % LATEST_PENALIZED_EXIT_LENGTH] += get_effective_balance(state, index) + state.latest_slashed_balances[get_current_epoch(state) % LATEST_SLASHED_EXIT_LENGTH] += get_effective_balance(state, index) whistleblower_index = get_beacon_proposer_index(state, state.slot) whistleblower_reward = get_effective_balance(state, index) // WHISTLEBLOWER_REWARD_QUOTIENT state.validator_balances[whistleblower_index] += whistleblower_reward state.validator_balances[index] -= whistleblower_reward - validator.penalized_epoch = get_current_epoch(state) + validator.slashed_epoch = get_current_epoch(state) ``` #### `prepare_validator_for_withdrawal` @@ -1528,7 +1528,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], latest_crosslinks=[Crosslink(epoch=GENESIS_EPOCH, shard_block_root=ZERO_HASH) for _ in range(SHARD_COUNT)], latest_block_roots=[ZERO_HASH for _ in range(LATEST_BLOCK_ROOTS_LENGTH)], latest_index_roots=[ZERO_HASH for _ in range(LATEST_INDEX_ROOTS_LENGTH)], - latest_penalized_balances=[0 for _ in range(LATEST_PENALIZED_EXIT_LENGTH)], + latest_slashed_balances=[0 for _ in range(LATEST_SLASHED_EXIT_LENGTH)], latest_attestations=[], batched_block_roots=[], @@ -1701,7 +1701,7 @@ For each `proposer_slashing` in `block.body.proposer_slashings`: * Verify that `proposer_slashing.proposal_data_1.slot == proposer_slashing.proposal_data_2.slot`. * Verify that `proposer_slashing.proposal_data_1.shard == proposer_slashing.proposal_data_2.shard`. * Verify that `proposer_slashing.proposal_data_1.block_root != proposer_slashing.proposal_data_2.block_root`. -* Verify that `proposer.penalized_epoch > get_current_epoch(state)`. +* Verify that `proposer.slashed_epoch > get_current_epoch(state)`. * Verify that `bls_verify(pubkey=proposer.pubkey, message=hash_tree_root(proposer_slashing.proposal_data_1), signature=proposer_slashing.proposal_signature_1, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_data_1.slot), DOMAIN_PROPOSAL))`. * Verify that `bls_verify(pubkey=proposer.pubkey, message=hash_tree_root(proposer_slashing.proposal_data_2), signature=proposer_slashing.proposal_signature_2, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_data_2.slot), DOMAIN_PROPOSAL))`. * Run `penalize_validator(state, proposer_slashing.proposer_index)`. @@ -1718,7 +1718,7 @@ For each `attester_slashing` in `block.body.attester_slashings`: * Verify that `is_double_vote(slashable_attestation_1.data, slashable_attestation_2.data)` or `is_surround_vote(slashable_attestation_1.data, slashable_attestation_2.data)`. * Verify that `verify_slashable_attestation(state, slashable_attestation_1)`. * Verify that `verify_slashable_attestation(state, slashable_attestation_2)`. -* Let `slashable_indices = [index for index in slashable_attestation_1.validator_indices if index in slashable_attestation_2.validator_indices and state.validator_registry[index].penalized_epoch > get_current_epoch(state)]`. +* Let `slashable_indices = [index for index in slashable_attestation_1.validator_indices if index in slashable_attestation_2.validator_indices and state.validator_registry[index].slashed_epoch > get_current_epoch(state)]`. * Verify that `len(slashable_indices) >= 1`. * Run `penalize_validator(state, index)` for each `index` in `slashable_indices`. @@ -1942,7 +1942,7 @@ Case 2: `epochs_since_finality > 4`: * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_justified_attester_indices`, loses `inactivity_penalty(state, index, epochs_since_finality)`. * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_boundary_attester_indices`, loses `inactivity_penalty(state, index, epochs_since_finality)`. * Any [active validator](#dfn-active-validator) `index` not in `previous_epoch_head_attester_indices`, loses `base_reward(state, index)`. -* Any [active_validator](#dfn-active-validator) `index` with `validator.penalized_epoch <= current_epoch`, loses `2 * inactivity_penalty(state, index, epochs_since_finality) + base_reward(state, index)`. +* Any [active_validator](#dfn-active-validator) `index` with `validator.slashed_epoch <= current_epoch`, loses `2 * inactivity_penalty(state, index, epochs_since_finality) + base_reward(state, index)`. * Any [validator](#dfn-validator) `index` in `previous_epoch_attester_indices` loses `base_reward(state, index) - base_reward(state, index) * MIN_ATTESTATION_INCLUSION_DELAY // inclusion_distance(state, index)` ##### Attestation inclusion @@ -2064,19 +2064,19 @@ def process_penalties_and_exits(state: BeaconState) -> None: total_balance = sum(get_effective_balance(state, i) for i in active_validator_indices) for index, validator in enumerate(state.validator_registry): - if current_epoch == validator.penalized_epoch + LATEST_PENALIZED_EXIT_LENGTH // 2: - epoch_index = current_epoch % LATEST_PENALIZED_EXIT_LENGTH - total_at_start = state.latest_penalized_balances[(epoch_index + 1) % LATEST_PENALIZED_EXIT_LENGTH] - total_at_end = state.latest_penalized_balances[epoch_index] + if current_epoch == validator.slashed_epoch + LATEST_SLASHED_EXIT_LENGTH // 2: + epoch_index = current_epoch % LATEST_SLASHED_EXIT_LENGTH + total_at_start = state.latest_slashed_balances[(epoch_index + 1) % LATEST_SLASHED_EXIT_LENGTH] + total_at_end = state.latest_slashed_balances[epoch_index] total_penalties = total_at_end - total_at_start penalty = get_effective_balance(state, index) * min(total_penalties * 3, total_balance) // total_balance state.validator_balances[index] -= penalty def eligible(index): validator = state.validator_registry[index] - if validator.penalized_epoch <= current_epoch: - penalized_withdrawal_epochs = LATEST_PENALIZED_EXIT_LENGTH // 2 - return current_epoch >= validator.penalized_epoch + penalized_withdrawal_epochs + if validator.slashed_epoch <= current_epoch: + slashed_withdrawal_epochs = LATEST_SLASHED_EXIT_LENGTH // 2 + return current_epoch >= validator.slashed_epoch + slashed_withdrawal_epochs else: return current_epoch >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_EPOCHS @@ -2095,7 +2095,7 @@ def process_penalties_and_exits(state: BeaconState) -> None: #### Final updates * Set `state.latest_index_roots[(next_epoch + ENTRY_EXIT_DELAY) % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, next_epoch + ENTRY_EXIT_DELAY))`. -* Set `state.latest_penalized_balances[(next_epoch) % LATEST_PENALIZED_EXIT_LENGTH] = state.latest_penalized_balances[current_epoch % LATEST_PENALIZED_EXIT_LENGTH]`. +* Set `state.latest_slashed_balances[(next_epoch) % LATEST_SLASHED_EXIT_LENGTH] = state.latest_slashed_balances[current_epoch % LATEST_SLASHED_EXIT_LENGTH]`. * Set `state.latest_randao_mixes[next_epoch % LATEST_RANDAO_MIXES_LENGTH] = get_randao_mix(state, current_epoch)`. * Remove any `attestation` in `state.latest_attestations` such that `slot_to_epoch(attestation.data.slot) < current_epoch`. From e2e2ce0a0478688d5f4422e09682ac6c899072f7 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 31 Jan 2019 07:56:48 -0800 Subject: [PATCH 02/11] name changes: active_exit_delay, latest_active_index_roots --- specs/core/0_beacon-chain.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 02e76fa58..fee1c7521 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -217,7 +217,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be | `MIN_ATTESTATION_INCLUSION_DELAY` | `2**2` (= 4) | slots | 24 seconds | | `EPOCH_LENGTH` | `2**6` (= 64) | slots | 6.4 minutes | | `MIN_SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes | -| `ENTRY_EXIT_DELAY` | `2**2` (= 4) | epochs | 25.6 minutes | +| `ACTIVATION_EXIT_DELAY` | `2**2` (= 4) | epochs | 25.6 minutes | | `ETH1_DATA_VOTING_PERIOD` | `2**4` (= 16) | epochs | ~1.7 hours | | `MIN_VALIDATOR_WITHDRAWAL_EPOCHS` | `2**8` (= 256) | epochs | ~27 hours | @@ -227,7 +227,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be | - | - | :-: | :-: | | `LATEST_BLOCK_ROOTS_LENGTH` | `2**13` (= 8,192) | slots | ~13 hours | | `LATEST_RANDAO_MIXES_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | -| `LATEST_INDEX_ROOTS_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | +| `LATEST_ACTIVE_INDEX_ROOTS_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | | `LATEST_SLASHED_EXIT_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | ### Reward and penalty quotients @@ -507,7 +507,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git # Recent state 'latest_crosslinks': [Crosslink], 'latest_block_roots': ['bytes32'], - 'latest_index_roots': ['bytes32'], + 'latest_active_index_roots': ['bytes32'], 'latest_slashed_balances': ['uint64'], # Balances slashed at every withdrawal period 'latest_attestations': [PendingAttestation], 'batched_block_roots': ['bytes32'], @@ -785,7 +785,7 @@ def get_shuffling(seed: Bytes32, return split(shuffled_active_validator_indices, committees_per_epoch) ``` -**Invariant**: if `get_shuffling(seed, validators, epoch)` returns some value `x` for some `epoch <= get_current_epoch(state) + ENTRY_EXIT_DELAY`, it should return the same value `x` for the same `seed` and `epoch` and possible future modifications of `validators` forever in phase 0, and until the ~1 year deletion delay in phase 2 and in the future. +**Invariant**: if `get_shuffling(seed, validators, epoch)` returns some value `x` for some `epoch <= get_current_epoch(state) + ACTIVATION_EXIT_DELAY`, it should return the same value `x` for the same `seed` and `epoch` and possible future modifications of `validators` forever in phase 0, and until the ~1 year deletion delay in phase 2 and in the future. **Note**: this definition and the next few definitions make heavy use of repetitive computing. Production implementations are expected to appropriately use caching/memoization to avoid redoing work. @@ -928,8 +928,8 @@ def get_active_index_root(state: BeaconState, """ Return the index root at a recent ``epoch``. """ - assert get_current_epoch(state) - LATEST_INDEX_ROOTS_LENGTH + ENTRY_EXIT_DELAY < epoch <= get_current_epoch(state) + ENTRY_EXIT_DELAY - return state.latest_index_roots[epoch % LATEST_INDEX_ROOTS_LENGTH] + assert get_current_epoch(state) - LATEST_ACTIVE_INDEX_ROOTS_LENGTH + ACTIVATION_EXIT_DELAY < epoch <= get_current_epoch(state) + ACTIVATION_EXIT_DELAY + return state.latest_active_index_roots[epoch % LATEST_ACTIVE_INDEX_ROOTS_LENGTH] ``` ### `generate_seed` @@ -1181,7 +1181,7 @@ def get_entry_exit_effect_epoch(epoch: EpochNumber) -> EpochNumber: An entry or exit triggered in the ``epoch`` given by the input takes effect at the epoch given by the output. """ - return epoch + 1 + ENTRY_EXIT_DELAY + return epoch + 1 + ACTIVATION_EXIT_DELAY ``` ### `bls_verify` @@ -1527,7 +1527,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], # Recent state latest_crosslinks=[Crosslink(epoch=GENESIS_EPOCH, shard_block_root=ZERO_HASH) for _ in range(SHARD_COUNT)], latest_block_roots=[ZERO_HASH for _ in range(LATEST_BLOCK_ROOTS_LENGTH)], - latest_index_roots=[ZERO_HASH for _ in range(LATEST_INDEX_ROOTS_LENGTH)], + latest_active_index_roots=[ZERO_HASH for _ in range(LATEST_ACTIVE_INDEX_ROOTS_LENGTH)], latest_slashed_balances=[0 for _ in range(LATEST_SLASHED_EXIT_LENGTH)], latest_attestations=[], batched_block_roots=[], @@ -1553,8 +1553,8 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], activate_validator(state, validator_index, is_genesis=True) genesis_active_index_root = hash_tree_root(get_active_validator_indices(state, GENESIS_EPOCH)) - for index in range(LATEST_INDEX_ROOTS_LENGTH): - state.latest_index_roots[index] = genesis_active_index_root + for index in range(LATEST_ACTIVE_INDEX_ROOTS_LENGTH): + state.latest_active_index_roots[index] = genesis_active_index_root state.current_epoch_seed = generate_seed(state, GENESIS_EPOCH) return state @@ -2094,7 +2094,7 @@ def process_penalties_and_exits(state: BeaconState) -> None: #### Final updates -* Set `state.latest_index_roots[(next_epoch + ENTRY_EXIT_DELAY) % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, next_epoch + ENTRY_EXIT_DELAY))`. +* Set `state.latest_active_index_roots[(next_epoch + ACTIVATION_EXIT_DELAY) % LATEST_ACTIVE_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, next_epoch + ACTIVATION_EXIT_DELAY))`. * Set `state.latest_slashed_balances[(next_epoch) % LATEST_SLASHED_EXIT_LENGTH] = state.latest_slashed_balances[current_epoch % LATEST_SLASHED_EXIT_LENGTH]`. * Set `state.latest_randao_mixes[next_epoch % LATEST_RANDAO_MIXES_LENGTH] = get_randao_mix(state, current_epoch)`. * Remove any `attestation` in `state.latest_attestations` such that `slot_to_epoch(attestation.data.slot) < current_epoch`. From 9ea095efe91027feceee61845fc0abd7b0ee01e2 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 31 Jan 2019 07:58:31 -0800 Subject: [PATCH 03/11] remove Number from custom types --- specs/core/0_beacon-chain.md | 42 ++++++++++++++++++------------------ tmp.md | 4 ++++ 2 files changed, 25 insertions(+), 21 deletions(-) create mode 100644 tmp.md diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fee1c7521..83f377ae5 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -606,9 +606,9 @@ We define the following Python custom types for type hinting and readability: | Name | SSZ equivalent | Description | | - | - | - | -| `SlotNumber` | `uint64` | a slot number | -| `EpochNumber` | `uint64` | an epoch number | -| `ShardNumber` | `uint64` | a shard number | +| `Slot` | `uint64` | a slot number | +| `Epoch` | `uint64` | an epoch number | +| `Shard` | `uint64` | a shard number | | `ValidatorIndex` | `uint64` | an index in the validator registry | | `Gwei` | `uint64` | an amount in Gwei | | `Bytes32` | `bytes32` | 32 bytes of binary data | @@ -632,7 +632,7 @@ Note: We aim to migrate to a S[T/N]ARK-friendly hash function in a future Ethere ### `slot_to_epoch` ```python -def slot_to_epoch(slot: SlotNumber) -> EpochNumber: +def slot_to_epoch(slot: Slot) -> Epoch: """ Return the epoch number of the given ``slot``. """ @@ -642,7 +642,7 @@ def slot_to_epoch(slot: SlotNumber) -> EpochNumber: ### `get_current_epoch` ```python -def get_current_epoch(state: BeaconState) -> EpochNumber: +def get_current_epoch(state: BeaconState) -> Epoch: """ Return the current epoch of the given ``state``. """ @@ -652,7 +652,7 @@ def get_current_epoch(state: BeaconState) -> EpochNumber: ### `get_epoch_start_slot` ```python -def get_epoch_start_slot(epoch: EpochNumber) -> SlotNumber: +def get_epoch_start_slot(epoch: Epoch) -> Slot: """ Return the starting slot of the given ``epoch``. """ @@ -661,7 +661,7 @@ def get_epoch_start_slot(epoch: EpochNumber) -> SlotNumber: ### `is_active_validator` ```python -def is_active_validator(validator: Validator, epoch: EpochNumber) -> bool: +def is_active_validator(validator: Validator, epoch: Epoch) -> bool: """ Check if ``validator`` is active. """ @@ -671,7 +671,7 @@ def is_active_validator(validator: Validator, epoch: EpochNumber) -> bool: ### `get_active_validator_indices` ```python -def get_active_validator_indices(validators: List[Validator], epoch: EpochNumber) -> List[ValidatorIndex]: +def get_active_validator_indices(validators: List[Validator], epoch: Epoch) -> List[ValidatorIndex]: """ Get indices of active validators from ``validators``. """ @@ -766,7 +766,7 @@ def get_epoch_committee_count(active_validator_count: int) -> int: ```python def get_shuffling(seed: Bytes32, validators: List[Validator], - epoch: EpochNumber) -> List[List[ValidatorIndex]] + epoch: Epoch) -> List[List[ValidatorIndex]] """ Shuffle ``validators`` into crosslink committees seeded by ``seed`` and ``epoch``. Return a list of ``committees_per_epoch`` committees where each @@ -832,8 +832,8 @@ def get_next_epoch_committee_count(state: BeaconState) -> int: ```python def get_crosslink_committees_at_slot(state: BeaconState, - slot: SlotNumber, - registry_change=False: bool) -> List[Tuple[List[ValidatorIndex], ShardNumber]]: + slot: Slot, + registry_change=False: bool) -> List[Tuple[List[ValidatorIndex], Shard]]: """ Return the list of ``(committee, shard)`` tuples for the ``slot``. @@ -897,7 +897,7 @@ def get_crosslink_committees_at_slot(state: BeaconState, ```python def get_block_root(state: BeaconState, - slot: SlotNumber) -> Bytes32: + slot: Slot) -> Bytes32: """ Return the block root at a recent ``slot``. """ @@ -912,7 +912,7 @@ def get_block_root(state: BeaconState, ```python def get_randao_mix(state: BeaconState, - epoch: EpochNumber) -> Bytes32: + epoch: Epoch) -> Bytes32: """ Return the randao mix at a recent ``epoch``. """ @@ -924,7 +924,7 @@ def get_randao_mix(state: BeaconState, ```python def get_active_index_root(state: BeaconState, - epoch: EpochNumber) -> Bytes32: + epoch: Epoch) -> Bytes32: """ Return the index root at a recent ``epoch``. """ @@ -936,7 +936,7 @@ def get_active_index_root(state: BeaconState, ```python def generate_seed(state: BeaconState, - epoch: EpochNumber) -> Bytes32: + epoch: Epoch) -> Bytes32: """ Generate a seed for the given ``epoch``. """ @@ -951,7 +951,7 @@ def generate_seed(state: BeaconState, ```python def get_beacon_proposer_index(state: BeaconState, - slot: SlotNumber) -> ValidatorIndex: + slot: Slot) -> ValidatorIndex: """ Return the beacon proposer index for the ``slot``. """ @@ -1029,7 +1029,7 @@ def get_effective_balance(state: State, index: ValidatorIndex) -> Gwei: ```python def get_fork_version(fork: Fork, - epoch: EpochNumber) -> int: + epoch: Epoch) -> int: """ Return the fork version of the given ``epoch``. """ @@ -1043,7 +1043,7 @@ def get_fork_version(fork: Fork, ```python def get_domain(fork: Fork, - epoch: EpochNumber, + epoch: Epoch, domain_type: int) -> int: """ Get the domain number that represents the fork meta and signature domain. @@ -1176,7 +1176,7 @@ def integer_squareroot(n: int) -> int: ### `get_entry_exit_effect_epoch` ```python -def get_entry_exit_effect_epoch(epoch: EpochNumber) -> EpochNumber: +def get_entry_exit_effect_epoch(epoch: Epoch) -> Epoch: """ An entry or exit triggered in the ``epoch`` given by the input takes effect at the epoch given by the output. @@ -1587,10 +1587,10 @@ The beacon chain fork choice rule is a hybrid that combines justification and fi * Abstractly define `Store` as the type of storage object for the chain data and `store` be the set of attestations and blocks that the [validator](#dfn-validator) `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not yet included in any chain are still included in `store`. * Let `finalized_head` be the finalized block with the highest epoch. (A block `B` is finalized if there is a descendant of `B` in `store` the processing of which sets `B` as finalized.) * Let `justified_head` be the descendant of `finalized_head` with the highest epoch that has been justified for at least 1 epoch. (A block `B` is justified if there is a descendant of `B` in `store` the processing of which sets `B` as justified.) If no such descendant exists set `justified_head` to `finalized_head`. -* Let `get_ancestor(store: Store, block: BeaconBlock, slot: SlotNumber) -> BeaconBlock` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as: +* Let `get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as: ```python -def get_ancestor(store: Store, block: BeaconBlock, slot: SlotNumber) -> BeaconBlock: +def get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock: """ Get the ancestor of ``block`` with slot number ``slot``; return ``None`` if not found. """ diff --git a/tmp.md b/tmp.md new file mode 100644 index 000000000..e9b31b31e --- /dev/null +++ b/tmp.md @@ -0,0 +1,4 @@ +Should we strength the registry change condition to all cro + +Need to set `active_index_root` for `ENTRY_EXIT_DELAY` in the future at the end +of the current registry change. \ No newline at end of file From 1593b926cce9f93338a1c584f3f858a6b5dafcc3 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 31 Jan 2019 08:02:54 -0800 Subject: [PATCH 04/11] rename current and previous vars for shuffling to use 'shuffling' --- specs/core/0_beacon-chain.md | 70 ++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 83f377ae5..ebad5c59f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -491,12 +491,12 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git # Randomness and committees 'latest_randao_mixes': ['bytes32'], - 'previous_epoch_start_shard': 'uint64', - 'current_epoch_start_shard': 'uint64', - 'previous_calculation_epoch': 'uint64', - 'current_calculation_epoch': 'uint64', - 'previous_epoch_seed': 'bytes32', - 'current_epoch_seed': 'bytes32', + 'previous_shuffling_start_shard': 'uint64', + 'current_shuffling_start_shard': 'uint64', + 'previous_shuffling_epoch': 'uint64', + 'current_shuffling_epoch': 'uint64', + 'previous_shuffling_seed': 'bytes32', + 'current_shuffling_seed': 'bytes32', # Finality 'previous_justified_epoch': 'uint64', @@ -798,7 +798,7 @@ def get_previous_epoch_committee_count(state: BeaconState) -> int: """ previous_active_validators = get_active_validator_indices( state.validator_registry, - state.previous_calculation_epoch, + state.previous_shuffling_epoch, ) return get_epoch_committee_count(len(previous_active_validators)) ``` @@ -812,7 +812,7 @@ def get_current_epoch_committee_count(state: BeaconState) -> int: """ current_active_validators = get_active_validator_indices( state.validator_registry, - state.current_calculation_epoch, + state.current_shuffling_epoch, ) return get_epoch_committee_count(len(current_active_validators)) ``` @@ -849,14 +849,14 @@ def get_crosslink_committees_at_slot(state: BeaconState, if epoch == previous_epoch: committees_per_epoch = get_previous_epoch_committee_count(state) - seed = state.previous_epoch_seed - shuffling_epoch = state.previous_calculation_epoch - shuffling_start_shard = state.previous_epoch_start_shard + seed = state.previous_shuffling_seed + shuffling_epoch = state.previous_shuffling_epoch + shuffling_start_shard = state.previous_shuffling_start_shard elif epoch == current_epoch: committees_per_epoch = get_current_epoch_committee_count(state) - seed = state.current_epoch_seed - shuffling_epoch = state.current_calculation_epoch - shuffling_start_shard = state.current_epoch_start_shard + seed = state.current_shuffling_seed + shuffling_epoch = state.current_shuffling_epoch + shuffling_start_shard = state.current_shuffling_start_shard elif epoch == next_epoch: current_committees_per_epoch = get_current_epoch_committee_count(state) committees_per_epoch = get_next_epoch_committee_count(state) @@ -865,13 +865,13 @@ def get_crosslink_committees_at_slot(state: BeaconState, epochs_since_last_registry_update = current_epoch - state.validator_registry_update_epoch if registry_change: seed = generate_seed(state, next_epoch) - shuffling_start_shard = (state.current_epoch_start_shard + current_committees_per_epoch) % SHARD_COUNT + shuffling_start_shard = (state.current_shuffling_start_shard + current_committees_per_epoch) % SHARD_COUNT elif epochs_since_last_registry_update > 1 and is_power_of_two(epochs_since_last_registry_update): seed = generate_seed(state, next_epoch) - shuffling_start_shard = state.current_epoch_start_shard + shuffling_start_shard = state.current_shuffling_start_shard else: - seed = state.current_epoch_seed - shuffling_start_shard = state.current_epoch_start_shard + seed = state.current_shuffling_seed + shuffling_start_shard = state.current_shuffling_start_shard shuffling = get_shuffling( seed, @@ -1511,12 +1511,12 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], # Randomness and committees latest_randao_mixes=[ZERO_HASH for _ in range(LATEST_RANDAO_MIXES_LENGTH)], - previous_epoch_start_shard=GENESIS_START_SHARD, - current_epoch_start_shard=GENESIS_START_SHARD, - previous_calculation_epoch=GENESIS_EPOCH, - current_calculation_epoch=GENESIS_EPOCH, - previous_epoch_seed=ZERO_HASH, - current_epoch_seed=ZERO_HASH, + previous_shuffling_start_shard=GENESIS_START_SHARD, + current_shuffling_start_shard=GENESIS_START_SHARD, + previous_shuffling_epoch=GENESIS_EPOCH, + current_shuffling_epoch=GENESIS_EPOCH, + previous_shuffling_seed=ZERO_HASH, + current_shuffling_seed=ZERO_HASH, # Finality previous_justified_epoch=GENESIS_EPOCH, @@ -1555,7 +1555,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], genesis_active_index_root = hash_tree_root(get_active_validator_indices(state, GENESIS_EPOCH)) for index in range(LATEST_ACTIVE_INDEX_ROOTS_LENGTH): state.latest_active_index_roots[index] = genesis_active_index_root - state.current_epoch_seed = generate_seed(state, GENESIS_EPOCH) + state.current_shuffling_seed = generate_seed(state, GENESIS_EPOCH) return state ``` @@ -1977,14 +1977,14 @@ def process_ejections(state: BeaconState) -> None: First, update the following: -* Set `state.previous_calculation_epoch = state.current_calculation_epoch`. -* Set `state.previous_epoch_start_shard = state.current_epoch_start_shard`. -* Set `state.previous_epoch_seed = state.current_epoch_seed`. +* Set `state.previous_shuffling_epoch = state.current_shuffling_epoch`. +* Set `state.previous_shuffling_start_shard = state.current_shuffling_start_shard`. +* Set `state.previous_shuffling_seed = state.current_shuffling_seed`. If the following are satisfied: * `state.finalized_epoch > state.validator_registry_update_epoch` -* `state.latest_crosslinks[shard].epoch > state.validator_registry_update_epoch` for every shard number `shard` in `[(state.current_epoch_start_shard + i) % SHARD_COUNT for i in range(get_current_epoch_committee_count(state))]` (that is, for every shard in the current committees) +* `state.latest_crosslinks[shard].epoch > state.validator_registry_update_epoch` for every shard number `shard` in `[(state.current_shuffling_start_shard + i) % SHARD_COUNT for i in range(get_current_epoch_committee_count(state))]` (that is, for every shard in the current committees) update the validator registry and associated fields by running @@ -2035,17 +2035,17 @@ def update_validator_registry(state: BeaconState) -> None: and perform the following updates: -* Set `state.current_calculation_epoch = next_epoch` -* Set `state.current_epoch_start_shard = (state.current_epoch_start_shard + get_current_epoch_committee_count(state)) % SHARD_COUNT` -* Set `state.current_epoch_seed = generate_seed(state, state.current_calculation_epoch)` +* Set `state.current_shuffling_epoch = next_epoch` +* Set `state.current_shuffling_start_shard = (state.current_shuffling_start_shard + get_current_epoch_committee_count(state)) % SHARD_COUNT` +* Set `state.current_shuffling_seed = generate_seed(state, state.current_shuffling_epoch)` If a validator registry update does _not_ happen do the following: * Let `epochs_since_last_registry_update = current_epoch - state.validator_registry_update_epoch`. * If `epochs_since_last_registry_update > 1` and `is_power_of_two(epochs_since_last_registry_update)`: - * Set `state.current_calculation_epoch = next_epoch`. - * Set `state.current_epoch_seed = generate_seed(state, state.current_calculation_epoch)` - * _Note_ that `state.current_epoch_start_shard` is left unchanged. + * Set `state.current_shuffling_epoch = next_epoch`. + * Set `state.current_shuffling_seed = generate_seed(state, state.current_shuffling_epoch)` + * _Note_ that `state.current_shuffling_start_shard` is left unchanged. **Invariant**: the active index root that is hashed into the shuffling seed actually is the `hash_tree_root` of the validator set that is used for that epoch. From 6716105f1915d92c88aa4b94e488ef3171a9508c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 31 Jan 2019 08:23:41 -0800 Subject: [PATCH 05/11] ChainStart -> Eth2Genesis --- specs/core/0_beacon-chain.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index ebad5c59f..e8deb821d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -100,7 +100,7 @@ - [Deposit arguments](#deposit-arguments) - [Withdrawal credentials](#withdrawal-credentials) - [`Deposit` logs](#deposit-logs) - - [`ChainStart` log](#chainstart-log) + - [`Eth2Genesis` log](#chainstart-log) - [Vyper code](#vyper-code) - [On startup](#on-startup) - [Beacon chain processing](#beacon-chain-processing) @@ -1369,13 +1369,13 @@ The private key corresponding to `withdrawal_pubkey` will be required to initiat Every Ethereum 1.0 deposit, of size between `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSIT_AMOUNT`, emits a `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12 signature) is not verified by the deposit contract. -### `ChainStart` log +### `Eth2Genesis` log -When sufficiently many full deposits have been made the deposit contract emits the `ChainStart` log. The beacon chain state may then be initialized by calling the `get_initial_beacon_state` function (defined below) where: +When sufficiently many full deposits have been made the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_initial_beacon_state` function (defined below) where: -* `genesis_time` equals `time` in the `ChainStart` log -* `latest_eth1_data.deposit_root` equals `deposit_root` in the `ChainStart` log, and `latest_eth1_data.block_hash` equals the hash of the block that included the log -* `initial_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `ChainStart` log, processed in the order in which they were emitted (oldest to newest) +* `genesis_time` equals `time` in the `Eth2Genesis` log +* `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log, and `latest_eth1_data.block_hash` equals the hash of the block that included the log +* `initial_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `Eth2Genesis` log, processed in the order in which they were emitted (oldest to newest) ### Vyper code @@ -1391,7 +1391,7 @@ TWO_TO_POWER_OF_TREE_DEPTH: constant(uint256) = 4294967296 # 2**32 SECONDS_PER_DAY: constant(uint256) = 86400 Deposit: event({deposit_root: bytes32, data: bytes[528], merkle_tree_index: bytes[8], branch: bytes32[32]}) -ChainStart: event({deposit_root: bytes32, time: bytes[8]}) +Eth2Genesis: event({deposit_root: bytes32, time: bytes[8]}) zerohashes: bytes32[32] branch: bytes32[32] @@ -1454,7 +1454,7 @@ def deposit(deposit_input: bytes[512]): if self.full_deposit_count == CHAIN_START_FULL_DEPOSIT_THRESHOLD: timestamp_day_boundary: uint256 = as_unitless_number(block.timestamp) - as_unitless_number(block.timestamp) % SECONDS_PER_DAY + SECONDS_PER_DAY chainstart_time: bytes[8] = slice(concat("", convert(timestamp_day_boundary, bytes32)), start=24, len=8) - log.ChainStart(new_deposit_root, chainstart_time) + log.Eth2Genesis(new_deposit_root, chainstart_time) self.chainStarted = True ``` @@ -1485,7 +1485,7 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val } ``` -`STARTUP_STATE_ROOT` (in the above "genesis block") is generated from the `get_initial_beacon_state` function below. When enough full deposits have been made to the deposit contract and the `ChainStart` log has been emitted, `get_initial_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`. +`STARTUP_STATE_ROOT` (in the above "genesis block") is generated from the `get_initial_beacon_state` function below. When enough full deposits have been made to the deposit contract and the `Eth2Genesis` log has been emitted, `get_initial_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`. ```python def get_initial_beacon_state(initial_validator_deposits: List[Deposit], From 7ff345404e02c81d687642128838ecedd0ab90de Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 31 Jan 2019 08:26:46 -0800 Subject: [PATCH 06/11] simplify bls types --- specs/core/0_beacon-chain.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index e8deb821d..cb44d7943 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -612,8 +612,8 @@ We define the following Python custom types for type hinting and readability: | `ValidatorIndex` | `uint64` | an index in the validator registry | | `Gwei` | `uint64` | an amount in Gwei | | `Bytes32` | `bytes32` | 32 bytes of binary data | -| `BLSPubkey` | `bytes48` | a BLS public key | -| `BLSSignature` | `bytes96` | a BLS signature | +| `Pubkey` | `bytes48` | a BLS12-381 public key | +| `Signature` | `bytes96` | a BLS12-381 signature | ## Helper functions @@ -1200,8 +1200,8 @@ def get_entry_exit_effect_epoch(epoch: Epoch) -> Epoch: ```python def validate_proof_of_possession(state: BeaconState, - pubkey: BLSPubkey, - proof_of_possession: BLSSignature, + pubkey: Pubkey, + proof_of_possession: Signature, withdrawal_credentials: Bytes32) -> bool: """ Verify the given ``proof_of_possession``. @@ -1230,9 +1230,9 @@ Used to add a [validator](#dfn-validator) or top up an existing [validator](#dfn ```python def process_deposit(state: BeaconState, - pubkey: BLSPubkey, + pubkey: Pubkey, amount: Gwei, - proof_of_possession: BLSSignature, + proof_of_possession: Signature, withdrawal_credentials: Bytes32) -> None: """ Process a deposit from Ethereum 1.0. From 11ae40fc4974f8b39cf9e079d62df2f5ac3ce584 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 1 Feb 2019 20:42:11 -0800 Subject: [PATCH 07/11] revery bls types to include BLS --- specs/core/0_beacon-chain.md | 12 ++++++------ tmp.md | 4 ---- 2 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 tmp.md diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index cb44d7943..372542a0a 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -612,8 +612,8 @@ We define the following Python custom types for type hinting and readability: | `ValidatorIndex` | `uint64` | an index in the validator registry | | `Gwei` | `uint64` | an amount in Gwei | | `Bytes32` | `bytes32` | 32 bytes of binary data | -| `Pubkey` | `bytes48` | a BLS12-381 public key | -| `Signature` | `bytes96` | a BLS12-381 signature | +| `BLSPubkey` | `bytes48` | a BLS12-381 public key | +| `BLSSignature` | `bytes96` | a BLS12-381 signature | ## Helper functions @@ -1200,8 +1200,8 @@ def get_entry_exit_effect_epoch(epoch: Epoch) -> Epoch: ```python def validate_proof_of_possession(state: BeaconState, - pubkey: Pubkey, - proof_of_possession: Signature, + pubkey: BLSPubkey, + proof_of_possession: BLSSignature, withdrawal_credentials: Bytes32) -> bool: """ Verify the given ``proof_of_possession``. @@ -1230,9 +1230,9 @@ Used to add a [validator](#dfn-validator) or top up an existing [validator](#dfn ```python def process_deposit(state: BeaconState, - pubkey: Pubkey, + pubkey: BLSPubkey, amount: Gwei, - proof_of_possession: Signature, + proof_of_possession: BLSSignature, withdrawal_credentials: Bytes32) -> None: """ Process a deposit from Ethereum 1.0. diff --git a/tmp.md b/tmp.md deleted file mode 100644 index e9b31b31e..000000000 --- a/tmp.md +++ /dev/null @@ -1,4 +0,0 @@ -Should we strength the registry change condition to all cro - -Need to set `active_index_root` for `ENTRY_EXIT_DELAY` in the future at the end -of the current registry change. \ No newline at end of file From de7263c838d947ac188c20abe7720be40220756c Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 12 Feb 2019 12:24:19 +0000 Subject: [PATCH 08/11] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 98 +++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 053177f46..691c58bda 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -19,10 +19,10 @@ - [State list lengths](#state-list-lengths) - [Reward and penalty quotients](#reward-and-penalty-quotients) - [Status flags](#status-flags) - - [Max operations per block](#max-operations-per-block) + - [Max transactions per block](#max-transactions-per-block) - [Signature domains](#signature-domains) - [Data structures](#data-structures) - - [Beacon chain operations](#beacon-chain-operations) + - [Beacon chain transactions](#beacon-chain-transactions) - [Proposer slashings](#proposer-slashings) - [`ProposerSlashing`](#proposerslashing) - [Attester slashings](#attester-slashings) @@ -36,8 +36,8 @@ - [`Deposit`](#deposit) - [`DepositData`](#depositdata) - [`DepositInput`](#depositinput) - - [Exits](#exits) - - [`Exit`](#exit) + - [Voluntary exits](#voluntary-exits) + - [`VoluntaryExit`](#voluntaryexit) - [Beacon chain blocks](#beacon-chain-blocks) - [`BeaconBlock`](#beaconblock) - [`BeaconBlockBody`](#beaconblockbody) @@ -98,15 +98,15 @@ - [`activate_validator`](#activate_validator) - [`initiate_validator_exit`](#initiate_validator_exit) - [`exit_validator`](#exit_validator) - - [`penalize_validator`](#penalize_validator) + - [`slash_validator`](#slash_validator) - [`prepare_validator_for_withdrawal`](#prepare_validator_for_withdrawal) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - [Deposit arguments](#deposit-arguments) - [Withdrawal credentials](#withdrawal-credentials) - [`Deposit` logs](#deposit-logs) - - [`Eth2Genesis` log](#chainstart-log) + - [`Eth2Genesis` log](#eth2genesis-log) - [Vyper code](#vyper-code) - - [On startup](#on-startup) + - [On genesis](#on-genesis) - [Beacon chain processing](#beacon-chain-processing) - [Beacon chain fork choice rule](#beacon-chain-fork-choice-rule) - [Beacon chain state transition function](#beacon-chain-state-transition-function) @@ -118,12 +118,12 @@ - [Proposer signature](#proposer-signature) - [RANDAO](#randao) - [Eth1 data](#eth1-data) - - [Operations](#operations) + - [Transactions](#transactions) - [Proposer slashings](#proposer-slashings-1) - [Attester slashings](#attester-slashings-1) - [Attestations](#attestations-1) - [Deposits](#deposits-1) - - [Exits](#exits-1) + - [Voluntary exits](#voluntary-exits-1) - [Per-epoch processing](#per-epoch-processing) - [Helper variables](#helper-variables) - [Eth1 data](#eth1-data-1) @@ -247,7 +247,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. | - | - | | `BASE_REWARD_QUOTIENT` | `2**5` (= 32) | | `WHISTLEBLOWER_REWARD_QUOTIENT` | `2**9` (= 512) | -| `INCLUDER_REWARD_QUOTIENT` | `2**3` (= 8) | +| `ATTESTATION_INCLUSION_REWARD_QUOTIENT` | `2**3` (= 8) | | `INACTIVITY_PENALTY_QUOTIENT` | `2**24` (= 16,777,216) | * The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It corresponds to ~2.54% annual interest assuming 10 million participating ETH in every epoch. @@ -260,7 +260,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. | `INITIATED_EXIT` | `2**0` (= 1) | | `WITHDRAWABLE` | `2**1` (= 2) | -### Max operations per block +### Max transactions per block | Name | Value | | - | - | @@ -268,7 +268,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. | `MAX_ATTESTER_SLASHINGS` | `2**0` (= 1) | | `MAX_ATTESTATIONS` | `2**7` (= 128) | | `MAX_DEPOSITS` | `2**4` (= 16) | -| `MAX_EXITS` | `2**4` (= 16) | +| `MAX_VOLUNTARY_EXITS` | `2**4` (= 16) | ### Signature domains @@ -284,7 +284,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. The following data structures are defined as [SimpleSerialize (SSZ)](https://github.com/ethereum/eth2.0-specs/blob/master/specs/simple-serialize.md) objects. -### Beacon chain operations +### Beacon chain transactions #### Proposer slashings @@ -425,9 +425,9 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git } ``` -#### Exits +#### Voluntary exits -##### `Exit` +##### `VoluntaryExit` ```python { @@ -467,7 +467,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git 'attester_slashings': [AttesterSlashing], 'attestations': [Attestation], 'deposits': [Deposit], - 'exits': [Exit], + 'voluntary_exits': [VoluntaryExit], } ``` @@ -621,7 +621,7 @@ We define the following Python custom types for type hinting and readability: | `Slot` | `uint64` | a slot number | | `Epoch` | `uint64` | an epoch number | | `Shard` | `uint64` | a shard number | -| `ValidatorIndex` | `uint64` | an index in the validator registry | +| `ValidatorIndex` | `uint64` | a validator registry index | | `Gwei` | `uint64` | an amount in Gwei | | `Bytes32` | `bytes32` | 32 bytes of binary data | | `BLSPubkey` | `bytes48` | a BLS12-381 public key | @@ -654,7 +654,7 @@ def slot_to_epoch(slot: Slot) -> Epoch: ### `get_previous_epoch` ```python -def get_previous_epoch(state: BeaconState) -> EpochNumber: +def get_previous_epoch(state: BeaconState) -> Epoch: """` Return the previous epoch of the given ``state``. If the current epoch is ``GENESIS_EPOCH``, return ``GENESIS_EPOCH``. @@ -1335,12 +1335,12 @@ def exit_validator(state: BeaconState, index: ValidatorIndex) -> None: validator.exit_epoch = get_entry_exit_effect_epoch(get_current_epoch(state)) ``` -#### `penalize_validator` +#### `slash_validator` ```python -def penalize_validator(state: BeaconState, index: ValidatorIndex) -> None: +def slash_validator(state: BeaconState, index: ValidatorIndex) -> None: """ - Penalize the validator of the given ``index``. + Slash the validator with index ``index``. Note that this function mutates ``state``. """ exit_validator(state, index) @@ -1389,11 +1389,12 @@ Every Ethereum 1.0 deposit, of size between `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSI ### `Eth2Genesis` log -When sufficiently many full deposits have been made the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_initial_beacon_state` function (defined below) where: +When sufficiently many full deposits have been made the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_genesis_beacon_state` function (defined below) where: * `genesis_time` equals `time` in the `Eth2Genesis` log -* `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log, and `latest_eth1_data.block_hash` equals the hash of the block that included the log -* `initial_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `Eth2Genesis` log, processed in the order in which they were emitted (oldest to newest) +* `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log +* `latest_eth1_data.block_hash` equals the hash of the block that included the log +* `genesis_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `Eth2Genesis` log, processed in the order in which they were emitted (oldest to newest) ### Vyper code @@ -1407,7 +1408,7 @@ For convenience, we provide the interface to the contract here: * `get_deposit_root() -> bytes32`: returns the current root of the deposit tree * `deposit(bytes[512])`: adds a deposit instance to the deposit tree, incorporating the input argument and the value transferred in the given call. Note: the amount of value transferred *must* be within `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSIT_AMOUNT`, inclusive. Each of these constants are specified in units of Gwei. -## On startup +## On genesis A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following values. Other validity rules (e.g. requiring a signature) do not apply. @@ -1415,7 +1416,7 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val { slot=GENESIS_SLOT, parent_root=ZERO_HASH, - state_root=STARTUP_STATE_ROOT, + state_root=GENESIS_STATE_ROOT, randao_reveal=EMPTY_SIGNATURE, eth1_data=Eth1Data( deposit_root=ZERO_HASH, @@ -1432,14 +1433,14 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val } ``` -`STARTUP_STATE_ROOT` (in the above "genesis block") is generated from the `get_initial_beacon_state` function below. When enough full deposits have been made to the deposit contract and the `Eth2Genesis` log has been emitted, `get_initial_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`. +`GENESIS_STATE_ROOT` (in the above "genesis block") is generated from the `get_genesis_beacon_state` function below. When enough full deposits have been made to the deposit contract and the `Eth2Genesis` log has been emitted, `get_genesis_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`. ```python -def get_initial_beacon_state(initial_validator_deposits: List[Deposit], +def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit], genesis_time: int, latest_eth1_data: Eth1Data) -> BeaconState: """ - Get the initial ``BeaconState``. + Get the genesis ``BeaconState``. """ state = BeaconState( # Misc @@ -1482,11 +1483,11 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], # Ethereum 1.0 chain data latest_eth1_data=latest_eth1_data, eth1_data_votes=[], - deposit_index=len(initial_validator_deposits) + deposit_index=len(genesis_validator_deposits) ) - # Process initial deposits - for deposit in initial_validator_deposits: + # Process genesis deposits + for deposit in genesis_validator_deposits: process_deposit( state=state, pubkey=deposit.deposit_data.deposit_input.pubkey, @@ -1495,7 +1496,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials, ) - # Process initial activations + # 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) @@ -1636,7 +1637,7 @@ Below are the processing steps that happen at every `block`. * If there exists an `eth1_data_vote` in `states.eth1_data_votes` for which `eth1_data_vote.eth1_data == block.eth1_data` (there will be at most one), set `eth1_data_vote.vote_count += 1`. * Otherwise, append to `state.eth1_data_votes` a new `Eth1DataVote(eth1_data=block.eth1_data, vote_count=1)`. -#### Operations +#### Transactions ##### Proposer slashings @@ -1651,7 +1652,7 @@ For each `proposer_slashing` in `block.body.proposer_slashings`: * Verify that `proposer.slashed_epoch > get_current_epoch(state)`. * Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=hash_tree_root(proposer_slashing.proposal_data_1), signature=proposer_slashing.proposal_signature_1, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_data_1.slot), DOMAIN_PROPOSAL))`. * Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=hash_tree_root(proposer_slashing.proposal_data_2), signature=proposer_slashing.proposal_signature_2, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_data_2.slot), DOMAIN_PROPOSAL))`. -* Run `penalize_validator(state, proposer_slashing.proposer_index)`. +* Run `slash_validator(state, proposer_slashing.proposer_index)`. ##### Attester slashings @@ -1667,7 +1668,7 @@ For each `attester_slashing` in `block.body.attester_slashings`: * Verify that `verify_slashable_attestation(state, slashable_attestation_2)`. * Let `slashable_indices = [index for index in slashable_attestation_1.validator_indices if index in slashable_attestation_2.validator_indices and state.validator_registry[index].slashed_epoch > get_current_epoch(state)]`. * Verify that `len(slashable_indices) >= 1`. -* Run `penalize_validator(state, index)` for each `index` in `slashable_indices`. +* Run `slash_validator(state, index)` for each `index` in `slashable_indices`. ##### Attestations @@ -1755,11 +1756,11 @@ process_deposit( * Set `state.deposit_index += 1`. -##### Exits +##### Voluntary exits -Verify that `len(block.body.exits) <= MAX_EXITS`. +Verify that `len(block.body.voluntary_exits) <= MAX_VOLUNTARY_EXITS`. -For each `exit` in `block.body.exits`: +For each `exit` in `block.body.voluntary_exits`: * Let `validator = state.validator_registry[exit.validator_index]`. * Verify that `validator.exit_epoch > get_entry_exit_effect_epoch(get_current_epoch(state))`. @@ -1893,7 +1894,7 @@ Case 2: `epochs_since_finality > 4`: ##### Attestation inclusion -For each `index` in `previous_epoch_attester_indices`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(state, index))` and set `state.validator_balances[proposer_index] += base_reward(state, index) // INCLUDER_REWARD_QUOTIENT`. +For each `index` in `previous_epoch_attester_indices`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(state, index))` and set `state.validator_balances[proposer_index] += base_reward(state, index) // ATTESTATION_INCLUSION_REWARD_QUOTIENT`. ##### Crosslinks @@ -1995,18 +1996,16 @@ If a validator registry update does _not_ happen do the following: **Invariant**: the active index root that is hashed into the shuffling seed actually is the `hash_tree_root` of the validator set that is used for that epoch. -Regardless of whether or not a validator set change happens, run the following: +Regardless of whether or not a validator set change happens run `process_slashings(state)` and `process_withdrawals(state): ```python -def process_penalties_and_exits(state: BeaconState) -> None: +def process_slashings(state: BeaconState) -> None: """ - Process the penalties and prepare the validators who are eligible to withdrawal. + Process the slashings. Note that this function mutates ``state``. """ current_epoch = get_current_epoch(state) - # The active validators active_validator_indices = get_active_validator_indices(state.validator_registry, current_epoch) - # The total effective balance of active validators total_balance = sum(get_effective_balance(state, i) for i in active_validator_indices) for index, validator in enumerate(state.validator_registry): @@ -2017,6 +2016,15 @@ def process_penalties_and_exits(state: BeaconState) -> None: total_penalties = total_at_end - total_at_start penalty = get_effective_balance(state, index) * min(total_penalties * 3, total_balance) // total_balance state.validator_balances[index] -= penalty +``` + +```python +def process_withdrawals(state: BeaconState) -> None: + """ + Process the withdrawals. + Note that this function mutates ``state``. + """ + current_epoch = get_current_epoch(state) def eligible(index): validator = state.validator_registry[index] From d4f79c8878375a9e146f3491e2b4d3043a35a30a Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 12 Feb 2019 12:28:13 +0000 Subject: [PATCH 09/11] Update 0_beacon-chain.md --- 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 691c58bda..a9dd7fc24 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1996,7 +1996,7 @@ If a validator registry update does _not_ happen do the following: **Invariant**: the active index root that is hashed into the shuffling seed actually is the `hash_tree_root` of the validator set that is used for that epoch. -Regardless of whether or not a validator set change happens run `process_slashings(state)` and `process_withdrawals(state): +Regardless of whether or not a validator set change happens run `process_slashings(state)` and `process_withdrawals(state)`: ```python def process_slashings(state: BeaconState) -> None: From bd9baeca0ccf436805464b57b62955a0b20c962a Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 12 Feb 2019 13:37:30 +0000 Subject: [PATCH 10/11] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index a9dd7fc24..2e5670706 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -177,15 +177,15 @@ Code snippets appearing in `this style` are to be interpreted as Python code. ### Misc -| Name | Value | Unit | +| Name | Value | | - | - | :-: | -| `SHARD_COUNT` | `2**10` (= 1,024) | shards | -| `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | [validators](#dfn-validator) | -| `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) | - | -| `BEACON_CHAIN_SHARD_NUMBER` | `2**64 - 1` | - | -| `MAX_INDICES_PER_SLASHABLE_VOTE` | `2**12` (= 4,096) | votes | -| `MAX_WITHDRAWALS_PER_EPOCH` | `2**2` (= 4) | withdrawals | -| `SHUFFLE_ROUND_COUNT` | 90 | - | +| `SHARD_COUNT` | `2**10` (= 1,024) | +| `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | +| `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) | +| `BEACON_CHAIN_SHARD_NUMBER` | `2**64 - 1` | +| `MAX_INDICES_PER_SLASHABLE_VOTE` | `2**12` (= 4,096) | +| `MAX_EXIT_DEQUEUES_PER_EPOCH` | `2**2` (= 4) | +| `SHUFFLE_ROUND_COUNT` | 90 | * For the safety of crosslinks `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `EPOCH_LENGTH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) @@ -1996,7 +1996,7 @@ If a validator registry update does _not_ happen do the following: **Invariant**: the active index root that is hashed into the shuffling seed actually is the `hash_tree_root` of the validator set that is used for that epoch. -Regardless of whether or not a validator set change happens run `process_slashings(state)` and `process_withdrawals(state)`: +Regardless of whether or not a validator set change happens run `process_slashings(state)` and `process_exit_queue(state)`: ```python def process_slashings(state: BeaconState) -> None: @@ -2019,9 +2019,9 @@ def process_slashings(state: BeaconState) -> None: ``` ```python -def process_withdrawals(state: BeaconState) -> None: +def process_exit_queue(state: BeaconState) -> None: """ - Process the withdrawals. + Process the exit queue. Note that this function mutates ``state``. """ current_epoch = get_current_epoch(state) @@ -2034,12 +2034,11 @@ def process_withdrawals(state: BeaconState) -> None: else: return current_epoch >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_EPOCHS - all_indices = list(range(len(state.validator_registry))) - eligible_indices = filter(eligible, all_indices) + eligible_indices = filter(eligible, list(range(len(state.validator_registry)))) # Sort in order of exit epoch, and validators that exit within the same epoch exit in order of validator index sorted_indices = sorted(eligible_indices, key=lambda index: state.validator_registry[index].exit_epoch) - for withdrawn_so_far, index in enumerate(sorted_indices): - if withdrawn_so_far >= MAX_WITHDRAWALS_PER_EPOCH: + for dequeues, index in enumerate(sorted_indices): + if dequeues >= MAX_EXIT_DEQUEUES_PER_EPOCH: break prepare_validator_for_withdrawal(state, index) ``` From b6d27edd6ea86385dde382675c1374616eef2ec6 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 12 Feb 2019 22:38:29 +0000 Subject: [PATCH 11/11] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 2e5670706..62cde4826 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -187,7 +187,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. | `MAX_EXIT_DEQUEUES_PER_EPOCH` | `2**2` (= 4) | | `SHUFFLE_ROUND_COUNT` | 90 | -* For the safety of crosslinks `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `EPOCH_LENGTH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes 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 crosslinks `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 at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) ### Deposit contract @@ -218,19 +218,19 @@ Code snippets appearing in `this style` are to be interpreted as Python code. | `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 `EPOCH_LENGTH` times as large as any value measured in epochs). +* `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 | | - | - | :-: | :-: | -| `SLOT_DURATION` | `6` | seconds | 6 seconds | +| `SECONDS_PER_SLOT` | `6` | seconds | 6 seconds | | `MIN_ATTESTATION_INCLUSION_DELAY` | `2**2` (= 4) | slots | 24 seconds | -| `EPOCH_LENGTH` | `2**6` (= 64) | slots | 6.4 minutes | +| `SLOTS_PER_EPOCH` | `2**6` (= 64) | slots | 6.4 minutes | | `MIN_SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes | | `ACTIVATION_EXIT_DELAY` | `2**2` (= 4) | epochs | 25.6 minutes | -| `ETH1_DATA_VOTING_PERIOD` | `2**4` (= 16) | epochs | ~1.7 hours | -| `MIN_VALIDATOR_WITHDRAWAL_EPOCHS` | `2**8` (= 256) | epochs | ~27 hours | +| `EPOCHS_PER_ETH1_VOTING_PERIOD` | `2**4` (= 16) | epochs | ~1.7 hours | +| `MIN_VALIDATOR_WITHDRAWAL_DELAY` | `2**8` (= 256) | epochs | ~27 hours | ### State list lengths @@ -648,7 +648,7 @@ def slot_to_epoch(slot: Slot) -> Epoch: """ Return the epoch number of the given ``slot``. """ - return slot // EPOCH_LENGTH + return slot // SLOTS_PER_EPOCH ``` ### `get_previous_epoch` @@ -682,7 +682,7 @@ def get_epoch_start_slot(epoch: Epoch) -> Slot: """ Return the starting slot of the given ``epoch``. """ - return epoch * EPOCH_LENGTH + return epoch * SLOTS_PER_EPOCH ``` ### `is_active_validator` @@ -751,10 +751,10 @@ def get_epoch_committee_count(active_validator_count: int) -> int: return max( 1, min( - SHARD_COUNT // EPOCH_LENGTH, - active_validator_count // EPOCH_LENGTH // TARGET_COMMITTEE_SIZE, + SHARD_COUNT // SLOTS_PER_EPOCH, + active_validator_count // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, ) - ) * EPOCH_LENGTH + ) * SLOTS_PER_EPOCH ``` ### `get_shuffling` @@ -879,8 +879,8 @@ def get_crosslink_committees_at_slot(state: BeaconState, state.validator_registry, shuffling_epoch, ) - offset = slot % EPOCH_LENGTH - committees_per_slot = committees_per_epoch // EPOCH_LENGTH + offset = slot % SLOTS_PER_EPOCH + committees_per_slot = committees_per_epoch // SLOTS_PER_EPOCH slot_start_shard = (shuffling_start_shard + committees_per_slot * offset) % SHARD_COUNT return [ @@ -1523,11 +1523,11 @@ For a beacon chain block, `block`, to be processed by a node, the following cond * The parent block with root `block.parent_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 * SLOT_DURATION`. (Note that leap seconds mean that slots will occasionally last `SLOT_DURATION + 1` or `SLOT_DURATION - 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. -Beacon block production is significantly different because of the proof of stake mechanism. A client simply checks what it thinks is the canonical chain when it should create a block, and looks up what its slot number is; when the slot arrives, it either proposes or attests to a block as required. Note that this requires each node to have a clock that is roughly (i.e. within `SLOT_DURATION` seconds) synchronized with the other nodes. +Beacon block production is significantly different because of the proof of stake mechanism. A client simply checks what it thinks is the canonical chain when it should create a block, and looks up what its slot number is; when the slot arrives, it either proposes or attests to a block as required. Note that this requires each node to have a clock that is roughly (i.e. within `SECONDS_PER_SLOT` seconds) synchronized with the other nodes. ### Beacon chain fork choice rule @@ -1590,7 +1590,7 @@ We now define the state transition function. At a high level the state transitio 1. The per-slot transitions, which happens at the start of every slot. 2. The per-block transitions, which happens at every block. -3. The per-epoch transitions, which happens at the end of the last slot of every epoch (i.e. `(state.slot + 1) % EPOCH_LENGTH == 0`). +3. The per-epoch transitions, which happens at the end of the last slot of every epoch (i.e. `(state.slot + 1) % SLOTS_PER_EPOCH == 0`). The per-slot transitions focus on the slot counter and block roots records updates; the per-block transitions generally focus on verifying aggregate signatures and saving temporary records relating to the per-block activity in the `BeaconState`; the per-epoch transitions focus on the [validator](#dfn-validator) registry, including adjusting balances and activating and exiting [validators](#dfn-validator), as well as processing crosslinks and managing block justification/finalization. @@ -1676,7 +1676,7 @@ Verify that `len(block.body.attestations) <= MAX_ATTESTATIONS`. For each `attestation` in `block.body.attestations`: -* Verify that `attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY < attestation.data.slot + EPOCH_LENGTH`. +* Verify that `attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY < attestation.data.slot + SLOTS_PER_EPOCH`. * Verify that `attestation.data.justified_epoch` is equal to `state.justified_epoch if attestation.data.slot >= get_epoch_start_slot(get_current_epoch(state)) else state.previous_justified_epoch`. * Verify that `attestation.data.justified_block_root` is equal to `get_block_root(state, get_epoch_start_slot(attestation.data.justified_epoch))`. * Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(shard_block_root=attestation.data.shard_block_root, epoch=slot_to_epoch(attestation.data.slot))`. @@ -1771,7 +1771,7 @@ For each `exit` in `block.body.voluntary_exits`: ### Per-epoch processing -The steps below happen when `(state.slot + 1) % EPOCH_LENGTH == 0`. +The steps below happen when `(state.slot + 1) % SLOTS_PER_EPOCH == 0`. #### Helper variables @@ -1824,9 +1824,9 @@ Define the following helpers to process attestation inclusion rewards and inclus #### Eth1 data -If `next_epoch % ETH1_DATA_VOTING_PERIOD == 0`: +If `next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0`: -* If `eth1_data_vote.vote_count * 2 > ETH1_DATA_VOTING_PERIOD * EPOCH_LENGTH` for some `eth1_data_vote` in `state.eth1_data_votes` (ie. more than half the votes in this voting period were for that value), set `state.latest_eth1_data = eth1_data_vote.eth1_data`. +* If `eth1_data_vote.vote_count * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH` for some `eth1_data_vote` in `state.eth1_data_votes` (ie. more than half the votes in this voting period were for that value), set `state.latest_eth1_data = eth1_data_vote.eth1_data`. * Set `state.eth1_data_votes = []`. #### Justification @@ -2032,7 +2032,7 @@ def process_exit_queue(state: BeaconState) -> None: slashed_withdrawal_epochs = LATEST_SLASHED_EXIT_LENGTH // 2 return current_epoch >= validator.slashed_epoch + slashed_withdrawal_epochs else: - return current_epoch >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_EPOCHS + return current_epoch >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_DELAY eligible_indices = filter(eligible, list(range(len(state.validator_registry)))) # Sort in order of exit epoch, and validators that exit within the same epoch exit in order of validator index