Skip to content

Commit

Permalink
implement EIP-7514 for Deneb: Add Max Epoch Churn Limit (#5442)
Browse files Browse the repository at this point in the history
* implement EIP-7514 for Deneb: Add Max Epoch Churn Limit

Cap activations per epoch according to EIP-7514:

- https://eips.ethereum.org/EIPS/eip-7514
- ethereum/consensus-specs#3499

* apply proposer boost to first block in case of equivocation

Implement spec changes to fork choice; this only affects equivocation
when multiple blocks are signed for the same slot. Regular operation
is not changed.

- ethereum/consensus-specs#3352

* bump test vectors to v1.4.0-beta.2-hotfix

---------

Co-authored-by: tersec <[email protected]>
  • Loading branch information
etan-status and tersec authored Sep 20, 2023
1 parent aacb853 commit 273f1d3
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 16 deletions.
13 changes: 11 additions & 2 deletions ConsensusSpecPreset-mainnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -2829,6 +2829,7 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK
ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_bloc OK
+ ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_slo OK
+ ForkChoice - mainnet/bellatrix/fork_choice/ex_ante/pyspec_tests/ex_ante_attestations_is_gr OK
+ ForkChoice - mainnet/bellatrix/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_boos OK
Expand All @@ -2845,6 +2846,7 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK
ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_b OK
+ ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_ OK
ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/all_valid Skip
ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/block_lookup_failed Skip
Expand All @@ -2865,6 +2867,7 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK
ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_blo OK
+ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_sl OK
+ ForkChoice - mainnet/deneb/fork_choice/ex_ante/pyspec_tests/ex_ante_attestations_is_greate OK
+ ForkChoice - mainnet/deneb/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_boost_no OK
Expand All @@ -2878,12 +2881,18 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - mainnet/deneb/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_wei OK
+ ForkChoice - mainnet/deneb/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attestat OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/basic OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/invalid_data_unavailable OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/invalid_incorrect_proof OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/invalid_wrong_blobs_length OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/invalid_wrong_proofs_length OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK
ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_block OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_slot OK
+ ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/simple_blob_data OK
```
OK: 60/68 Fail: 0/68 Skip: 8/68
OK: 69/77 Fail: 0/77 Skip: 8/77
## Sync
```diff
+ Sync - mainnet/bellatrix/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK
Expand All @@ -2893,4 +2902,4 @@ OK: 60/68 Fail: 0/68 Skip: 8/68
OK: 3/3 Fail: 0/3 Skip: 0/3

---TOTAL---
OK: 2327/2335 Fail: 0/2335 Skip: 8/2335
OK: 2336/2344 Fail: 0/2344 Skip: 8/2344
18 changes: 15 additions & 3 deletions ConsensusSpecPreset-minimal.md
Original file line number Diff line number Diff line change
Expand Up @@ -1873,6 +1873,9 @@ OK: 12/12 Fail: 0/12 Skip: 0/12
OK: 1/1 Fail: 0/1 Skip: 0/1
## EF - Deneb - Epoch Processing - Registry updates [Preset: minimal]
```diff
+ Registry updates - activation_churn_limit__equal_to_activation_limit [Preset: minimal] OK
+ Registry updates - activation_churn_limit__greater_than_activation_limit [Preset: minimal] OK
+ Registry updates - activation_churn_limit__less_than_activation_limit [Preset: minimal] OK
+ Registry updates - activation_queue_activation_and_ejection__1 [Preset: minimal] OK
+ Registry updates - activation_queue_activation_and_ejection__churn_limit [Preset: minimal] OK
+ Registry updates - activation_queue_activation_and_ejection__exceed_churn_limit [Preset: m OK
Expand All @@ -1889,7 +1892,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ Registry updates - ejection_past_churn_limit_scaled [Preset: minimal] OK
+ Registry updates - invalid_large_withdrawable_epoch [Preset: minimal] OK
```
OK: 15/15 Fail: 0/15 Skip: 0/15
OK: 18/18 Fail: 0/18 Skip: 0/18
## EF - Deneb - Epoch Processing - Rewards and penalties [Preset: minimal]
```diff
+ Rewards and penalties - almost_empty_attestations [Preset: minimal] OK
Expand Down Expand Up @@ -2993,6 +2996,7 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slot OK
ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_bloc OK
+ ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_slo OK
+ ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/pull_up_on_tick OK
+ ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/pull_up_past_epoch_block OK
Expand Down Expand Up @@ -3038,6 +3042,7 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_s OK
ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_b OK
+ ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_ OK
+ ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/pull_up_on_tick OK
+ ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/pull_up_past_epoch_block OK
Expand Down Expand Up @@ -3087,6 +3092,7 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slo OK
ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_blo OK
+ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_sl OK
+ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/pull_up_on_tick OK
+ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/pull_up_past_epoch_block OK
Expand Down Expand Up @@ -3116,6 +3122,10 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/basic OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/incompatible_justification_up OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/incompatible_justification_up OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/invalid_data_unavailable OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/invalid_incorrect_proof OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/invalid_wrong_blobs_length OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/invalid_wrong_proofs_length OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/justification_update_beginnin OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/justification_update_end_of_e OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/justification_withholding OK
Expand All @@ -3132,9 +3142,11 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slots OK
ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/proposer_boost OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_block OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_slot OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/pull_up_on_tick OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/pull_up_past_epoch_block OK
+ ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/simple_blob_data OK
+ ForkChoice - minimal/deneb/fork_choice/reorg/pyspec_tests/delayed_justification_current_ep OK
+ ForkChoice - minimal/deneb/fork_choice/reorg/pyspec_tests/delayed_justification_previous_e OK
+ ForkChoice - minimal/deneb/fork_choice/reorg/pyspec_tests/include_votes_another_empty_chai OK
Expand All @@ -3146,7 +3158,7 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ForkChoice - minimal/deneb/fork_choice/withholding/pyspec_tests/withholding_attack OK
+ ForkChoice - minimal/deneb/fork_choice/withholding/pyspec_tests/withholding_attack_unviabl OK
```
OK: 176/184 Fail: 0/184 Skip: 8/184
OK: 185/193 Fail: 0/193 Skip: 8/193
## Sync
```diff
+ Sync - minimal/bellatrix/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK
Expand All @@ -3156,4 +3168,4 @@ OK: 176/184 Fail: 0/184 Skip: 8/184
OK: 3/3 Fail: 0/3 Skip: 0/3

---TOTAL---
OK: 2566/2574 Fail: 0/2574 Skip: 8/2574
OK: 2578/2586 Fail: 0/2586 Skip: 8/2586
4 changes: 3 additions & 1 deletion beacon_chain/fork_choice/fork_choice.nim
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,9 @@ proc process_block*(self: var ForkChoice,

# Add proposer score boost if the block is timely
let slot = self.checkpoints.time.slotOrZero
if slot == blck.slot and self.checkpoints.time < slot.attestation_deadline:
if slot == blck.slot and
self.checkpoints.time < slot.attestation_deadline and
self.checkpoints.proposer_boost_root == ZERO_HASH:
self.checkpoints.proposer_boost_root = blckRef.root

# Update checkpoints in store if necessary
Expand Down
2 changes: 2 additions & 0 deletions beacon_chain/rpc/rest_config_api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) =
Base10.toString(cfg.MIN_PER_EPOCH_CHURN_LIMIT),
CHURN_LIMIT_QUOTIENT:
Base10.toString(cfg.CHURN_LIMIT_QUOTIENT),
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT:
Base10.toString(cfg.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT),
PROPOSER_SCORE_BOOST:
Base10.toString(PROPOSER_SCORE_BOOST),
DEPOSIT_CHAIN_ID:
Expand Down
9 changes: 9 additions & 0 deletions beacon_chain/spec/beaconstate.nim
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ func get_validator_churn_limit*(
count_active_validators(
state, state.get_current_epoch(), cache) div cfg.CHURN_LIMIT_QUOTIENT)

# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/beacon-chain.md#new-get_validator_activation_churn_limit
func get_validator_activation_churn_limit*(
cfg: RuntimeConfig, state: deneb.BeaconState, cache: var StateCache):
uint64 =
## Return the validator activation churn limit for the current epoch.
min(
cfg.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT,
get_validator_churn_limit(cfg, state, cache))

# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/beacon-chain.md#initiate_validator_exit
func initiate_validator_exit*(
cfg: RuntimeConfig, state: var ForkyBeaconState,
Expand Down
2 changes: 1 addition & 1 deletion beacon_chain/spec/datatypes/base.nim
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export
tables, results, json_serialization, timer, sszTypes, beacon_time, crypto,
digest, presets

const SPEC_VERSION* = "1.4.0-beta.1"
const SPEC_VERSION* = "1.4.0-beta.2-hotfix"
## Spec version we're aiming to be compatible with, right now

const
Expand Down
13 changes: 9 additions & 4 deletions beacon_chain/spec/presets.nim
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type
EJECTION_BALANCE*: uint64
MIN_PER_EPOCH_CHURN_LIMIT*: uint64
CHURN_LIMIT_QUOTIENT*: uint64
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT*: uint64

# Fork choice
# TODO PROPOSER_SCORE_BOOST*: uint64
Expand Down Expand Up @@ -194,7 +195,8 @@ when const_preset == "mainnet":
MIN_PER_EPOCH_CHURN_LIMIT: 4,
# 2**16 (= 65,536)
CHURN_LIMIT_QUOTIENT: 65536,

# [New in Deneb:EIP7514] 2**3 (= 8)
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8,

# Deposit contract
# ---------------------------------------------------------------
Expand Down Expand Up @@ -299,7 +301,8 @@ elif const_preset == "gnosis":
MIN_PER_EPOCH_CHURN_LIMIT: 4,
# 2**16 (= 65,536)
CHURN_LIMIT_QUOTIENT: 4096,

# [New in Deneb:EIP7514] 2**3 (= 8)
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8,

# Deposit contract
# ---------------------------------------------------------------
Expand Down Expand Up @@ -395,10 +398,12 @@ elif const_preset == "minimal":
INACTIVITY_SCORE_RECOVERY_RATE: 16,
# 2**4 * 10**9 (= 16,000,000,000) Gwei
EJECTION_BALANCE: 16000000000'u64,
# 2**2 (= 4)
MIN_PER_EPOCH_CHURN_LIMIT: 4,
# [customized] more easily demonstrate the difference between this value and the activation churn limit
MIN_PER_EPOCH_CHURN_LIMIT: 2,
# [customized] scale queue churn at much lower validator counts for testing
CHURN_LIMIT_QUOTIENT: 32,
# [New in Deneb:EIP7514] [customized]
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 4,


# Deposit contract
Expand Down
10 changes: 7 additions & 3 deletions beacon_chain/spec/state_transition_epoch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,11 @@ func process_registry_updates*(

## Queue validators eligible for activation and not dequeued for activation
var activation_queue: HeapQueue[(uint64, uint32)]
let churn_limit = get_validator_churn_limit(cfg, state, cache)
let churn_limit =
when typeof(state).toFork >= ConsensusFork.Deneb:
get_validator_activation_churn_limit(cfg, state, cache)
else:
get_validator_churn_limit(cfg, state, cache)
for vidx in state.validators.vindices:
if is_eligible_for_activation_queue(state.validators.item(vidx)):
state.validators.mitem(vidx).activation_eligibility_epoch =
Expand All @@ -859,8 +863,8 @@ func process_registry_updates*(
elif val_key > activation_queue[0]:
discard activation_queue.replace val_key

## Dequeued validators for activation up to churn limit (without resetting
## activation epoch)
## Dequeued validators for activation up to activation churn limit
## (without resetting activation epoch)
doAssert activation_queue.len.uint64 <= churn_limit
for i in 0 ..< activation_queue.len:
let (_, vidx_complement) = activation_queue[i]
Expand Down
Loading

0 comments on commit 273f1d3

Please sign in to comment.