-
Notifications
You must be signed in to change notification settings - Fork 996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add max epoch activation churn limit (EIP-7514) to Deneb #3499
Merged
Merged
Changes from 3 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
e6f7c99
Add limit inbound churn
dapplion fd37ffc
Add _features/eip7668 and make linter happy
hwwhww cc3ced5
Enable eip7668 pytest
hwwhww 298a630
review PR
dapplion 417b95c
Add basic activation churn limit tests
hwwhww 8878a31
Fix test_process_voluntary_exit.py
hwwhww 28286e7
Fix tests
hwwhww 19bf51d
Rename eip7668 to eip7514
dapplion a56c4d0
add extension
dapplion f165d39
Update mainnet.yaml
dapplion 0efd778
Update beacon_chain.md
dapplion e5e50e3
Add EIP-7514 into Deneb
hwwhww 26d3fa3
Apply suggestions from code review
hwwhww e804174
Apply PR feedback. Rename `inbound_limit` to `activation_limit`
hwwhww 264dfad
Merge branch 'dev' into pr3499
hwwhww File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
DENEB = 'deneb' | ||
EIP6110 = 'eip6110' | ||
EIP7002 = 'eip7002' | ||
EIP7668 = 'eip7668' | ||
WHISK = 'whisk' | ||
|
||
|
||
|
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,12 @@ | ||
from .base import BaseSpecBuilder | ||
from ..constants import EIP7668 | ||
|
||
|
||
class EIP7668SpecBuilder(BaseSpecBuilder): | ||
fork: str = EIP7668 | ||
|
||
@classmethod | ||
def imports(cls, preset_name: str): | ||
return super().imports(preset_name) + f''' | ||
from eth2spec.capella import {preset_name} as capella | ||
''' |
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,88 @@ | ||
Limit churn -- 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 --> | ||
|
||
- [Introduction](#introduction) | ||
- [Configuration](#configuration) | ||
- [Validator cycle](#validator-cycle) | ||
- [Helper functions](#helper-functions) | ||
- [Beacon state accessors](#beacon-state-accessors) | ||
- [New `get_validator_inbound_churn_limit`](#new-get_validator_inbound_churn_limit) | ||
- [Beacon chain state transition function](#beacon-chain-state-transition-function) | ||
- [Epoch processing](#epoch-processing) | ||
- [Registry updates](#registry-updates) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- /TOC --> | ||
|
||
## Introduction | ||
|
||
This is the beacon chain specification to limit the max inbound churn value, motivated to limit the validator active set growth rate. | ||
|
||
*Note:* This specification is built upon [Capella](../../capella/beacon_chain.md) and is under active development. | ||
|
||
## Configuration | ||
|
||
### Validator cycle | ||
|
||
| Name | Value | | ||
| - | - | | ||
| `MAX_PER_EPOCH_INBOUND_CHURN_LIMIT` | `uint64(12)` (= 12) | | ||
|
||
## Helper functions | ||
|
||
### Beacon state accessors | ||
|
||
#### New `get_validator_inbound_churn_limit` | ||
|
||
```python | ||
def get_validator_inbound_churn_limit(state: BeaconState) -> uint64: | ||
""" | ||
Return the validator inbound churn limit for the current epoch. | ||
""" | ||
active_validator_indices = get_active_validator_indices(state, get_current_epoch(state)) | ||
return min( | ||
MAX_PER_EPOCH_INBOUND_CHURN_LIMIT, | ||
max( | ||
dapplion marked this conversation as resolved.
Show resolved
Hide resolved
|
||
MIN_PER_EPOCH_CHURN_LIMIT, | ||
uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT, | ||
), | ||
) | ||
``` | ||
|
||
## Beacon chain state transition function | ||
|
||
### Epoch processing | ||
|
||
#### Registry updates | ||
|
||
dapplion marked this conversation as resolved.
Show resolved
Hide resolved
|
||
```python | ||
def process_registry_updates(state: BeaconState) -> None: | ||
# Process activation eligibility and ejections | ||
for index, validator in enumerate(state.validators): | ||
if is_eligible_for_activation_queue(validator): | ||
validator.activation_eligibility_epoch = get_current_epoch(state) + 1 | ||
|
||
if ( | ||
is_active_validator(validator, get_current_epoch(state)) | ||
and validator.effective_balance <= EJECTION_BALANCE | ||
): | ||
initiate_validator_exit(state, ValidatorIndex(index)) | ||
|
||
# Queue validators eligible for activation and not yet dequeued for activation | ||
activation_queue = sorted([ | ||
index for index, validator in enumerate(state.validators) | ||
if is_eligible_for_activation(state, validator) | ||
# Order by the sequence of activation_eligibility_epoch setting and then index | ||
], key=lambda index: (state.validators[index].activation_eligibility_epoch, index)) | ||
# Dequeued validators for activation up to churn limit | ||
# [Modified in limit churn] | ||
dapplion marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for index in activation_queue[:get_validator_inbound_churn_limit(state)]: | ||
validator = state.validators[index] | ||
validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) | ||
``` | ||
|
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,139 @@ | ||
# EIP-7668 -- Fork Logic | ||
|
||
**Notice**: This document is a work-in-progress for researchers and implementers. | ||
|
||
## 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 --> | ||
|
||
- [Introduction](#introduction) | ||
- [Configuration](#configuration) | ||
- [Helper functions](#helper-functions) | ||
- [Misc](#misc) | ||
- [Modified `compute_fork_version`](#modified-compute_fork_version) | ||
- [Fork to EIP-7668](#fork-to-eip-7668) | ||
- [Fork trigger](#fork-trigger) | ||
- [Upgrading the state](#upgrading-the-state) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
||
## Introduction | ||
|
||
This document describes the process of EIP-7668 upgrade. | ||
|
||
## Configuration | ||
|
||
Warning: this configuration is not definitive. | ||
|
||
| Name | Value | | ||
| - | - | | ||
| `EIP7668_FORK_VERSION` | `Version('0x05000000')` | | ||
| `EIP7668_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** | | ||
|
||
## Helper functions | ||
|
||
### Misc | ||
|
||
#### Modified `compute_fork_version` | ||
|
||
```python | ||
def compute_fork_version(epoch: Epoch) -> Version: | ||
""" | ||
Return the fork version at the given ``epoch``. | ||
""" | ||
if epoch >= EIP7668_FORK_EPOCH: | ||
return EIP7668_FORK_VERSION | ||
if epoch >= CAPELLA_FORK_EPOCH: | ||
return CAPELLA_FORK_VERSION | ||
if epoch >= BELLATRIX_FORK_EPOCH: | ||
return BELLATRIX_FORK_VERSION | ||
if epoch >= ALTAIR_FORK_EPOCH: | ||
return ALTAIR_FORK_VERSION | ||
return GENESIS_FORK_VERSION | ||
``` | ||
|
||
## Fork to EIP-7668 | ||
|
||
### Fork trigger | ||
|
||
TBD. This fork is defined for testing purposes, the EIP may be combined with other consensus-layer upgrade. | ||
For now, we assume the condition will be triggered at epoch `EIP7668_FORK_EPOCH`. | ||
|
||
Note that for the pure EIP-7668 networks, we don't apply `upgrade_to_eip7668` since it starts with EIP-7668 version logic. | ||
|
||
### Upgrading the state | ||
|
||
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == EIP7668_FORK_EPOCH`, | ||
an irregular state change is made to upgrade to EIP-7668. | ||
|
||
```python | ||
def upgrade_to_eip7668(pre: capella.BeaconState) -> BeaconState: | ||
epoch = capella.get_current_epoch(pre) | ||
latest_execution_payload_header = ExecutionPayloadHeader( | ||
parent_hash=pre.latest_execution_payload_header.parent_hash, | ||
fee_recipient=pre.latest_execution_payload_header.fee_recipient, | ||
state_root=pre.latest_execution_payload_header.state_root, | ||
receipts_root=pre.latest_execution_payload_header.receipts_root, | ||
logs_bloom=pre.latest_execution_payload_header.logs_bloom, | ||
prev_randao=pre.latest_execution_payload_header.prev_randao, | ||
block_number=pre.latest_execution_payload_header.block_number, | ||
gas_limit=pre.latest_execution_payload_header.gas_limit, | ||
gas_used=pre.latest_execution_payload_header.gas_used, | ||
timestamp=pre.latest_execution_payload_header.timestamp, | ||
extra_data=pre.latest_execution_payload_header.extra_data, | ||
base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas, | ||
block_hash=pre.latest_execution_payload_header.block_hash, | ||
transactions_root=pre.latest_execution_payload_header.transactions_root, | ||
withdrawals_root=pre.latest_execution_payload_header.withdrawals_root, | ||
) | ||
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=EIP7668_FORK_VERSION, # [Modified in EIP-7668] | ||
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=latest_execution_payload_header, | ||
# Withdrawals | ||
next_withdrawal_index=pre.next_withdrawal_index, | ||
next_withdrawal_validator_index=pre.next_withdrawal_validator_index, | ||
# Deep history valid from Capella onwards | ||
historical_summaries=pre.historical_summaries, | ||
) | ||
|
||
return post | ||
``` |
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would like to examine lower values here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I projected different levels of ETH staked for each constant and activation time. ethereum/EIPs#7668
What other reasoning do you propose to inform the decision for a specific lower value? Lower values will increase the effectiveness of this feature, but may raise more fairness concerns. I haven't found a strong framework to inform the decision of a specific value