mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-29 18:53:32 +00:00
Changes for fusaka-devnet-1 (#7559)
Changes for [fusaka-devnet-1](https://notes.ethereum.org/@ethpandaops/fusaka-devnet-1) [Consensus Specs v1.6.0-alpha.1](https://github.com/ethereum/consensus-specs/pull/4346) * [EIP-7917: Deterministic Proposer Lookahead](https://eips.ethereum.org/EIPS/eip-7917) * [EIP-7892: Blob Parameter Only Hardforks](https://eips.ethereum.org/EIPS/eip-7892)
This commit is contained in:
@@ -181,7 +181,7 @@ pub fn compute_proposer_duties_from_head<T: BeaconChainTypes>(
|
||||
ensure_state_is_in_epoch(&mut state, head_state_root, request_epoch, &chain.spec)?;
|
||||
|
||||
let indices = state
|
||||
.get_beacon_proposer_indices(&chain.spec)
|
||||
.get_beacon_proposer_indices(request_epoch, &chain.spec)
|
||||
.map_err(BeaconChainError::from)?;
|
||||
|
||||
let dependent_root = state
|
||||
|
||||
@@ -523,7 +523,8 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes, O: ObservationStrat
|
||||
&chain.spec,
|
||||
)?;
|
||||
|
||||
let proposers = state.get_beacon_proposer_indices(&chain.spec)?;
|
||||
let epoch = state.current_epoch();
|
||||
let proposers = state.get_beacon_proposer_indices(epoch, &chain.spec)?;
|
||||
let proposer_index = *proposers
|
||||
.get(blob_slot.as_usize() % T::EthSpec::slots_per_epoch() as usize)
|
||||
.ok_or_else(|| BeaconChainError::NoProposerForSlot(blob_slot))?;
|
||||
|
||||
@@ -962,7 +962,8 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
||||
&chain.spec,
|
||||
)?;
|
||||
|
||||
let proposers = state.get_beacon_proposer_indices(&chain.spec)?;
|
||||
let epoch = state.current_epoch();
|
||||
let proposers = state.get_beacon_proposer_indices(epoch, &chain.spec)?;
|
||||
let proposer_index = *proposers
|
||||
.get(block.slot().as_usize() % T::EthSpec::slots_per_epoch() as usize)
|
||||
.ok_or_else(|| BeaconChainError::NoProposerForSlot(block.slot()))?;
|
||||
|
||||
@@ -669,7 +669,8 @@ fn verify_proposer_and_signature<T: BeaconChainTypes>(
|
||||
&chain.spec,
|
||||
)?;
|
||||
|
||||
let proposers = state.get_beacon_proposer_indices(&chain.spec)?;
|
||||
let epoch = state.current_epoch();
|
||||
let proposers = state.get_beacon_proposer_indices(epoch, &chain.spec)?;
|
||||
// Prime the proposer shuffling cache with the newly-learned value.
|
||||
Ok::<_, GossipDataColumnError>(EpochBlockProposers {
|
||||
epoch: column_epoch,
|
||||
|
||||
@@ -377,7 +377,7 @@ fn advance_head<T: BeaconChainTypes>(beacon_chain: &Arc<BeaconChain<T>>) -> Resu
|
||||
state.current_epoch(),
|
||||
head_block_root,
|
||||
state
|
||||
.get_beacon_proposer_indices(&beacon_chain.spec)
|
||||
.get_beacon_proposer_indices(state.current_epoch(), &beacon_chain.spec)
|
||||
.map_err(BeaconChainError::from)?,
|
||||
state.fork(),
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ use beacon_chain::{
|
||||
BeaconChain, ChainConfig, NotifyExecutionLayer, StateSkipConfig, WhenSlotSkipped,
|
||||
};
|
||||
use operation_pool::PersistedOperationPool;
|
||||
use state_processing::EpochProcessingError;
|
||||
use state_processing::{per_slot_processing, per_slot_processing::Error as SlotProcessingError};
|
||||
use std::sync::LazyLock;
|
||||
use types::{
|
||||
@@ -67,11 +68,23 @@ fn massive_skips() {
|
||||
};
|
||||
|
||||
assert!(state.slot() > 1, "the state should skip at least one slot");
|
||||
assert_eq!(
|
||||
error,
|
||||
SlotProcessingError::BeaconStateError(BeaconStateError::InsufficientValidators),
|
||||
"should return error indicating that validators have been slashed out"
|
||||
)
|
||||
|
||||
if state.fork_name_unchecked().fulu_enabled() {
|
||||
// post-fulu this is done in per_epoch_processing
|
||||
assert_eq!(
|
||||
error,
|
||||
SlotProcessingError::EpochProcessingError(EpochProcessingError::BeaconStateError(
|
||||
BeaconStateError::InsufficientValidators
|
||||
)),
|
||||
"should return error indicating that validators have been slashed out"
|
||||
)
|
||||
} else {
|
||||
assert_eq!(
|
||||
error,
|
||||
SlotProcessingError::BeaconStateError(BeaconStateError::InsufficientValidators),
|
||||
"should return error indicating that validators have been slashed out"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -81,7 +81,7 @@ async fn missed_blocks_across_epochs() {
|
||||
epoch,
|
||||
decision_root,
|
||||
state
|
||||
.get_beacon_proposer_indices(&harness.chain.spec)
|
||||
.get_beacon_proposer_indices(epoch, &harness.chain.spec)
|
||||
.unwrap(),
|
||||
state.fork(),
|
||||
)
|
||||
@@ -147,7 +147,9 @@ async fn missed_blocks_basic() {
|
||||
let mut slot_in_epoch = slot % slots_per_epoch;
|
||||
let mut prev_slot = Slot::new(idx - 1);
|
||||
let mut duplicate_block_root = *_state.block_roots().get(idx as usize).unwrap();
|
||||
let mut validator_indexes = _state.get_beacon_proposer_indices(&harness1.spec).unwrap();
|
||||
let mut validator_indexes = _state
|
||||
.get_beacon_proposer_indices(epoch, &harness1.spec)
|
||||
.unwrap();
|
||||
let mut missed_block_proposer = validator_indexes[slot_in_epoch.as_usize()];
|
||||
let mut proposer_shuffling_decision_root = _state
|
||||
.proposer_shuffling_decision_root(duplicate_block_root)
|
||||
@@ -219,7 +221,9 @@ async fn missed_blocks_basic() {
|
||||
prev_slot = Slot::new(idx - 1);
|
||||
slot_in_epoch = slot % slots_per_epoch;
|
||||
duplicate_block_root = *_state2.block_roots().get(idx as usize).unwrap();
|
||||
validator_indexes = _state2.get_beacon_proposer_indices(&harness2.spec).unwrap();
|
||||
validator_indexes = _state2
|
||||
.get_beacon_proposer_indices(epoch, &harness2.spec)
|
||||
.unwrap();
|
||||
missed_block_proposer = validator_indexes[slot_in_epoch.as_usize()];
|
||||
|
||||
let beacon_proposer_cache = harness2
|
||||
@@ -317,7 +321,9 @@ async fn missed_blocks_basic() {
|
||||
slot_in_epoch = slot % slots_per_epoch;
|
||||
prev_slot = Slot::new(idx - 1);
|
||||
duplicate_block_root = *_state3.block_roots().get(idx as usize).unwrap();
|
||||
validator_indexes = _state3.get_beacon_proposer_indices(&harness3.spec).unwrap();
|
||||
validator_indexes = _state3
|
||||
.get_beacon_proposer_indices(epoch, &harness3.spec)
|
||||
.unwrap();
|
||||
missed_block_proposer = validator_indexes[slot_in_epoch.as_usize()];
|
||||
proposer_shuffling_decision_root = _state3
|
||||
.proposer_shuffling_decision_root_at_epoch(epoch, duplicate_block_root)
|
||||
|
||||
@@ -227,7 +227,7 @@ fn compute_historic_proposer_duties<T: BeaconChainTypes>(
|
||||
}
|
||||
|
||||
let indices = state
|
||||
.get_beacon_proposer_indices(&chain.spec)
|
||||
.get_beacon_proposer_indices(epoch, &chain.spec)
|
||||
.map_err(BeaconChainError::from)
|
||||
.map_err(warp_utils::reject::unhandled_error)?;
|
||||
|
||||
|
||||
@@ -147,6 +147,8 @@ where
|
||||
List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>,
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
|
||||
#[superstruct(only(Fulu))]
|
||||
pub proposer_lookahead: Vector<u64, E::ProposerLookaheadSlots>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> PartialBeaconState<E> {
|
||||
@@ -444,7 +446,8 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
|
||||
earliest_consolidation_epoch,
|
||||
pending_deposits,
|
||||
pending_partial_withdrawals,
|
||||
pending_consolidations
|
||||
pending_consolidations,
|
||||
proposer_lookahead
|
||||
],
|
||||
[historical_summaries]
|
||||
),
|
||||
|
||||
@@ -30,6 +30,7 @@ pub enum EpochProcessingError {
|
||||
MissingEarliestExitEpoch,
|
||||
MissingExitBalanceToConsume,
|
||||
PendingDepositsLogicError,
|
||||
ProposerLookaheadOutOfBounds(usize),
|
||||
}
|
||||
|
||||
impl From<InclusionError> for EpochProcessingError {
|
||||
|
||||
@@ -19,7 +19,7 @@ use types::{
|
||||
milhouse::Cow,
|
||||
ActivationQueue, BeaconState, BeaconStateError, ChainSpec, Checkpoint, DepositData, Epoch,
|
||||
EthSpec, ExitCache, ForkName, List, ParticipationFlags, PendingDeposit,
|
||||
ProgressiveBalancesCache, RelativeEpoch, Unsigned, Validator,
|
||||
ProgressiveBalancesCache, RelativeEpoch, Unsigned, Validator, Vector,
|
||||
};
|
||||
|
||||
pub struct SinglePassConfig {
|
||||
@@ -30,6 +30,7 @@ pub struct SinglePassConfig {
|
||||
pub pending_deposits: bool,
|
||||
pub pending_consolidations: bool,
|
||||
pub effective_balance_updates: bool,
|
||||
pub proposer_lookahead: bool,
|
||||
}
|
||||
|
||||
impl Default for SinglePassConfig {
|
||||
@@ -48,6 +49,7 @@ impl SinglePassConfig {
|
||||
pending_deposits: true,
|
||||
pending_consolidations: true,
|
||||
effective_balance_updates: true,
|
||||
proposer_lookahead: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +62,7 @@ impl SinglePassConfig {
|
||||
pending_deposits: false,
|
||||
pending_consolidations: false,
|
||||
effective_balance_updates: false,
|
||||
proposer_lookahead: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,9 +463,43 @@ pub fn process_epoch_single_pass<E: EthSpec>(
|
||||
next_epoch_cache.into_epoch_cache(next_epoch_activation_queue, spec)?;
|
||||
}
|
||||
|
||||
if conf.proposer_lookahead && fork_name.fulu_enabled() {
|
||||
process_proposer_lookahead(state, spec)?;
|
||||
}
|
||||
|
||||
Ok(summary)
|
||||
}
|
||||
|
||||
// TOOO(EIP-7917): use balances cache
|
||||
pub fn process_proposer_lookahead<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let mut lookahead = state.proposer_lookahead()?.clone().to_vec();
|
||||
|
||||
// Shift out proposers in the first epoch
|
||||
lookahead.copy_within((E::slots_per_epoch() as usize).., 0);
|
||||
|
||||
let next_epoch = state
|
||||
.current_epoch()
|
||||
.safe_add(spec.min_seed_lookahead.as_u64())?
|
||||
.safe_add(1)?;
|
||||
let last_epoch_proposers = state.get_beacon_proposer_indices(next_epoch, spec)?;
|
||||
|
||||
// Fill in the last epoch with new proposer indices
|
||||
let last_epoch_start = E::proposer_lookahead_slots().safe_sub(E::slots_per_epoch() as usize)?;
|
||||
for (i, proposer) in last_epoch_proposers.into_iter().enumerate() {
|
||||
let index = last_epoch_start.safe_add(i)?;
|
||||
*lookahead
|
||||
.get_mut(index)
|
||||
.ok_or(Error::ProposerLookaheadOutOfBounds(index))? = proposer as u64;
|
||||
}
|
||||
|
||||
*state.proposer_lookahead_mut()? = Vector::new(lookahead)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_single_inactivity_update(
|
||||
inactivity_score: &mut Cow<u64>,
|
||||
validator_info: &ValidatorInfo,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use safe_arith::SafeArith;
|
||||
use std::mem;
|
||||
use types::{BeaconState, BeaconStateError as Error, BeaconStateFulu, ChainSpec, EthSpec, Fork};
|
||||
use types::{
|
||||
BeaconState, BeaconStateError as Error, BeaconStateFulu, ChainSpec, EthSpec, Fork, Vector,
|
||||
};
|
||||
|
||||
/// Transform a `Electra` state into an `Fulu` state.
|
||||
pub fn upgrade_to_fulu<E: EthSpec>(
|
||||
@@ -15,11 +18,32 @@ pub fn upgrade_to_fulu<E: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn initialize_proposer_lookahead<E: EthSpec>(
|
||||
state: &BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vector<u64, E::ProposerLookaheadSlots>, Error> {
|
||||
let current_epoch = state.current_epoch();
|
||||
let mut lookahead = Vec::with_capacity(E::proposer_lookahead_slots());
|
||||
for i in 0..(spec.min_seed_lookahead.safe_add(1)?.as_u64()) {
|
||||
let target_epoch = current_epoch.safe_add(i)?;
|
||||
lookahead.extend(
|
||||
state
|
||||
.get_beacon_proposer_indices(target_epoch, spec)
|
||||
.map(|vec| vec.into_iter().map(|x| x as u64))?,
|
||||
);
|
||||
}
|
||||
|
||||
Vector::new(lookahead).map_err(|e| {
|
||||
Error::PleaseNotifyTheDevs(format!("Failed to initialize proposer lookahead: {:?}", e))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn upgrade_state_to_fulu<E: EthSpec>(
|
||||
pre_state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<BeaconState<E>, Error> {
|
||||
let epoch = pre_state.current_epoch();
|
||||
let proposer_lookahead = initialize_proposer_lookahead(pre_state, spec)?;
|
||||
let pre = pre_state.as_electra_mut()?;
|
||||
// Where possible, use something like `mem::take` to move fields from behind the &mut
|
||||
// reference. For other fields that don't have a good default value, use `clone`.
|
||||
@@ -89,6 +113,7 @@ pub fn upgrade_state_to_fulu<E: EthSpec>(
|
||||
exit_cache: mem::take(&mut pre.exit_cache),
|
||||
slashings_cache: mem::take(&mut pre.slashings_cache),
|
||||
epoch_cache: mem::take(&mut pre.epoch_cache),
|
||||
proposer_lookahead,
|
||||
});
|
||||
Ok(post)
|
||||
}
|
||||
|
||||
@@ -172,6 +172,7 @@ pub enum Error {
|
||||
AggregatorNotInCommittee {
|
||||
aggregator_index: u64,
|
||||
},
|
||||
PleaseNotifyTheDevs(String),
|
||||
}
|
||||
|
||||
/// Control whether an epoch-indexed field can be indexed at the next epoch or not.
|
||||
@@ -544,6 +545,12 @@ where
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
|
||||
|
||||
// Fulu
|
||||
#[compare_fields(as_iter)]
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Fulu))]
|
||||
pub proposer_lookahead: Vector<u64, E::ProposerLookaheadSlots>,
|
||||
|
||||
// Caching (not in the spec)
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
@@ -948,6 +955,25 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
}
|
||||
}
|
||||
|
||||
// Vec is just much easier to work with here
|
||||
fn compute_proposer_indices(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
seed: &[u8],
|
||||
indices: &[usize],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<usize>, Error> {
|
||||
epoch
|
||||
.slot_iter(E::slots_per_epoch())
|
||||
.map(|slot| {
|
||||
let mut preimage = seed.to_vec();
|
||||
preimage.append(&mut int_to_bytes8(slot.as_u64()));
|
||||
let seed = hash(&preimage);
|
||||
self.compute_proposer_index(indices, &seed, spec)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Fork-aware abstraction for the shuffling.
|
||||
///
|
||||
/// In Electra and later, the random value is a 16-bit integer stored in a `u64`.
|
||||
@@ -1062,37 +1088,48 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
|
||||
/// Returns the beacon proposer index for the `slot` in `self.current_epoch()`.
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
/// Spec v1.6.0-alpha.1
|
||||
pub fn get_beacon_proposer_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
|
||||
// Proposer indices are only known for the current epoch, due to the dependence on the
|
||||
// effective balances of validators, which change at every epoch transition.
|
||||
let epoch = slot.epoch(E::slots_per_epoch());
|
||||
// TODO(EIP-7917): Explore allowing this function to be called with a slot one epoch in the future.
|
||||
if epoch != self.current_epoch() {
|
||||
return Err(Error::SlotOutOfBounds);
|
||||
}
|
||||
|
||||
let seed = self.get_beacon_proposer_seed(slot, spec)?;
|
||||
let indices = self.get_active_validator_indices(epoch, spec)?;
|
||||
if let Ok(proposer_lookahead) = self.proposer_lookahead() {
|
||||
// Post-Fulu
|
||||
let index = slot.as_usize().safe_rem(E::slots_per_epoch() as usize)?;
|
||||
proposer_lookahead
|
||||
.get(index)
|
||||
.ok_or(Error::PleaseNotifyTheDevs(format!(
|
||||
"Proposer lookahead out of bounds: {} for slot: {}",
|
||||
index, slot
|
||||
)))
|
||||
.map(|index| *index as usize)
|
||||
} else {
|
||||
// Pre-Fulu
|
||||
let seed = self.get_beacon_proposer_seed(slot, spec)?;
|
||||
let indices = self.get_active_validator_indices(epoch, spec)?;
|
||||
|
||||
self.compute_proposer_index(&indices, &seed, spec)
|
||||
self.compute_proposer_index(&indices, &seed, spec)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the beacon proposer index for each `slot` in `self.current_epoch()`.
|
||||
/// Returns the beacon proposer index for each `slot` in `epoch`.
|
||||
///
|
||||
/// The returned `Vec` contains one proposer index for each slot. For example, if
|
||||
/// `state.current_epoch() == 1`, then `vec[0]` refers to slot `32` and `vec[1]` refers to slot
|
||||
/// `33`. It will always be the case that `vec.len() == SLOTS_PER_EPOCH`.
|
||||
pub fn get_beacon_proposer_indices(&self, spec: &ChainSpec) -> Result<Vec<usize>, Error> {
|
||||
/// The returned `Vec` contains one proposer index for each slot in the epoch.
|
||||
pub fn get_beacon_proposer_indices(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<usize>, Error> {
|
||||
// Not using the cached validator indices since they are shuffled.
|
||||
let indices = self.get_active_validator_indices(self.current_epoch(), spec)?;
|
||||
let indices = self.get_active_validator_indices(epoch, spec)?;
|
||||
|
||||
self.current_epoch()
|
||||
.slot_iter(E::slots_per_epoch())
|
||||
.map(|slot| {
|
||||
let seed = self.get_beacon_proposer_seed(slot, spec)?;
|
||||
self.compute_proposer_index(&indices, &seed, spec)
|
||||
})
|
||||
.collect()
|
||||
let preimage = self.get_seed(epoch, Domain::BeaconProposer, spec)?;
|
||||
self.compute_proposer_indices(epoch, preimage.as_slice(), &indices, spec)
|
||||
}
|
||||
|
||||
/// Compute the seed to use for the beacon proposer selection at the given `slot`.
|
||||
|
||||
@@ -118,6 +118,7 @@ pub trait EthSpec:
|
||||
type FieldElementsPerCell: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
type FieldElementsPerExtBlob: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
type KzgCommitmentsInclusionProofDepth: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
type ProposerLookaheadSlots: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
/*
|
||||
* Derived values (set these CAREFULLY)
|
||||
*/
|
||||
@@ -378,6 +379,10 @@ pub trait EthSpec:
|
||||
fn kzg_commitments_inclusion_proof_depth() -> usize {
|
||||
Self::KzgCommitmentsInclusionProofDepth::to_usize()
|
||||
}
|
||||
|
||||
fn proposer_lookahead_slots() -> usize {
|
||||
Self::ProposerLookaheadSlots::to_usize()
|
||||
}
|
||||
}
|
||||
|
||||
/// Macro to inherit some type values from another EthSpec.
|
||||
@@ -429,6 +434,7 @@ impl EthSpec for MainnetEthSpec {
|
||||
type MaxCellsPerBlock = U33554432;
|
||||
type KzgCommitmentInclusionProofDepth = U17;
|
||||
type KzgCommitmentsInclusionProofDepth = U4; // inclusion of the whole list of commitments
|
||||
type ProposerLookaheadSlots = U64; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
||||
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
|
||||
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
|
||||
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
|
||||
@@ -481,6 +487,7 @@ impl EthSpec for MinimalEthSpec {
|
||||
type MaxCellsPerBlock = U33554432;
|
||||
type BytesPerCell = U2048;
|
||||
type KzgCommitmentsInclusionProofDepth = U4;
|
||||
type ProposerLookaheadSlots = U16; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
||||
|
||||
params_from_eth_spec!(MainnetEthSpec {
|
||||
JustificationBitsLength,
|
||||
@@ -576,6 +583,7 @@ impl EthSpec for GnosisEthSpec {
|
||||
type MaxCellsPerBlock = U33554432;
|
||||
type BytesPerCell = U2048;
|
||||
type KzgCommitmentsInclusionProofDepth = U4;
|
||||
type ProposerLookaheadSlots = U32; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
|
||||
|
||||
fn default_spec() -> ChainSpec {
|
||||
ChainSpec::gnosis()
|
||||
@@ -592,9 +600,14 @@ mod test {
|
||||
use ssz_types::typenum::Unsigned;
|
||||
|
||||
fn assert_valid_spec<E: EthSpec>() {
|
||||
let spec = E::default_spec();
|
||||
E::kzg_commitments_tree_depth();
|
||||
E::block_body_tree_depth();
|
||||
assert!(E::MaxValidatorsPerSlot::to_i32() >= E::MaxValidatorsPerCommittee::to_i32());
|
||||
assert_eq!(
|
||||
E::proposer_lookahead_slots(),
|
||||
(spec.min_seed_lookahead.as_usize() + 1) * E::slots_per_epoch() as usize
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# To download/extract nightly tests, run:
|
||||
# CONSENSUS_SPECS_TEST_VERSION=nightly make
|
||||
CONSENSUS_SPECS_TEST_VERSION ?= v1.6.0-alpha.0
|
||||
CONSENSUS_SPECS_TEST_VERSION ?= v1.6.0-alpha.1
|
||||
REPO_NAME := consensus-spec-tests
|
||||
OUTPUT_DIR := ./$(REPO_NAME)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use state_processing::per_epoch_processing::effective_balance_updates::{
|
||||
process_effective_balance_updates, process_effective_balance_updates_slow,
|
||||
};
|
||||
use state_processing::per_epoch_processing::single_pass::{
|
||||
process_epoch_single_pass, SinglePassConfig,
|
||||
process_epoch_single_pass, process_proposer_lookahead, SinglePassConfig,
|
||||
};
|
||||
use state_processing::per_epoch_processing::{
|
||||
altair, base,
|
||||
@@ -77,6 +77,8 @@ pub struct SyncCommitteeUpdates;
|
||||
pub struct InactivityUpdates;
|
||||
#[derive(Debug)]
|
||||
pub struct ParticipationFlagUpdates;
|
||||
#[derive(Debug)]
|
||||
pub struct ProposerLookahead;
|
||||
|
||||
type_name!(
|
||||
JustificationAndFinalization,
|
||||
@@ -97,6 +99,7 @@ type_name!(ParticipationRecordUpdates, "participation_record_updates");
|
||||
type_name!(SyncCommitteeUpdates, "sync_committee_updates");
|
||||
type_name!(InactivityUpdates, "inactivity_updates");
|
||||
type_name!(ParticipationFlagUpdates, "participation_flag_updates");
|
||||
type_name!(ProposerLookahead, "proposer_lookahead");
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for JustificationAndFinalization {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
@@ -280,6 +283,16 @@ impl<E: EthSpec> EpochTransition<E> for ParticipationFlagUpdates {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for ProposerLookahead {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
if state.fork_name_unchecked().fulu_enabled() {
|
||||
process_proposer_lookahead(state, spec)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec, T: EpochTransition<E>> LoadCase for EpochProcessing<E, T> {
|
||||
fn load_from_dir(path: &Path, fork_name: ForkName) -> Result<Self, Error> {
|
||||
let spec = &testing_spec::<E>(fork_name);
|
||||
@@ -338,6 +351,11 @@ impl<E: EthSpec, T: EpochTransition<E>> Case for EpochProcessing<E, T> {
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if !fork_name.fulu_enabled() && T::name() == "proposer_lookahead" {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ pub use cases::{
|
||||
Case, DataColumnsByRootIdentifierWrapper, EffectiveBalanceUpdates, Eth1DataReset, FeatureName,
|
||||
HistoricalRootsUpdate, HistoricalSummariesUpdate, InactivityUpdates,
|
||||
JustificationAndFinalization, ParticipationFlagUpdates, ParticipationRecordUpdates,
|
||||
PendingBalanceDeposits, PendingConsolidations, RandaoMixesReset, RegistryUpdates,
|
||||
RewardsAndPenalties, Slashings, SlashingsReset, SyncCommitteeUpdates,
|
||||
PendingBalanceDeposits, PendingConsolidations, ProposerLookahead, RandaoMixesReset,
|
||||
RegistryUpdates, RewardsAndPenalties, Slashings, SlashingsReset, SyncCommitteeUpdates,
|
||||
};
|
||||
pub use decode::log_file_access;
|
||||
pub use error::Error;
|
||||
|
||||
@@ -833,6 +833,12 @@ fn epoch_processing_participation_flag_updates() {
|
||||
EpochProcessingHandler::<MainnetEthSpec, ParticipationFlagUpdates>::default().run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn epoch_processing_proposer_lookahead() {
|
||||
EpochProcessingHandler::<MinimalEthSpec, ProposerLookahead>::default().run();
|
||||
EpochProcessingHandler::<MainnetEthSpec, ProposerLookahead>::default().run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fork_upgrade() {
|
||||
ForkHandler::<MinimalEthSpec>::default().run();
|
||||
|
||||
Reference in New Issue
Block a user