mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-21 05:44:44 +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:
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user