-
Notifications
You must be signed in to change notification settings - Fork 997
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
12,634 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
# Cappela -- The Beacon Chain | ||
|
||
## Table of contents | ||
|
||
<!-- TOC --> | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- /TOC --> | ||
|
||
## Introduction | ||
|
||
Cappela is a consensus-layer upgrade containin a number of features related | ||
to validator withdrawals. Including: | ||
* Automatic withdrawals of `withdrawable` validators | ||
* Partial withdrawals during block proposal | ||
* Operation to change from `BLS_WITHDRAWAL_PREFIX` to | ||
`ETH1_ADDRESS_WITHDRAWAL_PREFIX` versioned withdrawal credentials to enable withdrawals for a validator | ||
|
||
## Custom types | ||
|
||
| Name | SSZ equivalent | Description | | ||
| - | - | - | | ||
| `WithdrawalReceiptIndex` | `uint64` | a withdrawal receipt index | | ||
|
||
## Constants | ||
|
||
## Preset | ||
|
||
### State list lengths | ||
|
||
| Name | Value | Unit | Duration | | ||
| - | - | :-: | :-: | | ||
| `WITHDRAWAL_RECEIPT_LIMIT` | `uint64(2**40)` (= 1,099,511,627,776) | withdrawal receipts| | ||
|
||
## Configuration | ||
|
||
## Containers | ||
|
||
### Extended Containers | ||
|
||
#### `BeaconState` | ||
|
||
```python | ||
class BeaconState(Container): | ||
# Versioning | ||
genesis_time: uint64 | ||
genesis_validators_root: Root | ||
slot: Slot | ||
fork: Fork | ||
# History | ||
latest_block_header: BeaconBlockHeader | ||
block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] | ||
state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] | ||
historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] | ||
# Eth1 | ||
eth1_data: Eth1Data | ||
eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] | ||
eth1_deposit_index: uint64 | ||
# Registry | ||
validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] | ||
balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] | ||
# Randomness | ||
randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] | ||
# Slashings | ||
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances | ||
# Participation | ||
previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] | ||
current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] | ||
# Finality | ||
justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch | ||
previous_justified_checkpoint: Checkpoint | ||
current_justified_checkpoint: Checkpoint | ||
finalized_checkpoint: Checkpoint | ||
# Inactivity | ||
inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] | ||
# Sync | ||
current_sync_committee: SyncCommittee | ||
next_sync_committee: SyncCommittee | ||
# Execution | ||
latest_execution_payload_header: ExecutionPayloadHeader | ||
# Withdrawals | ||
withdrawal_receipts: List[WithdrawalReceipt, WITHDRAWAL_RECEIPT_LIMIT] # [New in Cappela] | ||
``` | ||
|
||
### New containers | ||
|
||
#### `WithdrawalReceipt` | ||
|
||
```python | ||
class WithdrawalReceipt(Container): | ||
index: WithdrawalReceiptIndex | ||
address: ExecutionAddress | ||
amount: Gwei | ||
``` | ||
|
||
## Helpers | ||
|
||
### Beacon state mutators | ||
|
||
#### `withdraw` | ||
|
||
```python | ||
def withdraw(state: BeaconState, index: ValidatorIndex, amount: Gwei) -> None: | ||
# Decrease the validator's balance | ||
decrease_balance(state, index, amount) | ||
# Create a corresponding withdrawal receipt | ||
receipt = WithdrawalReceipt( | ||
index=WithdrawalReceiptIndex(len(state.withdrawal_receipts)), | ||
address=state.validators[index].withdrawal_credentials[12:], | ||
amount=amount, | ||
) | ||
state.withdrawal_receipts.append(receipt) | ||
``` | ||
|
||
### Predicates | ||
|
||
#### `is_withdrawable_validator` | ||
|
||
```python | ||
def is_withdrawable_validator(validator: Validator, epoch: Epoch) -> bool: | ||
""" | ||
Check if ``validator`` is withdrawable. | ||
""" | ||
return validator.withdrawable_epoch <= epoch | ||
``` | ||
|
||
## Beacon chain state transition function | ||
|
||
### Epoch processing | ||
|
||
```python | ||
def process_epoch(state: BeaconState) -> None: | ||
process_justification_and_finalization(state) | ||
process_inactivity_updates(state) | ||
process_rewards_and_penalties(state) | ||
process_registry_updates(state) | ||
process_slashings(state) | ||
process_eth1_data_reset(state) | ||
process_effective_balance_updates(state) | ||
process_slashings_reset(state) | ||
process_randao_mixes_reset(state) | ||
process_historical_roots_update(state) | ||
process_participation_flag_updates(state) | ||
process_sync_committee_updates(state) | ||
process_withdrawals(state) # [New in Cappela] | ||
``` | ||
|
||
#### Withdrawals | ||
|
||
*Note*: The function `process_inactivity_updates` is new. | ||
|
||
```python | ||
def process_withdrawals(state: BeaconState) -> None: | ||
current_epoch = get_current_epoch(state) | ||
for index, validator in enumerate(state.validators): | ||
balance = state.balances[index] | ||
is_balance_nonzero = state.balances[index] == 0 | ||
is_eth1_withdrawal_prefix = validator.withdrawal_credentials[0] != ETH1_ADDRESS_WITHDRAWAL_PREFIX | ||
if is_balance_nonzero and is_eth1_withdrawal_prefix and is_withdrawable_validator(validator, current_epoch): | ||
withdraw(state, ValidatorIndex(index), balance) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Capella -- Fork Logic | ||
|
||
## Table of contents | ||
|
||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
||
## Introduction | ||
|
||
This document describes the process of the Capella upgrade. | ||
|
||
## Configuration | ||
|
||
Warning: this configuration is not definitive. | ||
|
||
| Name | Value | | ||
| - | - | | ||
| `CAPELLA_FORK_VERSION` | `Version('0x03000000')` | | ||
| `CAPELLA_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** | | ||
|
||
|
||
## Fork to Capella | ||
|
||
### Fork trigger | ||
|
||
The fork is triggered at epoch `CAPELLA_FORK_EPOCH`. | ||
|
||
Note that for the pure Capella networks, we don't apply `upgrade_to_capella` since it starts with Capella version logic. | ||
|
||
### Upgrading the state | ||
|
||
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == CAPELLA_FORK_EPOCH`, | ||
an irregular state change is made to upgrade to Capella. | ||
|
||
The upgrade occurs after the completion of the inner loop of `process_slots` that sets `state.slot` equal to `CAPELLA_FORK_EPOCH * SLOTS_PER_EPOCH`. | ||
Care must be taken when transitioning through the fork boundary as implementations will need a modified [state transition function](../phase0/beacon-chain.md#beacon-chain-state-transition-function) that deviates from the Phase 0 document. | ||
In particular, the outer `state_transition` function defined in the Phase 0 document will not expose the precise fork slot to execute the upgrade in the presence of skipped slots at the fork boundary. Instead the logic must be within `process_slots`. | ||
|
||
```python | ||
def upgrade_to_capella(pre: merge.BeaconState) -> BeaconState: | ||
epoch = merge.get_current_epoch(pre) | ||
post = BeaconState( | ||
# Versioning | ||
genesis_time=pre.genesis_time, | ||
genesis_validators_root=pre.genesis_validators_root, | ||
slot=pre.slot, | ||
fork=Fork( | ||
previous_version=pre.fork.current_version, | ||
current_version=CAPELLA_FORK_VERSION, | ||
epoch=epoch, | ||
), | ||
# History | ||
latest_block_header=pre.latest_block_header, | ||
block_roots=pre.block_roots, | ||
state_roots=pre.state_roots, | ||
historical_roots=pre.historical_roots, | ||
# Eth1 | ||
eth1_data=pre.eth1_data, | ||
eth1_data_votes=pre.eth1_data_votes, | ||
eth1_deposit_index=pre.eth1_deposit_index, | ||
# Registry | ||
validators=pre.validators, | ||
balances=pre.balances, | ||
# Randomness | ||
randao_mixes=pre.randao_mixes, | ||
# Slashings | ||
slashings=pre.slashings, | ||
# Participation | ||
previous_epoch_participation=pre.previous_epoch_participation, | ||
current_epoch_participation=pre.current_epoch_participation, | ||
# Finality | ||
justification_bits=pre.justification_bits, | ||
previous_justified_checkpoint=pre.previous_justified_checkpoint, | ||
current_justified_checkpoint=pre.current_justified_checkpoint, | ||
finalized_checkpoint=pre.finalized_checkpoint, | ||
# Inactivity | ||
inactivity_scores=pre.inactivity_scores, | ||
# Sync | ||
current_sync_committee=pre.current_sync_committee, | ||
next_sync_committee=pre.next_sync_committee, | ||
# Execution-layer | ||
latest_execution_payload_header=pre.latest_execution_payload_header, | ||
# Withdrawals | ||
withdrawal_receipts=[], | ||
) | ||
|
||
return post | ||
``` |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import mainnet as spec # noqa:F401 |
Oops, something went wrong.