Electra spec changes for v1.5.0-beta.0 (#6731)

* First pass

* Add restrictions to RuntimeVariableList api

* Use empty_uninitialized and fix warnings

* Fix some todos

* Merge branch 'unstable' into max-blobs-preset

* Fix take impl on RuntimeFixedList

* cleanup

* Fix test compilations

* Fix some more tests

* Fix test from unstable

* Merge branch 'unstable' into max-blobs-preset

* Implement "Bugfix and more withdrawal tests"

* Implement "Add missed exit checks to consolidation processing"

* Implement "Update initial earliest_exit_epoch calculation"

* Implement "Limit consolidating balance by validator.effective_balance"

* Implement "Use 16-bit random value in validator filter"

* Implement "Do not change creds type on consolidation"

* Rename PendingPartialWithdraw index field to validator_index

* Skip slots to get test to pass and add TODO

* Implement "Synchronously check all transactions to have non-zero length"

* Merge remote-tracking branch 'origin/unstable' into max-blobs-preset

* Remove footgun function

* Minor simplifications

* Move from preset to config

* Fix typo

* Revert "Remove footgun function"

This reverts commit de01f923c7.

* Try fixing tests

* Implement "bump minimal preset MAX_BLOB_COMMITMENTS_PER_BLOCK and KZG_COMMITMENT_INCLUSION_PROOF_DEPTH"

* Thread through ChainSpec

* Fix release tests

* Move RuntimeFixedVector into module and rename

* Add test

* Implement "Remove post-altair `initialize_beacon_state_from_eth1` from specs"

* Update preset YAML

* Remove empty RuntimeVarList awefullness

* Make max_blobs_per_block a config parameter (#6329)

Squashed commit of the following:

commit 04b3743ec1
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 17:36:58 2025 +1100

    Add test

commit 440e854199
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 17:24:50 2025 +1100

    Move RuntimeFixedVector into module and rename

commit f66e179a40
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 17:17:17 2025 +1100

    Fix release tests

commit e4bfe71cd1
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 17:05:30 2025 +1100

    Thread through ChainSpec

commit 063b79c16a
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 15:32:16 2025 +1100

    Try fixing tests

commit 88bedf09bc
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 15:04:37 2025 +1100

    Revert "Remove footgun function"

    This reverts commit de01f923c7.

commit 32483d385b
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 15:04:32 2025 +1100

    Fix typo

commit 2e86585b47
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 15:04:15 2025 +1100

    Move from preset to config

commit 1095d60a40
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 14:38:40 2025 +1100

    Minor simplifications

commit de01f923c7
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 14:06:57 2025 +1100

    Remove footgun function

commit 0c2c8c4224
Merge: 21ecb58ff f51a292f7
Author: Michael Sproul <michael@sigmaprime.io>
Date:   Mon Jan 6 14:02:50 2025 +1100

    Merge remote-tracking branch 'origin/unstable' into max-blobs-preset

commit f51a292f77
Author: Daniel Knopik <107140945+dknopik@users.noreply.github.com>
Date:   Fri Jan 3 20:27:21 2025 +0100

    fully lint only explicitly to avoid unnecessary rebuilds (#6753)

    * fully lint only explicitly to avoid unnecessary rebuilds

commit 7e0cddef32
Author: Akihito Nakano <sora.akatsuki@gmail.com>
Date:   Tue Dec 24 10:38:56 2024 +0900

    Make sure we have fanout peers when publish (#6738)

    * Ensure that `fanout_peers` is always non-empty if it's `Some`

commit 21ecb58ff8
Merge: 2fcb2935e 9aefb5539
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Mon Oct 21 14:46:00 2024 -0700

    Merge branch 'unstable' into max-blobs-preset

commit 2fcb2935ec
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Fri Sep 6 18:28:31 2024 -0700

    Fix test from unstable

commit 12c6ef118a
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Wed Sep 4 16:16:36 2024 -0700

    Fix some more tests

commit d37733b846
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Wed Sep 4 12:47:36 2024 -0700

    Fix test compilations

commit 52bb581e07
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Tue Sep 3 18:38:19 2024 -0700

    cleanup

commit e71020e3e6
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Tue Sep 3 17:16:10 2024 -0700

    Fix take impl on RuntimeFixedList

commit 13f9bba647
Merge: 60100fc6b 4e675cf5d
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Tue Sep 3 16:08:59 2024 -0700

    Merge branch 'unstable' into max-blobs-preset

commit 60100fc6be
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Fri Aug 30 16:04:11 2024 -0700

    Fix some todos

commit a9cb329a22
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Fri Aug 30 15:54:00 2024 -0700

    Use empty_uninitialized and fix warnings

commit 4dc6e6515e
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Fri Aug 30 15:53:18 2024 -0700

    Add restrictions to RuntimeVariableList api

commit 25feedfde3
Author: Pawan Dhananjay <pawandhananjay@gmail.com>
Date:   Thu Aug 29 16:11:19 2024 -0700

    First pass

* Fix tests

* Implement max_blobs_per_block_electra

* Fix config issues

* Simplify BlobSidecarListFromRoot

* Disable PeerDAS tests

* Merge remote-tracking branch 'origin/unstable' into max-blobs-preset

* Bump quota to account for new target (6)

* Remove clone

* Fix issue from review

* Try to remove ugliness

* Merge branch 'unstable' into max-blobs-preset

* Merge remote-tracking branch 'origin/unstable' into electra-alpha10

* Merge commit '04b3743ec1e0b650269dd8e58b540c02430d1c0d' into electra-alpha10

* Merge remote-tracking branch 'pawan/max-blobs-preset' into electra-alpha10

* Update tests to v1.5.0-beta.0

* Resolve merge conflicts

* Linting

* fmt

* Fix test and add TODO

* Gracefully handle slashed proposers in fork choice tests

* Merge remote-tracking branch 'origin/unstable' into electra-alpha10

* Keep latest changes from max_blobs_per_block PR in codec.rs

* Revert a few more regressions and add a comment

* Disable more DAS tests

* Improve validator monitor test a little

* Make test more robust

* Fix sync test that didn't understand blobs

* Fill out cropped comment
This commit is contained in:
Michael Sproul
2025-01-14 10:17:00 +11:00
committed by GitHub
parent c9747fb77f
commit 06e4d22d49
29 changed files with 309 additions and 178 deletions

View File

@@ -10,6 +10,7 @@ use beacon_chain::{
use fork_choice::{
ForkChoiceStore, InvalidAttestation, InvalidBlock, PayloadVerificationStatus, QueuedAttestation,
};
use state_processing::state_advance::complete_state_advance;
use std::fmt;
use std::sync::Mutex;
use std::time::Duration;
@@ -172,6 +173,20 @@ impl ForkChoiceTest {
let validators = self.harness.get_all_validators();
loop {
let slot = self.harness.get_current_slot();
// Skip slashed proposers, as we expect validators to get slashed in these tests.
// Presently `make_block` will panic if the proposer is slashed, so we just avoid
// calling it in this case.
complete_state_advance(&mut state, None, slot, &self.harness.spec).unwrap();
state.build_caches(&self.harness.spec).unwrap();
let proposer_index = state
.get_beacon_proposer_index(slot, &self.harness.chain.spec)
.unwrap();
if state.validators().get(proposer_index).unwrap().slashed {
self.harness.advance_slot();
continue;
}
let (block_contents, state_) = self.harness.make_block(state, slot).await;
state = state_;
if !predicate(block_contents.0.message(), &state) {
@@ -196,17 +211,20 @@ impl ForkChoiceTest {
}
/// Apply `count` blocks to the chain (with attestations).
///
/// Note that in the case of slashed validators, their proposals will be skipped and the chain
/// may be advanced by *more than* `count` slots.
pub async fn apply_blocks(self, count: usize) -> Self {
self.harness.advance_slot();
self.harness
.extend_chain(
count,
BlockStrategy::OnCanonicalHead,
AttestationStrategy::AllValidators,
)
.await;
self
// Use `Self::apply_blocks_while` which gracefully handles slashed validators.
let mut blocks_applied = 0;
self.apply_blocks_while(|_, _| {
// Blocks are applied after the predicate is called, so continue applying the block if
// less than *or equal* to the count.
blocks_applied += 1;
blocks_applied <= count
})
.await
.unwrap()
}
/// Slash a validator from the previous epoch committee.
@@ -244,6 +262,7 @@ impl ForkChoiceTest {
/// Apply `count` blocks to the chain (without attestations).
pub async fn apply_blocks_without_new_attestations(self, count: usize) -> Self {
// This function does not gracefully handle slashed proposers, but may need to in future.
self.harness.advance_slot();
self.harness
.extend_chain(
@@ -1226,14 +1245,6 @@ async fn progressive_balances_cache_attester_slashing() {
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
.await
.unwrap()
// Note: This test may fail if the shuffling used changes, right now it re-runs with
// deterministic shuffling. A shuffling change my cause the slashed proposer to propose
// again in the next epoch, which results in a block processing failure
// (`HeaderInvalid::ProposerSlashed`). The harness should be re-worked to successfully skip
// the slot in this scenario rather than panic-ing. The same applies to
// `progressive_balances_cache_proposer_slashing`.
.apply_blocks(2)
.await
.add_previous_epoch_attester_slashing()
.await
// expect fork choice to import blocks successfully after a previous epoch attester is
@@ -1244,7 +1255,7 @@ async fn progressive_balances_cache_attester_slashing() {
// expect fork choice to import another epoch of blocks successfully - the slashed
// attester's balance should be excluded from the current epoch total balance in
// `ProgressiveBalancesCache` as well.
.apply_blocks(MainnetEthSpec::slots_per_epoch() as usize)
.apply_blocks(E::slots_per_epoch() as usize)
.await;
}
@@ -1257,15 +1268,7 @@ async fn progressive_balances_cache_proposer_slashing() {
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
.await
.unwrap()
// Note: This test may fail if the shuffling used changes, right now it re-runs with
// deterministic shuffling. A shuffling change may cause the slashed proposer to propose
// again in the next epoch, which results in a block processing failure
// (`HeaderInvalid::ProposerSlashed`). The harness should be re-worked to successfully skip
// the slot in this scenario rather than panic-ing. The same applies to
// `progressive_balances_cache_attester_slashing`.
.apply_blocks(1)
.await
.add_previous_epoch_proposer_slashing(MainnetEthSpec::slots_per_epoch())
.add_previous_epoch_proposer_slashing(E::slots_per_epoch())
.await
// expect fork choice to import blocks successfully after a previous epoch proposer is
// slashed, i.e. the slashed proposer's balance is correctly excluded from
@@ -1275,6 +1278,6 @@ async fn progressive_balances_cache_proposer_slashing() {
// expect fork choice to import another epoch of blocks successfully - the slashed
// proposer's balance should be excluded from the current epoch total balance in
// `ProgressiveBalancesCache` as well.
.apply_blocks(MainnetEthSpec::slots_per_epoch() as usize)
.apply_blocks(E::slots_per_epoch() as usize)
.await;
}

View File

@@ -1,7 +1,7 @@
use crate::consensus_context::ConsensusContext;
use errors::{BlockOperationError, BlockProcessingError, HeaderInvalid};
use rayon::prelude::*;
use safe_arith::{ArithError, SafeArith};
use safe_arith::{ArithError, SafeArith, SafeArithIter};
use signature_sets::{block_proposal_signature_set, get_pubkey_from_state, randao_signature_set};
use std::borrow::Cow;
use tree_hash::TreeHash;
@@ -509,7 +509,7 @@ pub fn compute_timestamp_at_slot<E: EthSpec>(
/// Compute the next batch of withdrawals which should be included in a block.
///
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md#new-get_expected_withdrawals
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/beacon-chain.md#new-get_expected_withdrawals
pub fn get_expected_withdrawals<E: EthSpec>(
state: &BeaconState<E>,
spec: &ChainSpec,
@@ -522,9 +522,9 @@ pub fn get_expected_withdrawals<E: EthSpec>(
// [New in Electra:EIP7251]
// Consume pending partial withdrawals
let partial_withdrawals_count =
let processed_partial_withdrawals_count =
if let Ok(partial_withdrawals) = state.pending_partial_withdrawals() {
let mut partial_withdrawals_count = 0;
let mut processed_partial_withdrawals_count = 0;
for withdrawal in partial_withdrawals {
if withdrawal.withdrawable_epoch > epoch
|| withdrawals.len() == spec.max_pending_partials_per_withdrawals_sweep as usize
@@ -532,8 +532,8 @@ pub fn get_expected_withdrawals<E: EthSpec>(
break;
}
let withdrawal_balance = state.get_balance(withdrawal.index as usize)?;
let validator = state.get_validator(withdrawal.index as usize)?;
let withdrawal_balance = state.get_balance(withdrawal.validator_index as usize)?;
let validator = state.get_validator(withdrawal.validator_index as usize)?;
let has_sufficient_effective_balance =
validator.effective_balance >= spec.min_activation_balance;
@@ -549,7 +549,7 @@ pub fn get_expected_withdrawals<E: EthSpec>(
);
withdrawals.push(Withdrawal {
index: withdrawal_index,
validator_index: withdrawal.index,
validator_index: withdrawal.validator_index,
address: validator
.get_execution_withdrawal_address(spec)
.ok_or(BeaconStateError::NonExecutionAddresWithdrawalCredential)?,
@@ -557,9 +557,9 @@ pub fn get_expected_withdrawals<E: EthSpec>(
});
withdrawal_index.safe_add_assign(1)?;
}
partial_withdrawals_count.safe_add_assign(1)?;
processed_partial_withdrawals_count.safe_add_assign(1)?;
}
Some(partial_withdrawals_count)
Some(processed_partial_withdrawals_count)
} else {
None
};
@@ -570,9 +570,19 @@ pub fn get_expected_withdrawals<E: EthSpec>(
);
for _ in 0..bound {
let validator = state.get_validator(validator_index as usize)?;
let balance = *state.balances().get(validator_index as usize).ok_or(
BeaconStateError::BalancesOutOfBounds(validator_index as usize),
)?;
let partially_withdrawn_balance = withdrawals
.iter()
.filter_map(|withdrawal| {
(withdrawal.validator_index == validator_index).then_some(withdrawal.amount)
})
.safe_sum()?;
let balance = state
.balances()
.get(validator_index as usize)
.ok_or(BeaconStateError::BalancesOutOfBounds(
validator_index as usize,
))?
.safe_sub(partially_withdrawn_balance)?;
if validator.is_fully_withdrawable_at(balance, epoch, spec, fork_name) {
withdrawals.push(Withdrawal {
index: withdrawal_index,
@@ -604,7 +614,7 @@ pub fn get_expected_withdrawals<E: EthSpec>(
.safe_rem(state.validators().len() as u64)?;
}
Ok((withdrawals.into(), partial_withdrawals_count))
Ok((withdrawals.into(), processed_partial_withdrawals_count))
}
/// Apply withdrawals to the state.

View File

@@ -507,11 +507,11 @@ pub fn process_withdrawal_requests<E: EthSpec>(
}
// Verify pubkey exists
let Some(index) = state.pubkey_cache().get(&request.validator_pubkey) else {
let Some(validator_index) = state.pubkey_cache().get(&request.validator_pubkey) else {
continue;
};
let validator = state.get_validator(index)?;
let validator = state.get_validator(validator_index)?;
// Verify withdrawal credentials
let has_correct_credential = validator.has_execution_withdrawal_credential(spec);
let is_correct_source_address = validator
@@ -542,16 +542,16 @@ pub fn process_withdrawal_requests<E: EthSpec>(
continue;
}
let pending_balance_to_withdraw = state.get_pending_balance_to_withdraw(index)?;
let pending_balance_to_withdraw = state.get_pending_balance_to_withdraw(validator_index)?;
if is_full_exit_request {
// Only exit validator if it has no pending withdrawals in the queue
if pending_balance_to_withdraw == 0 {
initiate_validator_exit(state, index, spec)?
initiate_validator_exit(state, validator_index, spec)?
}
continue;
}
let balance = state.get_balance(index)?;
let balance = state.get_balance(validator_index)?;
let has_sufficient_effective_balance =
validator.effective_balance >= spec.min_activation_balance;
let has_excess_balance = balance
@@ -576,7 +576,7 @@ pub fn process_withdrawal_requests<E: EthSpec>(
state
.pending_partial_withdrawals_mut()?
.push(PendingPartialWithdrawal {
index: index as u64,
validator_index: validator_index as u64,
amount: to_withdraw,
withdrawable_epoch,
})?;
@@ -739,8 +739,8 @@ pub fn process_consolidation_request<E: EthSpec>(
}
let target_validator = state.get_validator(target_index)?;
// Verify the target has execution withdrawal credentials
if !target_validator.has_execution_withdrawal_credential(spec) {
// Verify the target has compounding withdrawal credentials
if !target_validator.has_compounding_withdrawal_credential(spec) {
return Ok(());
}
@@ -757,6 +757,18 @@ pub fn process_consolidation_request<E: EthSpec>(
{
return Ok(());
}
// Verify the source has been active long enough
if current_epoch
< source_validator
.activation_epoch
.safe_add(spec.shard_committee_period)?
{
return Ok(());
}
// Verify the source has no pending withdrawals in the queue
if state.get_pending_balance_to_withdraw(source_index)? > 0 {
return Ok(());
}
// Initiate source validator exit and append pending consolidation
let source_exit_epoch = state
@@ -772,10 +784,5 @@ pub fn process_consolidation_request<E: EthSpec>(
target_index: target_index as u64,
})?;
let target_validator = state.get_validator(target_index)?;
// Churn any target excess active balance of target and raise its max
if target_validator.has_eth1_withdrawal_credential(spec) {
state.switch_to_compounding_validator(target_index, spec)?;
}
Ok(())
}

View File

@@ -1057,14 +1057,12 @@ fn process_pending_consolidations<E: EthSpec>(
}
// Calculate the consolidated balance
let max_effective_balance =
source_validator.get_max_effective_balance(spec, state_ctxt.fork_name);
let source_effective_balance = std::cmp::min(
*state
.balances()
.get(source_index)
.ok_or(BeaconStateError::UnknownValidator(source_index))?,
max_effective_balance,
source_validator.effective_balance,
);
// Move active balance to target. Excess balance is withdrawable.

View File

@@ -14,13 +14,15 @@ pub fn upgrade_to_electra<E: EthSpec>(
) -> Result<(), Error> {
let epoch = pre_state.current_epoch();
let activation_exit_epoch = spec.compute_activation_exit_epoch(epoch)?;
let earliest_exit_epoch = pre_state
.validators()
.iter()
.filter(|v| v.exit_epoch != spec.far_future_epoch)
.map(|v| v.exit_epoch)
.max()
.unwrap_or(epoch)
.unwrap_or(activation_exit_epoch)
.max(activation_exit_epoch)
.safe_add(1)?;
// The total active balance cache must be built before the consolidation churn limit

View File

@@ -10,7 +10,7 @@ MAX_EFFECTIVE_BALANCE_ELECTRA: 2048000000000
# State list lengths
# ---------------------------------------------------------------
# `uint64(2**27)` (= 134,217,728)
PENDING_BALANCE_DEPOSITS_LIMIT: 134217728
PENDING_DEPOSITS_LIMIT: 134217728
# `uint64(2**27)` (= 134,217,728)
PENDING_PARTIAL_WITHDRAWALS_LIMIT: 134217728
# `uint64(2**18)` (= 262,144)
@@ -29,12 +29,12 @@ WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA: 4096
MAX_ATTESTER_SLASHINGS_ELECTRA: 1
# `uint64(2**3)` (= 8)
MAX_ATTESTATIONS_ELECTRA: 8
# `uint64(2**0)` (= 1)
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1
# `uint64(2**1)` (= 2)
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 2
# Execution
# ---------------------------------------------------------------
# 2**13 (= 8192) receipts
# 2**13 (= 8192) deposit requests
MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: 8192
# 2**4 (= 16) withdrawal requests
MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: 16
@@ -43,3 +43,8 @@ MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: 16
# ---------------------------------------------------------------
# 2**3 ( = 8) pending withdrawals
MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: 8
# Pending deposits processing
# ---------------------------------------------------------------
# 2**4 ( = 4) pending deposits
MAX_PENDING_DEPOSITS_PER_EPOCH: 16

View File

@@ -22,3 +22,5 @@ EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 256
# ---------------------------------------------------------------
# 1
MIN_SYNC_COMMITTEE_PARTICIPANTS: 1
# SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD (= 32 * 256)
UPDATE_TIMEOUT: 8192

View File

@@ -10,7 +10,7 @@ MAX_EFFECTIVE_BALANCE_ELECTRA: 2048000000000
# State list lengths
# ---------------------------------------------------------------
# `uint64(2**27)` (= 134,217,728)
PENDING_BALANCE_DEPOSITS_LIMIT: 134217728
PENDING_DEPOSITS_LIMIT: 134217728
# `uint64(2**27)` (= 134,217,728)
PENDING_PARTIAL_WITHDRAWALS_LIMIT: 134217728
# `uint64(2**18)` (= 262,144)
@@ -29,12 +29,12 @@ WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA: 4096
MAX_ATTESTER_SLASHINGS_ELECTRA: 1
# `uint64(2**3)` (= 8)
MAX_ATTESTATIONS_ELECTRA: 8
# `uint64(2**0)` (= 1)
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1
# `uint64(2**1)` (= 2)
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 2
# Execution
# ---------------------------------------------------------------
# 2**13 (= 8192) receipts
# 2**13 (= 8192) deposit requests
MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: 8192
# 2**4 (= 16) withdrawal requests
MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: 16
@@ -43,3 +43,8 @@ MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: 16
# ---------------------------------------------------------------
# 2**3 ( = 8) pending withdrawals
MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: 8
# Pending deposits processing
# ---------------------------------------------------------------
# 2**4 ( = 4) pending deposits
MAX_PENDING_DEPOSITS_PER_EPOCH: 16

View File

@@ -85,4 +85,4 @@ MAX_ATTESTATIONS: 128
# 2**4 (= 16)
MAX_DEPOSITS: 16
# 2**4 (= 16)
MAX_VOLUNTARY_EXITS: 16
MAX_VOLUNTARY_EXITS: 16

View File

@@ -22,3 +22,5 @@ EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 8
# ---------------------------------------------------------------
# 1
MIN_SYNC_COMMITTEE_PARTICIPANTS: 1
# SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD (= 8 * 8)
UPDATE_TIMEOUT: 64

View File

@@ -2,9 +2,9 @@
# Misc
# ---------------------------------------------------------------
# [customized]
# `uint64(4096)`
FIELD_ELEMENTS_PER_BLOB: 4096
# [customized]
MAX_BLOB_COMMITMENTS_PER_BLOCK: 16
# [customized] `floorlog2(BLOB_KZG_COMMITMENTS_GINDEX) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 4 = 9
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: 9
MAX_BLOB_COMMITMENTS_PER_BLOCK: 32
# [customized] `floorlog2(get_generalized_index(BeaconBlockBody, 'blob_kzg_commitments')) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 5 = 10
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: 10

View File

@@ -10,7 +10,7 @@ MAX_EFFECTIVE_BALANCE_ELECTRA: 2048000000000
# State list lengths
# ---------------------------------------------------------------
# `uint64(2**27)` (= 134,217,728)
PENDING_BALANCE_DEPOSITS_LIMIT: 134217728
PENDING_DEPOSITS_LIMIT: 134217728
# [customized] `uint64(2**6)` (= 64)
PENDING_PARTIAL_WITHDRAWALS_LIMIT: 64
# [customized] `uint64(2**6)` (= 64)
@@ -29,8 +29,8 @@ WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA: 4096
MAX_ATTESTER_SLASHINGS_ELECTRA: 1
# `uint64(2**3)` (= 8)
MAX_ATTESTATIONS_ELECTRA: 8
# `uint64(2**0)` (= 1)
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1
# `uint64(2**1)` (= 2)
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 2
# Execution
# ---------------------------------------------------------------
@@ -41,5 +41,10 @@ MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: 2
# Withdrawals processing
# ---------------------------------------------------------------
# 2**0 ( = 1) pending withdrawals
MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: 1
# 2**1 ( = 2) pending withdrawals
MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: 2
# Pending deposits processing
# ---------------------------------------------------------------
# 2**4 ( = 4) pending deposits
MAX_PENDING_DEPOSITS_PER_EPOCH: 16

View File

@@ -4,11 +4,11 @@
# ---------------------------------------------------------------
# [customized] Just 4 committees for slot for testing purposes
MAX_COMMITTEES_PER_SLOT: 4
# [customized] unsecure, but fast
# [customized] insecure, but fast
TARGET_COMMITTEE_SIZE: 4
# 2**11 (= 2,048)
MAX_VALIDATORS_PER_COMMITTEE: 2048
# [customized] Faster, but unsecure.
# [customized] Faster, but insecure.
SHUFFLE_ROUND_COUNT: 10
# 4
HYSTERESIS_QUOTIENT: 4
@@ -85,4 +85,4 @@ MAX_ATTESTATIONS: 128
# 2**4 (= 16)
MAX_DEPOSITS: 16
# 2**4 (= 16)
MAX_VOLUNTARY_EXITS: 16
MAX_VOLUNTARY_EXITS: 16

View File

@@ -46,6 +46,7 @@ mod tests;
pub const CACHED_EPOCHS: usize = 3;
const MAX_RANDOM_BYTE: u64 = (1 << 8) - 1;
const MAX_RANDOM_VALUE: u64 = (1 << 16) - 1;
pub type Validators<E> = List<Validator, <E as EthSpec>::ValidatorRegistryLimit>;
pub type Balances<E> = List<u64, <E as EthSpec>::ValidatorRegistryLimit>;
@@ -916,6 +917,11 @@ impl<E: EthSpec> BeaconState<E> {
}
let max_effective_balance = spec.max_effective_balance_for_fork(self.fork_name_unchecked());
let max_random_value = if self.fork_name_unchecked().electra_enabled() {
MAX_RANDOM_VALUE
} else {
MAX_RANDOM_BYTE
};
let mut i = 0;
loop {
@@ -929,10 +935,10 @@ impl<E: EthSpec> BeaconState<E> {
let candidate_index = *indices
.get(shuffled_index)
.ok_or(Error::ShuffleIndexOutOfBounds(shuffled_index))?;
let random_byte = Self::shuffling_random_byte(i, seed)?;
let random_value = self.shuffling_random_value(i, seed)?;
let effective_balance = self.get_effective_balance(candidate_index)?;
if effective_balance.safe_mul(MAX_RANDOM_BYTE)?
>= max_effective_balance.safe_mul(u64::from(random_byte))?
if effective_balance.safe_mul(max_random_value)?
>= max_effective_balance.safe_mul(random_value)?
{
return Ok(candidate_index);
}
@@ -940,6 +946,19 @@ impl<E: EthSpec> BeaconState<E> {
}
}
/// Fork-aware abstraction for the shuffling.
///
/// In Electra and later, the random value is a 16-bit integer stored in a `u64`.
///
/// Prior to Electra, the random value is an 8-bit integer stored in a `u64`.
fn shuffling_random_value(&self, i: usize, seed: &[u8]) -> Result<u64, Error> {
if self.fork_name_unchecked().electra_enabled() {
Self::shuffling_random_u16_electra(i, seed).map(u64::from)
} else {
Self::shuffling_random_byte(i, seed).map(u64::from)
}
}
/// Get a random byte from the given `seed`.
///
/// Used by the proposer & sync committee selection functions.
@@ -953,6 +972,21 @@ impl<E: EthSpec> BeaconState<E> {
.ok_or(Error::ShuffleIndexOutOfBounds(index))
}
/// Get two random bytes from the given `seed`.
///
/// This is used in place of `shuffling_random_byte` from Electra onwards.
fn shuffling_random_u16_electra(i: usize, seed: &[u8]) -> Result<u16, Error> {
let mut preimage = seed.to_vec();
preimage.append(&mut int_to_bytes8(i.safe_div(16)? as u64));
let offset = i.safe_rem(16)?.safe_mul(2)?;
hash(&preimage)
.get(offset..offset.safe_add(2)?)
.ok_or(Error::ShuffleIndexOutOfBounds(offset))?
.try_into()
.map(u16::from_le_bytes)
.map_err(|_| Error::ShuffleIndexOutOfBounds(offset))
}
/// Convenience accessor for the `execution_payload_header` as an `ExecutionPayloadHeaderRef`.
pub fn latest_execution_payload_header(&self) -> Result<ExecutionPayloadHeaderRef<E>, Error> {
match self {
@@ -1120,6 +1154,11 @@ impl<E: EthSpec> BeaconState<E> {
let seed = self.get_seed(epoch, Domain::SyncCommittee, spec)?;
let max_effective_balance = spec.max_effective_balance_for_fork(self.fork_name_unchecked());
let max_random_value = if self.fork_name_unchecked().electra_enabled() {
MAX_RANDOM_VALUE
} else {
MAX_RANDOM_BYTE
};
let mut i = 0;
let mut sync_committee_indices = Vec::with_capacity(E::SyncCommitteeSize::to_usize());
@@ -1134,10 +1173,10 @@ impl<E: EthSpec> BeaconState<E> {
let candidate_index = *active_validator_indices
.get(shuffled_index)
.ok_or(Error::ShuffleIndexOutOfBounds(shuffled_index))?;
let random_byte = Self::shuffling_random_byte(i, seed.as_slice())?;
let random_value = self.shuffling_random_value(i, seed.as_slice())?;
let effective_balance = self.get_validator(candidate_index)?.effective_balance;
if effective_balance.safe_mul(MAX_RANDOM_BYTE)?
>= max_effective_balance.safe_mul(u64::from(random_byte))?
if effective_balance.safe_mul(max_random_value)?
>= max_effective_balance.safe_mul(random_value)?
{
sync_committee_indices.push(candidate_index);
}
@@ -2205,7 +2244,7 @@ impl<E: EthSpec> BeaconState<E> {
for withdrawal in self
.pending_partial_withdrawals()?
.iter()
.filter(|withdrawal| withdrawal.index as usize == validator_index)
.filter(|withdrawal| withdrawal.validator_index as usize == validator_index)
{
pending_balance.safe_add_assign(withdrawal.amount)?;
}

View File

@@ -191,6 +191,7 @@ pub struct ChainSpec {
pub max_pending_partials_per_withdrawals_sweep: u64,
pub min_per_epoch_churn_limit_electra: u64,
pub max_per_epoch_activation_exit_churn_limit: u64,
pub max_blobs_per_block_electra: u64,
/*
* Fulu hard fork params
@@ -623,9 +624,12 @@ impl ChainSpec {
}
/// Return the value of `MAX_BLOBS_PER_BLOCK` appropriate for `fork`.
pub fn max_blobs_per_block_by_fork(&self, _fork_name: ForkName) -> u64 {
// TODO(electra): add Electra blobs per block change here
self.max_blobs_per_block
pub fn max_blobs_per_block_by_fork(&self, fork_name: ForkName) -> u64 {
if fork_name.electra_enabled() {
self.max_blobs_per_block_electra
} else {
self.max_blobs_per_block
}
}
pub fn data_columns_per_subnet(&self) -> usize {
@@ -826,6 +830,7 @@ impl ChainSpec {
u64::checked_pow(2, 8)?.checked_mul(u64::checked_pow(10, 9)?)
})
.expect("calculation does not overflow"),
max_blobs_per_block_electra: default_max_blobs_per_block_electra(),
/*
* Fulu hard fork params
@@ -940,7 +945,7 @@ impl ChainSpec {
// Electra
electra_fork_version: [0x05, 0x00, 0x00, 0x01],
electra_fork_epoch: None,
max_pending_partials_per_withdrawals_sweep: u64::checked_pow(2, 0)
max_pending_partials_per_withdrawals_sweep: u64::checked_pow(2, 1)
.expect("pow does not overflow"),
min_per_epoch_churn_limit_electra: option_wrapper(|| {
u64::checked_pow(2, 6)?.checked_mul(u64::checked_pow(10, 9)?)
@@ -1156,6 +1161,7 @@ impl ChainSpec {
u64::checked_pow(2, 8)?.checked_mul(u64::checked_pow(10, 9)?)
})
.expect("calculation does not overflow"),
max_blobs_per_block_electra: default_max_blobs_per_block_electra(),
/*
* Fulu hard fork params
@@ -1412,6 +1418,9 @@ pub struct Config {
#[serde(default = "default_max_per_epoch_activation_exit_churn_limit")]
#[serde(with = "serde_utils::quoted_u64")]
max_per_epoch_activation_exit_churn_limit: u64,
#[serde(default = "default_max_blobs_per_block_electra")]
#[serde(with = "serde_utils::quoted_u64")]
max_blobs_per_block_electra: u64,
#[serde(default = "default_custody_requirement")]
#[serde(with = "serde_utils::quoted_u64")]
@@ -1554,6 +1563,10 @@ const fn default_max_per_epoch_activation_exit_churn_limit() -> u64 {
256_000_000_000
}
const fn default_max_blobs_per_block_electra() -> u64 {
9
}
const fn default_attestation_propagation_slot_range() -> u64 {
32
}
@@ -1773,6 +1786,7 @@ impl Config {
min_per_epoch_churn_limit_electra: spec.min_per_epoch_churn_limit_electra,
max_per_epoch_activation_exit_churn_limit: spec
.max_per_epoch_activation_exit_churn_limit,
max_blobs_per_block_electra: spec.max_blobs_per_block_electra,
custody_requirement: spec.custody_requirement,
data_column_sidecar_subnet_count: spec.data_column_sidecar_subnet_count,
@@ -1850,6 +1864,7 @@ impl Config {
min_per_epoch_churn_limit_electra,
max_per_epoch_activation_exit_churn_limit,
max_blobs_per_block_electra,
custody_requirement,
data_column_sidecar_subnet_count,
number_of_columns,
@@ -1919,6 +1934,7 @@ impl Config {
min_per_epoch_churn_limit_electra,
max_per_epoch_activation_exit_churn_limit,
max_blobs_per_block_electra,
// We need to re-derive any values that might have changed in the config.
max_blocks_by_root_request: max_blocks_by_root_request_common(max_request_blocks),

View File

@@ -3,10 +3,10 @@ use crate::*;
use safe_arith::SafeArith;
use serde::{Deserialize, Serialize};
use ssz_types::typenum::{
bit::B0, UInt, U0, U1, U1024, U1048576, U1073741824, U1099511627776, U128, U131072, U134217728,
U16, U16777216, U2, U2048, U256, U262144, U32, U4, U4096, U512, U625, U64, U65536, U8, U8192,
bit::B0, UInt, U0, U1, U10, U1024, U1048576, U1073741824, U1099511627776, U128, U131072,
U134217728, U16, U16777216, U17, U2, U2048, U256, U262144, U32, U4, U4096, U512, U625, U64,
U65536, U8, U8192,
};
use ssz_types::typenum::{U17, U9};
use std::fmt::{self, Debug};
use std::str::FromStr;
@@ -431,7 +431,7 @@ impl EthSpec for MainnetEthSpec {
type PendingDepositsLimit = U134217728;
type PendingPartialWithdrawalsLimit = U134217728;
type PendingConsolidationsLimit = U262144;
type MaxConsolidationRequestsPerPayload = U1;
type MaxConsolidationRequestsPerPayload = U2;
type MaxDepositRequestsPerPayload = U8192;
type MaxAttesterSlashingsElectra = U1;
type MaxAttestationsElectra = U8;
@@ -466,8 +466,8 @@ impl EthSpec for MinimalEthSpec {
type MaxWithdrawalsPerPayload = U4;
type FieldElementsPerBlob = U4096;
type BytesPerBlob = U131072;
type MaxBlobCommitmentsPerBlock = U16;
type KzgCommitmentInclusionProofDepth = U9;
type MaxBlobCommitmentsPerBlock = U32;
type KzgCommitmentInclusionProofDepth = U10;
type PendingPartialWithdrawalsLimit = U64;
type PendingConsolidationsLimit = U64;
type MaxDepositRequestsPerPayload = U4;
@@ -558,7 +558,7 @@ impl EthSpec for GnosisEthSpec {
type PendingDepositsLimit = U134217728;
type PendingPartialWithdrawalsLimit = U134217728;
type PendingConsolidationsLimit = U262144;
type MaxConsolidationRequestsPerPayload = U1;
type MaxConsolidationRequestsPerPayload = U2;
type MaxDepositRequestsPerPayload = U8192;
type MaxAttesterSlashingsElectra = U1;
type MaxAttestationsElectra = U8;

View File

@@ -21,7 +21,7 @@ use tree_hash_derive::TreeHash;
)]
pub struct PendingPartialWithdrawal {
#[serde(with = "serde_utils::quoted_u64")]
pub index: u64,
pub validator_index: u64,
#[serde(with = "serde_utils::quoted_u64")]
pub amount: u64,
pub withdrawable_epoch: Epoch,

View File

@@ -234,7 +234,7 @@ pub struct ElectraPreset {
#[serde(with = "serde_utils::quoted_u64")]
pub max_pending_partials_per_withdrawals_sweep: u64,
#[serde(with = "serde_utils::quoted_u64")]
pub pending_balance_deposits_limit: u64,
pub pending_deposits_limit: u64,
#[serde(with = "serde_utils::quoted_u64")]
pub pending_partial_withdrawals_limit: u64,
#[serde(with = "serde_utils::quoted_u64")]
@@ -260,7 +260,7 @@ impl ElectraPreset {
whistleblower_reward_quotient_electra: spec.whistleblower_reward_quotient_electra,
max_pending_partials_per_withdrawals_sweep: spec
.max_pending_partials_per_withdrawals_sweep,
pending_balance_deposits_limit: E::pending_deposits_limit() as u64,
pending_deposits_limit: E::pending_deposits_limit() as u64,
pending_partial_withdrawals_limit: E::pending_partial_withdrawals_limit() as u64,
pending_consolidations_limit: E::pending_consolidations_limit() as u64,
max_consolidation_requests_per_payload: E::max_consolidation_requests_per_payload()