diff --git a/fork_choice_control/src/controller.rs b/fork_choice_control/src/controller.rs index 58f002a56..e1f7bd596 100644 --- a/fork_choice_control/src/controller.rs +++ b/fork_choice_control/src/controller.rs @@ -922,7 +922,6 @@ where mutator_tx: self.owned_mutator_tx(), payload_bid, origin, - storage: self.owned_storage(), }) } diff --git a/fork_choice_control/src/mutator.rs b/fork_choice_control/src/mutator.rs index a4622a6b2..aa4081054 100644 --- a/fork_choice_control/src/mutator.rs +++ b/fork_choice_control/src/mutator.rs @@ -2062,13 +2062,22 @@ where .store .is_before_due_bps_deadline(self.store.chain_config().payload_due_bps); - debug_with_peers!( - "execution payload envelope accepted (\ - block root: {beacon_block_root:?}, \ - slot: {slot}, \ - is before deadline: {is_before_deadline} \ - )", - ); + if self.store.is_forward_synced() { + debug_with_peers!( + "execution payload envelope accepted (\ + block root: {beacon_block_root:?}, \ + slot: {slot}, \ + is before deadline: {is_before_deadline} \ + )", + ); + } else { + debug_with_peers!( + "execution payload envelope accepted (\ + block root: {beacon_block_root:?}, \ + slot: {slot} \ + )", + ); + } if should_generate_event { self.event_channels diff --git a/fork_choice_control/src/queries.rs b/fork_choice_control/src/queries.rs index c77683f79..d47e3a9d5 100644 --- a/fork_choice_control/src/queries.rs +++ b/fork_choice_control/src/queries.rs @@ -891,8 +891,10 @@ where .dependent_root(self.store_snapshot().as_ref(), state, epoch) } - pub fn proposer_dependent_root(&self, state: &BeaconState

, epoch: Epoch) -> Result { - self.dependent_root(state, epoch.saturating_sub(P::MinSeedLookahead::U64)) + #[must_use] + pub fn shuffling_dependent_root(&self, head_root: H256, epoch: Epoch) -> Option { + self.store_snapshot() + .shuffling_dependent_root(head_root, epoch) } #[instrument(skip_all, level = "debug", fields(slot = slot))] diff --git a/fork_choice_control/src/tasks.rs b/fork_choice_control/src/tasks.rs index 66eb72c14..19744cdc6 100644 --- a/fork_choice_control/src/tasks.rs +++ b/fork_choice_control/src/tasks.rs @@ -625,7 +625,6 @@ pub struct ExecutionPayloadBidTask { pub mutator_tx: Sender>, pub payload_bid: Arc>, pub origin: ExecutionPayloadBidOrigin, - pub storage: Arc>, } impl Run for ExecutionPayloadBidTask { @@ -636,13 +635,9 @@ impl Run for ExecutionPayloadBidTask { mutator_tx, payload_bid, origin, - storage, } = self; - let result = - store_snapshot.validate_execution_payload_bid(payload_bid, &origin, |state, epoch| { - storage.dependent_root(&store_snapshot, state, epoch.saturating_sub(1)) - }); + let result = store_snapshot.validate_execution_payload_bid(payload_bid, &origin); MutatorMessage::PayloadBid { result, origin }.send(&mutator_tx); } diff --git a/fork_choice_store/src/error.rs b/fork_choice_store/src/error.rs index 09bfe10af..54b6b4cf5 100644 --- a/fork_choice_store/src/error.rs +++ b/fork_choice_store/src/error.rs @@ -11,7 +11,7 @@ use types::{ gloas::containers::{ SignedExecutionPayloadBid, SignedExecutionPayloadEnvelope, SignedProposerPreferences, }, - phase0::primitives::{Epoch, ExecutionAddress, Gwei, H256, Slot, SubnetId, ValidatorIndex}, + phase0::primitives::{Epoch, Gwei, H256, Slot, SubnetId, ValidatorIndex}, preset::{Mainnet, Preset}, }; @@ -173,13 +173,6 @@ pub enum Error { "execution payload bid's slot {bid_slot} is not greater than parent slot {parent_slot}" )] ExecutionPayloadBidSlotNotGreaterThanParent { bid_slot: Slot, parent_slot: Slot }, - #[error( - "execution payload bid's fee recipient mismatch (in_bid: {in_bid:?}, in_preference: {in_preference:?})" - )] - ExecutionPayloadBidFeeRecipientMismatch { - in_preference: Box, - in_bid: Box, - }, #[error("off-protocol payment is disallowed in gossip: {payload_bid:?}")] ExecutionPayloadBidOffProtocolPaymentDisallowed { payload_bid: Arc>, diff --git a/fork_choice_store/src/store.rs b/fork_choice_store/src/store.rs index cb19ccd72..68e69cb59 100644 --- a/fork_choice_store/src/store.rs +++ b/fork_choice_store/src/store.rs @@ -1503,19 +1503,15 @@ impl> Store { .map(|chain_link| chain_link.block_root) } - /// Roughly corresponds to [`get_dependent_root`] from the Fork Choice specification. + /// Roughly corresponds to [`get_shuffling_dependent_root`] from the Fork Choice specification. /// - /// Computes the proposer dependent root from the block tree (not from a post-state), - /// using the current store epoch. Used to decide whether to apply the proposer score - /// boost: the boost is only applied when the candidate block and the canonical chain - /// head share the same dependent root. + /// Computes the shuffling dependent root for `epoch` from the block tree (not from a + /// post-state). Used to decide whether to apply the proposer score boost and to look up + /// the accepted `SignedProposerPreferences` during execution payload bid validation. /// - /// [`get_dependent_root`]: https://github.com/ethereum/consensus-specs/pull/5306 - fn proposer_boost_dependent_root(&self, root: H256) -> Option { - let epoch = self.current_epoch(); - - // Genesis block parent: both candidate and head collapse to the same value, - // so the boost still applies near genesis. + /// [`get_shuffling_dependent_root`]: https://github.com/ethereum/consensus-specs/pull/5374 + pub fn shuffling_dependent_root(&self, root: H256, epoch: Epoch) -> Option { + // Genesis block parent. if epoch <= P::MinSeedLookahead::U64 { return Some(H256::zero()); } @@ -1950,7 +1946,6 @@ impl> Store { &self, payload_bid: Arc>, origin: &ExecutionPayloadBidOrigin, - proposer_dependent_root: impl Fn(&BeaconState

, Epoch) -> Result, ) -> Result> { let bid = &payload_bid.message; let builder_index = bid.builder_index; @@ -2014,7 +2009,12 @@ impl> Store { }; // > the `SignedProposerPreferences` where `preferences.proposal_slot` is equal to `bid.slot` has been seen. - let dependent_root = proposer_dependent_root(&state, bid_epoch)?; + let Some(dependent_root) = self.shuffling_dependent_root(bid.parent_block_root, bid_epoch) + else { + return Ok(ExecutionPayloadBidAction::Ignore( + "shuffling dependent root unavailable for bid validation", + )); + }; let proposer_index = accessors::get_beacon_proposer_index_at_slot(&self.chain_config, &state, bid.slot)?; @@ -2028,13 +2028,11 @@ impl> Store { }; // > `bid.fee_recipient` matches the `fee_recipient` from the proposer's `SignedProposerPreferences` associated with `bid.slot`. - ensure!( - bid.fee_recipient == proposer_preference.message.fee_recipient, - Error::

::ExecutionPayloadBidFeeRecipientMismatch { - in_preference: Box::new(proposer_preference.message.fee_recipient), - in_bid: Box::new(bid.fee_recipient), - } - ); + if bid.fee_recipient != proposer_preference.message.fee_recipient { + return Ok(ExecutionPayloadBidAction::Ignore( + "`bid.fee_recipient` does not match the `fee_recipient` from the proposer's `SignedProposerPreferences` associated with `bid.slot`", + )); + } let Some(post_gloas_state) = state.post_gloas() else { return Ok(ExecutionPayloadBidAction::Ignore("state pre-gloas")); @@ -4027,8 +4025,10 @@ impl> Store { // > Add proposer score boost only if the block shares the same dependent root // > as the canonical chain head. // See . - let block_dependent_root = self.proposer_boost_dependent_root(chain_link.parent_root()); - let head_dependent_root = self.proposer_boost_dependent_root(old_head.block_root); + let epoch = self.current_epoch(); + let block_dependent_root = + self.shuffling_dependent_root(chain_link.parent_root(), epoch); + let head_dependent_root = self.shuffling_dependent_root(old_head.block_root, epoch); if block_dependent_root == head_dependent_root { self.proposer_boost_root = block_root; diff --git a/helper_functions/src/predicates.rs b/helper_functions/src/predicates.rs index e3709f80d..668639b1a 100644 --- a/helper_functions/src/predicates.rs +++ b/helper_functions/src/predicates.rs @@ -410,11 +410,6 @@ pub fn is_builder_withdrawal_credential(withdrawal_credentials: H256) -> bool { .starts_with(BUILDER_WITHDRAWAL_PREFIX) } -#[must_use] -pub fn has_builder_withdrawal_credential(validator: &Validator) -> bool { - is_builder_withdrawal_credential(validator.withdrawal_credentials) -} - // > Check if the builder is active. #[inline] #[must_use] diff --git a/p2p/src/network.rs b/p2p/src/network.rs index 78ebd68ba..9e2ab75a4 100644 --- a/p2p/src/network.rs +++ b/p2p/src/network.rs @@ -1517,8 +1517,8 @@ impl Network { let ExecutionPayloadEnvelopesByRangeRequest { start_slot, count } = request; - let max_request_blocks = self.controller.chain_config().max_request_blocks_deneb; - let difference = count.min(max_request_blocks).min(MAX_FOR_DOS_PREVENTION); + let max_request_payloads = self.controller.chain_config().max_request_payloads; + let difference = count.min(max_request_payloads).min(MAX_FOR_DOS_PREVENTION); let end_slot = start_slot .checked_add(difference) diff --git a/scripts/download_spec_tests.sh b/scripts/download_spec_tests.sh index 725b1a0b2..50b902ff5 100755 --- a/scripts/download_spec_tests.sh +++ b/scripts/download_spec_tests.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -SPEC_VERSION="${SPEC_VERSION:-v1.7.0-alpha.11}" +SPEC_VERSION="${SPEC_VERSION:-v1.7.0-alpha.12}" TESTS_DIR="consensus-spec-tests" VERSION_FILE="${TESTS_DIR}/.version" BASE_URL="https://github.com/ethereum/consensus-specs/releases/download/${SPEC_VERSION}" diff --git a/transition_functions/src/gloas/execution_payload_processing.rs b/transition_functions/src/gloas/execution_payload_processing.rs index 666278f2a..af156a80e 100644 --- a/transition_functions/src/gloas/execution_payload_processing.rs +++ b/transition_functions/src/gloas/execution_payload_processing.rs @@ -2,12 +2,17 @@ use anyhow::Result; use helper_functions::{ accessors::{get_current_epoch, get_pending_balance_to_withdraw_for_builder}, gloas::{add_builder_to_registry, initiate_builder_exit}, - predicates::{is_active_builder, is_valid_builder_deposit_signature}, + predicates::{ + is_active_builder, is_builder_withdrawal_credential, is_valid_builder_deposit_signature, + }, }; use pubkey_cache::PubkeyCache; use types::{ config::Config, - gloas::containers::{BuilderDepositRequest, BuilderExitRequest, ExecutionRequests}, + gloas::{ + consts::PAYLOAD_BUILDER_VERSION, + containers::{BuilderDepositRequest, BuilderExitRequest, ExecutionRequests}, + }, phase0::{consts::FAR_FUTURE_EPOCH, primitives::ExecutionAddress}, preset::Preset, traits::PostGloasBeaconState, @@ -58,6 +63,10 @@ pub fn process_builder_deposit_request( .. } = deposit_request; + if !is_builder_withdrawal_credential(withdrawal_credentials) { + return Ok(()); + } + if let Some(builder_index) = state .builders() .into_iter() @@ -70,14 +79,8 @@ pub fn process_builder_deposit_request( .get_mut(builder_index) .expect("builder index is valid since its pubkey found in builder registry"); - builder.balance = builder.balance.checked_add(amount).ok_or_else(|| { - anyhow::anyhow!( - "balance overflow when applying deposit for builder at index {builder_index}", - ) - })?; - // > If exited, reset the withdrawable epoch - if builder.withdrawable_epoch != FAR_FUTURE_EPOCH { + if builder.withdrawable_epoch != FAR_FUTURE_EPOCH && builder.balance == 0 { builder.withdrawable_epoch = current_epoch.checked_add(config.min_builder_withdrawability_delay).ok_or_else(|| { anyhow::anyhow!( @@ -85,6 +88,12 @@ pub fn process_builder_deposit_request( ) })?; } + + builder.balance = builder.balance.checked_add(amount).ok_or_else(|| { + anyhow::anyhow!( + "balance overflow when applying deposit for builder at index {builder_index}", + ) + })?; } else if is_valid_builder_deposit_signature(config, pubkey_cache, &deposit_request) { let mut address = ExecutionAddress::zero(); address.assign_from_slice(&withdrawal_credentials[12..]); @@ -92,7 +101,7 @@ pub fn process_builder_deposit_request( add_builder_to_registry( state, pubkey, - withdrawal_credentials[0], + PAYLOAD_BUILDER_VERSION, address, amount, state.slot(), diff --git a/types/src/config.rs b/types/src/config.rs index 54b4be377..b36a1585f 100644 --- a/types/src/config.rs +++ b/types/src/config.rs @@ -279,13 +279,13 @@ impl Default for Config { contribution_due_bps: 6667, // Gloas - min_builder_withdrawability_delay: 8192, + min_builder_withdrawability_delay: 64, attestation_due_bps_gloas: 2500, aggregate_due_bps_gloas: 5000, sync_message_due_bps_gloas: 2500, contribution_due_bps_gloas: 5000, payload_attestation_due_bps: 7500, - payload_due_bps: 7500, + payload_due_bps: 5000, // Validator cycle churn_limit_quotient: nonzero!(1_u64 << 16), diff --git a/types/src/gloas/consts.rs b/types/src/gloas/consts.rs index 026121c26..4012c129f 100644 --- a/types/src/gloas/consts.rs +++ b/types/src/gloas/consts.rs @@ -77,7 +77,7 @@ pub const BUILDER_PAYMENT_THRESHOLD_DENOMINATOR: u64 = 10; // // Bitwise flag which indicates that a `ValidatorIndex` should be treated as a `BuilderIndex` pub const BUILDER_INDEX_FLAG: u64 = 0x0100_0000_0000; -pub const BUILDER_WITHDRAWAL_PREFIX: &[u8] = &hex!("03"); +pub const BUILDER_WITHDRAWAL_PREFIX: &[u8] = &hex!("B0"); // Versioning pub const PAYLOAD_BUILDER_VERSION: u8 = 0; diff --git a/types/src/preset.rs b/types/src/preset.rs index fc1cba0dd..c19f4e234 100644 --- a/types/src/preset.rs +++ b/types/src/preset.rs @@ -401,7 +401,7 @@ impl Preset for Mainnet { type MaxPayloadAttestation = U4; type BuilderRegistryLimit = U1099511627776; type BuilderPendingWithdrawalsLimit = U1048576; - type MaxBuilderDepositRequestsPerPayload = U256; + type MaxBuilderDepositRequestsPerPayload = U64; type MaxBuilderExitRequestsPerPayload = U16; // Derived type-level variables diff --git a/validator/src/validator.rs b/validator/src/validator.rs index 603aa0afa..acd858e37 100644 --- a/validator/src/validator.rs +++ b/validator/src/validator.rs @@ -2736,6 +2736,7 @@ impl Validator { let signer = self.signer.clone_arc(); let p2p_tx = self.p2p_tx.clone(); let beacon_state = slot_head.beacon_state.clone_arc(); + let beacon_block_root = slot_head.beacon_block_root; let controller = self.controller.clone_arc(); tokio::spawn(async move { @@ -2755,14 +2756,14 @@ impl Validator { let fee_recipient = proposer_configs.fee_recipient(pubkey).ok()?; let target_gas_limit = proposer_configs.gas_limit(pubkey).ok()?; - let beacon_state = beacon_state.clone_arc(); let controller = controller.clone_arc(); Some(upcoming_slots.into_iter().filter_map(move |proposal_slot| { let proposal_epoch = misc::compute_epoch_at_slot::

(proposal_slot); - match controller.proposer_dependent_root(&beacon_state, proposal_epoch) { - Ok(dependent_root) => Some(( + match controller.shuffling_dependent_root(beacon_block_root, proposal_epoch) + { + Some(dependent_root) => Some(( pubkey, ProposerPreferences { dependent_root, @@ -2772,10 +2773,10 @@ impl Validator { target_gas_limit, }, )), - Err(error) => { + None => { warn_with_peers!( - "failed to compute dependent root for proposer preferences \ - (slot {proposal_slot}, epoch {proposal_epoch}): {error}" + "failed to compute shuffling dependent root for proposer \ + preferences (slot {proposal_slot}, epoch {proposal_epoch})" ); None