Merge pull request #200 from burnburn/validator_definitions
add links to validator definition
This commit is contained in:
commit
cf97bd18ea
|
@ -65,7 +65,7 @@
|
|||
|
||||
This document represents the specification for Phase 0 of Ethereum 2.0 -- The Beacon Chain.
|
||||
|
||||
At the core of Ethereum 2.0 is a system chain called the "beacon chain". The beacon chain stores and manages the registry of validators. In the initial deployment phases of Ethereum 2.0 the only mechanism to become a validator is to make a one-way ETH transaction to a deposit contract on Ethereum 1.0. Activation as a validator happens when deposit transaction receipts are processed by the beacon chain, the activation balance is reached, and after a queuing process. Exit is either voluntary or done forcibly as a penalty for misbehavior.
|
||||
At the core of Ethereum 2.0 is a system chain called the "beacon chain". The beacon chain stores and manages the registry of [validators](#dfn-validator). In the initial deployment phases of Ethereum 2.0 the only mechanism to become a [validator](#dfn-validator) is to make a one-way ETH transaction to a deposit contract on Ethereum 1.0. Activation as a [validator](#dfn-validator) happens when deposit transaction receipts are processed by the beacon chain, the activation balance is reached, and after a queuing process. Exit is either voluntary or done forcibly as a penalty for misbehavior.
|
||||
|
||||
The primary source of load on the beacon chain is "attestations". Attestations are availability votes for a shard block, and simultaneously proof of stake votes for a beacon chain block. A sufficient number of attestations for the same shard block create a "crosslink", confirming the shard segment up to that shard block into the beacon chain. Crosslinks also serve as infrastructure for asynchronous cross-shard communication.
|
||||
|
||||
|
@ -75,18 +75,18 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
|||
|
||||
## Terminology
|
||||
|
||||
* **Validator** - a participant in the Casper/sharding consensus system. You can become one by depositing 32 ETH into the Casper mechanism.
|
||||
* **Active validator** <a id="dfn-active-validator"></a> - a validator currently participating in the protocol which the Casper mechanism looks to produce and attest to blocks, crosslinks and other consensus objects.
|
||||
* **Committee** - a (pseudo-) randomly sampled subset of [active validators](#dfn-active-validator). When a committee is referred to collectively, as in "this committee attests to X", this is assumed to mean "some subset of that committee that contains enough validators that the protocol recognizes it as representing the committee".
|
||||
* **Proposer** - the validator that creates a beacon chain block
|
||||
* **Attester** - a validator that is part of a committee that needs to sign off on a beacon chain block while simultaneously creating a link (crosslink) to a recent shard block on a particular shard chain.
|
||||
* **Validator** <a id="dfn-validator"></a> - a participant in the Casper/sharding consensus system. You can become one by depositing 32 ETH into the Casper mechanism.
|
||||
* **Active validator** <a id="dfn-active-validator"></a> - a [validator](#dfn-validator) currently participating in the protocol which the Casper mechanism looks to produce and attest to blocks, crosslinks and other consensus objects.
|
||||
* **Committee** - a (pseudo-) randomly sampled subset of [active validators](#dfn-active-validator). When a committee is referred to collectively, as in "this committee attests to X", this is assumed to mean "some subset of that committee that contains enough [validators](#dfn-validator) that the protocol recognizes it as representing the committee".
|
||||
* **Proposer** - the [validator](#dfn-validator) that creates a beacon chain block
|
||||
* **Attester** - a [validator](#dfn-validator) that is part of a committee that needs to sign off on a beacon chain block while simultaneously creating a link (crosslink) to a recent shard block on a particular shard chain.
|
||||
* **Beacon chain** - the central PoS chain that is the base of the sharding system.
|
||||
* **Shard chain** - one of the chains on which user transactions take place and account data is stored.
|
||||
* **Crosslink** - a set of signatures from a committee attesting to a block in a shard chain, which can be included into the beacon chain. Crosslinks are the main means by which the beacon chain "learns about" the updated state of shard chains.
|
||||
* **Slot** - a period of `SLOT_DURATION` seconds, during which one proposer has the ability to create a beacon chain block and some attesters have the ability to make attestations
|
||||
* **Epoch** - an aligned span of slots during which all validators get exactly one chance to make an attestation
|
||||
* **Epoch** - an aligned span of slots during which all [validators](#dfn-validator) get exactly one chance to make an attestation
|
||||
* **Finalized**, **justified** - see Casper FFG finalization here: https://arxiv.org/abs/1710.09437
|
||||
* **Withdrawal period** - the number of slots between a validator exit and the validator balance being withdrawable
|
||||
* **Withdrawal period** - the number of slots between a [validator](#dfn-validator) exit and the [validator](#dfn-validator) balance being withdrawable
|
||||
* **Genesis time** - the Unix time of the genesis beacon chain block at slot 0
|
||||
|
||||
## Constants
|
||||
|
@ -94,7 +94,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
|||
| Name | Value | Unit |
|
||||
| - | - | :-: |
|
||||
| `SHARD_COUNT` | `2**10` (= 1,024)| shards |
|
||||
| `TARGET_COMMITTEE_SIZE` | `2**8` (= 256) | validators |
|
||||
| `TARGET_COMMITTEE_SIZE` | `2**8` (= 256) | [validators](#dfn-validator) |
|
||||
| `MAX_ATTESTATIONS_PER_BLOCK` | `2**7` (= 128) | attestations |
|
||||
| `MAX_DEPOSIT` | `2**5` (= 32) | ETH |
|
||||
| `MIN_BALANCE` | `2**4` (= 16) | ETH |
|
||||
|
@ -166,9 +166,9 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
|||
**Notes**
|
||||
|
||||
* See a recommended min committee size of 111 [here](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); the shuffling algorithm will generally ensure the committee size is at least half the target.
|
||||
* The `SQRT_E_DROP_TIME` constant is the amount of time it takes for the inactivity leak to cut deposits of non-participating validators by ~39.4%.
|
||||
* The `BASE_REWARD_QUOTIENT` constant dictates the per-epoch interest rate assuming all validators are participating, assuming total deposits of 1 ETH. It corresponds to ~2.57% annual interest assuming 10 million participating ETH.
|
||||
* At most `1/MAX_CHURN_QUOTIENT` of the validators can change during each validator registry change.
|
||||
* The `SQRT_E_DROP_TIME` constant is the amount of time it takes for the inactivity leak to cut deposits of non-participating [validators](#dfn-validator) by ~39.4%.
|
||||
* The `BASE_REWARD_QUOTIENT` constant dictates the per-epoch interest rate assuming all [validators](#dfn-validator) are participating, assuming total deposits of 1 ETH. It corresponds to ~2.57% annual interest assuming 10 million participating ETH.
|
||||
* At most `1/MAX_CHURN_QUOTIENT` of the [validators](#dfn-validator) can change during each [validator](#dfn-validator) registry change.
|
||||
|
||||
## Ethereum 1.0 chain deposit contract
|
||||
|
||||
|
@ -225,7 +225,7 @@ def get_receipt_root() -> bytes32:
|
|||
|
||||
```
|
||||
|
||||
The contract is at address `DEPOSIT_CONTRACT_ADDRESS`. When a user wishes to become a validator by moving their ETH from Ethereum 1.0 to the Ethereum 2.0 chain, they should call the `deposit` function, sending up to `MAX_DEPOSIT` ETH and providing as `deposit_parameters` a SimpleSerialize'd `DepositParametersRecord` object (defined in "Data structures" below). If the user wishes to deposit more than `MAX_DEPOSIT` ETH, they would need to make multiple calls.
|
||||
The contract is at address `DEPOSIT_CONTRACT_ADDRESS`. When a user wishes to become a [validator](#dfn-validator) by moving their ETH from Ethereum 1.0 to the Ethereum 2.0 chain, they should call the `deposit` function, sending up to `MAX_DEPOSIT` ETH and providing as `deposit_parameters` a SimpleSerialize'd `DepositParametersRecord` object (defined in "Data structures" below). If the user wishes to deposit more than `MAX_DEPOSIT` ETH, they would need to make multiple calls.
|
||||
|
||||
When the contract publishes a `ChainStart` log, this initializes the chain, calling `on_startup` with:
|
||||
|
||||
|
@ -482,7 +482,7 @@ A `ShardReassignmentRecord` object has the following fields:
|
|||
|
||||
The beacon chain is the system chain for Ethereum 2.0. The main responsibilities of the beacon chain are:
|
||||
|
||||
* Store and maintain the registry of validators
|
||||
* Store and maintain the registry of [validators](#dfn-validator)
|
||||
* Process crosslinks (see above)
|
||||
* Process its own block-by-block consensus, as well as the finality gadget
|
||||
|
||||
|
@ -500,13 +500,13 @@ Beacon block production is significantly different because of the proof of stake
|
|||
|
||||
### Beacon chain fork choice rule
|
||||
|
||||
The beacon chain fork choice rule is a hybrid that combines justification and finality with Latest Message Driven (LMD) Greediest Heaviest Observed SubTree (GHOST). At any point in time a validator `v` subjectively calculates the beacon chain head as follows.
|
||||
The beacon chain fork choice rule is a hybrid that combines justification and finality with Latest Message Driven (LMD) Greediest Heaviest Observed SubTree (GHOST). At any point in time a [validator](#dfn-validator) `v` subjectively calculates the beacon chain head as follows.
|
||||
|
||||
* Let `store` be the set of attestations and blocks that the validator `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not part of any chain are still included in `store`.
|
||||
* Let `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 part of any chain are still included in `store`.
|
||||
* Let `finalized_head` be the finalized block with the highest slot number. (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 slot number that has been justified for at least `EPOCH_LENGTH` slots. (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, block, slot)` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as `def get_ancestor(store, block, slot): return block if block.slot == slot else get_ancestor(store, store.get_parent(block), slot)`.
|
||||
* Let `get_latest_attestation(store, validator)` be the attestation with the highest slot number in `store` from `validator`. If several such attestations exist, use the one the validator `v` observed first.
|
||||
* Let `get_latest_attestation(store, validator)` be the attestation with the highest slot number in `store` from `validator`. If several such attestations exist, use the one the [validator](#dfn-validator) `v` observed first.
|
||||
* Let `get_latest_attestation_target(store, validator)` be the target block in the attestation `get_latest_attestation(store, validator)`.
|
||||
* The head is `lmd_ghost(store, justified_head)` where the function `lmd_ghost` is defined below. Note that the implementation below is suboptimal; there are implementations that compute the head in time logarithmic in slot count.
|
||||
|
||||
|
@ -536,7 +536,7 @@ We now define the state transition function. At a high level the state transitio
|
|||
1. The per-block processing, which happens every block, and only affects a few parts of the `state`.
|
||||
2. The inter-epoch state recalculation, which happens only if `block.slot >= state.latest_state_recalculation_slot + EPOCH_LENGTH`, and affects the entire `state`.
|
||||
|
||||
The inter-epoch state recalculation generally focuses on changes to the validator registry, including adjusting balances and adding and removing validators, as well as processing crosslinks and managing block justification/finalization, while the per-block processing generally focuses on verifying aggregate signatures and saving temporary records relating to the per-block activity in the `BeaconState`.
|
||||
The inter-epoch state recalculation generally focuses on changes to the [validator](#dfn-validator) registry, including adjusting balances and adding and removing [validators](#dfn-validator), as well as processing crosslinks and managing block justification/finalization, while the per-block processing generally focuses on verifying aggregate signatures and saving temporary records relating to the per-block activity in the `BeaconState`.
|
||||
|
||||
### Helper functions
|
||||
|
||||
|
@ -708,7 +708,7 @@ def get_block_hash(state: BeaconState,
|
|||
return state.latest_block_hashes[slot - earliest_slot_in_array]
|
||||
```
|
||||
|
||||
`get_block_hash(_, _, s)` should always return the block hash in the beacon chain at slot `s`, and `get_shard_and_committees_for_slot(_, s)` should not change unless the validator registry changes.
|
||||
`get_block_hash(_, _, s)` should always return the block hash in the beacon chain at slot `s`, and `get_shard_and_committees_for_slot(_, s)` should not change unless the [validator](#dfn-validator) registry changes.
|
||||
|
||||
#### `get_beacon_proposer_index`
|
||||
|
||||
|
@ -872,7 +872,7 @@ def on_startup(initial_validator_entries: List[Any],
|
|||
|
||||
### Routine for adding a validator
|
||||
|
||||
This routine should be run for every validator that is activated as part of a log created on Ethereum 1.0 [TODO: explain where to check for these logs]. The status of the validators added after genesis is `PENDING_ACTIVATION`. These logs should be processed in the order in which they are emitted by Ethereum 1.0.
|
||||
This routine should be run for every [validator](#dfn-validator) that is activated as part of a log created on Ethereum 1.0 [TODO: explain where to check for these logs]. The status of the [validators](#dfn-validator) added after genesis is `PENDING_ACTIVATION`. These logs should be processed in the order in which they are emitted by Ethereum 1.0.
|
||||
|
||||
First, some helper functions:
|
||||
|
||||
|
@ -950,7 +950,7 @@ def get_new_validators(validators: List[ValidatorRecord],
|
|||
return validators_copy, index
|
||||
```
|
||||
`BLSVerify` is a function for verifying a BLS12-381 signature, defined in the [BLS12-381 spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/bls_verify.md).
|
||||
Now, to add a validator or top up an existing validator's balance:
|
||||
Now, to add a [validator](#dfn-validator) or top up an existing [validator](#dfn-validator)'s balance:
|
||||
|
||||
```python
|
||||
def process_deposit(state: BeaconState,
|
||||
|
@ -1169,7 +1169,7 @@ def verify_special_attestation_data(state: State, obj: SpecialAttestationData) -
|
|||
* Verify that `len(intersection) >= 1`.
|
||||
* Verify that `vote_1.data.justified_slot + 1 < vote_2.data.justified_slot + 1 == vote_2.data.slot < vote_1.data.slot` or `vote_1.data.slot == vote_2.data.slot`.
|
||||
|
||||
For each validator index `i` in `intersection`, if `state.validator_registry[i].status` does not equal `EXITED_WITH_PENALTY`, then run `exit_validator(i, state, penalize=True, current_slot=block.slot)`
|
||||
For each [validator](#dfn-validator) index `i` in `intersection`, if `state.validator_registry[i].status` does not equal `EXITED_WITH_PENALTY`, then run `exit_validator(i, state, penalize=True, current_slot=block.slot)`
|
||||
|
||||
#### `PROPOSER_SLASHING`
|
||||
|
||||
|
@ -1243,29 +1243,29 @@ Note that `state.latest_state_recalculation_slot` will always be a multiple of `
|
|||
|
||||
### Precomputation
|
||||
|
||||
All validators:
|
||||
All [validators](#dfn-validator):
|
||||
|
||||
* Let `active_validators = [state.validator_registry[i] for i in get_active_validator_indices(state.validator_registry)]`.
|
||||
* Let `total_balance = sum([get_effective_balance(v) for v in active_validators])`. Let `total_balance_in_eth = total_balance // GWEI_PER_ETH`.
|
||||
* Let `reward_quotient = BASE_REWARD_QUOTIENT * integer_squareroot(total_balance_in_eth)`. (The per-slot maximum interest rate is `2/reward_quotient`.)
|
||||
|
||||
Validators justifying the epoch boundary block at the start of the current epoch:
|
||||
[Validators](#dfn-Validator) justifying the epoch boundary block at the start of the current epoch:
|
||||
|
||||
* Let `this_epoch_attestations = [a for a in state.latest_attestations if s <= a.data.slot < s + EPOCH_LENGTH]`. (note: this is the set of attestations _of slots in the epoch `s...s+EPOCH_LENGTH-1`_, not attestations _that got included in the chain during the epoch `s...s+EPOCH_LENGTH-1`_)
|
||||
* Let `this_epoch_boundary_attestations = [a for a in this_epoch_attestations if a.data.epoch_boundary_hash == get_block_hash(state, block, s) and a.justified_slot == state.justified_slot]`.
|
||||
* Let `this_epoch_boundary_attesters` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_boundary_attestations]`.
|
||||
* Let `this_epoch_boundary_attesters` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_boundary_attestations]`.
|
||||
* Let `this_epoch_boundary_attesting_balance = sum([get_effective_balance(v) for v in this_epoch_boundary_attesters])`.
|
||||
|
||||
Validators justifying the epoch boundary block at the start of the previous epoch:
|
||||
[Validators](#dfn-Validator) justifying the epoch boundary block at the start of the previous epoch:
|
||||
|
||||
* Let `previous_epoch_attestations = [a for a in state.latest_attestations if s - EPOCH_LENGTH <= a.slot < s]`.
|
||||
* Let `previous_epoch_boundary_attestations = [a for a in this_epoch_attestations + previous_epoch_attestations if a.epoch_boundary_hash == get_block_hash(state, block, s - EPOCH_LENGTH) and a.justified_slot == state.previous_justified_slot]`.
|
||||
* Let `previous_epoch_boundary_attesters` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_boundary_attestations]`.
|
||||
* Let `previous_epoch_boundary_attesters` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in previous_epoch_boundary_attestations]`.
|
||||
* Let `previous_epoch_boundary_attesting_balance = sum([get_effective_balance(v) for v in previous_epoch_boundary_attesters])`.
|
||||
|
||||
For every `ShardAndCommittee` object `obj` in `state.shard_and_committee_for_slots`:
|
||||
|
||||
* Let `attesting_validators(obj, shard_block_hash)` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_attestations + previous_epoch_attestations if a.shard == obj.shard and a.shard_block_hash == shard_block_hash]`.
|
||||
* Let `attesting_validators(obj, shard_block_hash)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.participation_bitfield) for a in this_epoch_attestations + previous_epoch_attestations if a.shard == obj.shard and a.shard_block_hash == shard_block_hash]`.
|
||||
* Let `attesting_validators(obj)` be equal to `attesting_validators(obj, shard_block_hash)` for the value of `shard_block_hash` such that `sum([get_effective_balance(v) for v in attesting_validators(obj, shard_block_hash)])` is maximized (ties broken by favoring lower `shard_block_hash` values).
|
||||
* Let `total_attesting_balance(obj)` be the sum of the balances-at-stake of `attesting_validators(obj)`.
|
||||
* Let `winning_hash(obj)` be the winning `shard_block_hash` value.
|
||||
|
@ -1278,7 +1278,7 @@ def adjust_for_inclusion_distance(magnitude: int, distance: int) -> int:
|
|||
return magnitude // 2 + (magnitude // 2) * MIN_ATTESTATION_INCLUSION_DELAY // distance
|
||||
```
|
||||
|
||||
For any validator `v`, let `base_reward(v) = get_effective_balance(v) // reward_quotient`.
|
||||
For any [validator](#dfn-validator) `v`, let `base_reward(v) = get_effective_balance(v) // reward_quotient`.
|
||||
|
||||
### Adjust justified slots and crosslink status
|
||||
|
||||
|
@ -1298,18 +1298,18 @@ For every `ShardAndCommittee` object `obj`:
|
|||
|
||||
Note: When applying penalties in the following balance recalculations implementers should make sure the `uint64` does not underflow.
|
||||
|
||||
* Let `inactivity_penalty_quotient = SQRT_E_DROP_TIME**2`. (The portion lost by offline validators after `D` epochs is about `D*D/2/inactivity_penalty_quotient`.)
|
||||
* Let `inactivity_penalty_quotient = SQRT_E_DROP_TIME**2`. (The portion lost by offline [validators](#dfn-validator) after `D` epochs is about `D*D/2/inactivity_penalty_quotient`.)
|
||||
* Let `time_since_finality = block.slot - state.finalized_slot`.
|
||||
|
||||
Case 1: `time_since_finality <= 4 * EPOCH_LENGTH`:
|
||||
|
||||
* Any validator `v` in `previous_epoch_boundary_attesters` gains `adjust_for_inclusion_distance(base_reward(v) * previous_epoch_boundary_attesting_balance // total_balance, inclusion_distance(v))`.
|
||||
* Any [validator](#dfn-validator) `v` in `previous_epoch_boundary_attesters` gains `adjust_for_inclusion_distance(base_reward(v) * previous_epoch_boundary_attesting_balance // total_balance, inclusion_distance(v))`.
|
||||
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_boundary_attesters` loses `base_reward(v)`.
|
||||
|
||||
Case 2: `time_since_finality > 4 * EPOCH_LENGTH`:
|
||||
|
||||
* Any validator in `previous_epoch_boundary_attesters` sees their balance unchanged.
|
||||
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_boundary_attesters`, and any validator with `status == EXITED_WITH_PENALTY`, loses `base_reward(v) + get_effective_balance(v) * time_since_finality // inactivity_penalty_quotient`.
|
||||
* Any [validator](#dfn-validator) in `previous_epoch_boundary_attesters` sees their balance unchanged.
|
||||
* Any [active validator](#dfn-active-validator) `v` not in `previous_epoch_boundary_attesters`, and any [validator](#dfn-validator) with `status == EXITED_WITH_PENALTY`, loses `base_reward(v) + get_effective_balance(v) * time_since_finality // inactivity_penalty_quotient`.
|
||||
|
||||
For each `v` in `previous_epoch_boundary_attesters`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(v))` and set `state.validator_registry[proposer_index].balance += base_reward(v) // INCLUDER_REWARD_QUOTIENT`.
|
||||
|
||||
|
@ -1329,7 +1329,7 @@ If `state.latest_state_recalculation_slot % POW_RECEIPT_ROOT_VOTING_PERIOD == 0`
|
|||
|
||||
### Validator registry change
|
||||
|
||||
A validator registry change occurs if all of the following criteria are satisfied:
|
||||
A [validator](#dfn-validator) registry change occurs if all of the following criteria are satisfied:
|
||||
|
||||
* `state.finalized_slot > state.validator_registry_latest_change_slot`
|
||||
* For every shard number `shard` in `state.shard_and_committee_for_slots`, `crosslinks[shard].slot > state.validator_registry_latest_change_slot`
|
||||
|
@ -1395,7 +1395,7 @@ def get_changed_validators(validators: List[ValidatorRecord],
|
|||
return validators, latest_penalized_exit_balances, validator_registry_delta_chain_tip
|
||||
```
|
||||
|
||||
Then, run the following algorithm to update the validator registry:
|
||||
Then, run the following algorithm to update the [validator](#dfn-validator) registry:
|
||||
|
||||
```python
|
||||
def change_validators(state: BeaconState,
|
||||
|
@ -1457,7 +1457,7 @@ while len(state.persistent_committee_reassignments) > 0 and state.persistent_com
|
|||
### Finally...
|
||||
|
||||
* Remove all attestation records older than slot `s`.
|
||||
* For any validator with index `i` with balance less than `MIN_BALANCE` and status `ACTIVE`, run `exit_validator(i, state, penalize=False, current_slot=block.slot)`.
|
||||
* For any [validator](#dfn-validator) with index `i` with balance less than `MIN_BALANCE` and status `ACTIVE`, run `exit_validator(i, state, penalize=False, current_slot=block.slot)`.
|
||||
* Set `state.latest_block_hashes = state.latest_block_hashes[EPOCH_LENGTH:]`.
|
||||
* Set `state.latest_state_recalculation_slot += EPOCH_LENGTH`.
|
||||
|
||||
|
|
Loading…
Reference in New Issue