diff --git a/fork_choice_control/src/tasks.rs b/fork_choice_control/src/tasks.rs index 1e2d196be..29463aa6d 100644 --- a/fork_choice_control/src/tasks.rs +++ b/fork_choice_control/src/tasks.rs @@ -1050,6 +1050,9 @@ fn initialize_preprocessed_state_cache( accessors::get_or_init_total_active_balance(state, false); accessors::get_or_init_validator_indices(state, false); + if let Some(post_gloas_state) = state.post_gloas() { + accessors::get_or_init_builder_indices(post_gloas_state, false); + } Ok(()) } diff --git a/helper_functions/src/accessors.rs b/helper_functions/src/accessors.rs index 075a642da..01e773410 100644 --- a/helper_functions/src/accessors.rs +++ b/helper_functions/src/accessors.rs @@ -225,6 +225,44 @@ pub fn get_or_init_validator_indices( }) } +pub fn builder_public_key( + state: &(impl PostGloasBeaconState

+ ?Sized), + builder_index: BuilderIndex, +) -> Result<&PublicKeyBytes> { + Ok(&state.builders().get(builder_index)?.pubkey) +} + +#[must_use] +pub fn builder_index_of_public_key( + state: &(impl PostGloasBeaconState

+ ?Sized), + public_key: &PublicKeyBytes, +) -> Option { + get_or_init_builder_indices(state, true) + .get(public_key) + .copied() +} + +pub fn get_or_init_builder_indices( + state: &(impl PostGloasBeaconState

+ ?Sized), + report_cache_miss: bool, +) -> &HashMap { + state.cache().builder_indices.get_or_init(|| { + if report_cache_miss { + #[cfg(feature = "metrics")] + if let Some(metrics) = METRICS.get() { + metrics.builder_indices_init_count.inc(); + } + } + + state + .builders() + .into_iter() + .map(|builder| builder.pubkey) + .zip(0..) + .collect() + }) +} + pub fn get_active_validator_indices( state: &impl BeaconState

, relative_epoch: RelativeEpoch, @@ -1176,8 +1214,8 @@ pub fn get_builder_payment_quorum_threshold(state: &impl BeaconState< } pub fn get_active_builder_indices( - state: &(impl PostGloasBeaconState

+ ?Sized), -) -> impl Iterator + '_ { + state: &dyn PostGloasBeaconState

, +) -> impl Iterator + '_ { (0..) .zip(state.builders()) .filter(move |(_, builder)| { diff --git a/http_api/src/standard.rs b/http_api/src/standard.rs index bf3f6a245..74a2fc500 100644 --- a/http_api/src/standard.rs +++ b/http_api/src/standard.rs @@ -3672,13 +3672,13 @@ pub async fn validator_execution_payload_bid( return Err(Error::InvalidSlot(slot)); }; - // TODO(gloas): check builder exist with `builder_indices` cache in beacon state - let _ = beacon_state - .post_gloas() - .ok_or(Error::StatePreGloas)? - .builders() - .get(builder_index) - .map_err(|_| Error::InvalidBuilderIndex(builder_index))?; + let Some(gloas_state) = beacon_state.post_gloas() else { + return Err(Error::StatePreGloas); + }; + + if !accessors::get_active_builder_indices(gloas_state).contains(&builder_index) { + return Err(Error::InvalidBuilderIndex(builder_index)); + } let version = beacon_state.phase(); let signed_bid = controller diff --git a/prometheus_metrics/src/metrics.rs b/prometheus_metrics/src/metrics.rs index f77fcd639..5020db2bb 100644 --- a/prometheus_metrics/src/metrics.rs +++ b/prometheus_metrics/src/metrics.rs @@ -184,6 +184,7 @@ pub struct Metrics { pub beacon_proposer_index_init_count: IntCounter, pub total_active_balance_init_count: IntCounter, pub validator_indices_init_count: IntCounter, + pub builder_indices_init_count: IntCounter, // Transition function metrics pub blinded_block_transition_times: Histogram, @@ -197,6 +198,7 @@ pub struct Metrics { beacon_current_justified_epoch: IntGauge, beacon_previous_justified_epoch: IntGauge, beacon_current_active_validators: IntGauge, + beacon_current_active_builders: IntGauge, pub beacon_reorgs_total: IntCounter, @@ -847,6 +849,11 @@ impl Metrics { "Validator indices cache init count", )?, + builder_indices_init_count: IntCounter::new( + "BUILDER_INDICES_INIT_COUNT", + "Builder indices init count", + )?, + // Transition function metrics blinded_block_transition_times: Histogram::with_opts(histogram_opts!( "BLINDED_BLOCK_TRANSITION_TIMES", @@ -891,6 +898,11 @@ impl Metrics { "Current total active validators", )?, + beacon_current_active_builders: IntGauge::new( + "beacon_current_active_builders", + "Current total active builders", + )?, + beacon_reorgs_total: IntCounter::new( "beacon_reorgs_total", "Total number of chain reorganizations", @@ -1177,6 +1189,7 @@ impl Metrics { default_registry.register(Box::new(self.beacon_proposer_index_init_count.clone()))?; default_registry.register(Box::new(self.total_active_balance_init_count.clone()))?; default_registry.register(Box::new(self.validator_indices_init_count.clone()))?; + default_registry.register(Box::new(self.builder_indices_init_count.clone()))?; default_registry.register(Box::new(self.blinded_block_transition_times.clone()))?; default_registry.register(Box::new(self.block_transition_times.clone()))?; default_registry.register(Box::new(self.epoch_processing_times.clone()))?; @@ -1186,6 +1199,7 @@ impl Metrics { default_registry.register(Box::new(self.beacon_current_justified_epoch.clone()))?; default_registry.register(Box::new(self.beacon_previous_justified_epoch.clone()))?; default_registry.register(Box::new(self.beacon_current_active_validators.clone()))?; + default_registry.register(Box::new(self.beacon_current_active_builders.clone()))?; default_registry.register(Box::new(self.beacon_reorgs_total.clone()))?; default_registry.register(Box::new(self.beacon_processed_deposits_total.clone()))?; default_registry.register(Box::new( @@ -1514,6 +1528,11 @@ impl Metrics { .set(validator_count as i64); } + pub fn set_beacon_current_active_builders(&self, builder_count: usize) { + self.beacon_current_active_builders + .set(builder_count as i64); + } + pub fn set_beacon_processed_deposits_total(&self, total_deposits: u64) { self.beacon_processed_deposits_total .set(total_deposits as i64); diff --git a/types/src/cache.rs b/types/src/cache.rs index 1ee9660da..03e9686b1 100644 --- a/types/src/cache.rs +++ b/types/src/cache.rs @@ -11,7 +11,8 @@ use once_cell::sync::OnceCell; use std::collections::HashMap; use crate::{ - altair::primitives::NonZeroGwei, nonstandard::RelativeEpoch, phase0::primitives::ValidatorIndex, + altair::primitives::NonZeroGwei, gloas::primitives::BuilderIndex, nonstandard::RelativeEpoch, + phase0::primitives::ValidatorIndex, }; // Possible optimization: cache all proposer indices in an epoch. @@ -34,6 +35,7 @@ pub struct Cache { pub active_validator_indices_shuffled: EnumMap>, pub total_active_balance: EnumMap>, pub validator_indices: OnceCell>, + pub builder_indices: OnceCell>, } impl Cache {