Get rid of state_transition.py
This commit is contained in:
parent
591a2b47c8
commit
5df79d7565
|
@ -105,7 +105,6 @@
|
|||
- [Registry updates](#registry-updates)
|
||||
- [Slashings](#slashings)
|
||||
- [Final updates](#final-updates)
|
||||
- [Per-slot processing](#per-slot-processing)
|
||||
- [Per-block processing](#per-block-processing)
|
||||
- [Block header](#block-header)
|
||||
- [RANDAO](#randao)
|
||||
|
@ -1264,27 +1263,27 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
|
|||
|
||||
## Beacon chain state transition function
|
||||
|
||||
We now define the state transition function. At a high level, the state transition is made up of four parts:
|
||||
The post-state corresponding to a pre-state `state` and a block `block` is defined as `state_transition(state, block)`.
|
||||
|
||||
1. State caching, which happens at the start of every slot.
|
||||
2. The per-epoch transitions, which happens at the start of the first slot of every epoch.
|
||||
3. The per-slot transitions, which happens at every slot.
|
||||
4. The per-block transitions, which happens at every block.
|
||||
```python
|
||||
def state_transition(state: BeaconState, block: BeaconBlock) -> BeaconState:
|
||||
assert state.slot < block.slot
|
||||
while state.slot < block.slot:
|
||||
# State caching at the start of every slot
|
||||
cache_state(state)
|
||||
# Per-epoch processing at the start of the first slot of every epoch
|
||||
if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
|
||||
process_epoch_transition(state)
|
||||
# Slot incrementing
|
||||
state.slot += 1
|
||||
# Block processing at every block
|
||||
process_block(state, block)
|
||||
```
|
||||
|
||||
Transition section notes:
|
||||
* The state caching caches the state root of the previous slot and updates block and state roots records.
|
||||
* 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.
|
||||
* The per-slot transitions focus on the slot counter.
|
||||
* The per-block transitions generally focus on verifying aggregate signatures and saving temporary records relating to the per-block activity in the `BeaconState`.
|
||||
|
||||
Beacon blocks that trigger unhandled Python exceptions (e.g. out-of-range list accesses) and failed `assert`s during the state transition are considered invalid.
|
||||
|
||||
Note: If there are skipped slots between a block and its parent block, run the steps in the [state-root](#state-caching), [per-epoch](#per-epoch-processing), and [per-slot](#per-slot-processing) sections once for each skipped slot and then once for the slot containing the new block.
|
||||
Note: Beacon blocks that trigger unhandled Python exceptions (e.g. out-of-range list accesses) and failed `assert`s during the state transition are considered invalid.
|
||||
|
||||
### State caching
|
||||
|
||||
At every `slot > GENESIS_SLOT` run the following function:
|
||||
|
||||
```python
|
||||
def cache_state(state: BeaconState) -> None:
|
||||
# Cache latest known state root (for previous slot)
|
||||
|
@ -1302,12 +1301,18 @@ def cache_state(state: BeaconState) -> None:
|
|||
|
||||
### Per-epoch processing
|
||||
|
||||
The steps below happen when `state.slot > GENESIS_SLOT and (state.slot + 1) % SLOTS_PER_EPOCH == 0`.
|
||||
```python
|
||||
def process_epoch_transition(state: BeaconState) -> None:
|
||||
process_justification_and_finalization(state)
|
||||
process_crosslinks(state)
|
||||
process_rewards_and_penalties(state)
|
||||
process_registry_updates(state)
|
||||
process_slashings(state)
|
||||
process_final_updates(state)
|
||||
```
|
||||
|
||||
#### Helper functions
|
||||
|
||||
We define epoch transition helper functions:
|
||||
|
||||
```python
|
||||
def get_total_active_balance(state: BeaconState) -> Gwei:
|
||||
return get_total_balance(state, get_active_validator_indices(state, get_current_epoch(state)))
|
||||
|
@ -1387,8 +1392,6 @@ def get_earliest_attestation(state: BeaconState, attestations: List[PendingAttes
|
|||
|
||||
#### Justification and finalization
|
||||
|
||||
Run the following function:
|
||||
|
||||
```python
|
||||
def process_justification_and_finalization(state: BeaconState) -> None:
|
||||
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
|
||||
|
@ -1436,8 +1439,6 @@ def process_justification_and_finalization(state: BeaconState) -> None:
|
|||
|
||||
#### Crosslinks
|
||||
|
||||
Run the following function:
|
||||
|
||||
```python
|
||||
def process_crosslinks(state: BeaconState) -> None:
|
||||
state.previous_crosslinks = [c for c in state.current_crosslinks]
|
||||
|
@ -1453,8 +1454,6 @@ def process_crosslinks(state: BeaconState) -> None:
|
|||
|
||||
#### Rewards and penalties
|
||||
|
||||
First, we define additional helpers:
|
||||
|
||||
```python
|
||||
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
||||
adjusted_quotient = integer_squareroot(get_total_active_balance(state)) // BASE_REWARD_QUOTIENT
|
||||
|
@ -1526,8 +1525,6 @@ def get_crosslink_deltas(state: BeaconState) -> Tuple[List[Gwei], List[Gwei]]:
|
|||
return [rewards, penalties]
|
||||
```
|
||||
|
||||
Run the following function:
|
||||
|
||||
```python
|
||||
def process_rewards_and_penalties(state: BeaconState) -> None:
|
||||
if get_current_epoch(state) == GENESIS_EPOCH:
|
||||
|
@ -1542,8 +1539,6 @@ def process_rewards_and_penalties(state: BeaconState) -> None:
|
|||
|
||||
#### Registry updates
|
||||
|
||||
Run the following function:
|
||||
|
||||
```python
|
||||
def process_registry_updates(state: BeaconState) -> None:
|
||||
# Process activation eligibility and ejections
|
||||
|
@ -1568,8 +1563,6 @@ def process_registry_updates(state: BeaconState) -> None:
|
|||
|
||||
#### Slashings
|
||||
|
||||
Run the following function:
|
||||
|
||||
```python
|
||||
def process_slashings(state: BeaconState) -> None:
|
||||
current_epoch = get_current_epoch(state)
|
||||
|
@ -1592,8 +1585,6 @@ def process_slashings(state: BeaconState) -> None:
|
|||
|
||||
#### Final updates
|
||||
|
||||
Run the following function:
|
||||
|
||||
```python
|
||||
def process_final_updates(state: BeaconState) -> None:
|
||||
current_epoch = get_current_epoch(state)
|
||||
|
@ -1632,18 +1623,16 @@ def process_final_updates(state: BeaconState) -> None:
|
|||
state.current_epoch_attestations = []
|
||||
```
|
||||
|
||||
### Per-slot processing
|
||||
|
||||
At every `slot > GENESIS_SLOT` run the following function:
|
||||
|
||||
```python
|
||||
def advance_slot(state: BeaconState) -> None:
|
||||
state.slot += 1
|
||||
```
|
||||
|
||||
### Per-block processing
|
||||
|
||||
For every `block` except the genesis block, run `process_block_header(state, block)`, `process_randao(state, block)` and `process_eth1_data(state, block)`.
|
||||
```python
|
||||
def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
||||
process_block_header(state, block)
|
||||
process_randao(state, block)
|
||||
process_eth1_data(state, block)
|
||||
process_operations(state, block.body)
|
||||
# verify_block_state_root(state, block)
|
||||
```
|
||||
|
||||
#### Block header
|
||||
|
||||
|
@ -1691,8 +1680,6 @@ def process_eth1_data(state: BeaconState, block: BeaconBlock) -> None:
|
|||
|
||||
#### Operations
|
||||
|
||||
The sub-sections below define helper functions, one per operation type. The full processing of operations is done by running `process_operations(state, block.body)`.
|
||||
|
||||
```python
|
||||
def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
||||
assert len(body.deposits) == min(MAX_DEPOSITS, state.latest_eth1_data.deposit_count - state.deposit_index)
|
||||
|
@ -1913,8 +1900,6 @@ def process_transfer(state: BeaconState, transfer: Transfer) -> None:
|
|||
|
||||
#### State root verification
|
||||
|
||||
Verify the block's `state_root` by running the following function:
|
||||
|
||||
```python
|
||||
def verify_block_state_root(state: BeaconState, block: BeaconBlock) -> None:
|
||||
assert block.state_root == hash_tree_root(state)
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
from . import spec
|
||||
|
||||
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
List
|
||||
)
|
||||
|
||||
from .spec import (
|
||||
BeaconState,
|
||||
BeaconBlock,
|
||||
Slot,
|
||||
)
|
||||
|
||||
|
||||
def process_block(state: BeaconState, block: BeaconBlock, verify_state_root) -> None:
|
||||
spec.process_block_header(state, block)
|
||||
spec.process_randao(state, block)
|
||||
spec.process_eth1_data(state, block)
|
||||
spec.process_operations(state, block.body)
|
||||
if verify_state_root:
|
||||
spec.verify_block_state_root(state, block)
|
||||
|
||||
|
||||
def process_epoch_transition(state: BeaconState) -> None:
|
||||
spec.process_justification_and_finalization(state)
|
||||
spec.process_crosslinks(state)
|
||||
spec.process_rewards_and_penalties(state)
|
||||
spec.process_registry_updates(state)
|
||||
spec.process_slashings(state)
|
||||
spec.process_final_updates(state)
|
||||
|
||||
|
||||
def state_transition_to(state: BeaconState, up_to: Slot) -> BeaconState:
|
||||
while state.slot < up_to:
|
||||
spec.cache_state(state)
|
||||
if (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0:
|
||||
process_epoch_transition(state)
|
||||
spec.advance_slot(state)
|
||||
|
||||
|
||||
def state_transition(state: BeaconState,
|
||||
block: BeaconBlock,
|
||||
verify_state_root: bool=False) -> BeaconState:
|
||||
state_transition_to(state, block.slot)
|
||||
process_block(state, block, verify_state_root)
|
|
@ -3,13 +3,11 @@ import pytest
|
|||
|
||||
import eth2spec.phase0.spec as spec
|
||||
|
||||
from eth2spec.phase0.state_transition import (
|
||||
state_transition,
|
||||
)
|
||||
from eth2spec.phase0.spec import (
|
||||
get_current_epoch,
|
||||
process_attestation,
|
||||
slot_to_epoch,
|
||||
state_transition,
|
||||
)
|
||||
from tests.helpers import (
|
||||
build_empty_block_for_next_slot,
|
||||
|
|
|
@ -5,10 +5,10 @@ import pytest
|
|||
from eth2spec.phase0.spec import (
|
||||
get_beacon_proposer_index,
|
||||
cache_state,
|
||||
advance_slot,
|
||||
process_block_header,
|
||||
)
|
||||
from tests.helpers import (
|
||||
advance_slot,
|
||||
build_empty_block_for_next_slot,
|
||||
next_slot,
|
||||
)
|
||||
|
|
|
@ -3,13 +3,11 @@ import pytest
|
|||
|
||||
import eth2spec.phase0.spec as spec
|
||||
|
||||
from eth2spec.phase0.state_transition import (
|
||||
state_transition,
|
||||
)
|
||||
from eth2spec.phase0.spec import (
|
||||
cache_state,
|
||||
get_crosslink_deltas,
|
||||
process_crosslinks,
|
||||
state_transition,
|
||||
)
|
||||
from tests.helpers import (
|
||||
add_attestation_to_state,
|
||||
|
|
|
@ -2,9 +2,6 @@ from copy import deepcopy
|
|||
|
||||
from py_ecc import bls
|
||||
|
||||
from eth2spec.phase0.state_transition import (
|
||||
state_transition,
|
||||
)
|
||||
import eth2spec.phase0.spec as spec
|
||||
from eth2spec.utils.minimal_ssz import signing_root
|
||||
from eth2spec.phase0.spec import (
|
||||
|
@ -38,6 +35,7 @@ from eth2spec.phase0.spec import (
|
|||
get_shard_delta,
|
||||
hash_tree_root,
|
||||
slot_to_epoch,
|
||||
state_transition,
|
||||
verify_merkle_branch,
|
||||
hash,
|
||||
)
|
||||
|
@ -53,6 +51,10 @@ pubkeys = [bls.privtopub(privkey) for privkey in privkeys]
|
|||
pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)}
|
||||
|
||||
|
||||
def advance_slot(state) -> None:
|
||||
state.slot += 1
|
||||
|
||||
|
||||
def get_balance(state, index):
|
||||
return state.balances[index]
|
||||
|
||||
|
|
|
@ -4,9 +4,6 @@ import pytest
|
|||
|
||||
import eth2spec.phase0.spec as spec
|
||||
|
||||
from eth2spec.phase0.state_transition import (
|
||||
state_transition,
|
||||
)
|
||||
from .helpers import (
|
||||
build_empty_block_for_next_slot,
|
||||
fill_aggregate_attestation,
|
||||
|
@ -67,7 +64,7 @@ def next_epoch_with_attestations(state,
|
|||
fill_aggregate_attestation(post_state, prev_attestation)
|
||||
block.body.attestations.append(prev_attestation)
|
||||
|
||||
state_transition(post_state, block)
|
||||
spec.state_transition(post_state, block)
|
||||
blocks.append(block)
|
||||
|
||||
return state, blocks, post_state
|
||||
|
|
|
@ -20,13 +20,10 @@ from eth2spec.phase0.spec import (
|
|||
get_state_root,
|
||||
get_current_epoch,
|
||||
get_domain,
|
||||
advance_slot,
|
||||
cache_state,
|
||||
verify_merkle_branch,
|
||||
hash,
|
||||
)
|
||||
from eth2spec.phase0.state_transition import (
|
||||
state_transition,
|
||||
hash,
|
||||
)
|
||||
from eth2spec.utils.merkle_minimal import (
|
||||
calc_merkle_tree_from_leaves,
|
||||
|
@ -34,6 +31,7 @@ from eth2spec.utils.merkle_minimal import (
|
|||
get_merkle_root,
|
||||
)
|
||||
from .helpers import (
|
||||
advance_slot,
|
||||
get_balance,
|
||||
build_deposit_data,
|
||||
build_empty_block_for_next_slot,
|
||||
|
|
Loading…
Reference in New Issue