From ba336501f6c3970fd068ca6ea2a303f9f39c07cd Mon Sep 17 00:00:00 2001 From: jacobkaufmann Date: Tue, 10 Dec 2024 14:44:08 -0700 Subject: [PATCH] feat: add beacon committee indices getter method --- consensus/types/src/beacon_state.rs | 54 +++++++++++++++++++++++++++++ consensus/types/src/chain_spec.rs | 3 ++ consensus/types/src/eth_spec.rs | 9 +++++ 3 files changed, 66 insertions(+) diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index 833231dca3..fe5509b0a6 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -809,6 +809,60 @@ impl BeaconState { cache.get_all_beacon_committees() } + /// Returns the inclusion list committee for the given `slot` in the current or next epoch. + /// + /// Spec v0.12.1 + pub fn get_inclusion_list_commitee( + &self, + slot: Slot, + spec: &ChainSpec, + ) -> Result, Error> { + let epoch = slot.epoch(E::slots_per_epoch()); + let current_epoch = self.current_epoch(); + let next_epoch = current_epoch + 1; + if epoch != current_epoch || epoch != next_epoch { + return Err(Error::SlotOutOfBounds); + } + + let seed = self.get_inclusion_list_seed(slot, spec)?; + let indices = self.get_active_validator_indices(epoch, spec)?; + + let start = + (slot % E::slots_per_epoch()).as_usize() * E::InclusionListCommitteeSize::to_usize(); + let end = start + E::InclusionListCommitteeSize::to_usize(); + + let mut i = start; + let mut il_committee_indices = + Vec::with_capacity(E::InclusionListCommitteeSize::to_usize()); + while i < end { + let shuffled_index = compute_shuffled_index( + i.safe_rem(indices.len())?, + indices.len(), + &seed, + spec.shuffle_round_count, + ) + .ok_or(Error::UnableToShuffle)?; + il_committee_indices.push(shuffled_index); + i.safe_add_assign(1)?; + } + + Ok(il_committee_indices) + } + + /// Compute the seed to use for the beacon inclusion list committee selection at the given + /// `slot`. + /// + /// Spec v0.12.1 + pub fn get_inclusion_list_seed(&self, slot: Slot, spec: &ChainSpec) -> Result, Error> { + let epoch = slot.epoch(E::slots_per_epoch()); + let mut preimage = self + .get_seed(epoch, Domain::InclusionListCommittee, spec)? + .as_slice() + .to_vec(); + preimage.append(&mut int_to_bytes8(slot.as_u64())); + Ok(hash(&preimage)) + } + /// Returns the block root which decided the proposer shuffling for the epoch passed in parameter. This root /// can be used to key this proposer shuffling. /// diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index 46fbd11f2d..4aadc16b49 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -192,6 +192,7 @@ pub struct ChainSpec { * FOCIL params */ pub domain_inclusion_list_committee: u32, + pub inclusion_list_committee_size: u64, /* * DAS params @@ -808,6 +809,7 @@ impl ChainSpec { * FOCIL params */ domain_inclusion_list_committee: 13, + inclusion_list_committee_size: 16, /* * DAS params @@ -1131,6 +1133,7 @@ impl ChainSpec { * FOCIL params */ domain_inclusion_list_committee: 13, + inclusion_list_committee_size: 16, /* * DAS params diff --git a/consensus/types/src/eth_spec.rs b/consensus/types/src/eth_spec.rs index c8e6fbaa97..e1c5a70221 100644 --- a/consensus/types/src/eth_spec.rs +++ b/consensus/types/src/eth_spec.rs @@ -163,6 +163,7 @@ pub trait EthSpec: /* * FOCIL */ + type InclusionListCommitteeSize: Unsigned + Clone + Sync + Send + Debug + PartialEq; type MaxTransactionsPerInclusionList: Unsigned + Clone + Sync + Send + Debug + PartialEq; fn default_spec() -> ChainSpec; @@ -380,6 +381,11 @@ pub trait EthSpec: Self::KzgCommitmentsInclusionProofDepth::to_usize() } + /// Returns the `IL_COMMITTEE_SIZE` constant for this specification. + fn inclusion_list_committee_size() -> usize { + Self::InclusionListCommitteeSize::to_usize() + } + /// Returns the `MAX_TRANSACTIONS_PER_INCLUSION_LIST` constant for this specification. fn max_transactions_per_inclusion_list() -> usize { Self::MaxTransactionsPerInclusionList::to_usize() @@ -448,6 +454,7 @@ impl EthSpec for MainnetEthSpec { type MaxAttesterSlashingsElectra = U1; type MaxAttestationsElectra = U8; type MaxWithdrawalRequestsPerPayload = U16; + type InclusionListCommitteeSize = U16; type MaxTransactionsPerInclusionList = U16; fn default_spec() -> ChainSpec { @@ -515,6 +522,7 @@ impl EthSpec for MinimalEthSpec { MaxConsolidationRequestsPerPayload, MaxAttesterSlashingsElectra, MaxAttestationsElectra, + InclusionListCommitteeSize, MaxTransactionsPerInclusionList }); @@ -581,6 +589,7 @@ impl EthSpec for GnosisEthSpec { type FieldElementsPerExtBlob = U8192; type BytesPerCell = U2048; type KzgCommitmentsInclusionProofDepth = U4; + type InclusionListCommitteeSize = U16; type MaxTransactionsPerInclusionList = U16; fn default_spec() -> ChainSpec {