diff --git a/.gitignore b/.gitignore index ae9f83c46d..1b7e5dbb88 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ genesis.ssz # IntelliJ /*.iml +.idea \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 560d382224..12733d4bca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -619,7 +619,7 @@ dependencies = [ [[package]] name = "beacon_node" -version = "3.5.0" +version = "3.5.1" dependencies = [ "beacon_chain", "clap", @@ -787,7 +787,7 @@ dependencies = [ [[package]] name = "boot_node" -version = "3.5.0" +version = "3.5.1" dependencies = [ "beacon_node", "clap", @@ -3721,7 +3721,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lcli" -version = "3.5.0" +version = "3.5.1" dependencies = [ "account_utils", "beacon_chain", @@ -4325,7 +4325,7 @@ dependencies = [ [[package]] name = "lighthouse" -version = "3.5.0" +version = "3.5.1" dependencies = [ "account_manager", "account_utils", @@ -6788,16 +6788,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-big-array" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18b20e7752957bbe9661cff4e0bb04d183d0948cdab2ea58cdb9df36a61dfe62" -dependencies = [ - "serde", - "serde_derive", -] - [[package]] name = "serde_array_query" version = "0.1.0" @@ -8305,7 +8295,6 @@ dependencies = [ "rusqlite", "safe_arith", "serde", - "serde-big-array", "serde_derive", "serde_json", "serde_with", diff --git a/Makefile b/Makefile index 05c6c74d51..89362d12d8 100644 --- a/Makefile +++ b/Makefile @@ -38,15 +38,24 @@ PROFILE ?= release # they run for different forks. FORKS=phase0 altair merge capella +# Extra flags for Cargo +CARGO_INSTALL_EXTRA_FLAGS?= + # Builds the Lighthouse binary in release (optimized). # # Binaries will most likely be found in `./target/release` install: - cargo install --path lighthouse --force --locked --features "$(FEATURES)" --profile "$(PROFILE)" + cargo install --path lighthouse --force --locked \ + --features "$(FEATURES)" \ + --profile "$(PROFILE)" \ + $(CARGO_INSTALL_EXTRA_FLAGS) # Builds the lcli binary in release (optimized). install-lcli: - cargo install --path lcli --force --locked --features "$(FEATURES)" --profile "$(PROFILE)" + cargo install --path lcli --force --locked \ + --features "$(FEATURES)" \ + --profile "$(PROFILE)" \ + $(CARGO_INSTALL_EXTRA_FLAGS) # The following commands use `cross` to build a cross-compile. # @@ -124,7 +133,7 @@ run-ef-tests: test-beacon-chain: $(patsubst %,test-beacon-chain-%,$(FORKS)) test-beacon-chain-%: - env FORK_NAME=$* cargo test --release --features fork_from_env -p beacon_chain + env FORK_NAME=$* cargo test --release --features fork_from_env,slasher/lmdb -p beacon_chain # Run the tests in the `operation_pool` crate for all known forks. test-op-pool: $(patsubst %,test-op-pool-%,$(FORKS)) diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml index a2acd60552..521e2b89c1 100644 --- a/beacon_node/Cargo.toml +++ b/beacon_node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "beacon_node" -version = "3.5.0" +version = "3.5.1" authors = ["Paul Hauner ", "Age Manning BeaconChain { })) } + pub fn get_expected_withdrawals( + &self, + forkchoice_update_params: &ForkchoiceUpdateParameters, + proposal_slot: Slot, + ) -> Result, Error> { + let cached_head = self.canonical_head.cached_head(); + let head_state = &cached_head.snapshot.beacon_state; + + let parent_block_root = forkchoice_update_params.head_root; + + let (unadvanced_state, unadvanced_state_root) = + if cached_head.head_block_root() == parent_block_root { + (Cow::Borrowed(head_state), cached_head.head_state_root()) + } else if let Some(snapshot) = self + .snapshot_cache + .try_read_for(BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT) + .ok_or(Error::SnapshotCacheLockTimeout)? + .get_cloned(parent_block_root, CloneConfig::none()) + { + debug!( + self.log, + "Hit snapshot cache during withdrawals calculation"; + "slot" => proposal_slot, + "parent_block_root" => ?parent_block_root, + ); + let state_root = snapshot.beacon_state_root(); + (Cow::Owned(snapshot.beacon_state), state_root) + } else { + info!( + self.log, + "Missed snapshot cache during withdrawals calculation"; + "slot" => proposal_slot, + "parent_block_root" => ?parent_block_root + ); + let block = self + .get_blinded_block(&parent_block_root)? + .ok_or(Error::MissingBeaconBlock(parent_block_root))?; + let state = self + .get_state(&block.state_root(), Some(block.slot()))? + .ok_or(Error::MissingBeaconState(block.state_root()))?; + (Cow::Owned(state), block.state_root()) + }; + + // Parent state epoch is the same as the proposal, we don't need to advance because the + // list of expected withdrawals can only change after an epoch advance or a + // block application. + let proposal_epoch = proposal_slot.epoch(T::EthSpec::slots_per_epoch()); + if head_state.current_epoch() == proposal_epoch { + return get_expected_withdrawals(&unadvanced_state, &self.spec) + .map_err(Error::PrepareProposerFailed); + } + + // Advance the state using the partial method. + debug!( + self.log, + "Advancing state for withdrawals calculation"; + "proposal_slot" => proposal_slot, + "parent_block_root" => ?parent_block_root, + ); + let mut advanced_state = unadvanced_state.into_owned(); + partial_state_advance( + &mut advanced_state, + Some(unadvanced_state_root), + proposal_epoch.start_slot(T::EthSpec::slots_per_epoch()), + &self.spec, + )?; + get_expected_withdrawals(&advanced_state, &self.spec).map_err(Error::PrepareProposerFailed) + } + /// Determine whether a fork choice update to the execution layer should be overridden. /// /// This is *only* necessary when proposer re-orgs are enabled, because we have to prevent the @@ -4106,9 +4176,6 @@ impl BeaconChain { None }; - //FIXME(sean) waiting for the BN<>EE api for this to stabilize - let kzg_commitments = vec![]; - // Part 3/3 (blocking) // // Perform the final steps of combining all the parts and computing the state root. @@ -4119,7 +4186,6 @@ impl BeaconChain { chain.complete_partial_beacon_block( partial_beacon_block, block_contents, - kzg_commitments, verification, ) }, @@ -4190,7 +4256,7 @@ impl BeaconChain { // allows it to run concurrently with things like attestation packing. let prepare_payload_handle = match &state { BeaconState::Base(_) | BeaconState::Altair(_) => None, - BeaconState::Merge(_) | BeaconState::Capella(_) | BeaconState::Eip4844(_) => { + BeaconState::Merge(_) | BeaconState::Capella(_) => { let prepare_payload_handle = get_execution_payload(self.clone(), &state, proposer_index, builder_params)?; Some(prepare_payload_handle) @@ -4373,7 +4439,6 @@ impl BeaconChain { &self, partial_beacon_block: PartialBeaconBlock, block_contents: Option>, - kzg_commitments: Vec, verification: ProduceBlockVerification, ) -> Result, BlockProductionError> { let PartialBeaconBlock { @@ -4481,31 +4546,6 @@ impl BeaconChain { bls_to_execution_changes: bls_to_execution_changes.into(), }, }), - BeaconState::Eip4844(_) => BeaconBlock::Eip4844(BeaconBlockEip4844 { - slot, - proposer_index, - parent_root, - state_root: Hash256::zero(), - body: BeaconBlockBodyEip4844 { - randao_reveal, - eth1_data, - graffiti, - proposer_slashings: proposer_slashings.into(), - attester_slashings: attester_slashings.into(), - attestations: attestations.into(), - deposits: deposits.into(), - voluntary_exits: voluntary_exits.into(), - sync_aggregate: sync_aggregate - .ok_or(BlockProductionError::MissingSyncAggregate)?, - execution_payload: block_contents - .ok_or(BlockProductionError::MissingExecutionPayload)? - .to_payload() - .try_into() - .map_err(|_| BlockProductionError::InvalidPayloadFork)?, - bls_to_execution_changes: bls_to_execution_changes.into(), - blob_kzg_commitments: VariableList::from(kzg_commitments), - }, - }), }; let block = SignedBeaconBlock::from_block( @@ -4694,7 +4734,9 @@ impl BeaconChain { // Nothing to do if there are no proposers registered with the EL, exit early to avoid // wasting cycles. - if !execution_layer.has_any_proposer_preparation_data().await { + if !self.config.always_prepare_payload + && !execution_layer.has_any_proposer_preparation_data().await + { return Ok(()); } @@ -4751,64 +4793,60 @@ impl BeaconChain { // If the execution layer doesn't have any proposer data for this validator then we assume // it's not connected to this BN and no action is required. let proposer = pre_payload_attributes.proposer_index; - if !execution_layer - .has_proposer_preparation_data(proposer) - .await + if !self.config.always_prepare_payload + && !execution_layer + .has_proposer_preparation_data(proposer) + .await { return Ok(()); } - let withdrawals = match self.spec.fork_name_at_slot::(prepare_slot) { - ForkName::Base | ForkName::Altair | ForkName::Merge => None, - ForkName::Capella | ForkName::Eip4844 => { - // We must use the advanced state because balances can change at epoch boundaries - // and balances affect withdrawals. - // FIXME(mark) - // Might implement caching here in the future.. - let prepare_state = self - .state_at_slot(prepare_slot, StateSkipConfig::WithoutStateRoots) - .map_err(|e| { - error!(self.log, "State advance for withdrawals failed"; "error" => ?e); - e - })?; - Some(get_expected_withdrawals(&prepare_state, &self.spec)) - } - } - .transpose() - .map_err(|e| { - error!(self.log, "Error preparing beacon proposer"; "error" => ?e); - e - }) - .map(|withdrawals_opt| withdrawals_opt.map(|w| w.into())) - .map_err(Error::PrepareProposerFailed)?; - + // Fetch payoad attributes from the execution layer's cache, or compute them from scratch + // if no matching entry is found. This saves recomputing the withdrawals which can take + // considerable time to compute if a state load is required. let head_root = forkchoice_update_params.head_root; - let payload_attributes = PayloadAttributes::new( - self.slot_clock - .start_of(prepare_slot) - .ok_or(Error::InvalidSlot(prepare_slot))? - .as_secs(), - pre_payload_attributes.prev_randao, - execution_layer.get_suggested_fee_recipient(proposer).await, - withdrawals, - ); + let payload_attributes = if let Some(payload_attributes) = execution_layer + .payload_attributes(prepare_slot, head_root) + .await + { + payload_attributes + } else { + let withdrawals = match self.spec.fork_name_at_slot::(prepare_slot) { + ForkName::Base | ForkName::Altair | ForkName::Merge => None, + ForkName::Capella => { + let chain = self.clone(); + self.spawn_blocking_handle( + move || { + chain.get_expected_withdrawals(&forkchoice_update_params, prepare_slot) + }, + "prepare_beacon_proposer_withdrawals", + ) + .await? + .map(Some)? + } + }; - debug!( - self.log, - "Preparing beacon proposer"; - "payload_attributes" => ?payload_attributes, - "prepare_slot" => prepare_slot, - "validator" => proposer, - "parent_root" => ?head_root, - ); + let payload_attributes = PayloadAttributes::new( + self.slot_clock + .start_of(prepare_slot) + .ok_or(Error::InvalidSlot(prepare_slot))? + .as_secs(), + pre_payload_attributes.prev_randao, + execution_layer.get_suggested_fee_recipient(proposer).await, + withdrawals.map(Into::into), + ); - let already_known = execution_layer - .insert_proposer(prepare_slot, head_root, proposer, payload_attributes) - .await; + execution_layer + .insert_proposer( + prepare_slot, + head_root, + proposer, + payload_attributes.clone(), + ) + .await; - // Only push a log to the user if this is the first time we've seen this proposer for this - // slot. - if !already_known { + // Only push a log to the user if this is the first time we've seen this proposer for + // this slot. info!( self.log, "Prepared beacon proposer"; @@ -4816,6 +4854,23 @@ impl BeaconChain { "validator" => proposer, "parent_root" => ?head_root, ); + payload_attributes + }; + + // Push a server-sent event (probably to a block builder or relay). + if let Some(event_handler) = &self.event_handler { + if event_handler.has_payload_attributes_subscribers() { + event_handler.register(EventKind::PayloadAttributes(ForkVersionedResponse { + data: SseExtendedPayloadAttributes { + proposal_slot: prepare_slot, + proposer_index: proposer, + parent_block_root: head_root, + parent_block_hash: forkchoice_update_params.head_hash.unwrap_or_default(), + payload_attributes: payload_attributes.into(), + }, + version: Some(self.spec.fork_name_at_slot::(prepare_slot)), + })); + } } let till_prepare_slot = @@ -4838,7 +4893,9 @@ impl BeaconChain { // If we are close enough to the proposal slot, send an fcU, which will have payload // attributes filled in by the execution layer cache we just primed. - if till_prepare_slot <= self.config.prepare_payload_lookahead { + if self.config.always_prepare_payload + || till_prepare_slot <= self.config.prepare_payload_lookahead + { debug!( self.log, "Sending forkchoiceUpdate for proposer prep"; @@ -5046,26 +5103,43 @@ impl BeaconChain { "status" => ?status ); - // This implies that the terminal block was invalid. We are being explicit in - // invalidating only the head block in this case. - if latest_valid_hash == ExecutionBlockHash::zero() { - self.process_invalid_execution_payload( - &InvalidationOperation::InvalidateOne { - block_root: head_block_root, - }, - ) - .await?; - } else { + match latest_valid_hash { + // The `latest_valid_hash` is set to `None` when the EE + // "cannot determine the ancestor of the invalid + // payload". In such a scenario we should only + // invalidate the head block and nothing else. + None => { + self.process_invalid_execution_payload( + &InvalidationOperation::InvalidateOne { + block_root: head_block_root, + }, + ) + .await?; + } + // An all-zeros execution block hash implies that + // the terminal block was invalid. We are being + // explicit in invalidating only the head block in + // this case. + Some(hash) if hash == ExecutionBlockHash::zero() => { + self.process_invalid_execution_payload( + &InvalidationOperation::InvalidateOne { + block_root: head_block_root, + }, + ) + .await?; + } // The execution engine has stated that all blocks between the // `head_execution_block_hash` and `latest_valid_hash` are invalid. - self.process_invalid_execution_payload( - &InvalidationOperation::InvalidateMany { - head_block_root, - always_invalidate_head: true, - latest_valid_ancestor: latest_valid_hash, - }, - ) - .await?; + Some(latest_valid_hash) => { + self.process_invalid_execution_payload( + &InvalidationOperation::InvalidateMany { + head_block_root, + always_invalidate_head: true, + latest_valid_ancestor: latest_valid_hash, + }, + ) + .await?; + } } Err(BeaconChainError::ExecutionForkChoiceUpdateInvalid { status }) diff --git a/beacon_node/beacon_chain/src/blob_verification.rs b/beacon_node/beacon_chain/src/blob_verification.rs deleted file mode 100644 index f792882033..0000000000 --- a/beacon_node/beacon_chain/src/blob_verification.rs +++ /dev/null @@ -1,136 +0,0 @@ -use derivative::Derivative; -use slot_clock::SlotClock; - -use crate::beacon_chain::{BeaconChain, BeaconChainTypes, MAXIMUM_GOSSIP_CLOCK_DISPARITY}; -use crate::BeaconChainError; -use bls::PublicKey; -use types::{consts::eip4844::BLS_MODULUS, BeaconStateError, BlobsSidecar, Slot}; - -pub enum BlobError { - /// The blob sidecar is from a slot that is later than the current slot (with respect to the - /// gossip clock disparity). - /// - /// ## Peer scoring - /// - /// Assuming the local clock is correct, the peer has sent an invalid message. - FutureSlot { - message_slot: Slot, - latest_permissible_slot: Slot, - }, - /// The blob sidecar is from a slot that is prior to the earliest permissible slot (with - /// respect to the gossip clock disparity). - /// - /// ## Peer scoring - /// - /// Assuming the local clock is correct, the peer has sent an invalid message. - PastSlot { - message_slot: Slot, - earliest_permissible_slot: Slot, - }, - - /// The blob sidecar contains an incorrectly formatted `BLSFieldElement` > `BLS_MODULUS`. - /// - /// - /// ## Peer scoring - /// - /// The peer has sent an invalid message. - BlobOutOfRange { blob_index: usize }, - - /// The blob sidecar contains a KZGCommitment that is not a valid G1 point on - /// the bls curve. - /// - /// ## Peer scoring - /// - /// The peer has sent an invalid message. - InvalidKZGCommitment, - /// The proposal signature in invalid. - /// - /// ## Peer scoring - /// - /// The signature on the blob sidecar invalid and the peer is faulty. - ProposalSignatureInvalid, - - /// A blob sidecar for this proposer and slot has already been observed. - /// - /// ## Peer scoring - /// - /// The `proposer` has already proposed a sidecar at this slot. The existing sidecar may or may not - /// be equal to the given sidecar. - RepeatSidecar { proposer: u64, slot: Slot }, - - /// There was an error whilst processing the sync contribution. It is not known if it is valid or invalid. - /// - /// ## Peer scoring - /// - /// We were unable to process this sync committee message due to an internal error. It's unclear if the - /// sync committee message is valid. - BeaconChainError(BeaconChainError), -} - -impl From for BlobError { - fn from(e: BeaconChainError) -> Self { - BlobError::BeaconChainError(e) - } -} - -impl From for BlobError { - fn from(e: BeaconStateError) -> Self { - BlobError::BeaconChainError(BeaconChainError::BeaconStateError(e)) - } -} - -/// A wrapper around a `BlobsSidecar` that indicates it has been verified w.r.t the corresponding -/// `SignedBeaconBlock`. -#[derive(Derivative)] -#[derivative(Debug(bound = "T: BeaconChainTypes"))] -pub struct VerifiedBlobsSidecar<'a, T: BeaconChainTypes> { - pub blob_sidecar: &'a BlobsSidecar, -} - -impl<'a, T: BeaconChainTypes> VerifiedBlobsSidecar<'a, T> { - pub fn verify( - blob_sidecar: &'a BlobsSidecar, - chain: &BeaconChain, - ) -> Result { - let blob_slot = blob_sidecar.beacon_block_slot; - // Do not gossip or process blobs from future or past slots. - let latest_permissible_slot = chain - .slot_clock - .now_with_future_tolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY) - .ok_or(BeaconChainError::UnableToReadSlot)?; - if blob_slot > latest_permissible_slot { - return Err(BlobError::FutureSlot { - message_slot: latest_permissible_slot, - latest_permissible_slot: blob_slot, - }); - } - - let earliest_permissible_slot = chain - .slot_clock - .now_with_past_tolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY) - .ok_or(BeaconChainError::UnableToReadSlot)?; - if blob_slot > earliest_permissible_slot { - return Err(BlobError::PastSlot { - message_slot: earliest_permissible_slot, - earliest_permissible_slot: blob_slot, - }); - } - - // Verify that blobs are properly formatted - //TODO: add the check while constructing a Blob type from bytes instead of after - for (i, blob) in blob_sidecar.blobs.iter().enumerate() { - if blob.iter().any(|b| *b >= *BLS_MODULUS) { - return Err(BlobError::BlobOutOfRange { blob_index: i }); - } - } - - // Verify that the KZG proof is a valid G1 point - if PublicKey::deserialize(&blob_sidecar.kzg_aggregate_proof.0).is_err() { - return Err(BlobError::InvalidKZGCommitment); - } - - // TODO: Check that we have not already received a sidecar with a valid signature for this slot. - - Ok(Self { blob_sidecar }) - } -} diff --git a/beacon_node/beacon_chain/src/chain_config.rs b/beacon_node/beacon_chain/src/chain_config.rs index 2051a62369..6e3538aeda 100644 --- a/beacon_node/beacon_chain/src/chain_config.rs +++ b/beacon_node/beacon_chain/src/chain_config.rs @@ -67,6 +67,10 @@ pub struct ChainConfig { pub prepare_payload_lookahead: Duration, /// Use EL-free optimistic sync for the finalized part of the chain. pub optimistic_finalized_sync: bool, + /// Whether to send payload attributes every slot, regardless of connected proposers. + /// + /// This is useful for block builders and testing. + pub always_prepare_payload: bool, } impl Default for ChainConfig { @@ -93,6 +97,7 @@ impl Default for ChainConfig { prepare_payload_lookahead: Duration::from_secs(4), // This value isn't actually read except in tests. optimistic_finalized_sync: true, + always_prepare_payload: false, } } } diff --git a/beacon_node/beacon_chain/src/errors.rs b/beacon_node/beacon_chain/src/errors.rs index 102b0c06c1..4560978342 100644 --- a/beacon_node/beacon_chain/src/errors.rs +++ b/beacon_node/beacon_chain/src/errors.rs @@ -258,11 +258,6 @@ pub enum BlockProductionError { BlockingFailed(execution_layer::Error), TerminalPoWBlockLookupFailed(execution_layer::Error), GetPayloadFailed(execution_layer::Error), - GetBlobsFailed(execution_layer::Error), - BlobPayloadMismatch { - blob_block_hash: ExecutionBlockHash, - payload_block_hash: ExecutionBlockHash, - }, FailedToReadFinalizedBlock(store::Error), MissingFinalizedBlock(Hash256), BlockTooLarge(usize), diff --git a/beacon_node/beacon_chain/src/events.rs b/beacon_node/beacon_chain/src/events.rs index 6f4415ef4f..b3fa6627f7 100644 --- a/beacon_node/beacon_chain/src/events.rs +++ b/beacon_node/beacon_chain/src/events.rs @@ -14,6 +14,7 @@ pub struct ServerSentEventHandler { exit_tx: Sender>, chain_reorg_tx: Sender>, contribution_tx: Sender>, + payload_attributes_tx: Sender>, late_head: Sender>, block_reward_tx: Sender>, log: Logger, @@ -32,6 +33,7 @@ impl ServerSentEventHandler { let (exit_tx, _) = broadcast::channel(capacity); let (chain_reorg_tx, _) = broadcast::channel(capacity); let (contribution_tx, _) = broadcast::channel(capacity); + let (payload_attributes_tx, _) = broadcast::channel(capacity); let (late_head, _) = broadcast::channel(capacity); let (block_reward_tx, _) = broadcast::channel(capacity); @@ -43,6 +45,7 @@ impl ServerSentEventHandler { exit_tx, chain_reorg_tx, contribution_tx, + payload_attributes_tx, late_head, block_reward_tx, log, @@ -50,28 +53,55 @@ impl ServerSentEventHandler { } pub fn register(&self, kind: EventKind) { - let result = match kind { - EventKind::Attestation(attestation) => self + let log_count = |name, count| { + trace!( + self.log, + "Registering server-sent event"; + "kind" => name, + "receiver_count" => count + ); + }; + let result = match &kind { + EventKind::Attestation(_) => self .attestation_tx - .send(EventKind::Attestation(attestation)) - .map(|count| trace!(self.log, "Registering server-sent attestation event"; "receiver_count" => count)), - EventKind::Block(block) => self.block_tx.send(EventKind::Block(block)) - .map(|count| trace!(self.log, "Registering server-sent block event"; "receiver_count" => count)), - EventKind::FinalizedCheckpoint(checkpoint) => self.finalized_tx - .send(EventKind::FinalizedCheckpoint(checkpoint)) - .map(|count| trace!(self.log, "Registering server-sent finalized checkpoint event"; "receiver_count" => count)), - EventKind::Head(head) => self.head_tx.send(EventKind::Head(head)) - .map(|count| trace!(self.log, "Registering server-sent head event"; "receiver_count" => count)), - EventKind::VoluntaryExit(exit) => self.exit_tx.send(EventKind::VoluntaryExit(exit)) - .map(|count| trace!(self.log, "Registering server-sent voluntary exit event"; "receiver_count" => count)), - EventKind::ChainReorg(reorg) => self.chain_reorg_tx.send(EventKind::ChainReorg(reorg)) - .map(|count| trace!(self.log, "Registering server-sent chain reorg event"; "receiver_count" => count)), - EventKind::ContributionAndProof(contribution_and_proof) => self.contribution_tx.send(EventKind::ContributionAndProof(contribution_and_proof)) - .map(|count| trace!(self.log, "Registering server-sent contribution and proof event"; "receiver_count" => count)), - EventKind::LateHead(late_head) => self.late_head.send(EventKind::LateHead(late_head)) - .map(|count| trace!(self.log, "Registering server-sent late head event"; "receiver_count" => count)), - EventKind::BlockReward(block_reward) => self.block_reward_tx.send(EventKind::BlockReward(block_reward)) - .map(|count| trace!(self.log, "Registering server-sent contribution and proof event"; "receiver_count" => count)), + .send(kind) + .map(|count| log_count(count, "attestation")), + EventKind::Block(_) => self + .block_tx + .send(kind) + .map(|count| log_count(count, "block")), + EventKind::FinalizedCheckpoint(_) => self + .finalized_tx + .send(kind) + .map(|count| log_count(count, "finalized checkpoint")), + EventKind::Head(_) => self + .head_tx + .send(kind) + .map(|count| log_count(count, "head")), + EventKind::VoluntaryExit(_) => self + .exit_tx + .send(kind) + .map(|count| log_count(count, "exit")), + EventKind::ChainReorg(_) => self + .chain_reorg_tx + .send(kind) + .map(|count| log_count(count, "chain reorg")), + EventKind::ContributionAndProof(_) => self + .contribution_tx + .send(kind) + .map(|count| log_count(count, "contribution and proof")), + EventKind::PayloadAttributes(_) => self + .payload_attributes_tx + .send(kind) + .map(|count| log_count(count, "payload attributes")), + EventKind::LateHead(_) => self + .late_head + .send(kind) + .map(|count| log_count(count, "late head")), + EventKind::BlockReward(_) => self + .block_reward_tx + .send(kind) + .map(|count| log_count(count, "block reward")), }; if let Err(SendError(event)) = result { trace!(self.log, "No receivers registered to listen for event"; "event" => ?event); @@ -106,6 +136,10 @@ impl ServerSentEventHandler { self.contribution_tx.subscribe() } + pub fn subscribe_payload_attributes(&self) -> Receiver> { + self.payload_attributes_tx.subscribe() + } + pub fn subscribe_late_head(&self) -> Receiver> { self.late_head.subscribe() } @@ -142,6 +176,10 @@ impl ServerSentEventHandler { self.contribution_tx.receiver_count() > 0 } + pub fn has_payload_attributes_subscribers(&self) -> bool { + self.payload_attributes_tx.receiver_count() > 0 + } + pub fn has_late_head_subscribers(&self) -> bool { self.late_head.receiver_count() > 0 } diff --git a/beacon_node/beacon_chain/src/execution_payload.rs b/beacon_node/beacon_chain/src/execution_payload.rs index 825538d562..5cc8ee2d28 100644 --- a/beacon_node/beacon_chain/src/execution_payload.rs +++ b/beacon_node/beacon_chain/src/execution_payload.rs @@ -172,21 +172,34 @@ async fn notify_new_payload<'a, T: BeaconChainTypes>( "method" => "new_payload", ); - // latest_valid_hash == 0 implies that this was the terminal block - // Hence, we don't need to run `BeaconChain::process_invalid_execution_payload`. - if latest_valid_hash == ExecutionBlockHash::zero() { - return Err(ExecutionPayloadError::RejectedByExecutionEngine { status }.into()); + // Only trigger payload invalidation in fork choice if the + // `latest_valid_hash` is `Some` and non-zero. + // + // A `None` latest valid hash indicates that the EE was unable + // to determine the most recent valid ancestor. Since `block` + // has not yet been applied to fork choice, there's nothing to + // invalidate. + // + // An all-zeros payload indicates that an EIP-3675 check has + // failed regarding the validity of the terminal block. Rather + // than iterating back in the chain to find the terminal block + // and invalidating that, we simply reject this block without + // invalidating anything else. + if let Some(latest_valid_hash) = + latest_valid_hash.filter(|hash| *hash != ExecutionBlockHash::zero()) + { + // This block has not yet been applied to fork choice, so the latest block that was + // imported to fork choice was the parent. + let latest_root = block.parent_root(); + + chain + .process_invalid_execution_payload(&InvalidationOperation::InvalidateMany { + head_block_root: latest_root, + always_invalidate_head: false, + latest_valid_ancestor: latest_valid_hash, + }) + .await?; } - // This block has not yet been applied to fork choice, so the latest block that was - // imported to fork choice was the parent. - let latest_root = block.parent_root(); - chain - .process_invalid_execution_payload(&InvalidationOperation::InvalidateMany { - head_block_root: latest_root, - always_invalidate_head: false, - latest_valid_ancestor: latest_valid_hash, - }) - .await?; Err(ExecutionPayloadError::RejectedByExecutionEngine { status }.into()) } @@ -406,9 +419,7 @@ pub fn get_execution_payload< let latest_execution_payload_header_block_hash = state.latest_execution_payload_header()?.block_hash(); let withdrawals = match state { - &BeaconState::Capella(_) | &BeaconState::Eip4844(_) => { - Some(get_expected_withdrawals(state, spec)?.into()) - } + &BeaconState::Capella(_) => Some(get_expected_withdrawals(state, spec)?.into()), &BeaconState::Merge(_) => None, // These shouldn't happen but they're here to make the pattern irrefutable &BeaconState::Base(_) | &BeaconState::Altair(_) => None, diff --git a/beacon_node/beacon_chain/src/lib.rs b/beacon_node/beacon_chain/src/lib.rs index 6b980eea7f..0f94c651aa 100644 --- a/beacon_node/beacon_chain/src/lib.rs +++ b/beacon_node/beacon_chain/src/lib.rs @@ -7,7 +7,6 @@ mod beacon_chain; mod beacon_fork_choice_store; pub mod beacon_proposer_cache; mod beacon_snapshot; -pub mod blob_verification; pub mod block_reward; mod block_times_cache; mod block_verification; diff --git a/beacon_node/beacon_chain/src/metrics.rs b/beacon_node/beacon_chain/src/metrics.rs index 315f869514..b52c4258fe 100644 --- a/beacon_node/beacon_chain/src/metrics.rs +++ b/beacon_node/beacon_chain/src/metrics.rs @@ -972,22 +972,6 @@ lazy_static! { "beacon_pre_finalization_block_lookup_count", "Number of block roots subject to single block lookups" ); - - /* - * Blob sidecar Verification - */ - pub static ref BLOBS_SIDECAR_PROCESSING_REQUESTS: Result = try_create_int_counter( - "beacon_blobs_sidecar_processing_requests_total", - "Count of all blob sidecars submitted for processing" - ); - pub static ref BLOBS_SIDECAR_PROCESSING_SUCCESSES: Result = try_create_int_counter( - "beacon_blobs_sidecar_processing_successes_total", - "Number of blob sidecars verified for gossip" - ); - pub static ref BLOBS_SIDECAR_GOSSIP_VERIFICATION_TIMES: Result = try_create_histogram( - "beacon_blobs_sidecar_gossip_verification_seconds", - "Full runtime of blob sidecars gossip verification" - ); } // Fifth lazy-static block is used to account for macro recursion limit. diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index f1b9bc83c5..afb31bba77 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -108,6 +108,14 @@ pub enum AttestationStrategy { SomeValidators(Vec), } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SyncCommitteeStrategy { + /// All sync committee validators sign. + AllValidators, + /// No validators sign. + NoValidators, +} + /// Indicates whether the `BeaconChainHarness` should use the `state.current_sync_committee` or /// `state.next_sync_committee` when creating sync messages or contributions. #[derive(Clone, Debug)] @@ -420,10 +428,6 @@ where spec.capella_fork_epoch.map(|epoch| { genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64() }); - mock.server.execution_block_generator().eip4844_time = - spec.eip4844_fork_epoch.map(|epoch| { - genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64() - }); self } @@ -433,14 +437,10 @@ where let shanghai_time = spec.capella_fork_epoch.map(|epoch| { HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64() }); - let eip4844_time = spec.eip4844_fork_epoch.map(|epoch| { - HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64() - }); let mock = MockExecutionLayer::new( self.runtime.task_executor.clone(), DEFAULT_TERMINAL_BLOCK, shanghai_time, - eip4844_time, None, Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()), spec, @@ -464,14 +464,10 @@ where let shanghai_time = spec.capella_fork_epoch.map(|epoch| { HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64() }); - let eip4844_time = spec.eip4844_fork_epoch.map(|epoch| { - HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64() - }); let mock_el = MockExecutionLayer::new( self.runtime.task_executor.clone(), DEFAULT_TERMINAL_BLOCK, shanghai_time, - eip4844_time, builder_threshold, Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()), spec.clone(), @@ -1764,15 +1760,64 @@ where self.process_attestations(attestations); } + pub fn sync_committee_sign_block( + &self, + state: &BeaconState, + block_hash: Hash256, + slot: Slot, + relative_sync_committee: RelativeSyncCommittee, + ) { + let sync_contributions = + self.make_sync_contributions(state, block_hash, slot, relative_sync_committee); + self.process_sync_contributions(sync_contributions).unwrap() + } + pub async fn add_attested_block_at_slot( &self, slot: Slot, state: BeaconState, state_root: Hash256, validators: &[usize], + ) -> Result<(SignedBeaconBlockHash, BeaconState), BlockError> { + self.add_attested_block_at_slot_with_sync( + slot, + state, + state_root, + validators, + SyncCommitteeStrategy::NoValidators, + ) + .await + } + + pub async fn add_attested_block_at_slot_with_sync( + &self, + slot: Slot, + state: BeaconState, + state_root: Hash256, + validators: &[usize], + sync_committee_strategy: SyncCommitteeStrategy, ) -> Result<(SignedBeaconBlockHash, BeaconState), BlockError> { let (block_hash, block, state) = self.add_block_at_slot(slot, state).await?; self.attest_block(&state, state_root, block_hash, &block, validators); + + if sync_committee_strategy == SyncCommitteeStrategy::AllValidators + && state.current_sync_committee().is_ok() + { + self.sync_committee_sign_block( + &state, + block_hash.into(), + slot, + if (slot + 1).epoch(E::slots_per_epoch()) + % self.spec.epochs_per_sync_committee_period + == 0 + { + RelativeSyncCommittee::Next + } else { + RelativeSyncCommittee::Current + }, + ); + } + Ok((block_hash, state)) } @@ -1782,10 +1827,35 @@ where state_root: Hash256, slots: &[Slot], validators: &[usize], + ) -> AddBlocksResult { + self.add_attested_blocks_at_slots_with_sync( + state, + state_root, + slots, + validators, + SyncCommitteeStrategy::NoValidators, + ) + .await + } + + pub async fn add_attested_blocks_at_slots_with_sync( + &self, + state: BeaconState, + state_root: Hash256, + slots: &[Slot], + validators: &[usize], + sync_committee_strategy: SyncCommitteeStrategy, ) -> AddBlocksResult { assert!(!slots.is_empty()); - self.add_attested_blocks_at_slots_given_lbh(state, state_root, slots, validators, None) - .await + self.add_attested_blocks_at_slots_given_lbh( + state, + state_root, + slots, + validators, + None, + sync_committee_strategy, + ) + .await } async fn add_attested_blocks_at_slots_given_lbh( @@ -1795,6 +1865,7 @@ where slots: &[Slot], validators: &[usize], mut latest_block_hash: Option, + sync_committee_strategy: SyncCommitteeStrategy, ) -> AddBlocksResult { assert!( slots.windows(2).all(|w| w[0] <= w[1]), @@ -1804,7 +1875,13 @@ where let mut state_hash_from_slot: HashMap = HashMap::new(); for slot in slots { let (block_hash, new_state) = self - .add_attested_block_at_slot(*slot, state, state_root, validators) + .add_attested_block_at_slot_with_sync( + *slot, + state, + state_root, + validators, + sync_committee_strategy, + ) .await .unwrap(); state = new_state; @@ -1886,6 +1963,7 @@ where &epoch_slots, &validators, Some(head_block), + SyncCommitteeStrategy::NoValidators, // for backwards compat ) .await; @@ -2002,6 +2080,22 @@ where num_blocks: usize, block_strategy: BlockStrategy, attestation_strategy: AttestationStrategy, + ) -> Hash256 { + self.extend_chain_with_sync( + num_blocks, + block_strategy, + attestation_strategy, + SyncCommitteeStrategy::NoValidators, + ) + .await + } + + pub async fn extend_chain_with_sync( + &self, + num_blocks: usize, + block_strategy: BlockStrategy, + attestation_strategy: AttestationStrategy, + sync_committee_strategy: SyncCommitteeStrategy, ) -> Hash256 { let (mut state, slots) = match block_strategy { BlockStrategy::OnCanonicalHead => { @@ -2033,7 +2127,13 @@ where }; let state_root = state.update_tree_hash_cache().unwrap(); let (_, _, last_produced_block_hash, _) = self - .add_attested_blocks_at_slots(state, state_root, &slots, &validators) + .add_attested_blocks_at_slots_with_sync( + state, + state_root, + &slots, + &validators, + sync_committee_strategy, + ) .await; last_produced_block_hash.into() } diff --git a/beacon_node/client/Cargo.toml b/beacon_node/client/Cargo.toml index 9a49843a9f..876458eea5 100644 --- a/beacon_node/client/Cargo.toml +++ b/beacon_node/client/Cargo.toml @@ -39,7 +39,7 @@ time = "0.3.5" directory = {path = "../../common/directory"} http_api = { path = "../http_api" } http_metrics = { path = "../http_metrics" } -slasher = { path = "../../slasher" } +slasher = { path = "../../slasher", default-features = false } slasher_service = { path = "../../slasher/service" } monitoring_api = {path = "../../common/monitoring_api"} execution_layer = { path = "../execution_layer" } diff --git a/beacon_node/client/src/config.rs b/beacon_node/client/src/config.rs index 22b868256a..95a00b3749 100644 --- a/beacon_node/client/src/config.rs +++ b/beacon_node/client/src/config.rs @@ -79,6 +79,7 @@ pub struct Config { pub monitoring_api: Option, pub slasher: Option, pub logger_config: LoggerConfig, + pub always_prefer_builder_payload: bool, } impl Default for Config { @@ -105,6 +106,7 @@ impl Default for Config { validator_monitor_pubkeys: vec![], validator_monitor_individual_tracking_threshold: DEFAULT_INDIVIDUAL_TRACKING_THRESHOLD, logger_config: LoggerConfig::default(), + always_prefer_builder_payload: false, } } } diff --git a/beacon_node/execution_layer/src/engine_api.rs b/beacon_node/execution_layer/src/engine_api.rs index 9918b679c3..38311b8230 100644 --- a/beacon_node/execution_layer/src/engine_api.rs +++ b/beacon_node/execution_layer/src/engine_api.rs @@ -4,6 +4,7 @@ use crate::http::{ ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, }; +use eth2::types::{SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2}; pub use ethers_core::types::Transaction; use ethers_core::utils::rlp::{self, Decodable, Rlp}; use http::deposit_methods::RpcError; @@ -17,7 +18,7 @@ pub use types::{ Address, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadHeader, ExecutionPayloadRef, FixedVector, ForkName, Hash256, Uint256, VariableList, Withdrawal, }; -use types::{ExecutionPayloadCapella, ExecutionPayloadEip4844, ExecutionPayloadMerge}; +use types::{ExecutionPayloadCapella, ExecutionPayloadMerge}; pub mod auth; pub mod http; @@ -134,7 +135,7 @@ pub struct ExecutionBlock { /// Representation of an execution block with enough detail to reconstruct a payload. #[superstruct( - variants(Merge, Capella, Eip4844), + variants(Merge, Capella), variant_attributes( derive(Clone, Debug, PartialEq, Serialize, Deserialize,), serde(bound = "T: EthSpec", rename_all = "camelCase"), @@ -165,13 +166,10 @@ pub struct ExecutionBlockWithTransactions { #[serde(with = "ssz_types::serde_utils::hex_var_list")] pub extra_data: VariableList, pub base_fee_per_gas: Uint256, - #[superstruct(only(Eip4844))] - #[serde(with = "eth2_serde_utils::u256_hex_be")] - pub excess_data_gas: Uint256, #[serde(rename = "hash")] pub block_hash: ExecutionBlockHash, pub transactions: Vec, - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] pub withdrawals: Vec, } @@ -226,33 +224,6 @@ impl TryFrom> for ExecutionBlockWithTransactions .collect(), }) } - ExecutionPayload::Eip4844(block) => { - Self::Eip4844(ExecutionBlockWithTransactionsEip4844 { - parent_hash: block.parent_hash, - fee_recipient: block.fee_recipient, - state_root: block.state_root, - receipts_root: block.receipts_root, - logs_bloom: block.logs_bloom, - prev_randao: block.prev_randao, - block_number: block.block_number, - gas_limit: block.gas_limit, - gas_used: block.gas_used, - timestamp: block.timestamp, - extra_data: block.extra_data, - base_fee_per_gas: block.base_fee_per_gas, - excess_data_gas: block.excess_data_gas, - block_hash: block.block_hash, - transactions: block - .transactions - .iter() - .map(|tx| Transaction::decode(&Rlp::new(tx))) - .collect::, _>>()?, - withdrawals: Vec::from(block.withdrawals) - .into_iter() - .map(|withdrawal| withdrawal.into()) - .collect(), - }) - } }; Ok(json_payload) } @@ -299,6 +270,33 @@ impl PayloadAttributes { } } +impl From for SsePayloadAttributes { + fn from(pa: PayloadAttributes) -> Self { + match pa { + PayloadAttributes::V1(PayloadAttributesV1 { + timestamp, + prev_randao, + suggested_fee_recipient, + }) => Self::V1(SsePayloadAttributesV1 { + timestamp, + prev_randao, + suggested_fee_recipient, + }), + PayloadAttributes::V2(PayloadAttributesV2 { + timestamp, + prev_randao, + suggested_fee_recipient, + withdrawals, + }) => Self::V2(SsePayloadAttributesV2 { + timestamp, + prev_randao, + suggested_fee_recipient, + withdrawals, + }), + } + } +} + #[derive(Clone, Debug, PartialEq)] pub struct ForkchoiceUpdatedResponse { pub payload_status: PayloadStatusV1, @@ -320,7 +318,7 @@ pub struct ProposeBlindedBlockResponse { } #[superstruct( - variants(Merge, Capella, Eip4844), + variants(Merge, Capella), variant_attributes(derive(Clone, Debug, PartialEq),), map_into(ExecutionPayload), map_ref_into(ExecutionPayloadRef), @@ -333,8 +331,6 @@ pub struct GetPayloadResponse { pub execution_payload: ExecutionPayloadMerge, #[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))] pub execution_payload: ExecutionPayloadCapella, - #[superstruct(only(Eip4844), partial_getter(rename = "execution_payload_eip4844"))] - pub execution_payload: ExecutionPayloadEip4844, pub block_value: Uint256, } @@ -365,10 +361,6 @@ impl From> for (ExecutionPayload, Uint256) ExecutionPayload::Capella(inner.execution_payload), inner.block_value, ), - GetPayloadResponse::Eip4844(inner) => ( - ExecutionPayload::Eip4844(inner.execution_payload), - inner.block_value, - ), } } } diff --git a/beacon_node/execution_layer/src/engine_api/http.rs b/beacon_node/execution_layer/src/engine_api/http.rs index 4416d6a37e..8492dbc4ce 100644 --- a/beacon_node/execution_layer/src/engine_api/http.rs +++ b/beacon_node/execution_layer/src/engine_api/http.rs @@ -38,9 +38,6 @@ pub const ENGINE_GET_PAYLOAD_V1: &str = "engine_getPayloadV1"; pub const ENGINE_GET_PAYLOAD_V2: &str = "engine_getPayloadV2"; pub const ENGINE_GET_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2); -pub const ENGINE_GET_BLOBS_BUNDLE_V1: &str = "engine_getBlobsBundleV1"; -pub const ENGINE_GET_BLOBS_BUNDLE_TIMEOUT: Duration = Duration::from_secs(2); - pub const ENGINE_FORKCHOICE_UPDATED_V1: &str = "engine_forkchoiceUpdatedV1"; pub const ENGINE_FORKCHOICE_UPDATED_V2: &str = "engine_forkchoiceUpdatedV2"; pub const ENGINE_FORKCHOICE_UPDATED_TIMEOUT: Duration = Duration::from_secs(8); @@ -742,14 +739,6 @@ impl HttpJsonRpc { ) .await?, ), - ForkName::Eip4844 => ExecutionBlockWithTransactions::Eip4844( - self.rpc_request( - ETH_GET_BLOCK_BY_HASH, - params, - ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier, - ) - .await?, - ), ForkName::Base | ForkName::Altair => { return Err(Error::UnsupportedForkVariant(format!( "called get_block_by_hash_with_txns with fork {:?}", @@ -844,29 +833,13 @@ impl HttpJsonRpc { .await?; Ok(JsonGetPayloadResponse::V2(response).into()) } - ForkName::Base | ForkName::Altair | ForkName::Eip4844 => Err( - Error::UnsupportedForkVariant(format!("called get_payload_v2 with {}", fork_name)), - ), + ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!( + "called get_payload_v2 with {}", + fork_name + ))), } } - pub async fn get_blobs_bundle_v1( - &self, - payload_id: PayloadId, - ) -> Result, Error> { - let params = json!([JsonPayloadIdRequest::from(payload_id)]); - - let response: JsonBlobBundles = self - .rpc_request( - ENGINE_GET_BLOBS_BUNDLE_V1, - params, - ENGINE_GET_BLOBS_BUNDLE_TIMEOUT, - ) - .await?; - - Ok(response) - } - pub async fn forkchoice_updated_v1( &self, forkchoice_state: ForkchoiceState, diff --git a/beacon_node/execution_layer/src/engine_api/json_structures.rs b/beacon_node/execution_layer/src/engine_api/json_structures.rs index a6ebc19527..dcfa635453 100644 --- a/beacon_node/execution_layer/src/engine_api/json_structures.rs +++ b/beacon_node/execution_layer/src/engine_api/json_structures.rs @@ -3,12 +3,9 @@ use serde::{Deserialize, Serialize}; use strum::EnumString; use superstruct::superstruct; use types::{ - Blob, EthSpec, ExecutionBlockHash, FixedVector, KzgCommitment, Transaction, Unsigned, - VariableList, Withdrawal, -}; -use types::{ - ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadEip4844, ExecutionPayloadMerge, + EthSpec, ExecutionBlockHash, FixedVector, Transaction, Unsigned, VariableList, Withdrawal, }; +use types::{ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadMerge}; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -64,7 +61,7 @@ pub struct JsonPayloadIdResponse { } #[superstruct( - variants(V1, V2, V3), + variants(V1, V2), variant_attributes( derive(Debug, PartialEq, Default, Serialize, Deserialize,), serde(bound = "T: EthSpec", rename_all = "camelCase"), @@ -94,14 +91,11 @@ pub struct JsonExecutionPayload { pub extra_data: VariableList, #[serde(with = "eth2_serde_utils::u256_hex_be")] pub base_fee_per_gas: Uint256, - #[superstruct(only(V3))] - #[serde(with = "eth2_serde_utils::u256_hex_be")] - pub excess_data_gas: Uint256, pub block_hash: ExecutionBlockHash, #[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] pub transactions: VariableList, T::MaxTransactionsPerPayload>, - #[superstruct(only(V2, V3))] + #[superstruct(only(V2))] pub withdrawals: VariableList, } @@ -151,40 +145,12 @@ impl From> for JsonExecutionPayloadV2 } } } -impl From> for JsonExecutionPayloadV3 { - fn from(payload: ExecutionPayloadEip4844) -> Self { - JsonExecutionPayloadV3 { - parent_hash: payload.parent_hash, - fee_recipient: payload.fee_recipient, - state_root: payload.state_root, - receipts_root: payload.receipts_root, - logs_bloom: payload.logs_bloom, - prev_randao: payload.prev_randao, - block_number: payload.block_number, - gas_limit: payload.gas_limit, - gas_used: payload.gas_used, - timestamp: payload.timestamp, - extra_data: payload.extra_data, - base_fee_per_gas: payload.base_fee_per_gas, - excess_data_gas: payload.excess_data_gas, - block_hash: payload.block_hash, - transactions: payload.transactions, - withdrawals: payload - .withdrawals - .into_iter() - .map(Into::into) - .collect::>() - .into(), - } - } -} impl From> for JsonExecutionPayload { fn from(execution_payload: ExecutionPayload) -> Self { match execution_payload { ExecutionPayload::Merge(payload) => JsonExecutionPayload::V1(payload.into()), ExecutionPayload::Capella(payload) => JsonExecutionPayload::V2(payload.into()), - ExecutionPayload::Eip4844(payload) => JsonExecutionPayload::V3(payload.into()), } } } @@ -235,46 +201,18 @@ impl From> for ExecutionPayloadCapella } } } -impl From> for ExecutionPayloadEip4844 { - fn from(payload: JsonExecutionPayloadV3) -> Self { - ExecutionPayloadEip4844 { - parent_hash: payload.parent_hash, - fee_recipient: payload.fee_recipient, - state_root: payload.state_root, - receipts_root: payload.receipts_root, - logs_bloom: payload.logs_bloom, - prev_randao: payload.prev_randao, - block_number: payload.block_number, - gas_limit: payload.gas_limit, - gas_used: payload.gas_used, - timestamp: payload.timestamp, - extra_data: payload.extra_data, - base_fee_per_gas: payload.base_fee_per_gas, - excess_data_gas: payload.excess_data_gas, - block_hash: payload.block_hash, - transactions: payload.transactions, - withdrawals: payload - .withdrawals - .into_iter() - .map(Into::into) - .collect::>() - .into(), - } - } -} impl From> for ExecutionPayload { fn from(json_execution_payload: JsonExecutionPayload) -> Self { match json_execution_payload { JsonExecutionPayload::V1(payload) => ExecutionPayload::Merge(payload.into()), JsonExecutionPayload::V2(payload) => ExecutionPayload::Capella(payload.into()), - JsonExecutionPayload::V3(payload) => ExecutionPayload::Eip4844(payload.into()), } } } #[superstruct( - variants(V1, V2, V3), + variants(V1, V2), variant_attributes( derive(Debug, PartialEq, Serialize, Deserialize), serde(bound = "T: EthSpec", rename_all = "camelCase") @@ -289,8 +227,6 @@ pub struct JsonGetPayloadResponse { pub execution_payload: JsonExecutionPayloadV1, #[superstruct(only(V2), partial_getter(rename = "execution_payload_v2"))] pub execution_payload: JsonExecutionPayloadV2, - #[superstruct(only(V3), partial_getter(rename = "execution_payload_v3"))] - pub execution_payload: JsonExecutionPayloadV3, #[serde(with = "eth2_serde_utils::u256_hex_be")] pub block_value: Uint256, } @@ -310,12 +246,6 @@ impl From> for GetPayloadResponse { block_value: response.block_value, }) } - JsonGetPayloadResponse::V3(response) => { - GetPayloadResponse::Eip4844(GetPayloadResponseEip4844 { - execution_payload: response.execution_payload.into(), - block_value: response.block_value, - }) - } } } } @@ -410,14 +340,6 @@ impl From for PayloadAttributes { } } -#[derive(Debug, PartialEq, Serialize, Deserialize)] -#[serde(bound = "T: EthSpec", rename_all = "camelCase")] -pub struct JsonBlobBundles { - pub block_hash: ExecutionBlockHash, - pub kzgs: Vec, - pub blobs: Vec>, -} - #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct JsonForkchoiceStateV1 { diff --git a/beacon_node/execution_layer/src/lib.rs b/beacon_node/execution_layer/src/lib.rs index af5e491556..d12f9996d8 100644 --- a/beacon_node/execution_layer/src/lib.rs +++ b/beacon_node/execution_layer/src/lib.rs @@ -26,6 +26,7 @@ use std::collections::HashMap; use std::fmt; use std::future::Future; use std::io::Write; +use std::marker::PhantomData; use std::path::PathBuf; use std::sync::Arc; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; @@ -37,12 +38,11 @@ use tokio::{ }; use tokio_stream::wrappers::WatchStream; use tree_hash::TreeHash; -use types::{AbstractExecPayload, BeaconStateError, Blob, ExecPayload, KzgCommitment, Withdrawals}; +use types::{AbstractExecPayload, BeaconStateError, ExecPayload, Withdrawals}; use types::{ BlindedPayload, BlockType, ChainSpec, Epoch, ExecutionBlockHash, ExecutionPayload, - ExecutionPayloadCapella, ExecutionPayloadEip4844, ExecutionPayloadMerge, ForkName, - ForkVersionedResponse, ProposerPreparationData, PublicKeyBytes, Signature, SignedBeaconBlock, - Slot, Uint256, + ExecutionPayloadCapella, ExecutionPayloadMerge, ForkName, ForkVersionedResponse, + ProposerPreparationData, PublicKeyBytes, Signature, SignedBeaconBlock, Slot, Uint256, }; mod block_hash; @@ -122,12 +122,8 @@ pub enum BlockProposalContents> { Payload { payload: Payload, block_value: Uint256, - }, - PayloadAndBlobs { - payload: Payload, - block_value: Uint256, - kzg_commitments: Vec, - blobs: Vec>, + // TODO: remove for 4844, since it appears in PayloadAndBlobs + _phantom: PhantomData, }, } @@ -137,12 +133,7 @@ impl> BlockProposalContents payload, - Self::PayloadAndBlobs { - payload, - block_value: _, - kzg_commitments: _, - blobs: _, + _phantom: _, } => payload, } } @@ -151,41 +142,8 @@ impl> BlockProposalContents payload, - Self::PayloadAndBlobs { - payload, - block_value: _, - kzg_commitments: _, - blobs: _, - } => payload, - } - } - pub fn kzg_commitments(&self) -> Option<&[KzgCommitment]> { - match self { - Self::Payload { - payload: _, - block_value: _, - } => None, - Self::PayloadAndBlobs { - payload: _, - block_value: _, - kzg_commitments, - blobs: _, - } => Some(kzg_commitments), - } - } - pub fn blobs(&self) -> Option<&[Blob]> { - match self { - Self::Payload { - payload: _, - block_value: _, - } => None, - Self::PayloadAndBlobs { - payload: _, - block_value: _, - kzg_commitments: _, - blobs, - } => Some(blobs), } } pub fn block_value(&self) -> &Uint256 { @@ -193,12 +151,7 @@ impl> BlockProposalContents block_value, - Self::PayloadAndBlobs { - payload: _, - block_value, - kzg_commitments: _, - blobs: _, + _phantom: _, } => block_value, } } @@ -208,14 +161,9 @@ impl> BlockProposalContents BlockProposalContents::PayloadAndBlobs { - payload: Payload::default_at_fork(fork_name)?, - block_value: Uint256::zero(), - blobs: vec![], - kzg_commitments: vec![], - }, }) } } @@ -271,6 +219,7 @@ struct Inner { payload_cache: PayloadCache, builder_profit_threshold: Uint256, log: Logger, + always_prefer_builder_payload: bool, } #[derive(Debug, Default, Clone, Serialize, Deserialize)] @@ -293,6 +242,7 @@ pub struct Config { /// The minimum value of an external payload for it to be considered in a proposal. pub builder_profit_threshold: u128, pub execution_timeout_multiplier: Option, + pub always_prefer_builder_payload: bool, } /// Provides access to one execution engine and provides a neat interface for consumption by the @@ -315,6 +265,7 @@ impl ExecutionLayer { default_datadir, builder_profit_threshold, execution_timeout_multiplier, + always_prefer_builder_payload, } = config; if urls.len() > 1 { @@ -387,6 +338,7 @@ impl ExecutionLayer { payload_cache: PayloadCache::default(), builder_profit_threshold: Uint256::from(builder_profit_threshold), log, + always_prefer_builder_payload, }; Ok(Self { @@ -848,7 +800,9 @@ impl ExecutionLayer { let relay_value = relay.data.message.value; let local_value = *local.block_value(); - if local_value >= relay_value { + if !self.inner.always_prefer_builder_payload + && local_value >= relay_value + { info!( self.log(), "Local block is more profitable than relay block"; @@ -871,6 +825,7 @@ impl ExecutionLayer { BlockProposalContents::Payload { payload: relay.data.message.header, block_value: relay.data.message.value, + _phantom: PhantomData::default(), }, )), Err(reason) if !reason.payload_invalid() => { @@ -925,6 +880,7 @@ impl ExecutionLayer { BlockProposalContents::Payload { payload: relay.data.message.header, block_value: relay.data.message.value, + _phantom: PhantomData::default(), }, )), // If the payload is valid then use it. The local EE failed @@ -933,6 +889,7 @@ impl ExecutionLayer { BlockProposalContents::Payload { payload: relay.data.message.header, block_value: relay.data.message.value, + _phantom: PhantomData::default(), }, )), Err(reason) => { @@ -1101,24 +1058,6 @@ impl ExecutionLayer { } }; - let blob_fut = async { - match current_fork { - ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => { - None - } - ForkName::Eip4844 => { - debug!( - self.log(), - "Issuing engine_getBlobsBundle"; - "suggested_fee_recipient" => ?payload_attributes.suggested_fee_recipient(), - "prev_randao" => ?payload_attributes.prev_randao(), - "timestamp" => payload_attributes.timestamp(), - "parent_hash" => ?parent_hash, - ); - Some(engine.api.get_blobs_bundle_v1::(payload_id).await) - } - } - }; let payload_fut = async { debug!( self.log(), @@ -1130,7 +1069,7 @@ impl ExecutionLayer { ); engine.api.get_payload::(current_fork, payload_id).await }; - let (blob, payload_response) = tokio::join!(blob_fut, payload_fut); + let payload_response = payload_fut.await; let (execution_payload, block_value) = payload_response.map(|payload_response| { if payload_response.execution_payload_ref().fee_recipient() != payload_attributes.suggested_fee_recipient() { error!( @@ -1154,20 +1093,11 @@ impl ExecutionLayer { } payload_response.into() })?; - if let Some(blob) = blob.transpose()? { - // FIXME(sean) cache blobs - Ok(BlockProposalContents::PayloadAndBlobs { - payload: execution_payload.into(), - block_value, - blobs: blob.blobs, - kzg_commitments: blob.kzgs, - }) - } else { - Ok(BlockProposalContents::Payload { - payload: execution_payload.into(), - block_value, - }) - } + Ok(BlockProposalContents::Payload { + payload: execution_payload.into(), + block_value, + _phantom: PhantomData::default(), + }) }) .await .map_err(Box::new) @@ -1667,7 +1597,6 @@ impl ExecutionLayer { return match fork { ForkName::Merge => Ok(Some(ExecutionPayloadMerge::default().into())), ForkName::Capella => Ok(Some(ExecutionPayloadCapella::default().into())), - ForkName::Eip4844 => Ok(Some(ExecutionPayloadEip4844::default().into())), ForkName::Base | ForkName::Altair => Err(ApiError::UnsupportedForkVariant( format!("called get_payload_by_block_hash_from_engine with {}", fork), )), @@ -1740,34 +1669,6 @@ impl ExecutionLayer { withdrawals, }) } - ExecutionBlockWithTransactions::Eip4844(eip4844_block) => { - let withdrawals = VariableList::new( - eip4844_block - .withdrawals - .into_iter() - .map(Into::into) - .collect(), - ) - .map_err(ApiError::DeserializeWithdrawals)?; - ExecutionPayload::Eip4844(ExecutionPayloadEip4844 { - parent_hash: eip4844_block.parent_hash, - fee_recipient: eip4844_block.fee_recipient, - state_root: eip4844_block.state_root, - receipts_root: eip4844_block.receipts_root, - logs_bloom: eip4844_block.logs_bloom, - prev_randao: eip4844_block.prev_randao, - block_number: eip4844_block.block_number, - gas_limit: eip4844_block.gas_limit, - gas_used: eip4844_block.gas_used, - timestamp: eip4844_block.timestamp, - extra_data: eip4844_block.extra_data, - base_fee_per_gas: eip4844_block.base_fee_per_gas, - excess_data_gas: eip4844_block.excess_data_gas, - block_hash: eip4844_block.block_hash, - transactions, - withdrawals, - }) - } }; Ok(Some(payload)) diff --git a/beacon_node/execution_layer/src/payload_status.rs b/beacon_node/execution_layer/src/payload_status.rs index 7db8e234d1..5405fd7009 100644 --- a/beacon_node/execution_layer/src/payload_status.rs +++ b/beacon_node/execution_layer/src/payload_status.rs @@ -10,7 +10,9 @@ use types::ExecutionBlockHash; pub enum PayloadStatus { Valid, Invalid { - latest_valid_hash: ExecutionBlockHash, + /// The EE will provide a `None` LVH when it is unable to determine the + /// latest valid ancestor. + latest_valid_hash: Option, validation_error: Option, }, Syncing, @@ -55,22 +57,10 @@ pub fn process_payload_status( }) } } - PayloadStatusV1Status::Invalid => { - if let Some(latest_valid_hash) = response.latest_valid_hash { - // The response is only valid if `latest_valid_hash` is not `null`. - Ok(PayloadStatus::Invalid { - latest_valid_hash, - validation_error: response.validation_error.clone(), - }) - } else { - Err(EngineError::Api { - error: ApiError::BadResponse( - "new_payload: response.status = INVALID but null latest_valid_hash" - .to_string(), - ), - }) - } - } + PayloadStatusV1Status::Invalid => Ok(PayloadStatus::Invalid { + latest_valid_hash: response.latest_valid_hash, + validation_error: response.validation_error, + }), PayloadStatusV1Status::InvalidBlockHash => { // In the interests of being liberal with what we accept, only raise a // warning here. diff --git a/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs b/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs index 63893375db..c016a16a21 100644 --- a/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs +++ b/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs @@ -13,8 +13,8 @@ use std::collections::HashMap; use tree_hash::TreeHash; use tree_hash_derive::TreeHash; use types::{ - EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadCapella, - ExecutionPayloadEip4844, ExecutionPayloadMerge, ForkName, Hash256, Uint256, + EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadMerge, + ForkName, Hash256, Uint256, }; const GAS_LIMIT: u64 = 16384; @@ -118,7 +118,6 @@ pub struct ExecutionBlockGenerator { * Post-merge fork triggers */ pub shanghai_time: Option, // withdrawals - pub eip4844_time: Option, // 4844 } impl ExecutionBlockGenerator { @@ -127,7 +126,6 @@ impl ExecutionBlockGenerator { terminal_block_number: u64, terminal_block_hash: ExecutionBlockHash, shanghai_time: Option, - eip4844_time: Option, ) -> Self { let mut gen = Self { head_block: <_>::default(), @@ -141,7 +139,6 @@ impl ExecutionBlockGenerator { next_payload_id: 0, payload_ids: <_>::default(), shanghai_time, - eip4844_time, }; gen.insert_pow_block(0).unwrap(); @@ -174,12 +171,9 @@ impl ExecutionBlockGenerator { } pub fn get_fork_at_timestamp(&self, timestamp: u64) -> ForkName { - match self.eip4844_time { - Some(fork_time) if timestamp >= fork_time => ForkName::Eip4844, - _ => match self.shanghai_time { - Some(fork_time) if timestamp >= fork_time => ForkName::Capella, - _ => ForkName::Merge, - }, + match self.shanghai_time { + Some(fork_time) if timestamp >= fork_time => ForkName::Capella, + _ => ForkName::Merge, } } @@ -490,67 +484,42 @@ impl ExecutionBlockGenerator { block_hash: ExecutionBlockHash::zero(), transactions: vec![].into(), }), - PayloadAttributes::V2(pa) => { - match self.get_fork_at_timestamp(pa.timestamp) { - ForkName::Merge => ExecutionPayload::Merge(ExecutionPayloadMerge { - parent_hash: forkchoice_state.head_block_hash, - fee_recipient: pa.suggested_fee_recipient, - receipts_root: Hash256::repeat_byte(42), - state_root: Hash256::repeat_byte(43), - logs_bloom: vec![0; 256].into(), - prev_randao: pa.prev_randao, - block_number: parent.block_number() + 1, - gas_limit: GAS_LIMIT, - gas_used: GAS_USED, - timestamp: pa.timestamp, - extra_data: "block gen was here".as_bytes().to_vec().into(), - base_fee_per_gas: Uint256::one(), - block_hash: ExecutionBlockHash::zero(), - transactions: vec![].into(), - }), - ForkName::Capella => { - ExecutionPayload::Capella(ExecutionPayloadCapella { - parent_hash: forkchoice_state.head_block_hash, - fee_recipient: pa.suggested_fee_recipient, - receipts_root: Hash256::repeat_byte(42), - state_root: Hash256::repeat_byte(43), - logs_bloom: vec![0; 256].into(), - prev_randao: pa.prev_randao, - block_number: parent.block_number() + 1, - gas_limit: GAS_LIMIT, - gas_used: GAS_USED, - timestamp: pa.timestamp, - extra_data: "block gen was here".as_bytes().to_vec().into(), - base_fee_per_gas: Uint256::one(), - block_hash: ExecutionBlockHash::zero(), - transactions: vec![].into(), - withdrawals: pa.withdrawals.clone().into(), - }) - } - ForkName::Eip4844 => { - ExecutionPayload::Eip4844(ExecutionPayloadEip4844 { - parent_hash: forkchoice_state.head_block_hash, - fee_recipient: pa.suggested_fee_recipient, - receipts_root: Hash256::repeat_byte(42), - state_root: Hash256::repeat_byte(43), - logs_bloom: vec![0; 256].into(), - prev_randao: pa.prev_randao, - block_number: parent.block_number() + 1, - gas_limit: GAS_LIMIT, - gas_used: GAS_USED, - timestamp: pa.timestamp, - extra_data: "block gen was here".as_bytes().to_vec().into(), - base_fee_per_gas: Uint256::one(), - // FIXME(4844): maybe this should be set to something? - excess_data_gas: Uint256::one(), - block_hash: ExecutionBlockHash::zero(), - transactions: vec![].into(), - withdrawals: pa.withdrawals.clone().into(), - }) - } - _ => unreachable!(), - } - } + PayloadAttributes::V2(pa) => match self.get_fork_at_timestamp(pa.timestamp) { + ForkName::Merge => ExecutionPayload::Merge(ExecutionPayloadMerge { + parent_hash: forkchoice_state.head_block_hash, + fee_recipient: pa.suggested_fee_recipient, + receipts_root: Hash256::repeat_byte(42), + state_root: Hash256::repeat_byte(43), + logs_bloom: vec![0; 256].into(), + prev_randao: pa.prev_randao, + block_number: parent.block_number() + 1, + gas_limit: GAS_LIMIT, + gas_used: GAS_USED, + timestamp: pa.timestamp, + extra_data: "block gen was here".as_bytes().to_vec().into(), + base_fee_per_gas: Uint256::one(), + block_hash: ExecutionBlockHash::zero(), + transactions: vec![].into(), + }), + ForkName::Capella => ExecutionPayload::Capella(ExecutionPayloadCapella { + parent_hash: forkchoice_state.head_block_hash, + fee_recipient: pa.suggested_fee_recipient, + receipts_root: Hash256::repeat_byte(42), + state_root: Hash256::repeat_byte(43), + logs_bloom: vec![0; 256].into(), + prev_randao: pa.prev_randao, + block_number: parent.block_number() + 1, + gas_limit: GAS_LIMIT, + gas_used: GAS_USED, + timestamp: pa.timestamp, + extra_data: "block gen was here".as_bytes().to_vec().into(), + base_fee_per_gas: Uint256::one(), + block_hash: ExecutionBlockHash::zero(), + transactions: vec![].into(), + withdrawals: pa.withdrawals.clone().into(), + }), + _ => unreachable!(), + }, }; *execution_payload.block_hash_mut() = @@ -641,7 +610,6 @@ mod test { TERMINAL_BLOCK, ExecutionBlockHash::zero(), None, - None, ); for i in 0..=TERMINAL_BLOCK { diff --git a/beacon_node/execution_layer/src/test_utils/handle_rpc.rs b/beacon_node/execution_layer/src/test_utils/handle_rpc.rs index 138c8f6bcb..2a54dfae61 100644 --- a/beacon_node/execution_layer/src/test_utils/handle_rpc.rs +++ b/beacon_node/execution_layer/src/test_utils/handle_rpc.rs @@ -223,7 +223,6 @@ pub async fn handle_rpc( }) .unwrap() } - _ => unreachable!(), }), _ => unreachable!(), } diff --git a/beacon_node/execution_layer/src/test_utils/mock_builder.rs b/beacon_node/execution_layer/src/test_utils/mock_builder.rs index 1997265013..668d1fb3b1 100644 --- a/beacon_node/execution_layer/src/test_utils/mock_builder.rs +++ b/beacon_node/execution_layer/src/test_utils/mock_builder.rs @@ -405,7 +405,7 @@ impl mev_rs::BlindedBlockProvider for MockBuilder { let payload_attributes = match fork { ForkName::Merge => PayloadAttributes::new(timestamp, *prev_randao, fee_recipient, None), // the withdrawals root is filled in by operations - ForkName::Capella | ForkName::Eip4844 => { + ForkName::Capella => { PayloadAttributes::new(timestamp, *prev_randao, fee_recipient, Some(vec![])) } ForkName::Base | ForkName::Altair => { @@ -452,7 +452,7 @@ impl mev_rs::BlindedBlockProvider for MockBuilder { value: to_ssz_rs(&Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI))?, public_key: self.builder_sk.public_key(), }), - ForkName::Base | ForkName::Altair | ForkName::Eip4844 => { + ForkName::Base | ForkName::Altair => { return Err(BlindedBlockProviderError::Custom(format!( "Unsupported fork: {}", fork diff --git a/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs b/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs index 1a5d1fd198..2b512d8b1c 100644 --- a/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs +++ b/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs @@ -29,7 +29,6 @@ impl MockExecutionLayer { DEFAULT_TERMINAL_BLOCK, None, None, - None, Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()), spec, None, @@ -41,7 +40,6 @@ impl MockExecutionLayer { executor: TaskExecutor, terminal_block: u64, shanghai_time: Option, - eip4844_time: Option, builder_threshold: Option, jwt_key: Option, spec: ChainSpec, @@ -57,7 +55,6 @@ impl MockExecutionLayer { terminal_block, spec.terminal_block_hash, shanghai_time, - eip4844_time, ); let url = SensitiveUrl::parse(&server.url()).unwrap(); diff --git a/beacon_node/execution_layer/src/test_utils/mod.rs b/beacon_node/execution_layer/src/test_utils/mod.rs index 077d29575e..36b24bfc39 100644 --- a/beacon_node/execution_layer/src/test_utils/mod.rs +++ b/beacon_node/execution_layer/src/test_utils/mod.rs @@ -58,7 +58,6 @@ pub struct MockExecutionConfig { pub terminal_block: u64, pub terminal_block_hash: ExecutionBlockHash, pub shanghai_time: Option, - pub eip4844_time: Option, } impl Default for MockExecutionConfig { @@ -70,7 +69,6 @@ impl Default for MockExecutionConfig { terminal_block_hash: ExecutionBlockHash::zero(), server_config: Config::default(), shanghai_time: None, - eip4844_time: None, } } } @@ -91,7 +89,6 @@ impl MockServer { DEFAULT_TERMINAL_BLOCK, ExecutionBlockHash::zero(), None, // FIXME(capella): should this be the default? - None, // FIXME(eip4844): should this be the default? ) } @@ -103,7 +100,6 @@ impl MockServer { terminal_block_hash, server_config, shanghai_time, - eip4844_time, } = config; let last_echo_request = Arc::new(RwLock::new(None)); let preloaded_responses = Arc::new(Mutex::new(vec![])); @@ -112,7 +108,6 @@ impl MockServer { terminal_block, terminal_block_hash, shanghai_time, - eip4844_time, ); let ctx: Arc> = Arc::new(Context { @@ -171,7 +166,6 @@ impl MockServer { terminal_block: u64, terminal_block_hash: ExecutionBlockHash, shanghai_time: Option, - eip4844_time: Option, ) -> Self { Self::new_with_config( handle, @@ -182,7 +176,6 @@ impl MockServer { terminal_block, terminal_block_hash, shanghai_time, - eip4844_time, }, ) } diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index a0975a5c73..6cca673b85 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -1123,9 +1123,7 @@ pub fn serve( chain: Arc>, network_tx: UnboundedSender>, log: Logger| async move { - // need to have cached the blob sidecar somewhere in the beacon chain - // to publish - publish_blocks::publish_block(None, block, None, chain, &network_tx, log) + publish_blocks::publish_block(None, block, chain, &network_tx, log) .await .map(|()| warp::reply()) }, @@ -2380,11 +2378,19 @@ pub fn serve( .and(not_while_syncing_filter.clone()) .and(warp::query::()) .and(chain_filter.clone()) + .and(log_filter.clone()) .and_then( |endpoint_version: EndpointVersion, slot: Slot, query: api_types::ValidatorBlocksQuery, - chain: Arc>| async move { + chain: Arc>, + log: Logger| async move { + debug!( + log, + "Block production request from HTTP API"; + "slot" => slot + ); + let randao_reveal = query.randao_reveal.decompress().map_err(|e| { warp_utils::reject::custom_bad_request(format!( "randao reveal is not a valid BLS signature: {:?}", @@ -3514,6 +3520,9 @@ pub fn serve( api_types::EventTopic::ContributionAndProof => { event_handler.subscribe_contributions() } + api_types::EventTopic::PayloadAttributes => { + event_handler.subscribe_payload_attributes() + } api_types::EventTopic::LateHead => { event_handler.subscribe_late_head() } diff --git a/beacon_node/http_api/src/metrics.rs b/beacon_node/http_api/src/metrics.rs index 6851913733..1c3ab1f680 100644 --- a/beacon_node/http_api/src/metrics.rs +++ b/beacon_node/http_api/src/metrics.rs @@ -41,16 +41,4 @@ lazy_static::lazy_static! { "http_api_block_published_very_late_total", "The count of times a block was published beyond the attestation deadline" ); - pub static ref HTTP_API_BLOB_BROADCAST_DELAY_TIMES: Result = try_create_histogram( - "http_api_blob_broadcast_delay_times", - "Time between start of the slot and when the blob was broadcast" - ); - pub static ref HTTP_API_BLOB_PUBLISHED_LATE_TOTAL: Result = try_create_int_counter( - "http_api_blob_published_late_total", - "The count of times a blob was published beyond more than half way to the attestation deadline" - ); - pub static ref HTTP_API_BLOB_PUBLISHED_VERY_LATE_TOTAL: Result = try_create_int_counter( - "http_api_blob_published_very_late_total", - "The count of times a blob was published beyond the attestation deadline" - ); } diff --git a/beacon_node/http_api/src/publish_blocks.rs b/beacon_node/http_api/src/publish_blocks.rs index 83ab8ceee6..673ead1f21 100644 --- a/beacon_node/http_api/src/publish_blocks.rs +++ b/beacon_node/http_api/src/publish_blocks.rs @@ -3,16 +3,16 @@ use beacon_chain::validator_monitor::{get_block_delay_ms, timestamp_now}; use beacon_chain::{ BeaconChain, BeaconChainTypes, BlockError, CountUnrealized, NotifyExecutionLayer, }; -use lighthouse_network::{PubsubMessage, SignedBeaconBlockAndBlobsSidecar}; +use lighthouse_network::PubsubMessage; use network::NetworkMessage; -use slog::{error, info, warn, Logger}; +use slog::{debug, error, info, warn, Logger}; use slot_clock::SlotClock; use std::sync::Arc; use tokio::sync::mpsc::UnboundedSender; use tree_hash::TreeHash; use types::{ - AbstractExecPayload, BlindedPayload, BlobsSidecar, EthSpec, ExecPayload, ExecutionBlockHash, - FullPayload, Hash256, SignedBeaconBlock, + AbstractExecPayload, BlindedPayload, EthSpec, ExecPayload, ExecutionBlockHash, FullPayload, + Hash256, SignedBeaconBlock, }; use warp::Rejection; @@ -20,32 +20,22 @@ use warp::Rejection; pub async fn publish_block( block_root: Option, block: Arc>, - blobs_sidecar: Option>>, chain: Arc>, network_tx: &UnboundedSender>, log: Logger, ) -> Result<(), Rejection> { let seen_timestamp = timestamp_now(); + debug!( + log, + "Signed block published to HTTP API"; + "slot" => block.slot() + ); + // Send the block, regardless of whether or not it is valid. The API // specification is very clear that this is the desired behaviour. - let message = match &*block { - SignedBeaconBlock::Eip4844(block) => { - if let Some(sidecar) = blobs_sidecar { - PubsubMessage::BeaconBlockAndBlobsSidecars(Arc::new( - SignedBeaconBlockAndBlobsSidecar { - beacon_block: block.clone(), - blobs_sidecar: (*sidecar).clone(), - }, - )) - } else { - //TODO(pawan): return an empty sidecar instead - return Err(warp_utils::reject::broadcast_without_import(String::new())); - } - } - _ => PubsubMessage::BeaconBlock(block.clone()), - }; + let message = PubsubMessage::BeaconBlock(block.clone()); crate::publish_pubsub_message(network_tx, message)?; // Determine the delay after the start of the slot, register it with metrics. @@ -160,7 +150,6 @@ pub async fn publish_blinded_block( publish_block::( Some(block_root), Arc::new(full_block), - None, chain, network_tx, log, diff --git a/beacon_node/http_api/tests/interactive_tests.rs b/beacon_node/http_api/tests/interactive_tests.rs index 7096fac425..7db1b22d67 100644 --- a/beacon_node/http_api/tests/interactive_tests.rs +++ b/beacon_node/http_api/tests/interactive_tests.rs @@ -2,13 +2,15 @@ use crate::common::*; use beacon_chain::{ chain_config::ReOrgThreshold, - test_utils::{AttestationStrategy, BlockStrategy}, + test_utils::{AttestationStrategy, BlockStrategy, SyncCommitteeStrategy}, }; use eth2::types::DepositContractData; use execution_layer::{ForkchoiceState, PayloadAttributes}; use parking_lot::Mutex; use slot_clock::SlotClock; -use state_processing::state_advance::complete_state_advance; +use state_processing::{ + per_block_processing::get_expected_withdrawals, state_advance::complete_state_advance, +}; use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; @@ -106,13 +108,15 @@ pub struct ReOrgTest { percent_head_votes: usize, should_re_org: bool, misprediction: bool, + /// Whether to expect withdrawals to change on epoch boundaries. + expect_withdrawals_change_on_epoch: bool, } impl Default for ReOrgTest { /// Default config represents a regular easy re-org. fn default() -> Self { Self { - head_slot: Slot::new(30), + head_slot: Slot::new(E::slots_per_epoch() - 2), parent_distance: 1, head_distance: 1, re_org_threshold: 20, @@ -122,6 +126,7 @@ impl Default for ReOrgTest { percent_head_votes: 0, should_re_org: true, misprediction: false, + expect_withdrawals_change_on_epoch: false, } } } @@ -136,13 +141,40 @@ pub async fn proposer_boost_re_org_zero_weight() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] pub async fn proposer_boost_re_org_epoch_boundary() { proposer_boost_re_org_test(ReOrgTest { - head_slot: Slot::new(31), + head_slot: Slot::new(E::slots_per_epoch() - 1), should_re_org: false, ..Default::default() }) .await; } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +pub async fn proposer_boost_re_org_epoch_boundary_skip1() { + // Proposing a block on a boundary after a skip will change the set of expected withdrawals + // sent in the payload attributes. + proposer_boost_re_org_test(ReOrgTest { + head_slot: Slot::new(2 * E::slots_per_epoch() - 2), + head_distance: 2, + should_re_org: false, + expect_withdrawals_change_on_epoch: true, + ..Default::default() + }) + .await; +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +pub async fn proposer_boost_re_org_epoch_boundary_skip32() { + // Propose a block at 64 after a whole epoch of skipped slots. + proposer_boost_re_org_test(ReOrgTest { + head_slot: Slot::new(E::slots_per_epoch() - 1), + head_distance: E::slots_per_epoch() + 1, + should_re_org: false, + expect_withdrawals_change_on_epoch: true, + ..Default::default() + }) + .await; +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] pub async fn proposer_boost_re_org_slot_after_epoch_boundary() { proposer_boost_re_org_test(ReOrgTest { @@ -187,7 +219,7 @@ pub async fn proposer_boost_re_org_finality() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] pub async fn proposer_boost_re_org_parent_distance() { proposer_boost_re_org_test(ReOrgTest { - head_slot: Slot::new(30), + head_slot: Slot::new(E::slots_per_epoch() - 2), parent_distance: 2, should_re_org: false, ..Default::default() @@ -198,7 +230,7 @@ pub async fn proposer_boost_re_org_parent_distance() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] pub async fn proposer_boost_re_org_head_distance() { proposer_boost_re_org_test(ReOrgTest { - head_slot: Slot::new(29), + head_slot: Slot::new(E::slots_per_epoch() - 3), head_distance: 2, should_re_org: false, ..Default::default() @@ -209,7 +241,7 @@ pub async fn proposer_boost_re_org_head_distance() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] pub async fn proposer_boost_re_org_very_unhealthy() { proposer_boost_re_org_test(ReOrgTest { - head_slot: Slot::new(31), + head_slot: Slot::new(E::slots_per_epoch() - 1), parent_distance: 2, head_distance: 2, percent_parent_votes: 10, @@ -225,7 +257,6 @@ pub async fn proposer_boost_re_org_very_unhealthy() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] pub async fn proposer_boost_re_org_weight_misprediction() { proposer_boost_re_org_test(ReOrgTest { - head_slot: Slot::new(30), percent_empty_votes: 70, percent_head_votes: 30, should_re_org: false, @@ -254,12 +285,13 @@ pub async fn proposer_boost_re_org_test( percent_head_votes, should_re_org, misprediction, + expect_withdrawals_change_on_epoch, }: ReOrgTest, ) { assert!(head_slot > 0); - // We require a network with execution enabled so we can check EL message timings. - let mut spec = ForkName::Merge.make_genesis_spec(E::default_spec()); + // Test using Capella so that we simulate conditions as similar to mainnet as possible. + let mut spec = ForkName::Capella.make_genesis_spec(E::default_spec()); spec.terminal_total_difficulty = 1.into(); // Ensure there are enough validators to have `attesters_per_slot`. @@ -323,13 +355,15 @@ pub async fn proposer_boost_re_org_test( ) .await; - // Create some chain depth. + // Create some chain depth. Sign sync committee signatures so validator balances don't dip + // below 32 ETH and become ineligible for withdrawals. harness.advance_slot(); harness - .extend_chain( + .extend_chain_with_sync( num_initial as usize, BlockStrategy::OnCanonicalHead, AttestationStrategy::AllValidators, + SyncCommitteeStrategy::AllValidators, ) .await; @@ -364,6 +398,16 @@ pub async fn proposer_boost_re_org_test( let slot_b = slot_a + parent_distance; let slot_c = slot_b + head_distance; + // We need to transition to at least epoch 2 in order to trigger + // `process_rewards_and_penalties`. This allows us to test withdrawals changes at epoch + // boundaries. + if expect_withdrawals_change_on_epoch { + assert!( + slot_c.epoch(E::slots_per_epoch()) >= 2, + "for withdrawals to change, test must end at an epoch >= 2" + ); + } + harness.advance_slot(); let (block_a_root, block_a, state_a) = harness .add_block_at_slot(slot_a, harness.get_current_state()) @@ -457,6 +501,10 @@ pub async fn proposer_boost_re_org_test( // Produce block C. // Advance state_b so we can get the proposer. + assert_eq!(state_b.slot(), slot_b); + let pre_advance_withdrawals = get_expected_withdrawals(&state_b, &harness.chain.spec) + .unwrap() + .to_vec(); complete_state_advance(&mut state_b, None, slot_c, &harness.chain.spec).unwrap(); let proposer_index = state_b @@ -514,6 +562,28 @@ pub async fn proposer_boost_re_org_test( .unwrap(); let payload_attribs = first_update.payload_attributes.as_ref().unwrap(); + // Check that withdrawals from the payload attributes match those computed from the parent's + // advanced state. + let expected_withdrawals = if should_re_org { + let mut state_a_advanced = state_a.clone(); + complete_state_advance(&mut state_a_advanced, None, slot_c, &harness.chain.spec).unwrap(); + get_expected_withdrawals(&state_a_advanced, &harness.chain.spec) + } else { + get_expected_withdrawals(&state_b, &harness.chain.spec) + } + .unwrap() + .to_vec(); + let payload_attribs_withdrawals = payload_attribs.withdrawals().unwrap(); + assert_eq!(expected_withdrawals, *payload_attribs_withdrawals); + assert!(!expected_withdrawals.is_empty()); + + if should_re_org + || expect_withdrawals_change_on_epoch + && slot_c.epoch(E::slots_per_epoch()) != slot_b.epoch(E::slots_per_epoch()) + { + assert_ne!(expected_withdrawals, pre_advance_withdrawals); + } + let lookahead = slot_clock .start_of(slot_c) .unwrap() diff --git a/beacon_node/http_metrics/src/lib.rs b/beacon_node/http_metrics/src/lib.rs index dfdb8f7ff1..2895506c3b 100644 --- a/beacon_node/http_metrics/src/lib.rs +++ b/beacon_node/http_metrics/src/lib.rs @@ -116,7 +116,13 @@ pub fn serve( .and_then(|ctx: Arc>| async move { Ok::<_, warp::Rejection>( metrics::gather_prometheus_metrics(&ctx) - .map(|body| Response::builder().status(200).body(body).unwrap()) + .map(|body| { + Response::builder() + .status(200) + .header("Content-Type", "text/plain") + .body(body) + .unwrap() + }) .unwrap_or_else(|e| { Response::builder() .status(500) diff --git a/beacon_node/http_metrics/tests/tests.rs b/beacon_node/http_metrics/tests/tests.rs index b3e02d4cb6..89fde32374 100644 --- a/beacon_node/http_metrics/tests/tests.rs +++ b/beacon_node/http_metrics/tests/tests.rs @@ -1,6 +1,7 @@ use beacon_chain::test_utils::EphemeralHarnessType; use environment::null_logger; use http_metrics::Config; +use reqwest::header::HeaderValue; use reqwest::StatusCode; use std::net::{IpAddr, Ipv4Addr}; use std::sync::Arc; @@ -45,7 +46,13 @@ async fn returns_200_ok() { listening_socket.port() ); - assert_eq!(reqwest::get(&url).await.unwrap().status(), StatusCode::OK); + let response = reqwest::get(&url).await.unwrap(); + + assert_eq!(response.status(), StatusCode::OK); + assert_eq!( + response.headers().get("Content-Type").unwrap(), + &HeaderValue::from_str("text/plain").unwrap() + ); } .await } diff --git a/beacon_node/lighthouse_network/src/config.rs b/beacon_node/lighthouse_network/src/config.rs index e403843323..1e32315019 100644 --- a/beacon_node/lighthouse_network/src/config.rs +++ b/beacon_node/lighthouse_network/src/config.rs @@ -305,9 +305,7 @@ pub fn gossipsub_config(network_load: u8, fork_context: Arc) -> Gos ) -> Vec { let topic_bytes = message.topic.as_str().as_bytes(); match fork_context.current_fork() { - // according to: https://github.com/ethereum/consensus-specs/blob/dev/specs/merge/p2p-interface.md#the-gossip-domain-gossipsub - // the derivation of the message-id remains the same in the merge and for eip 4844. - ForkName::Altair | ForkName::Merge | ForkName::Capella | ForkName::Eip4844 => { + ForkName::Altair | ForkName::Merge | ForkName::Capella => { let topic_len_bytes = topic_bytes.len().to_le_bytes(); let mut vec = Vec::with_capacity( prefix.len() + topic_len_bytes.len() + topic_bytes.len() + message.data.len(), diff --git a/beacon_node/lighthouse_network/src/lib.rs b/beacon_node/lighthouse_network/src/lib.rs index d7733f7cd3..be4da809cb 100644 --- a/beacon_node/lighthouse_network/src/lib.rs +++ b/beacon_node/lighthouse_network/src/lib.rs @@ -15,7 +15,6 @@ pub mod peer_manager; pub mod rpc; pub mod types; -pub use crate::types::SignedBeaconBlockAndBlobsSidecar; pub use config::gossip_max_size; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; diff --git a/beacon_node/lighthouse_network/src/peer_manager/mod.rs b/beacon_node/lighthouse_network/src/peer_manager/mod.rs index d9ea0dea03..03f6a746ac 100644 --- a/beacon_node/lighthouse_network/src/peer_manager/mod.rs +++ b/beacon_node/lighthouse_network/src/peer_manager/mod.rs @@ -534,7 +534,6 @@ impl PeerManager { Protocol::Ping => PeerAction::MidToleranceError, Protocol::BlocksByRange => PeerAction::MidToleranceError, Protocol::BlocksByRoot => PeerAction::MidToleranceError, - Protocol::BlobsByRange => PeerAction::MidToleranceError, Protocol::LightClientBootstrap => PeerAction::LowToleranceError, Protocol::Goodbye => PeerAction::LowToleranceError, Protocol::MetaData => PeerAction::LowToleranceError, @@ -551,7 +550,6 @@ impl PeerManager { Protocol::Ping => PeerAction::Fatal, Protocol::BlocksByRange => return, Protocol::BlocksByRoot => return, - Protocol::BlobsByRange => return, Protocol::Goodbye => return, Protocol::LightClientBootstrap => return, Protocol::MetaData => PeerAction::LowToleranceError, @@ -568,7 +566,6 @@ impl PeerManager { Protocol::Ping => PeerAction::LowToleranceError, Protocol::BlocksByRange => PeerAction::MidToleranceError, Protocol::BlocksByRoot => PeerAction::MidToleranceError, - Protocol::BlobsByRange => PeerAction::MidToleranceError, Protocol::LightClientBootstrap => return, Protocol::Goodbye => return, Protocol::MetaData => return, diff --git a/beacon_node/lighthouse_network/src/rpc/codec/base.rs b/beacon_node/lighthouse_network/src/rpc/codec/base.rs index 164a7c025d..6c6ce2da32 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec/base.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec/base.rs @@ -194,19 +194,16 @@ mod tests { let altair_fork_epoch = Epoch::new(1); let merge_fork_epoch = Epoch::new(2); let capella_fork_epoch = Epoch::new(3); - let eip4844_fork_epoch = Epoch::new(4); chain_spec.altair_fork_epoch = Some(altair_fork_epoch); chain_spec.bellatrix_fork_epoch = Some(merge_fork_epoch); chain_spec.capella_fork_epoch = Some(capella_fork_epoch); - chain_spec.eip4844_fork_epoch = Some(eip4844_fork_epoch); let current_slot = match fork_name { ForkName::Base => Slot::new(0), ForkName::Altair => altair_fork_epoch.start_slot(Spec::slots_per_epoch()), ForkName::Merge => merge_fork_epoch.start_slot(Spec::slots_per_epoch()), ForkName::Capella => capella_fork_epoch.start_slot(Spec::slots_per_epoch()), - ForkName::Eip4844 => eip4844_fork_epoch.start_slot(Spec::slots_per_epoch()), }; ForkContext::new::(current_slot, Hash256::zero(), &chain_spec) } diff --git a/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs b/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs index fe4c05fde7..28fea40a20 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs @@ -17,9 +17,8 @@ use std::sync::Arc; use tokio_util::codec::{Decoder, Encoder}; use types::light_client_bootstrap::LightClientBootstrap; use types::{ - BlobsSidecar, EthSpec, ForkContext, ForkName, Hash256, SignedBeaconBlock, - SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockCapella, - SignedBeaconBlockEip4844, SignedBeaconBlockMerge, + EthSpec, ForkContext, ForkName, Hash256, SignedBeaconBlock, SignedBeaconBlockAltair, + SignedBeaconBlockBase, SignedBeaconBlockCapella, SignedBeaconBlockMerge, }; use unsigned_varint::codec::Uvi; @@ -72,7 +71,6 @@ impl Encoder> for SSZSnappyInboundCodec< RPCResponse::Status(res) => res.as_ssz_bytes(), RPCResponse::BlocksByRange(res) => res.as_ssz_bytes(), RPCResponse::BlocksByRoot(res) => res.as_ssz_bytes(), - RPCResponse::BlobsByRange(res) => res.as_ssz_bytes(), RPCResponse::LightClientBootstrap(res) => res.as_ssz_bytes(), RPCResponse::Pong(res) => res.data.as_ssz_bytes(), RPCResponse::MetaData(res) => @@ -232,7 +230,6 @@ impl Encoder> for SSZSnappyOutboundCodec< OutboundRequest::Goodbye(req) => req.as_ssz_bytes(), OutboundRequest::BlocksByRange(req) => req.as_ssz_bytes(), OutboundRequest::BlocksByRoot(req) => req.block_roots.as_ssz_bytes(), - OutboundRequest::BlobsByRange(req) => req.as_ssz_bytes(), OutboundRequest::Ping(req) => req.as_ssz_bytes(), OutboundRequest::MetaData(_) => return Ok(()), // no metadata to encode OutboundRequest::LightClientBootstrap(req) => req.as_ssz_bytes(), @@ -413,10 +410,6 @@ fn context_bytes( return match **ref_box_block { // NOTE: If you are adding another fork type here, be sure to modify the // `fork_context.to_context_bytes()` function to support it as well! - SignedBeaconBlock::Eip4844 { .. } => { - // Eip4844 context being `None` implies that "merge never happened". - fork_context.to_context_bytes(ForkName::Eip4844) - } SignedBeaconBlock::Capella { .. } => { // Capella context being `None` implies that "merge never happened". fork_context.to_context_bytes(ForkName::Capella) @@ -483,9 +476,6 @@ fn handle_v1_request( Protocol::BlocksByRoot => Ok(Some(InboundRequest::BlocksByRoot(BlocksByRootRequest { block_roots: VariableList::from_ssz_bytes(decoded_buffer)?, }))), - Protocol::BlobsByRange => Ok(Some(InboundRequest::BlobsByRange( - BlobsByRangeRequest::from_ssz_bytes(decoded_buffer)?, - ))), Protocol::Ping => Ok(Some(InboundRequest::Ping(Ping { data: u64::from_ssz_bytes(decoded_buffer)?, }))), @@ -522,9 +512,6 @@ fn handle_v2_request( Protocol::BlocksByRoot => Ok(Some(InboundRequest::BlocksByRoot(BlocksByRootRequest { block_roots: VariableList::from_ssz_bytes(decoded_buffer)?, }))), - Protocol::BlobsByRange => Ok(Some(InboundRequest::BlobsByRange( - BlobsByRangeRequest::from_ssz_bytes(decoded_buffer)?, - ))), // MetaData requests return early from InboundUpgrade and do not reach the decoder. // Handle this case just for completeness. Protocol::MetaData => { @@ -562,7 +549,6 @@ fn handle_v1_response( Protocol::BlocksByRoot => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), )))), - Protocol::BlobsByRange => Err(RPCError::InvalidData("blobs by range via v1".to_string())), Protocol::Ping => Ok(Some(RPCResponse::Pong(Ping { data: u64::from_ssz_bytes(decoded_buffer)?, }))), @@ -619,11 +605,6 @@ fn handle_v2_response( decoded_buffer, )?), )))), - ForkName::Eip4844 => Ok(Some(RPCResponse::BlocksByRange(Arc::new( - SignedBeaconBlock::Eip4844(SignedBeaconBlockEip4844::from_ssz_bytes( - decoded_buffer, - )?), - )))), }, Protocol::BlocksByRoot => match fork_name { ForkName::Altair => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( @@ -644,20 +625,6 @@ fn handle_v2_response( decoded_buffer, )?), )))), - ForkName::Eip4844 => Ok(Some(RPCResponse::BlocksByRoot(Arc::new( - SignedBeaconBlock::Eip4844(SignedBeaconBlockEip4844::from_ssz_bytes( - decoded_buffer, - )?), - )))), - }, - Protocol::BlobsByRange => match fork_name { - ForkName::Eip4844 => Ok(Some(RPCResponse::BlobsByRange(Arc::new( - BlobsSidecar::from_ssz_bytes(decoded_buffer)?, - )))), - _ => Err(RPCError::ErrorResponse( - RPCResponseErrorCode::InvalidRequest, - "Invalid forkname for blobsbyrange".to_string(), - )), }, _ => Err(RPCError::ErrorResponse( RPCResponseErrorCode::InvalidRequest, @@ -708,19 +675,16 @@ mod tests { let altair_fork_epoch = Epoch::new(1); let merge_fork_epoch = Epoch::new(2); let capella_fork_epoch = Epoch::new(3); - let eip4844_fork_epoch = Epoch::new(4); chain_spec.altair_fork_epoch = Some(altair_fork_epoch); chain_spec.bellatrix_fork_epoch = Some(merge_fork_epoch); chain_spec.capella_fork_epoch = Some(capella_fork_epoch); - chain_spec.eip4844_fork_epoch = Some(eip4844_fork_epoch); let current_slot = match fork_name { ForkName::Base => Slot::new(0), ForkName::Altair => altair_fork_epoch.start_slot(Spec::slots_per_epoch()), ForkName::Merge => merge_fork_epoch.start_slot(Spec::slots_per_epoch()), ForkName::Capella => capella_fork_epoch.start_slot(Spec::slots_per_epoch()), - ForkName::Eip4844 => eip4844_fork_epoch.start_slot(Spec::slots_per_epoch()), }; ForkContext::new::(current_slot, Hash256::zero(), &chain_spec) } @@ -924,9 +888,6 @@ mod tests { OutboundRequest::BlocksByRoot(bbroot) => { assert_eq!(decoded, InboundRequest::BlocksByRoot(bbroot)) } - OutboundRequest::BlobsByRange(blbrange) => { - assert_eq!(decoded, InboundRequest::BlobsByRange(blbrange)) - } OutboundRequest::Ping(ping) => { assert_eq!(decoded, InboundRequest::Ping(ping)) } diff --git a/beacon_node/lighthouse_network/src/rpc/config.rs b/beacon_node/lighthouse_network/src/rpc/config.rs index e89d458503..bea0929fb0 100644 --- a/beacon_node/lighthouse_network/src/rpc/config.rs +++ b/beacon_node/lighthouse_network/src/rpc/config.rs @@ -67,7 +67,6 @@ pub struct OutboundRateLimiterConfig { pub(super) goodbye_quota: Quota, pub(super) blocks_by_range_quota: Quota, pub(super) blocks_by_root_quota: Quota, - pub(super) blobs_by_range_quota: Quota, } impl OutboundRateLimiterConfig { @@ -78,8 +77,6 @@ impl OutboundRateLimiterConfig { pub const DEFAULT_BLOCKS_BY_RANGE_QUOTA: Quota = Quota::n_every(methods::MAX_REQUEST_BLOCKS, 10); pub const DEFAULT_BLOCKS_BY_ROOT_QUOTA: Quota = Quota::n_every(128, 10); - pub const DEFAULT_BLOBS_BY_RANGE_QUOTA: Quota = - Quota::n_every(methods::MAX_REQUEST_BLOBS_SIDECARS, 10); } impl Default for OutboundRateLimiterConfig { @@ -91,7 +88,6 @@ impl Default for OutboundRateLimiterConfig { goodbye_quota: Self::DEFAULT_GOODBYE_QUOTA, blocks_by_range_quota: Self::DEFAULT_BLOCKS_BY_RANGE_QUOTA, blocks_by_root_quota: Self::DEFAULT_BLOCKS_BY_ROOT_QUOTA, - blobs_by_range_quota: Self::DEFAULT_BLOBS_BY_RANGE_QUOTA, } } } @@ -115,7 +111,6 @@ impl Debug for OutboundRateLimiterConfig { .field("goodbye", fmt_q!(&self.goodbye_quota)) .field("blocks_by_range", fmt_q!(&self.blocks_by_range_quota)) .field("blocks_by_root", fmt_q!(&self.blocks_by_root_quota)) - .field("blobs_by_range", fmt_q!(&self.blobs_by_range_quota)) .finish() } } @@ -134,7 +129,6 @@ impl FromStr for OutboundRateLimiterConfig { let mut goodbye_quota = None; let mut blocks_by_range_quota = None; let mut blocks_by_root_quota = None; - let mut blobs_by_range_quota = None; for proto_def in s.split(';') { let ProtocolQuota { protocol, quota } = proto_def.parse()?; let quota = Some(quota); @@ -145,7 +139,6 @@ impl FromStr for OutboundRateLimiterConfig { Protocol::BlocksByRoot => blocks_by_root_quota = blocks_by_root_quota.or(quota), Protocol::Ping => ping_quota = ping_quota.or(quota), Protocol::MetaData => meta_data_quota = meta_data_quota.or(quota), - Protocol::BlobsByRange => blobs_by_range_quota = blobs_by_range_quota.or(quota), Protocol::LightClientBootstrap => return Err("Lighthouse does not send LightClientBootstrap requests. Quota should not be set."), } } @@ -158,8 +151,6 @@ impl FromStr for OutboundRateLimiterConfig { .unwrap_or(Self::DEFAULT_BLOCKS_BY_RANGE_QUOTA), blocks_by_root_quota: blocks_by_root_quota .unwrap_or(Self::DEFAULT_BLOCKS_BY_ROOT_QUOTA), - blobs_by_range_quota: blobs_by_range_quota - .unwrap_or(Self::DEFAULT_BLOBS_BY_RANGE_QUOTA), }) } } diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index d66d587a07..5da595c3db 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -13,8 +13,7 @@ use std::sync::Arc; use strum::IntoStaticStr; use superstruct::superstruct; use types::{ - blobs_sidecar::BlobsSidecar, light_client_bootstrap::LightClientBootstrap, Epoch, EthSpec, - Hash256, SignedBeaconBlock, Slot, + light_client_bootstrap::LightClientBootstrap, Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot, }; /// Maximum number of blocks in a single request. @@ -25,9 +24,6 @@ pub const MAX_REQUEST_BLOCKS: u64 = 1024; pub type MaxErrorLen = U256; pub const MAX_ERROR_LEN: u64 = 256; -pub type MaxRequestBlobsSidecars = U1024; -pub const MAX_REQUEST_BLOBS_SIDECARS: u64 = 1024; - /// Wrapper over SSZ List to represent error message in rpc responses. #[derive(Debug, Clone)] pub struct ErrorType(pub VariableList); @@ -210,16 +206,6 @@ pub struct BlocksByRangeRequest { pub count: u64, } -/// Request a number of beacon blobs from a peer. -#[derive(Encode, Decode, Clone, Debug, PartialEq)] -pub struct BlobsByRangeRequest { - /// The starting slot to request blobs. - pub start_slot: u64, - - /// The number of blobs from the start slot. - pub count: u64, -} - /// Request a number of beacon block roots from a peer. #[derive(Encode, Decode, Clone, Debug, PartialEq)] pub struct OldBlocksByRangeRequest { @@ -259,9 +245,6 @@ pub enum RPCResponse { /// A response to a get BLOCKS_BY_ROOT request. BlocksByRoot(Arc>), - /// A response to a get BLOBS_BY_RANGE request - BlobsByRange(Arc>), - /// A response to a get LIGHTCLIENT_BOOTSTRAP request. LightClientBootstrap(LightClientBootstrap), @@ -280,9 +263,6 @@ pub enum ResponseTermination { /// Blocks by root stream termination. BlocksByRoot, - - /// Blobs by range stream termination. - BlobsByRange, } /// The structured response containing a result/code indicating success or failure @@ -350,7 +330,6 @@ impl RPCCodedResponse { RPCResponse::Status(_) => false, RPCResponse::BlocksByRange(_) => true, RPCResponse::BlocksByRoot(_) => true, - RPCResponse::BlobsByRange(_) => true, RPCResponse::Pong(_) => false, RPCResponse::MetaData(_) => false, RPCResponse::LightClientBootstrap(_) => false, @@ -386,7 +365,6 @@ impl RPCResponse { RPCResponse::Status(_) => Protocol::Status, RPCResponse::BlocksByRange(_) => Protocol::BlocksByRange, RPCResponse::BlocksByRoot(_) => Protocol::BlocksByRoot, - RPCResponse::BlobsByRange(_) => Protocol::BlobsByRange, RPCResponse::Pong(_) => Protocol::Ping, RPCResponse::MetaData(_) => Protocol::MetaData, RPCResponse::LightClientBootstrap(_) => Protocol::LightClientBootstrap, @@ -423,9 +401,6 @@ impl std::fmt::Display for RPCResponse { RPCResponse::BlocksByRoot(block) => { write!(f, "BlocksByRoot: Block slot: {}", block.slot()) } - RPCResponse::BlobsByRange(blob) => { - write!(f, "BlobsByRange: Blob slot: {}", blob.beacon_block_slot) - } RPCResponse::Pong(ping) => write!(f, "Pong: {}", ping.data), RPCResponse::MetaData(metadata) => write!(f, "Metadata: {}", metadata.seq_number()), RPCResponse::LightClientBootstrap(bootstrap) => { @@ -477,12 +452,6 @@ impl std::fmt::Display for OldBlocksByRangeRequest { } } -impl std::fmt::Display for BlobsByRangeRequest { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Start Slot: {}, Count: {}", self.start_slot, self.count) - } -} - impl slog::KV for StatusMessage { fn serialize( &self, diff --git a/beacon_node/lighthouse_network/src/rpc/mod.rs b/beacon_node/lighthouse_network/src/rpc/mod.rs index a455cef1a1..31569b820b 100644 --- a/beacon_node/lighthouse_network/src/rpc/mod.rs +++ b/beacon_node/lighthouse_network/src/rpc/mod.rs @@ -24,7 +24,6 @@ pub(crate) use handler::HandlerErr; pub(crate) use methods::{MetaData, MetaDataV1, MetaDataV2, Ping, RPCCodedResponse, RPCResponse}; pub(crate) use protocol::{InboundRequest, RPCProtocol}; -use crate::rpc::methods::MAX_REQUEST_BLOBS_SIDECARS; pub use handler::SubstreamId; pub use methods::{ BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, LightClientBootstrapRequest, @@ -145,11 +144,6 @@ impl RPC { Duration::from_secs(10), ) .n_every(Protocol::BlocksByRoot, 128, Duration::from_secs(10)) - .n_every( - Protocol::BlobsByRange, - MAX_REQUEST_BLOBS_SIDECARS, - Duration::from_secs(10), - ) .build() .expect("Configuration parameters are valid"); @@ -345,7 +339,6 @@ where match end { ResponseTermination::BlocksByRange => Protocol::BlocksByRange, ResponseTermination::BlocksByRoot => Protocol::BlocksByRoot, - ResponseTermination::BlobsByRange => Protocol::BlobsByRange, }, ), }, diff --git a/beacon_node/lighthouse_network/src/rpc/outbound.rs b/beacon_node/lighthouse_network/src/rpc/outbound.rs index 250df1fa6b..774303800e 100644 --- a/beacon_node/lighthouse_network/src/rpc/outbound.rs +++ b/beacon_node/lighthouse_network/src/rpc/outbound.rs @@ -38,7 +38,6 @@ pub enum OutboundRequest { Goodbye(GoodbyeReason), BlocksByRange(OldBlocksByRangeRequest), BlocksByRoot(BlocksByRootRequest), - BlobsByRange(BlobsByRangeRequest), LightClientBootstrap(LightClientBootstrapRequest), Ping(Ping), MetaData(PhantomData), @@ -77,11 +76,6 @@ impl OutboundRequest { ProtocolId::new(Protocol::BlocksByRoot, Version::V2, Encoding::SSZSnappy), ProtocolId::new(Protocol::BlocksByRoot, Version::V1, Encoding::SSZSnappy), ], - OutboundRequest::BlobsByRange(_) => vec![ProtocolId::new( - Protocol::BlobsByRange, - Version::V1, - Encoding::SSZSnappy, - )], OutboundRequest::Ping(_) => vec![ProtocolId::new( Protocol::Ping, Version::V1, @@ -106,7 +100,6 @@ impl OutboundRequest { OutboundRequest::Goodbye(_) => 0, OutboundRequest::BlocksByRange(req) => req.count, OutboundRequest::BlocksByRoot(req) => req.block_roots.len() as u64, - OutboundRequest::BlobsByRange(req) => req.count, OutboundRequest::Ping(_) => 1, OutboundRequest::MetaData(_) => 1, OutboundRequest::LightClientBootstrap(_) => 1, @@ -120,7 +113,6 @@ impl OutboundRequest { OutboundRequest::Goodbye(_) => Protocol::Goodbye, OutboundRequest::BlocksByRange(_) => Protocol::BlocksByRange, OutboundRequest::BlocksByRoot(_) => Protocol::BlocksByRoot, - OutboundRequest::BlobsByRange(_) => Protocol::BlobsByRange, OutboundRequest::Ping(_) => Protocol::Ping, OutboundRequest::MetaData(_) => Protocol::MetaData, OutboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap, @@ -135,7 +127,6 @@ impl OutboundRequest { // variants that have `multiple_responses()` can have values. OutboundRequest::BlocksByRange(_) => ResponseTermination::BlocksByRange, OutboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot, - OutboundRequest::BlobsByRange(_) => ResponseTermination::BlobsByRange, OutboundRequest::LightClientBootstrap(_) => unreachable!(), OutboundRequest::Status(_) => unreachable!(), OutboundRequest::Goodbye(_) => unreachable!(), @@ -192,7 +183,6 @@ impl std::fmt::Display for OutboundRequest { OutboundRequest::Goodbye(reason) => write!(f, "Goodbye: {}", reason), OutboundRequest::BlocksByRange(req) => write!(f, "Blocks by range: {}", req), OutboundRequest::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req), - OutboundRequest::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req), OutboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data), OutboundRequest::MetaData(_) => write!(f, "MetaData request"), OutboundRequest::LightClientBootstrap(bootstrap) => { diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index b6651021d8..8d7b22029d 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -20,9 +20,8 @@ use tokio_util::{ codec::Framed, compat::{Compat, FuturesAsyncReadCompatExt}, }; -use types::BlobsSidecar; use types::{ - BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockCapella, BeaconBlockMerge, Blob, + BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockCapella, BeaconBlockMerge, EmptyBlock, EthSpec, ForkContext, ForkName, Hash256, MainnetEthSpec, Signature, SignedBeaconBlock, }; @@ -84,12 +83,6 @@ lazy_static! { + types::ExecutionPayload::::max_execution_payload_capella_size() // adding max size of execution payload (~16gb) + ssz::BYTES_PER_LENGTH_OFFSET; // Adding the additional ssz offset for the `ExecutionPayload` field - pub static ref SIGNED_BEACON_BLOCK_EIP4844_MAX: usize = *SIGNED_BEACON_BLOCK_CAPELLA_MAX_WITHOUT_PAYLOAD - + types::ExecutionPayload::::max_execution_payload_eip4844_size() // adding max size of execution payload (~16gb) - + ssz::BYTES_PER_LENGTH_OFFSET // Adding the additional offsets for the `ExecutionPayload` - + (::ssz_fixed_len() * ::max_blobs_per_block()) - + ssz::BYTES_PER_LENGTH_OFFSET; // Length offset for the blob commitments field. - pub static ref BLOCKS_BY_ROOT_REQUEST_MIN: usize = VariableList::::from(Vec::::new()) .as_ssz_bytes() @@ -114,13 +107,6 @@ lazy_static! { ]) .as_ssz_bytes() .len(); - - pub static ref BLOBS_SIDECAR_MIN: usize = BlobsSidecar::::empty() - .as_ssz_bytes() - .len(); - - pub static ref BLOBS_SIDECAR_MAX: usize = *BLOBS_SIDECAR_MIN // Max size of variable length `blobs` field - + (MainnetEthSpec::max_blobs_per_block() * as Encode>::ssz_fixed_len()); } /// The maximum bytes that can be sent across the RPC pre-merge. @@ -128,8 +114,6 @@ pub(crate) const MAX_RPC_SIZE: usize = 1_048_576; // 1M /// The maximum bytes that can be sent across the RPC post-merge. pub(crate) const MAX_RPC_SIZE_POST_MERGE: usize = 10 * 1_048_576; // 10M pub(crate) const MAX_RPC_SIZE_POST_CAPELLA: usize = 10 * 1_048_576; // 10M - // FIXME(sean) should this be increased to account for blobs? -pub(crate) const MAX_RPC_SIZE_POST_EIP4844: usize = 10 * 1_048_576; // 10M /// The protocol prefix the RPC protocol id. const PROTOCOL_PREFIX: &str = "/eth2/beacon_chain/req"; /// Time allowed for the first byte of a request to arrive before we time out (Time To First Byte). @@ -144,7 +128,6 @@ pub fn max_rpc_size(fork_context: &ForkContext) -> usize { ForkName::Altair | ForkName::Base => MAX_RPC_SIZE, ForkName::Merge => MAX_RPC_SIZE_POST_MERGE, ForkName::Capella => MAX_RPC_SIZE_POST_CAPELLA, - ForkName::Eip4844 => MAX_RPC_SIZE_POST_EIP4844, } } @@ -169,10 +152,6 @@ pub fn rpc_block_limits_by_fork(current_fork: ForkName) -> RpcLimits { *SIGNED_BEACON_BLOCK_BASE_MIN, // Base block is smaller than altair and merge blocks *SIGNED_BEACON_BLOCK_CAPELLA_MAX, // Capella block is larger than base, altair and merge blocks ), - ForkName::Eip4844 => RpcLimits::new( - *SIGNED_BEACON_BLOCK_BASE_MIN, // Base block is smaller than altair and merge blocks - *SIGNED_BEACON_BLOCK_EIP4844_MAX, // EIP 4844 block is larger than all prior fork blocks - ), } } @@ -190,8 +169,6 @@ pub enum Protocol { /// The `BlocksByRoot` protocol name. #[strum(serialize = "beacon_blocks_by_root")] BlocksByRoot, - /// The `BlobsByRange` protocol name. - BlobsByRange, /// The `Ping` protocol name. Ping, /// The `MetaData` protocol name. @@ -327,10 +304,6 @@ impl ProtocolId { Protocol::BlocksByRoot => { RpcLimits::new(*BLOCKS_BY_ROOT_REQUEST_MIN, *BLOCKS_BY_ROOT_REQUEST_MAX) } - Protocol::BlobsByRange => RpcLimits::new( - ::ssz_fixed_len(), - ::ssz_fixed_len(), - ), Protocol::Ping => RpcLimits::new( ::ssz_fixed_len(), ::ssz_fixed_len(), @@ -353,7 +326,6 @@ impl ProtocolId { Protocol::Goodbye => RpcLimits::new(0, 0), // Goodbye request has no response Protocol::BlocksByRange => rpc_block_limits_by_fork(fork_context.current_fork()), Protocol::BlocksByRoot => rpc_block_limits_by_fork(fork_context.current_fork()), - Protocol::BlobsByRange => RpcLimits::new(*BLOBS_SIDECAR_MIN, *BLOBS_SIDECAR_MAX), Protocol::Ping => RpcLimits::new( ::ssz_fixed_len(), ::ssz_fixed_len(), @@ -471,7 +443,6 @@ pub enum InboundRequest { Goodbye(GoodbyeReason), BlocksByRange(OldBlocksByRangeRequest), BlocksByRoot(BlocksByRootRequest), - BlobsByRange(BlobsByRangeRequest), LightClientBootstrap(LightClientBootstrapRequest), Ping(Ping), MetaData(PhantomData), @@ -488,7 +459,6 @@ impl InboundRequest { InboundRequest::Goodbye(_) => 0, InboundRequest::BlocksByRange(req) => req.count, InboundRequest::BlocksByRoot(req) => req.block_roots.len() as u64, - InboundRequest::BlobsByRange(req) => req.count, InboundRequest::Ping(_) => 1, InboundRequest::MetaData(_) => 1, InboundRequest::LightClientBootstrap(_) => 1, @@ -502,7 +472,6 @@ impl InboundRequest { InboundRequest::Goodbye(_) => Protocol::Goodbye, InboundRequest::BlocksByRange(_) => Protocol::BlocksByRange, InboundRequest::BlocksByRoot(_) => Protocol::BlocksByRoot, - InboundRequest::BlobsByRange(_) => Protocol::BlobsByRange, InboundRequest::Ping(_) => Protocol::Ping, InboundRequest::MetaData(_) => Protocol::MetaData, InboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap, @@ -517,7 +486,6 @@ impl InboundRequest { // variants that have `multiple_responses()` can have values. InboundRequest::BlocksByRange(_) => ResponseTermination::BlocksByRange, InboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot, - InboundRequest::BlobsByRange(_) => ResponseTermination::BlobsByRange, InboundRequest::Status(_) => unreachable!(), InboundRequest::Goodbye(_) => unreachable!(), InboundRequest::Ping(_) => unreachable!(), @@ -624,7 +592,6 @@ impl std::fmt::Display for InboundRequest { InboundRequest::Goodbye(reason) => write!(f, "Goodbye: {}", reason), InboundRequest::BlocksByRange(req) => write!(f, "Blocks by range: {}", req), InboundRequest::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req), - InboundRequest::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req), InboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data), InboundRequest::MetaData(_) => write!(f, "MetaData request"), InboundRequest::LightClientBootstrap(bootstrap) => { diff --git a/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs b/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs index 163d9a84ea..a1f7b89a2f 100644 --- a/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs +++ b/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs @@ -93,8 +93,6 @@ pub struct RPCRateLimiter { bbrange_rl: Limiter, /// BlocksByRoot rate limiter. bbroots_rl: Limiter, - /// BlobsByRange rate limiter. - blbrange_rl: Limiter, /// LightClientBootstrap rate limiter. lcbootstrap_rl: Limiter, } @@ -123,8 +121,6 @@ pub struct RPCRateLimiterBuilder { bbrange_quota: Option, /// Quota for the BlocksByRoot protocol. bbroots_quota: Option, - /// Quota for the BlobsByRange protocol. - blbrange_quota: Option, /// Quota for the LightClientBootstrap protocol. lcbootstrap_quota: Option, } @@ -140,7 +136,6 @@ impl RPCRateLimiterBuilder { Protocol::Goodbye => self.goodbye_quota = q, Protocol::BlocksByRange => self.bbrange_quota = q, Protocol::BlocksByRoot => self.bbroots_quota = q, - Protocol::BlobsByRange => self.blbrange_quota = q, Protocol::LightClientBootstrap => self.lcbootstrap_quota = q, } self @@ -185,10 +180,6 @@ impl RPCRateLimiterBuilder { .lcbootstrap_quota .ok_or("LightClientBootstrap quota not specified")?; - let blbrange_quota = self - .blbrange_quota - .ok_or("BlobsByRange quota not specified")?; - // create the rate limiters let ping_rl = Limiter::from_quota(ping_quota)?; let metadata_rl = Limiter::from_quota(metadata_quota)?; @@ -196,7 +187,6 @@ impl RPCRateLimiterBuilder { let goodbye_rl = Limiter::from_quota(goodbye_quota)?; let bbroots_rl = Limiter::from_quota(bbroots_quota)?; let bbrange_rl = Limiter::from_quota(bbrange_quota)?; - let blbrange_rl = Limiter::from_quota(blbrange_quota)?; let lcbootstrap_rl = Limiter::from_quota(lcbootstrap_quote)?; // check for peers to prune every 30 seconds, starting in 30 seconds @@ -211,7 +201,6 @@ impl RPCRateLimiterBuilder { goodbye_rl, bbroots_rl, bbrange_rl, - blbrange_rl, lcbootstrap_rl, init_time: Instant::now(), }) @@ -265,7 +254,6 @@ impl RPCRateLimiter { Protocol::Goodbye => &mut self.goodbye_rl, Protocol::BlocksByRange => &mut self.bbrange_rl, Protocol::BlocksByRoot => &mut self.bbroots_rl, - Protocol::BlobsByRange => &mut self.blbrange_rl, Protocol::LightClientBootstrap => &mut self.lcbootstrap_rl, }; check(limiter) @@ -279,7 +267,6 @@ impl RPCRateLimiter { self.goodbye_rl.prune(time_since_start); self.bbrange_rl.prune(time_since_start); self.bbroots_rl.prune(time_since_start); - self.blbrange_rl.prune(time_since_start); } } diff --git a/beacon_node/lighthouse_network/src/rpc/self_limiter.rs b/beacon_node/lighthouse_network/src/rpc/self_limiter.rs index 61e9b46a90..451c6206f3 100644 --- a/beacon_node/lighthouse_network/src/rpc/self_limiter.rs +++ b/beacon_node/lighthouse_network/src/rpc/self_limiter.rs @@ -60,7 +60,6 @@ impl SelfRateLimiter { goodbye_quota, blocks_by_range_quota, blocks_by_root_quota, - blobs_by_range_quota, } = config; let limiter = RateLimiter::builder() @@ -70,7 +69,6 @@ impl SelfRateLimiter { .set_quota(Protocol::Goodbye, goodbye_quota) .set_quota(Protocol::BlocksByRange, blocks_by_range_quota) .set_quota(Protocol::BlocksByRoot, blocks_by_root_quota) - .set_quota(Protocol::BlobsByRange, blobs_by_range_quota) // Manually set the LightClientBootstrap quota, since we use the same rate limiter for // inbound and outbound requests, and the LightClientBootstrap is an only inbound // protocol. diff --git a/beacon_node/lighthouse_network/src/service/api_types.rs b/beacon_node/lighthouse_network/src/service/api_types.rs index 5152c187e3..bd3df79769 100644 --- a/beacon_node/lighthouse_network/src/service/api_types.rs +++ b/beacon_node/lighthouse_network/src/service/api_types.rs @@ -2,9 +2,8 @@ use std::sync::Arc; use libp2p::core::connection::ConnectionId; use types::light_client_bootstrap::LightClientBootstrap; -use types::{BlobsSidecar, EthSpec, SignedBeaconBlock}; +use types::{EthSpec, SignedBeaconBlock}; -use crate::rpc::methods::BlobsByRangeRequest; use crate::rpc::{ methods::{ BlocksByRangeRequest, BlocksByRootRequest, LightClientBootstrapRequest, @@ -34,8 +33,6 @@ pub enum Request { Status(StatusMessage), /// A blocks by range request. BlocksByRange(BlocksByRangeRequest), - /// A blobs by range request. - BlobsByRange(BlobsByRangeRequest), /// A request blocks root request. BlocksByRoot(BlocksByRootRequest), // light client bootstrap request @@ -53,7 +50,6 @@ impl std::convert::From for OutboundRequest { step: 1, }) } - Request::BlobsByRange(r) => OutboundRequest::BlobsByRange(r), Request::LightClientBootstrap(b) => OutboundRequest::LightClientBootstrap(b), Request::Status(s) => OutboundRequest::Status(s), } @@ -72,8 +68,6 @@ pub enum Response { Status(StatusMessage), /// A response to a get BLOCKS_BY_RANGE request. A None response signals the end of the batch. BlocksByRange(Option>>), - /// A response to a get BLOBS_BY_RANGE request. A None response signals the end of the batch. - BlobsByRange(Option>>), /// A response to a get BLOCKS_BY_ROOT request. BlocksByRoot(Option>>), /// A response to a LightClientUpdate request. @@ -91,10 +85,6 @@ impl std::convert::From> for RPCCodedResponse RPCCodedResponse::Success(RPCResponse::BlocksByRange(b)), None => RPCCodedResponse::StreamTermination(ResponseTermination::BlocksByRange), }, - Response::BlobsByRange(r) => match r { - Some(b) => RPCCodedResponse::Success(RPCResponse::BlobsByRange(b)), - None => RPCCodedResponse::StreamTermination(ResponseTermination::BlobsByRange), - }, Response::Status(s) => RPCCodedResponse::Success(RPCResponse::Status(s)), Response::LightClientBootstrap(b) => { RPCCodedResponse::Success(RPCResponse::LightClientBootstrap(b)) diff --git a/beacon_node/lighthouse_network/src/service/gossip_cache.rs b/beacon_node/lighthouse_network/src/service/gossip_cache.rs index d3971a7d74..2865d5b3f6 100644 --- a/beacon_node/lighthouse_network/src/service/gossip_cache.rs +++ b/beacon_node/lighthouse_network/src/service/gossip_cache.rs @@ -20,8 +20,6 @@ pub struct GossipCache { topic_msgs: HashMap, Key>>, /// Timeout for blocks. beacon_block: Option, - /// Timeout for blobs. - beacon_block_and_blobs_sidecar: Option, /// Timeout for aggregate attestations. aggregates: Option, /// Timeout for attestations. @@ -49,8 +47,6 @@ pub struct GossipCacheBuilder { default_timeout: Option, /// Timeout for blocks. beacon_block: Option, - /// Timeout for blob sidecars. - beacon_block_and_blobs_sidecar: Option, /// Timeout for aggregate attestations. aggregates: Option, /// Timeout for attestations. @@ -151,7 +147,6 @@ impl GossipCacheBuilder { let GossipCacheBuilder { default_timeout, beacon_block, - beacon_block_and_blobs_sidecar, aggregates, attestation, voluntary_exit, @@ -167,7 +162,6 @@ impl GossipCacheBuilder { expirations: DelayQueue::default(), topic_msgs: HashMap::default(), beacon_block: beacon_block.or(default_timeout), - beacon_block_and_blobs_sidecar: beacon_block_and_blobs_sidecar.or(default_timeout), aggregates: aggregates.or(default_timeout), attestation: attestation.or(default_timeout), voluntary_exit: voluntary_exit.or(default_timeout), @@ -193,7 +187,6 @@ impl GossipCache { pub fn insert(&mut self, topic: GossipTopic, data: Vec) { let expire_timeout = match topic.kind() { GossipKind::BeaconBlock => self.beacon_block, - GossipKind::BeaconBlocksAndBlobsSidecar => self.beacon_block_and_blobs_sidecar, GossipKind::BeaconAggregateAndProof => self.aggregates, GossipKind::Attestation(_) => self.attestation, GossipKind::VoluntaryExit => self.voluntary_exit, diff --git a/beacon_node/lighthouse_network/src/service/mod.rs b/beacon_node/lighthouse_network/src/service/mod.rs index 151eef4e80..e20b86e546 100644 --- a/beacon_node/lighthouse_network/src/service/mod.rs +++ b/beacon_node/lighthouse_network/src/service/mod.rs @@ -13,8 +13,8 @@ use crate::rpc::*; use crate::service::behaviour::BehaviourEvent; pub use crate::service::behaviour::Gossipsub; use crate::types::{ - subnet_from_topic_hash, GossipEncoding, GossipKind, GossipTopic, SnappyTransform, Subnet, - SubnetDiscovery, + fork_core_topics, subnet_from_topic_hash, GossipEncoding, GossipKind, GossipTopic, + SnappyTransform, Subnet, SubnetDiscovery, }; use crate::EnrExt; use crate::Eth2Enr; @@ -41,6 +41,7 @@ use std::{ sync::Arc, task::{Context, Poll}, }; +use types::ForkName; use types::{ consts::altair::SYNC_COMMITTEE_SUBNET_COUNT, EnrForkId, EthSpec, ForkContext, Slot, SubnetId, }; @@ -559,13 +560,20 @@ impl Network { self.unsubscribe(gossip_topic) } - /// Subscribe to all currently subscribed topics with the new fork digest. - pub fn subscribe_new_fork_topics(&mut self, new_fork_digest: [u8; 4]) { + /// Subscribe to all required topics for the `new_fork` with the given `new_fork_digest`. + pub fn subscribe_new_fork_topics(&mut self, new_fork: ForkName, new_fork_digest: [u8; 4]) { + // Subscribe to existing topics with new fork digest let subscriptions = self.network_globals.gossipsub_subscriptions.read().clone(); for mut topic in subscriptions.into_iter() { topic.fork_digest = new_fork_digest; self.subscribe(topic); } + + // Subscribe to core topics for the new fork + for kind in fork_core_topics(&new_fork) { + let topic = GossipTopic::new(kind, GossipEncoding::default(), new_fork_digest); + self.subscribe(topic); + } } /// Unsubscribe from all topics that doesn't have the given fork_digest @@ -998,9 +1006,6 @@ impl Network { Request::BlocksByRoot { .. } => { metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blocks_by_root"]) } - Request::BlobsByRange { .. } => { - metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blobs_by_range"]) - } } NetworkEvent::RequestReceived { peer_id, @@ -1264,14 +1269,6 @@ impl Network { ); Some(event) } - InboundRequest::BlobsByRange(req) => { - let event = self.build_request( - peer_request_id, - peer_id, - Request::BlobsByRange(req), - ); - Some(event) - } InboundRequest::LightClientBootstrap(req) => { let event = self.build_request( peer_request_id, @@ -1304,9 +1301,6 @@ impl Network { RPCResponse::BlocksByRange(resp) => { self.build_response(id, peer_id, Response::BlocksByRange(Some(resp))) } - RPCResponse::BlobsByRange(resp) => { - self.build_response(id, peer_id, Response::BlobsByRange(Some(resp))) - } RPCResponse::BlocksByRoot(resp) => { self.build_response(id, peer_id, Response::BlocksByRoot(Some(resp))) } @@ -1320,7 +1314,6 @@ impl Network { let response = match termination { ResponseTermination::BlocksByRange => Response::BlocksByRange(None), ResponseTermination::BlocksByRoot => Response::BlocksByRoot(None), - ResponseTermination::BlobsByRange => Response::BlobsByRange(None), }; self.build_response(id, peer_id, response) } diff --git a/beacon_node/lighthouse_network/src/types/mod.rs b/beacon_node/lighthouse_network/src/types/mod.rs index e8894cb711..e7457f25da 100644 --- a/beacon_node/lighthouse_network/src/types/mod.rs +++ b/beacon_node/lighthouse_network/src/types/mod.rs @@ -13,10 +13,10 @@ pub type EnrSyncCommitteeBitfield = BitVector<::SyncCommitteeSu pub type Enr = discv5::enr::Enr; pub use globals::NetworkGlobals; -pub use pubsub::{PubsubMessage, SignedBeaconBlockAndBlobsSidecar, SnappyTransform}; +pub use pubsub::{PubsubMessage, SnappyTransform}; pub use subnet::{Subnet, SubnetDiscovery}; pub use sync_state::{BackFillState, SyncState}; pub use topics::{ - subnet_from_topic_hash, GossipEncoding, GossipKind, GossipTopic, CORE_TOPICS, - LIGHT_CLIENT_GOSSIP_TOPICS, + core_topics_to_subscribe, fork_core_topics, subnet_from_topic_hash, GossipEncoding, GossipKind, + GossipTopic, LIGHT_CLIENT_GOSSIP_TOPICS, }; diff --git a/beacon_node/lighthouse_network/src/types/pubsub.rs b/beacon_node/lighthouse_network/src/types/pubsub.rs index 08efeb7c69..bb0397de1e 100644 --- a/beacon_node/lighthouse_network/src/types/pubsub.rs +++ b/beacon_node/lighthouse_network/src/types/pubsub.rs @@ -3,39 +3,23 @@ use crate::types::{GossipEncoding, GossipKind, GossipTopic}; use crate::TopicHash; use libp2p::gossipsub::{DataTransform, GossipsubMessage, RawGossipsubMessage}; -use serde_derive::{Deserialize, Serialize}; use snap::raw::{decompress_len, Decoder, Encoder}; use ssz::{Decode, Encode}; -use ssz_derive::{Decode, Encode}; use std::boxed::Box; use std::io::{Error, ErrorKind}; use std::sync::Arc; -use tree_hash_derive::TreeHash; use types::{ - Attestation, AttesterSlashing, BlobsSidecar, EthSpec, ForkContext, ForkName, - LightClientFinalityUpdate, LightClientOptimisticUpdate, ProposerSlashing, - SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockAltair, SignedBeaconBlockBase, - SignedBeaconBlockCapella, SignedBeaconBlockEip4844, SignedBeaconBlockMerge, - SignedBlsToExecutionChange, SignedContributionAndProof, SignedVoluntaryExit, SubnetId, - SyncCommitteeMessage, SyncSubnetId, + Attestation, AttesterSlashing, EthSpec, ForkContext, ForkName, LightClientFinalityUpdate, + LightClientOptimisticUpdate, ProposerSlashing, SignedAggregateAndProof, SignedBeaconBlock, + SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockCapella, + SignedBeaconBlockMerge, SignedBlsToExecutionChange, SignedContributionAndProof, + SignedVoluntaryExit, SubnetId, SyncCommitteeMessage, SyncSubnetId, }; -/// TODO(pawan): move this to consensus/types? strictly not a consensus type -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, PartialEq)] -#[serde(bound = "T: EthSpec")] -pub struct SignedBeaconBlockAndBlobsSidecar { - // TODO(pawan): switch to a SignedBeaconBlock and use ssz offsets for decoding to make this - // future proof? - pub beacon_block: SignedBeaconBlockEip4844, - pub blobs_sidecar: BlobsSidecar, -} - #[derive(Debug, Clone, PartialEq)] pub enum PubsubMessage { /// Gossipsub message providing notification of a new block. BeaconBlock(Arc>), - /// Gossipsub message providing notification of a new SignedBeaconBlock coupled with a blobs sidecar. - BeaconBlockAndBlobsSidecars(Arc>), /// Gossipsub message providing notification of a Aggregate attestation and associated proof. AggregateAndProofAttestation(Box>), /// Gossipsub message providing notification of a raw un-aggregated attestation with its shard id. @@ -129,9 +113,6 @@ impl PubsubMessage { pub fn kind(&self) -> GossipKind { match self { PubsubMessage::BeaconBlock(_) => GossipKind::BeaconBlock, - PubsubMessage::BeaconBlockAndBlobsSidecars(_) => { - GossipKind::BeaconBlocksAndBlobsSidecar - } PubsubMessage::AggregateAndProofAttestation(_) => GossipKind::BeaconAggregateAndProof, PubsubMessage::Attestation(attestation_data) => { GossipKind::Attestation(attestation_data.0) @@ -198,12 +179,6 @@ impl PubsubMessage { SignedBeaconBlockMerge::from_ssz_bytes(data) .map_err(|e| format!("{:?}", e))?, ), - Some(ForkName::Eip4844) => { - return Err( - "beacon_block topic is not used from eip4844 fork onwards" - .to_string(), - ) - } Some(ForkName::Capella) => SignedBeaconBlock::::Capella( SignedBeaconBlockCapella::from_ssz_bytes(data) .map_err(|e| format!("{:?}", e))?, @@ -217,28 +192,6 @@ impl PubsubMessage { }; Ok(PubsubMessage::BeaconBlock(Arc::new(beacon_block))) } - GossipKind::BeaconBlocksAndBlobsSidecar => { - match fork_context.from_context_bytes(gossip_topic.fork_digest) { - Some(ForkName::Eip4844) => { - let block_and_blobs_sidecar = - SignedBeaconBlockAndBlobsSidecar::from_ssz_bytes(data) - .map_err(|e| format!("{:?}", e))?; - Ok(PubsubMessage::BeaconBlockAndBlobsSidecars(Arc::new( - block_and_blobs_sidecar, - ))) - } - Some( - ForkName::Base - | ForkName::Altair - | ForkName::Merge - | ForkName::Capella, - ) - | None => Err(format!( - "beacon_blobs_and_sidecar topic invalid for given fork digest {:?}", - gossip_topic.fork_digest - )), - } - } GossipKind::VoluntaryExit => { let voluntary_exit = SignedVoluntaryExit::from_ssz_bytes(data) .map_err(|e| format!("{:?}", e))?; @@ -307,7 +260,6 @@ impl PubsubMessage { // messages for us. match &self { PubsubMessage::BeaconBlock(data) => data.as_ssz_bytes(), - PubsubMessage::BeaconBlockAndBlobsSidecars(data) => data.as_ssz_bytes(), PubsubMessage::AggregateAndProofAttestation(data) => data.as_ssz_bytes(), PubsubMessage::VoluntaryExit(data) => data.as_ssz_bytes(), PubsubMessage::ProposerSlashing(data) => data.as_ssz_bytes(), @@ -331,12 +283,6 @@ impl std::fmt::Display for PubsubMessage { block.slot(), block.message().proposer_index() ), - PubsubMessage::BeaconBlockAndBlobsSidecars(block_and_blob) => write!( - f, - "Beacon block and Blobs Sidecar: slot: {}, blobs: {}", - block_and_blob.beacon_block.message.slot, - block_and_blob.blobs_sidecar.blobs.len(), - ), PubsubMessage::AggregateAndProofAttestation(att) => write!( f, "Aggregate and Proof: slot: {}, index: {}, aggregator_index: {}", diff --git a/beacon_node/lighthouse_network/src/types/topics.rs b/beacon_node/lighthouse_network/src/types/topics.rs index b83b03d6b2..0e4aefbb5c 100644 --- a/beacon_node/lighthouse_network/src/types/topics.rs +++ b/beacon_node/lighthouse_network/src/types/topics.rs @@ -1,7 +1,7 @@ use libp2p::gossipsub::{IdentTopic as Topic, TopicHash}; use serde_derive::{Deserialize, Serialize}; use strum::AsRefStr; -use types::{SubnetId, SyncSubnetId}; +use types::{ForkName, SubnetId, SyncSubnetId}; use crate::Subnet; @@ -11,7 +11,6 @@ use crate::Subnet; pub const TOPIC_PREFIX: &str = "eth2"; pub const SSZ_SNAPPY_ENCODING_POSTFIX: &str = "ssz_snappy"; pub const BEACON_BLOCK_TOPIC: &str = "beacon_block"; -pub const BEACON_BLOCK_AND_BLOBS_SIDECAR_TOPIC: &str = "beacon_block_and_blobs_sidecar"; pub const BEACON_AGGREGATE_AND_PROOF_TOPIC: &str = "beacon_aggregate_and_proof"; pub const BEACON_ATTESTATION_PREFIX: &str = "beacon_attestation_"; pub const VOLUNTARY_EXIT_TOPIC: &str = "voluntary_exit"; @@ -23,21 +22,45 @@ pub const BLS_TO_EXECUTION_CHANGE_TOPIC: &str = "bls_to_execution_change"; pub const LIGHT_CLIENT_FINALITY_UPDATE: &str = "light_client_finality_update"; pub const LIGHT_CLIENT_OPTIMISTIC_UPDATE: &str = "light_client_optimistic_update"; -pub const CORE_TOPICS: [GossipKind; 7] = [ +pub const BASE_CORE_TOPICS: [GossipKind; 5] = [ GossipKind::BeaconBlock, GossipKind::BeaconAggregateAndProof, GossipKind::VoluntaryExit, GossipKind::ProposerSlashing, GossipKind::AttesterSlashing, - GossipKind::SignedContributionAndProof, - GossipKind::BlsToExecutionChange, ]; +pub const ALTAIR_CORE_TOPICS: [GossipKind; 1] = [GossipKind::SignedContributionAndProof]; + +pub const CAPELLA_CORE_TOPICS: [GossipKind; 1] = [GossipKind::BlsToExecutionChange]; + pub const LIGHT_CLIENT_GOSSIP_TOPICS: [GossipKind; 2] = [ GossipKind::LightClientFinalityUpdate, GossipKind::LightClientOptimisticUpdate, ]; +/// Returns the core topics associated with each fork that are new to the previous fork +pub fn fork_core_topics(fork_name: &ForkName) -> Vec { + match fork_name { + ForkName::Base => BASE_CORE_TOPICS.to_vec(), + ForkName::Altair => ALTAIR_CORE_TOPICS.to_vec(), + ForkName::Merge => vec![], + ForkName::Capella => CAPELLA_CORE_TOPICS.to_vec(), + } +} + +/// Returns all the topics that we need to subscribe to for a given fork +/// including topics from older forks and new topics for the current fork. +pub fn core_topics_to_subscribe(mut current_fork: ForkName) -> Vec { + let mut topics = fork_core_topics(¤t_fork); + while let Some(previous_fork) = current_fork.previous_fork() { + let previous_fork_topics = fork_core_topics(&previous_fork); + topics.extend(previous_fork_topics); + current_fork = previous_fork; + } + topics +} + /// A gossipsub topic which encapsulates the type of messages that should be sent and received over /// the pubsub protocol and the way the messages should be encoded. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] @@ -57,8 +80,6 @@ pub struct GossipTopic { pub enum GossipKind { /// Topic for publishing beacon blocks. BeaconBlock, - /// Topic for publishing beacon block coupled with blob sidecars. - BeaconBlocksAndBlobsSidecar, /// Topic for publishing aggregate attestations and proofs. BeaconAggregateAndProof, /// Topic for publishing raw attestations on a particular subnet. @@ -150,7 +171,6 @@ impl GossipTopic { let kind = match topic_parts[3] { BEACON_BLOCK_TOPIC => GossipKind::BeaconBlock, BEACON_AGGREGATE_AND_PROOF_TOPIC => GossipKind::BeaconAggregateAndProof, - BEACON_BLOCK_AND_BLOBS_SIDECAR_TOPIC => GossipKind::BeaconBlocksAndBlobsSidecar, SIGNED_CONTRIBUTION_AND_PROOF_TOPIC => GossipKind::SignedContributionAndProof, VOLUNTARY_EXIT_TOPIC => GossipKind::VoluntaryExit, PROPOSER_SLASHING_TOPIC => GossipKind::ProposerSlashing, @@ -207,7 +227,6 @@ impl std::fmt::Display for GossipTopic { let kind = match self.kind { GossipKind::BeaconBlock => BEACON_BLOCK_TOPIC.into(), - GossipKind::BeaconBlocksAndBlobsSidecar => BEACON_BLOCK_AND_BLOBS_SIDECAR_TOPIC.into(), GossipKind::BeaconAggregateAndProof => BEACON_AGGREGATE_AND_PROOF_TOPIC.into(), GossipKind::VoluntaryExit => VOLUNTARY_EXIT_TOPIC.into(), GossipKind::ProposerSlashing => PROPOSER_SLASHING_TOPIC.into(), @@ -292,7 +311,6 @@ mod tests { VoluntaryExit, ProposerSlashing, AttesterSlashing, - BeaconBlocksAndBlobsSidecar, ] .iter() { @@ -396,4 +414,15 @@ mod tests { assert_eq!("proposer_slashing", ProposerSlashing.as_ref()); assert_eq!("attester_slashing", AttesterSlashing.as_ref()); } + + #[test] + fn test_core_topics_to_subscribe() { + let mut all_topics = Vec::new(); + all_topics.extend(CAPELLA_CORE_TOPICS); + all_topics.extend(ALTAIR_CORE_TOPICS); + all_topics.extend(BASE_CORE_TOPICS); + + let latest_fork = *ForkName::list_all().last().unwrap(); + assert_eq!(core_topics_to_subscribe(latest_fork), all_topics); + } } diff --git a/beacon_node/lighthouse_network/tests/common.rs b/beacon_node/lighthouse_network/tests/common.rs index 8cc46940b9..dfceb6c4c6 100644 --- a/beacon_node/lighthouse_network/tests/common.rs +++ b/beacon_node/lighthouse_network/tests/common.rs @@ -26,19 +26,16 @@ pub fn fork_context(fork_name: ForkName) -> ForkContext { let altair_fork_epoch = Epoch::new(1); let merge_fork_epoch = Epoch::new(2); let capella_fork_epoch = Epoch::new(3); - let eip4844_fork_epoch = Epoch::new(4); chain_spec.altair_fork_epoch = Some(altair_fork_epoch); chain_spec.bellatrix_fork_epoch = Some(merge_fork_epoch); chain_spec.capella_fork_epoch = Some(capella_fork_epoch); - chain_spec.eip4844_fork_epoch = Some(eip4844_fork_epoch); let current_slot = match fork_name { ForkName::Base => Slot::new(0), ForkName::Altair => altair_fork_epoch.start_slot(E::slots_per_epoch()), ForkName::Merge => merge_fork_epoch.start_slot(E::slots_per_epoch()), ForkName::Capella => capella_fork_epoch.start_slot(E::slots_per_epoch()), - ForkName::Eip4844 => eip4844_fork_epoch.start_slot(E::slots_per_epoch()), }; ForkContext::new::(current_slot, Hash256::zero(), &chain_spec) } diff --git a/beacon_node/network/src/beacon_processor/mod.rs b/beacon_node/network/src/beacon_processor/mod.rs index 018e6f7e34..61e3367e2f 100644 --- a/beacon_node/network/src/beacon_processor/mod.rs +++ b/beacon_node/network/src/beacon_processor/mod.rs @@ -45,9 +45,7 @@ use beacon_chain::{BeaconChain, BeaconChainTypes, GossipVerifiedBlock, NotifyExe use derivative::Derivative; use futures::stream::{Stream, StreamExt}; use futures::task::Poll; -use lighthouse_network::rpc::methods::BlobsByRangeRequest; use lighthouse_network::rpc::LightClientBootstrapRequest; -use lighthouse_network::SignedBeaconBlockAndBlobsSidecar; use lighthouse_network::{ rpc::{BlocksByRangeRequest, BlocksByRootRequest, StatusMessage}, Client, MessageId, NetworkGlobals, PeerId, PeerRequestId, @@ -116,10 +114,6 @@ const MAX_AGGREGATED_ATTESTATION_REPROCESS_QUEUE_LEN: usize = 1_024; /// before we start dropping them. const MAX_GOSSIP_BLOCK_QUEUE_LEN: usize = 1_024; -/// The maximum number of queued `SignedBeaconBlockAndBlobsSidecar` objects received on gossip that -/// will be stored before we start dropping them. -const MAX_GOSSIP_BLOCK_AND_BLOB_QUEUE_LEN: usize = 1_024; - /// The maximum number of queued `SignedBeaconBlock` objects received prior to their slot (but /// within acceptable clock disparity) that will be queued before we start dropping them. const MAX_DELAYED_BLOCK_QUEUE_LEN: usize = 1_024; @@ -172,8 +166,6 @@ const MAX_STATUS_QUEUE_LEN: usize = 1_024; /// will be stored before we start dropping them. const MAX_BLOCKS_BY_RANGE_QUEUE_LEN: usize = 1_024; -const MAX_BLOBS_BY_RANGE_QUEUE_LEN: usize = 1_024; - /// The maximum number of queued `BlocksByRootRequest` objects received from the network RPC that /// will be stored before we start dropping them. const MAX_BLOCKS_BY_ROOTS_QUEUE_LEN: usize = 1_024; @@ -216,7 +208,6 @@ pub const GOSSIP_ATTESTATION_BATCH: &str = "gossip_attestation_batch"; pub const GOSSIP_AGGREGATE: &str = "gossip_aggregate"; pub const GOSSIP_AGGREGATE_BATCH: &str = "gossip_aggregate_batch"; pub const GOSSIP_BLOCK: &str = "gossip_block"; -pub const GOSSIP_BLOCK_AND_BLOBS_SIDECAR: &str = "gossip_block_and_blobs_sidecar"; pub const DELAYED_IMPORT_BLOCK: &str = "delayed_import_block"; pub const GOSSIP_VOLUNTARY_EXIT: &str = "gossip_voluntary_exit"; pub const GOSSIP_PROPOSER_SLASHING: &str = "gossip_proposer_slashing"; @@ -230,7 +221,6 @@ pub const CHAIN_SEGMENT: &str = "chain_segment"; pub const STATUS_PROCESSING: &str = "status_processing"; pub const BLOCKS_BY_RANGE_REQUEST: &str = "blocks_by_range_request"; pub const BLOCKS_BY_ROOTS_REQUEST: &str = "blocks_by_roots_request"; -pub const BLOBS_BY_RANGE_REQUEST: &str = "blobs_by_range_request"; pub const LIGHT_CLIENT_BOOTSTRAP_REQUEST: &str = "light_client_bootstrap"; pub const UNKNOWN_BLOCK_ATTESTATION: &str = "unknown_block_attestation"; pub const UNKNOWN_BLOCK_AGGREGATE: &str = "unknown_block_aggregate"; @@ -439,26 +429,6 @@ impl WorkEvent { } } - /// Create a new `Work` event for some blobs sidecar. - pub fn gossip_block_and_blobs_sidecar( - message_id: MessageId, - peer_id: PeerId, - peer_client: Client, - block_and_blobs: Arc>, - seen_timestamp: Duration, - ) -> Self { - Self { - drop_during_sync: false, - work: Work::GossipBlockAndBlobsSidecar { - message_id, - peer_id, - peer_client, - block_and_blobs, - seen_timestamp, - }, - } - } - /// Create a new `Work` event for some sync committee signature. pub fn gossip_sync_signature( message_id: MessageId, @@ -668,21 +638,6 @@ impl WorkEvent { } } - pub fn blobs_by_range_request( - peer_id: PeerId, - request_id: PeerRequestId, - request: BlobsByRangeRequest, - ) -> Self { - Self { - drop_during_sync: false, - work: Work::BlobsByRangeRequest { - peer_id, - request_id, - request, - }, - } - } - /// Create a new work event to process `LightClientBootstrap`s from the RPC network. pub fn lightclient_bootstrap_request( peer_id: PeerId, @@ -838,13 +793,6 @@ pub enum Work { block: Arc>, seen_timestamp: Duration, }, - GossipBlockAndBlobsSidecar { - message_id: MessageId, - peer_id: PeerId, - peer_client: Client, - block_and_blobs: Arc>, - seen_timestamp: Duration, - }, DelayedImportBlock { peer_id: PeerId, block: Box>, @@ -915,11 +863,6 @@ pub enum Work { request_id: PeerRequestId, request: BlocksByRootRequest, }, - BlobsByRangeRequest { - peer_id: PeerId, - request_id: PeerRequestId, - request: BlobsByRangeRequest, - }, GossipBlsToExecutionChange { message_id: MessageId, peer_id: PeerId, @@ -941,7 +884,6 @@ impl Work { Work::GossipAggregate { .. } => GOSSIP_AGGREGATE, Work::GossipAggregateBatch { .. } => GOSSIP_AGGREGATE_BATCH, Work::GossipBlock { .. } => GOSSIP_BLOCK, - Work::GossipBlockAndBlobsSidecar { .. } => GOSSIP_BLOCK_AND_BLOBS_SIDECAR, Work::DelayedImportBlock { .. } => DELAYED_IMPORT_BLOCK, Work::GossipVoluntaryExit { .. } => GOSSIP_VOLUNTARY_EXIT, Work::GossipProposerSlashing { .. } => GOSSIP_PROPOSER_SLASHING, @@ -955,7 +897,6 @@ impl Work { Work::Status { .. } => STATUS_PROCESSING, Work::BlocksByRangeRequest { .. } => BLOCKS_BY_RANGE_REQUEST, Work::BlocksByRootsRequest { .. } => BLOCKS_BY_ROOTS_REQUEST, - Work::BlobsByRangeRequest { .. } => BLOBS_BY_RANGE_REQUEST, Work::LightClientBootstrapRequest { .. } => LIGHT_CLIENT_BOOTSTRAP_REQUEST, Work::UnknownBlockAttestation { .. } => UNKNOWN_BLOCK_ATTESTATION, Work::UnknownBlockAggregate { .. } => UNKNOWN_BLOCK_AGGREGATE, @@ -1103,14 +1044,11 @@ impl BeaconProcessor { let mut chain_segment_queue = FifoQueue::new(MAX_CHAIN_SEGMENT_QUEUE_LEN); let mut backfill_chain_segment = FifoQueue::new(MAX_CHAIN_SEGMENT_QUEUE_LEN); let mut gossip_block_queue = FifoQueue::new(MAX_GOSSIP_BLOCK_QUEUE_LEN); - let mut gossip_block_and_blobs_sidecar_queue = - FifoQueue::new(MAX_GOSSIP_BLOCK_AND_BLOB_QUEUE_LEN); let mut delayed_block_queue = FifoQueue::new(MAX_DELAYED_BLOCK_QUEUE_LEN); let mut status_queue = FifoQueue::new(MAX_STATUS_QUEUE_LEN); let mut bbrange_queue = FifoQueue::new(MAX_BLOCKS_BY_RANGE_QUEUE_LEN); let mut bbroots_queue = FifoQueue::new(MAX_BLOCKS_BY_ROOTS_QUEUE_LEN); - let mut blbrange_queue = FifoQueue::new(MAX_BLOBS_BY_RANGE_QUEUE_LEN); let mut gossip_bls_to_execution_change_queue = FifoQueue::new(MAX_BLS_TO_EXECUTION_CHANGE_QUEUE_LEN); @@ -1217,8 +1155,6 @@ impl BeaconProcessor { // required to verify some attestations. } else if let Some(item) = gossip_block_queue.pop() { self.spawn_worker(item, toolbox); - } else if let Some(item) = gossip_block_and_blobs_sidecar_queue.pop() { - self.spawn_worker(item, toolbox); // Check the aggregates, *then* the unaggregates since we assume that // aggregates are more valuable to local validators and effectively give us // more information with less signature verification time. @@ -1428,9 +1364,6 @@ impl BeaconProcessor { Work::GossipBlock { .. } => { gossip_block_queue.push(work, work_id, &self.log) } - Work::GossipBlockAndBlobsSidecar { .. } => { - gossip_block_and_blobs_sidecar_queue.push(work, work_id, &self.log) - } Work::DelayedImportBlock { .. } => { delayed_block_queue.push(work, work_id, &self.log) } @@ -1470,9 +1403,6 @@ impl BeaconProcessor { Work::BlocksByRootsRequest { .. } => { bbroots_queue.push(work, work_id, &self.log) } - Work::BlobsByRangeRequest { .. } => { - blbrange_queue.push(work, work_id, &self.log) - } Work::LightClientBootstrapRequest { .. } => { lcbootstrap_queue.push(work, work_id, &self.log) } @@ -1705,12 +1635,6 @@ impl BeaconProcessor { ) .await }), - /* - * Verification for blobs sidecars received on gossip. - */ - Work::GossipBlockAndBlobsSidecar { .. } => { - warn!(self.log, "Unexpected block and blobs on gossip") - } /* * Import for blocks that we received earlier than their intended slot. */ @@ -1912,9 +1836,6 @@ impl BeaconProcessor { request, ) }), - Work::BlobsByRangeRequest { .. } => { - warn!(self.log.clone(), "Unexpected BlobsByRange Request") - } /* * Processing of lightclient bootstrap requests from other peers. */ diff --git a/beacon_node/network/src/metrics.rs b/beacon_node/network/src/metrics.rs index ee029e1351..09caaaa11e 100644 --- a/beacon_node/network/src/metrics.rs +++ b/beacon_node/network/src/metrics.rs @@ -167,15 +167,6 @@ lazy_static! { "beacon_processor_rpc_block_imported_total", "Total number of gossip blocks imported to fork choice, etc." ); - // Rpc blobs. - pub static ref BEACON_PROCESSOR_RPC_BLOB_QUEUE_TOTAL: Result = try_create_int_gauge( - "beacon_processor_rpc_blob_queue_total", - "Count of blobs from the rpc waiting to be verified." - ); - pub static ref BEACON_PROCESSOR_RPC_BLOB_IMPORTED_TOTAL: Result = try_create_int_counter( - "beacon_processor_rpc_blob_imported_total", - "Total number of gossip blobs imported." - ); // Chain segments. pub static ref BEACON_PROCESSOR_CHAIN_SEGMENT_QUEUE_TOTAL: Result = try_create_int_gauge( "beacon_processor_chain_segment_queue_total", diff --git a/beacon_node/network/src/router/mod.rs b/beacon_node/network/src/router/mod.rs index ceb5abc568..231f30f3ee 100644 --- a/beacon_node/network/src/router/mod.rs +++ b/beacon_node/network/src/router/mod.rs @@ -168,9 +168,6 @@ impl Router { Request::BlocksByRoot(request) => self .processor .on_blocks_by_root_request(peer_id, id, request), - Request::BlobsByRange(request) => self - .processor - .on_blobs_by_range_request(peer_id, id, request), Request::LightClientBootstrap(request) => self .processor .on_lightclient_bootstrap(peer_id, id, request), @@ -198,10 +195,6 @@ impl Router { self.processor .on_blocks_by_root_response(peer_id, request_id, beacon_block); } - Response::BlobsByRange(beacon_blob) => { - self.processor - .on_blobs_by_range_response(peer_id, request_id, beacon_blob); - } Response::LightClientBootstrap(_) => unreachable!(), } } @@ -240,14 +233,6 @@ impl Router { block, ); } - PubsubMessage::BeaconBlockAndBlobsSidecars(block_and_blobs) => { - self.processor.on_block_and_blobs_sidecar_gossip( - id, - peer_id, - self.network_globals.client(&peer_id), - block_and_blobs, - ); - } PubsubMessage::VoluntaryExit(exit) => { debug!(self.log, "Received a voluntary exit"; "peer_id" => %peer_id); self.processor.on_voluntary_exit_gossip(id, peer_id, exit); diff --git a/beacon_node/network/src/router/processor.rs b/beacon_node/network/src/router/processor.rs index cd42c57fca..d3ba024e4c 100644 --- a/beacon_node/network/src/router/processor.rs +++ b/beacon_node/network/src/router/processor.rs @@ -6,8 +6,7 @@ use crate::status::status_message; use crate::sync::manager::RequestId as SyncId; use crate::sync::SyncMessage; use beacon_chain::{BeaconChain, BeaconChainTypes}; -use lighthouse_network::rpc::methods::BlobsByRangeRequest; -use lighthouse_network::{rpc::*, SignedBeaconBlockAndBlobsSidecar}; +use lighthouse_network::rpc::*; use lighthouse_network::{ Client, MessageId, NetworkGlobals, PeerId, PeerRequestId, Request, Response, }; @@ -18,10 +17,9 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use store::SyncCommitteeMessage; use tokio::sync::mpsc; use types::{ - Attestation, AttesterSlashing, BlobsSidecar, EthSpec, LightClientFinalityUpdate, - LightClientOptimisticUpdate, ProposerSlashing, SignedAggregateAndProof, SignedBeaconBlock, - SignedBlsToExecutionChange, SignedContributionAndProof, SignedVoluntaryExit, SubnetId, - SyncSubnetId, + Attestation, AttesterSlashing, EthSpec, LightClientFinalityUpdate, LightClientOptimisticUpdate, + ProposerSlashing, SignedAggregateAndProof, SignedBeaconBlock, SignedBlsToExecutionChange, + SignedContributionAndProof, SignedVoluntaryExit, SubnetId, SyncSubnetId, }; /// Processes validated messages from the network. It relays necessary data to the syncing thread @@ -163,17 +161,6 @@ impl Processor { )) } - pub fn on_blobs_by_range_request( - &mut self, - peer_id: PeerId, - request_id: PeerRequestId, - request: BlobsByRangeRequest, - ) { - self.send_beacon_processor_work(BeaconWorkEvent::blobs_by_range_request( - peer_id, request_id, request, - )) - } - /// Handle a `LightClientBootstrap` request from the peer. pub fn on_lightclient_bootstrap( &mut self, @@ -230,33 +217,6 @@ impl Processor { }); } - pub fn on_blobs_by_range_response( - &mut self, - peer_id: PeerId, - request_id: RequestId, - blob_wrapper: Option>>, - ) { - trace!( - self.log, - "Received BlobsByRange Response"; - "peer" => %peer_id, - ); - - if let RequestId::Sync(id) = request_id { - self.send_to_sync(SyncMessage::RpcBlob { - peer_id, - request_id: id, - blob_sidecar: blob_wrapper, - seen_timestamp: timestamp_now(), - }); - } else { - debug!( - self.log, - "All blobs by range responses should belong to sync" - ); - } - } - /// Handle a `BlocksByRoot` response from the peer. pub fn on_blocks_by_root_response( &mut self, @@ -308,22 +268,6 @@ impl Processor { )) } - pub fn on_block_and_blobs_sidecar_gossip( - &mut self, - message_id: MessageId, - peer_id: PeerId, - peer_client: Client, - block_and_blobs: Arc>, - ) { - self.send_beacon_processor_work(BeaconWorkEvent::gossip_block_and_blobs_sidecar( - message_id, - peer_id, - peer_client, - block_and_blobs, - timestamp_now(), - )) - } - pub fn on_unaggregated_attestation_gossip( &mut self, message_id: MessageId, diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index 4568ed1a22..410461bcd3 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -19,7 +19,7 @@ use lighthouse_network::{ Context, PeerAction, PeerRequestId, PubsubMessage, ReportSource, Request, Response, Subnet, }; use lighthouse_network::{ - types::{GossipEncoding, GossipTopic}, + types::{core_topics_to_subscribe, GossipEncoding, GossipTopic}, MessageId, NetworkEvent, NetworkGlobals, PeerId, }; use slog::{crit, debug, error, info, o, trace, warn}; @@ -445,7 +445,7 @@ impl NetworkService { let fork_version = self.beacon_chain.spec.fork_version_for_name(fork_name); let fork_digest = ChainSpec::compute_fork_digest(fork_version, self.beacon_chain.genesis_validators_root); info!(self.log, "Subscribing to new fork topics"); - self.libp2p.subscribe_new_fork_topics(fork_digest); + self.libp2p.subscribe_new_fork_topics(fork_name, fork_digest); self.next_fork_subscriptions = Box::pin(None.into()); } else { @@ -684,7 +684,7 @@ impl NetworkService { } let mut subscribed_topics: Vec = vec![]; - for topic_kind in lighthouse_network::types::CORE_TOPICS.iter() { + for topic_kind in core_topics_to_subscribe(self.fork_context.current_fork()) { for fork_digest in self.required_gossip_fork_digests() { let topic = GossipTopic::new( topic_kind.clone(), diff --git a/beacon_node/network/src/sync/manager.rs b/beacon_node/network/src/sync/manager.rs index 0548b0906b..230c883a93 100644 --- a/beacon_node/network/src/sync/manager.rs +++ b/beacon_node/network/src/sync/manager.rs @@ -47,13 +47,13 @@ use lighthouse_network::rpc::methods::MAX_REQUEST_BLOCKS; use lighthouse_network::types::{NetworkGlobals, SyncState}; use lighthouse_network::SyncInfo; use lighthouse_network::{PeerAction, PeerId}; -use slog::{crit, debug, error, info, trace, warn, Logger}; +use slog::{crit, debug, error, info, trace, Logger}; use std::boxed::Box; use std::ops::Sub; use std::sync::Arc; use std::time::Duration; use tokio::sync::mpsc; -use types::{BlobsSidecar, EthSpec, Hash256, SignedBeaconBlock, Slot}; +use types::{EthSpec, Hash256, SignedBeaconBlock, Slot}; /// The number of slots ahead of us that is allowed before requesting a long-range (batch) Sync /// from a peer. If a peer is within this tolerance (forwards or backwards), it is treated as a @@ -93,14 +93,6 @@ pub enum SyncMessage { seen_timestamp: Duration, }, - /// A blob has been received from RPC. - RpcBlob { - peer_id: PeerId, - request_id: RequestId, - blob_sidecar: Option>>, - seen_timestamp: Duration, - }, - /// A block with an unknown parent has been received. UnknownBlock(PeerId, Arc>, Hash256), @@ -592,9 +584,6 @@ impl SyncManager { .block_lookups .parent_chain_processed(chain_hash, result, &mut self.network), }, - SyncMessage::RpcBlob { .. } => { - warn!(self.log, "Unexpected blob message received"); - } } } diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index b4da83315c..792d625348 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -819,6 +819,15 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { for ensuring the EL is given ample notice. Default: 1/3 of a slot.") .takes_value(true) ) + .arg( + Arg::with_name("always-prepare-payload") + .long("always-prepare-payload") + .help("Send payload attributes with every fork choice update. This is intended for \ + use by block builders, relays and developers. You should set a fee \ + recipient on this BN and also consider adjusting the \ + --prepare-payload-lookahead flag.") + .takes_value(false) + ) .arg( Arg::with_name("fork-choice-before-proposal-timeout") .long("fork-choice-before-proposal-timeout") @@ -948,4 +957,13 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { This is equivalent to --http and --validator-monitor-auto.") .takes_value(false) ) + .arg( + Arg::with_name("always-prefer-builder-payload") + .long("always-prefer-builder-payload") + .help("If set, the beacon node always uses the payload from the builder instead of the local payload.") + // The builder profit threshold flag is used to provide preference + // to local payloads, therefore it fundamentally conflicts with + // always using the builder. + .conflicts_with("builder-profit-threshold") + ) } diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index 726f8368ea..55335081cb 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -711,6 +711,8 @@ pub fn get_config( / DEFAULT_PREPARE_PAYLOAD_LOOKAHEAD_FACTOR }); + client_config.chain.always_prepare_payload = cli_args.is_present("always-prepare-payload"); + if let Some(timeout) = clap_utils::parse_optional(cli_args, "fork-choice-before-proposal-timeout")? { @@ -751,6 +753,11 @@ pub fn get_config( client_config.chain.optimistic_finalized_sync = !cli_args.is_present("disable-optimistic-finalized-sync"); + // Payload selection configs + if cli_args.is_present("always-prefer-builder-payload") { + client_config.always_prefer_builder_payload = true; + } + Ok(client_config) } diff --git a/beacon_node/store/src/config.rs b/beacon_node/store/src/config.rs index 53d99f75eb..027b8152ee 100644 --- a/beacon_node/store/src/config.rs +++ b/beacon_node/store/src/config.rs @@ -7,7 +7,6 @@ use types::{EthSpec, MinimalEthSpec}; pub const PREV_DEFAULT_SLOTS_PER_RESTORE_POINT: u64 = 2048; pub const DEFAULT_SLOTS_PER_RESTORE_POINT: u64 = 8192; pub const DEFAULT_BLOCK_CACHE_SIZE: usize = 5; -pub const DEFAULT_BLOB_CACHE_SIZE: usize = 5; /// Database configuration parameters. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -18,8 +17,6 @@ pub struct StoreConfig { pub slots_per_restore_point_set_explicitly: bool, /// Maximum number of blocks to store in the in-memory block cache. pub block_cache_size: usize, - /// Maximum number of blobs to store in the in-memory blob cache. - pub blob_cache_size: usize, /// Whether to compact the database on initialization. pub compact_on_init: bool, /// Whether to compact the database during database pruning. @@ -46,7 +43,6 @@ impl Default for StoreConfig { slots_per_restore_point: MinimalEthSpec::slots_per_historical_root() as u64, slots_per_restore_point_set_explicitly: false, block_cache_size: DEFAULT_BLOCK_CACHE_SIZE, - blob_cache_size: DEFAULT_BLOB_CACHE_SIZE, compact_on_init: false, compact_on_prune: true, prune_payloads: true, diff --git a/beacon_node/store/src/hot_cold_store.rs b/beacon_node/store/src/hot_cold_store.rs index 965bbb3bd4..3255006b55 100644 --- a/beacon_node/store/src/hot_cold_store.rs +++ b/beacon_node/store/src/hot_cold_store.rs @@ -60,8 +60,6 @@ pub struct HotColdDB, Cold: ItemStore> { /// /// The hot database also contains all blocks. pub hot_db: Hot, - /// LRU cache of deserialized blobs. Updated whenever a blob is loaded. - blob_cache: Mutex>>, /// LRU cache of deserialized blocks. Updated whenever a block is loaded. block_cache: Mutex>>, /// Chain spec. @@ -131,7 +129,6 @@ impl HotColdDB, MemoryStore> { cold_db: MemoryStore::open(), hot_db: MemoryStore::open(), block_cache: Mutex::new(LruCache::new(config.block_cache_size)), - blob_cache: Mutex::new(LruCache::new(config.blob_cache_size)), config, spec, log, @@ -165,7 +162,6 @@ impl HotColdDB, LevelDB> { cold_db: LevelDB::open(cold_path)?, hot_db: LevelDB::open(hot_path)?, block_cache: Mutex::new(LruCache::new(config.block_cache_size)), - blob_cache: Mutex::new(LruCache::new(config.blob_cache_size)), config, spec, log, @@ -488,41 +484,6 @@ impl, Cold: ItemStore> HotColdDB .key_delete(DBColumn::ExecPayload.into(), block_root.as_bytes()) } - pub fn put_blobs(&self, block_root: &Hash256, blobs: BlobsSidecar) -> Result<(), Error> { - self.hot_db.put_bytes( - DBColumn::BeaconBlob.into(), - block_root.as_bytes(), - &blobs.as_ssz_bytes(), - )?; - self.blob_cache.lock().push(*block_root, blobs); - Ok(()) - } - - pub fn get_blobs(&self, block_root: &Hash256) -> Result>, Error> { - if let Some(blobs) = self.blob_cache.lock().get(block_root) { - Ok(Some(blobs.clone())) - } else if let Some(bytes) = self - .hot_db - .get_bytes(DBColumn::BeaconBlob.into(), block_root.as_bytes())? - { - let ret = BlobsSidecar::from_ssz_bytes(&bytes)?; - self.blob_cache.lock().put(*block_root, ret.clone()); - Ok(Some(ret)) - } else { - Ok(None) - } - } - - pub fn blobs_as_kv_store_ops( - &self, - key: &Hash256, - blobs: &BlobsSidecar, - ops: &mut Vec, - ) { - let db_key = get_key_for_col(DBColumn::BeaconBlob.into(), key.as_bytes()); - ops.push(KeyValueStoreOp::PutKeyValue(db_key, blobs.as_ssz_bytes())); - } - pub fn put_state_summary( &self, state_root: &Hash256, @@ -750,10 +711,6 @@ impl, Cold: ItemStore> HotColdDB self.store_hot_state(&state_root, state, &mut key_value_batch)?; } - StoreOp::PutBlobs(block_root, blobs) => { - self.blobs_as_kv_store_ops(&block_root, &blobs, &mut key_value_batch); - } - StoreOp::PutStateSummary(state_root, summary) => { key_value_batch.push(summary.as_kv_store_op(state_root)); } @@ -802,7 +759,6 @@ impl, Cold: ItemStore> HotColdDB // Update the block cache whilst holding a lock, to ensure that the cache updates atomically // with the database. let mut guard = self.block_cache.lock(); - let mut guard_blob = self.blob_cache.lock(); for op in &batch { match op { @@ -810,10 +766,6 @@ impl, Cold: ItemStore> HotColdDB guard.put(*block_root, (**block).clone()); } - StoreOp::PutBlobs(block_root, blobs) => { - guard_blob.put(*block_root, (**blobs).clone()); - } - StoreOp::PutState(_, _) => (), StoreOp::PutStateSummary(_, _) => (), diff --git a/beacon_node/store/src/impls/execution_payload.rs b/beacon_node/store/src/impls/execution_payload.rs index ad68d1fba0..b5753f3797 100644 --- a/beacon_node/store/src/impls/execution_payload.rs +++ b/beacon_node/store/src/impls/execution_payload.rs @@ -1,9 +1,6 @@ use crate::{DBColumn, Error, StoreItem}; use ssz::{Decode, Encode}; -use types::{ - EthSpec, ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadEip4844, - ExecutionPayloadMerge, -}; +use types::{EthSpec, ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadMerge}; macro_rules! impl_store_item { ($ty_name:ident) => { @@ -24,7 +21,6 @@ macro_rules! impl_store_item { } impl_store_item!(ExecutionPayloadMerge); impl_store_item!(ExecutionPayloadCapella); -impl_store_item!(ExecutionPayloadEip4844); /// This fork-agnostic implementation should be only used for writing. /// @@ -40,13 +36,9 @@ impl StoreItem for ExecutionPayload { } fn from_store_bytes(bytes: &[u8]) -> Result { - ExecutionPayloadEip4844::from_ssz_bytes(bytes) - .map(Self::Eip4844) - .or_else(|_| { - ExecutionPayloadCapella::from_ssz_bytes(bytes) - .map(Self::Capella) - .or_else(|_| ExecutionPayloadMerge::from_ssz_bytes(bytes).map(Self::Merge)) - }) + ExecutionPayloadCapella::from_ssz_bytes(bytes) + .map(Self::Capella) + .or_else(|_| ExecutionPayloadMerge::from_ssz_bytes(bytes).map(Self::Merge)) .map_err(Into::into) } } diff --git a/beacon_node/store/src/lib.rs b/beacon_node/store/src/lib.rs index 47ddd8fc7e..ee01fa1ae1 100644 --- a/beacon_node/store/src/lib.rs +++ b/beacon_node/store/src/lib.rs @@ -155,7 +155,6 @@ pub trait ItemStore: KeyValueStore + Sync + Send + Sized + 'stati pub enum StoreOp<'a, E: EthSpec> { PutBlock(Hash256, Arc>), PutState(Hash256, &'a BeaconState), - PutBlobs(Hash256, Arc>), PutStateSummary(Hash256, HotStateSummary), PutStateTemporaryFlag(Hash256), DeleteStateTemporaryFlag(Hash256), @@ -173,8 +172,6 @@ pub enum DBColumn { BeaconMeta, #[strum(serialize = "blk")] BeaconBlock, - #[strum(serialize = "blb")] - BeaconBlob, /// For full `BeaconState`s in the hot database (finalized or fork-boundary states). #[strum(serialize = "ste")] BeaconState, diff --git a/beacon_node/store/src/partial_beacon_state.rs b/beacon_node/store/src/partial_beacon_state.rs index 55697bd316..cd923da40d 100644 --- a/beacon_node/store/src/partial_beacon_state.rs +++ b/beacon_node/store/src/partial_beacon_state.rs @@ -15,7 +15,7 @@ use types::*; /// /// Utilises lazy-loading from separate storage for its vector fields. #[superstruct( - variants(Base, Altair, Merge, Capella, Eip4844), + variants(Base, Altair, Merge, Capella), variant_attributes(derive(Debug, PartialEq, Clone, Encode, Decode)) )] #[derive(Debug, PartialEq, Clone, Encode)] @@ -67,9 +67,9 @@ where pub current_epoch_attestations: VariableList, T::MaxPendingAttestations>, // Participation (Altair and later) - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub previous_epoch_participation: VariableList, - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub current_epoch_participation: VariableList, // Finality @@ -79,13 +79,13 @@ where pub finalized_checkpoint: Checkpoint, // Inactivity - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub inactivity_scores: VariableList, // Light-client sync committees - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub current_sync_committee: Arc>, - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub next_sync_committee: Arc>, // Execution @@ -99,20 +99,15 @@ where partial_getter(rename = "latest_execution_payload_header_capella") )] pub latest_execution_payload_header: ExecutionPayloadHeaderCapella, - #[superstruct( - only(Eip4844), - partial_getter(rename = "latest_execution_payload_header_eip4844") - )] - pub latest_execution_payload_header: ExecutionPayloadHeaderEip4844, // Capella - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] pub next_withdrawal_index: u64, - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] pub next_withdrawal_validator_index: u64, #[ssz(skip_serializing, skip_deserializing)] - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] pub historical_summaries: Option>, } @@ -227,23 +222,6 @@ impl PartialBeaconState { ], [historical_summaries] ), - BeaconState::Eip4844(s) => impl_from_state_forgetful!( - s, - outer, - Eip4844, - PartialBeaconStateEip4844, - [ - previous_epoch_participation, - current_epoch_participation, - current_sync_committee, - next_sync_committee, - inactivity_scores, - latest_execution_payload_header, - next_withdrawal_index, - next_withdrawal_validator_index - ], - [historical_summaries] - ), } } @@ -472,22 +450,6 @@ impl TryInto> for PartialBeaconState { ], [historical_summaries] ), - PartialBeaconState::Eip4844(inner) => impl_try_into_beacon_state!( - inner, - Eip4844, - BeaconStateEip4844, - [ - previous_epoch_participation, - current_epoch_participation, - current_sync_committee, - next_sync_committee, - inactivity_scores, - latest_execution_payload_header, - next_withdrawal_index, - next_withdrawal_validator_index - ], - [historical_summaries] - ), }; Ok(state) } diff --git a/beacon_node/tests/test.rs b/beacon_node/tests/test.rs index 1c11a8349d..8ccb260d29 100644 --- a/beacon_node/tests/test.rs +++ b/beacon_node/tests/test.rs @@ -1,5 +1,5 @@ #![cfg(test)] -#![recursion_limit = "256"] +#![recursion_limit = "512"] use beacon_chain::StateSkipConfig; use node_test_rig::{ diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 470407ebee..7def1821dd 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -33,6 +33,11 @@ * [Authorization Header](./api-vc-auth-header.md) * [Signature Header](./api-vc-sig-header.md) * [Prometheus Metrics](./advanced_metrics.md) +* [Lighthouse UI (Siren)](./lighthouse-ui.md) + * [Installation](./ui-installation.md) + * [Configuration](./ui-configuration.md) + * [Usage](./ui-usage.md) + * [FAQs](./ui-faqs.md) * [Advanced Usage](./advanced.md) * [Checkpoint Sync](./checkpoint-sync.md) * [Custom Data Directories](./advanced-datadir.md) diff --git a/book/src/database-migrations.md b/book/src/database-migrations.md index 7219a0f6b6..ef7e95cc7a 100644 --- a/book/src/database-migrations.md +++ b/book/src/database-migrations.md @@ -116,7 +116,7 @@ Several conditions need to be met in order to run `lighthouse db`: 2. The command must run as the user that owns the beacon node database. If you are using systemd then your beacon node might run as a user called `lighthousebeacon`. 3. The `--datadir` flag must be set to the location of the Lighthouse data directory. -4. The `--network` flag must be set to the correct network, e.g. `mainnet`, `prater` or `ropsten`. +4. The `--network` flag must be set to the correct network, e.g. `mainnet`, `prater` or `sepolia`. The general form for a `lighthouse db` command is: diff --git a/book/src/imgs/ui-account-earnings.png b/book/src/imgs/ui-account-earnings.png new file mode 100644 index 0000000000..69e9456035 Binary files /dev/null and b/book/src/imgs/ui-account-earnings.png differ diff --git a/book/src/imgs/ui-balance-modal.png b/book/src/imgs/ui-balance-modal.png new file mode 100644 index 0000000000..9d7c0e36b4 Binary files /dev/null and b/book/src/imgs/ui-balance-modal.png differ diff --git a/book/src/imgs/ui-configuration.png b/book/src/imgs/ui-configuration.png new file mode 100644 index 0000000000..87ec95d7bb Binary files /dev/null and b/book/src/imgs/ui-configuration.png differ diff --git a/book/src/imgs/ui-dashboard.png b/book/src/imgs/ui-dashboard.png new file mode 100644 index 0000000000..00552fe076 Binary files /dev/null and b/book/src/imgs/ui-dashboard.png differ diff --git a/book/src/imgs/ui-device.png b/book/src/imgs/ui-device.png new file mode 100644 index 0000000000..0f1a0e77d3 Binary files /dev/null and b/book/src/imgs/ui-device.png differ diff --git a/book/src/imgs/ui-hardware.png b/book/src/imgs/ui-hardware.png new file mode 100644 index 0000000000..4178687f5d Binary files /dev/null and b/book/src/imgs/ui-hardware.png differ diff --git a/book/src/imgs/ui-settings.png b/book/src/imgs/ui-settings.png new file mode 100644 index 0000000000..da9cbca9fa Binary files /dev/null and b/book/src/imgs/ui-settings.png differ diff --git a/book/src/imgs/ui-validator-balance1.png b/book/src/imgs/ui-validator-balance1.png new file mode 100644 index 0000000000..4488cdd053 Binary files /dev/null and b/book/src/imgs/ui-validator-balance1.png differ diff --git a/book/src/imgs/ui-validator-balance2.png b/book/src/imgs/ui-validator-balance2.png new file mode 100644 index 0000000000..44c5f51671 Binary files /dev/null and b/book/src/imgs/ui-validator-balance2.png differ diff --git a/book/src/imgs/ui-validator-management.png b/book/src/imgs/ui-validator-management.png new file mode 100644 index 0000000000..b28b372109 Binary files /dev/null and b/book/src/imgs/ui-validator-management.png differ diff --git a/book/src/imgs/ui-validator-modal.png b/book/src/imgs/ui-validator-modal.png new file mode 100644 index 0000000000..d53dc78098 Binary files /dev/null and b/book/src/imgs/ui-validator-modal.png differ diff --git a/book/src/imgs/ui-validator-table.png b/book/src/imgs/ui-validator-table.png new file mode 100644 index 0000000000..10bcbd6f14 Binary files /dev/null and b/book/src/imgs/ui-validator-table.png differ diff --git a/book/src/imgs/ui.png b/book/src/imgs/ui.png new file mode 100644 index 0000000000..208cb3101d Binary files /dev/null and b/book/src/imgs/ui.png differ diff --git a/book/src/installation-source.md b/book/src/installation-source.md index 8e515a41bd..c89dd1add4 100644 --- a/book/src/installation-source.md +++ b/book/src/installation-source.md @@ -133,6 +133,15 @@ Commonly used features include: * `slasher-lmdb`: support for the LMDB slasher backend. * `jemalloc`: use [`jemalloc`][jemalloc] to allocate memory. Enabled by default on Linux and macOS. Not supported on Windows. +* `spec-minimal`: support for the minimal preset (useful for testing). + +Default features (e.g. `slasher-mdbx`) may be opted out of using the `--no-default-features` +argument for `cargo`, which can plumbed in via the `CARGO_INSTALL_EXTRA_FLAGS` environment variable. +E.g. + +``` +CARGO_INSTALL_EXTRA_FLAGS="--no-default-features" make +``` [jemalloc]: https://jemalloc.net/ diff --git a/book/src/lighthouse-ui.md b/book/src/lighthouse-ui.md new file mode 100644 index 0000000000..225f293f97 --- /dev/null +++ b/book/src/lighthouse-ui.md @@ -0,0 +1,33 @@ +# Lighthouse UI (Siren) + +_Documentation for Siren users and developers._ + +[![Chat Badge]][Chat Link] + +[Chat Badge]: https://img.shields.io/badge/chat-discord-%237289da +[Chat Link]: https://discord.gg/cyAszAh + +![ui-overview](./imgs/ui.png) + +Siren is a user interface built for Lighthouse that connects to a Lighthouse Beacon Node and +a Lighthouse Validator Client to monitor performance and display key validator +metrics. + +The UI is currently in active development. Its resides in the +[Siren](https://github.com/sigp/siren) repository. + +## Topics + +See the following Siren specific topics for more context-specific +information: + +- [Installation Guide](./ui-installation.md) - Information to install and run the Lighthouse UI. +- [Configuration Guide](./ui-configuration.md) - Explanation of how to setup + and configure Siren. +- [Usage](./ui-usage.md) - Details various Siren components. +- [FAQs](./ui-faqs.md) - Frequently Asked Questions. + +## Contributing + +If you find and issue or bug or would otherwise like to help out with the +development of the Siren project, please submit issues and PRs to the [Siren](https://github.com/sigp/siren) repository. diff --git a/book/src/ui-configuration.md b/book/src/ui-configuration.md new file mode 100644 index 0000000000..5b67b03b37 --- /dev/null +++ b/book/src/ui-configuration.md @@ -0,0 +1,47 @@ +# Configuration + +Siren requires a connection to both a Lighthouse Validator Client +and a Lighthouse Beacon Node. Upon running you will first be greeted by the +following configuration screen. + +![ui-configuration](./imgs/ui-configuration.png) + + +## Connecting to the Clients + +This allows you to enter the address and ports of the associated Lighthouse +Beacon node and Lighthouse Validator client. + +> The Beacon Node must be run with the `--gui` flag set. To allow the browser +> to access the node beyond your local computer you also need to allow CORS in +> the http API. This can be done via `--http-allow-origin "*"`. + +A green tick will appear once Siren is able to connect to both clients. You +can specify different ports for each client by clicking on the advanced tab. + + +## API Token + +The API Token is a secret key that allows you to connect to the validator +client. The validator client's HTTP API is guarded by this key because it +contains sensitive validator information and the ability to modify +validators. Please see [`Validator Authorization`](./api-vc-auth-header.md) +for further details. + +Siren requires this token in order to connect to the Validator client. +The token is located in the default data directory of the validator +client. The default path is +`~/.lighthouse//validators/api-token.txt`. + +The contents of this file for the desired valdiator client needs to be +entered. + +## Name + +This is your name, it can be modified and is solely used for aesthetics. + +## Device + +This is a name that can be associated with the validator client/beacon +node pair. Multiple such pairs can be remembered for quick swapping between +them. diff --git a/book/src/ui-faqs.md b/book/src/ui-faqs.md new file mode 100644 index 0000000000..240195421c --- /dev/null +++ b/book/src/ui-faqs.md @@ -0,0 +1,13 @@ +# Frequently Asked Questions + +## 1. Where can I find my API token? +The required Api token may be found in the default data directory of the validator client. For more information please refer to the lighthouse ui configuration [`api token section`](./ui-configuration.md#api-token). + +## 2. How do I fix the Node Network Errors? +If you recieve a red notification with a BEACON or VALIDATOR NODE NETWORK ERROR you can refer to the lighthouse ui configuration and [`connecting to clients section`](./ui-configuration.md#connecting-to-the-clients). + +## 3. How do I change my Beacon or Validator address after logging in? +Once you have successfully arrived to the main dashboard, use the sidebar to access the settings view. In the top right hand corner there is a `Configurtion` action button that will redirect you back to the configuration screen where you can make appropriate changes. + +## 4. Why doesn't my validator balance graph show any data? +If your graph is not showing data, it usually means your validator node is still caching data. The application must wait at least 3 epochs before it can render any graphical visualizations. This could take up to 20min. diff --git a/book/src/ui-installation.md b/book/src/ui-installation.md new file mode 100644 index 0000000000..0b96b1923b --- /dev/null +++ b/book/src/ui-installation.md @@ -0,0 +1,103 @@ +# 📦 Installation + +Siren runs on Linux, MacOS and Windows. + + +## Pre-Built Electron Packages + +There are pre-compiled electron packages for each operating systems which can +be downloaded and executed. These can be found on the +[releases](https://github.com/sigp/siren/releases) page of the +Siren repository. + +Simply download the package specific to your operating system and run it. + +## Building From Source + +### Requirements + +Building from source requires `Node v18` and `yarn`. + +### Building From Source + +The electron app can be built from source by first cloning the repository and +entering the directory: + +``` +$ git clone https://github.com/sigp/siren.git +$ cd siren +``` + +Once cloned, the electron app can be built and ran via the Makefile by: + +``` +$ make +``` + +alternatively it can be built via: + +``` +$ yarn +``` + +Once completed successfully the electron app can be run via: + +``` +$ yarn dev +``` + +### Running In The Browser + +#### Docker (Recommended) + +Docker is the recommended way to run a webserver that hosts Siren and can be +connected to via a web browser. We recommend this method as it establishes a +production-grade web-server to host the application. + +`docker` is required to be installed with the service running. + +The docker image can be built and run via the Makefile by running: +``` +$ make docker +``` + +Alternatively, to run with Docker, the image needs to be built. From the repository directory +run: +``` +$ docker build -t siren . +``` + +Then to run the image: +``` +$ docker run --rm -ti --name siren -p 80:80 siren +``` + +This will open port 80 and allow your browser to connect. You can choose +another local port by modifying the command. For example `-p 8000:80` will open +port 8000. + +To view Siren, simply go to `http://localhost` in your web browser. + +#### Development Server + +A development server can also be built which will expose a local port 3000 via: +``` +$ yarn start +``` + +Once executed, you can direct your web browser to the following URL to interact +with the app: +``` +http://localhost:3000 +``` + +A production version of the app can be built via +``` +$ yarn build +``` +and then further hosted via a production web server. + +### Known Issues + +If you experience any issues in running the UI please create an issue on the +[Lighthouse UI](https://github.com/sigp/lighthouse-ui) repository. diff --git a/book/src/ui-usage.md b/book/src/ui-usage.md new file mode 100644 index 0000000000..e88c4677a8 --- /dev/null +++ b/book/src/ui-usage.md @@ -0,0 +1,61 @@ +# Usage + +# Dashboard + +Siren's dashboard view provides a summary of all performance and key validator metrics. Sync statuses, uptimes, accumulated rewards, hardware and network metrics are all consolidated on the dashboard for evaluation. + +![](imgs/ui-dashboard.png) + +## Account Earnings + +The account earnings component accumulates reward data from all registered validators providing a summation of total rewards earned while staking. Given current conversion rates, this component also converts your balance into your selected fiat currency. + +Below in the earning section, you can also view your total earnings or click the adjacent buttons to view your estimated earnings given a specific timeframe based on current device and network conditions. + +![](imgs/ui-account-earnings.png) + +## Validator Table + +The validator table component is a list of all registered validators, which includes data such as name, index, total balance, earned rewards and current status. Each validator row also contains a link to a detailed data modal and additional data provided by [Beaconcha.in](https://beaconcha.in). + +![](imgs/ui-validator-table.png) + +## Validator Balance Chart + +The validator balance component is a graphical representation of each validator balance over the latest 10 epochs. Take note that only active validators are rendered in the chart visualization. + +![](imgs/ui-validator-balance1.png) + +By clicking on the chart component you can filter selected validators in the render. This call allow for greater resolution in the rendered visualization. + + + + + + +## Hardware Usage and Device Diagnostics + +The hardware usage component gathers information about the device the Beacon Node is currently running. It displays the Disk usage, CPU metrics and memory usage of the Beacon Node device. The device diagnostics component provides the sync status of the execution client and beacon node. + + + + + + +# Validator Management + +Siren's validator management view provides a detailed overview of all validators with options to deposit to and/or add new validators. Each validator table row displays the validator name, index, balance, rewards, status and all available actions per validator. + +![](imgs/ui-validator-management.png) + +## Validator Modal + +Clicking the validator icon activates a detailed validator modal component. This component also allows users to trigger validator actions and as well to view and update validator graffiti. Each modal contains the validator total income with hourly, daily and weekly earnings estimates. + + + +# Settings + +Siren's settings view provides access to the application theme, version, name, device name and important external links. From the settings page users can also access the configuration screen to adjust any beacon or validator node parameters. + +![](imgs/ui-settings.png) diff --git a/boot_node/Cargo.toml b/boot_node/Cargo.toml index 5d24d1203e..266dcdfe6f 100644 --- a/boot_node/Cargo.toml +++ b/boot_node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "boot_node" -version = "3.5.0" +version = "3.5.1" authors = ["Sigma Prime "] edition = "2021" diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs index 03f96f34e2..4d74299fff 100644 --- a/common/eth2/src/lib.rs +++ b/common/eth2/src/lib.rs @@ -1395,32 +1395,6 @@ impl BeaconNodeHttpClient { self.get(path).await } - /// `GET v1/validator/blocks_and_blobs/{slot}` - pub async fn get_validator_blocks_and_blobs>( - &self, - slot: Slot, - randao_reveal: &SignatureBytes, - graffiti: Option<&Graffiti>, - ) -> Result>, Error> { - let mut path = self.eth_path(V1)?; - - path.path_segments_mut() - .map_err(|()| Error::InvalidUrl(self.server.clone()))? - .push("validator") - .push("blocks_and_blobs") - .push(&slot.to_string()); - - path.query_pairs_mut() - .append_pair("randao_reveal", &randao_reveal.to_string()); - - if let Some(graffiti) = graffiti { - path.query_pairs_mut() - .append_pair("graffiti", &graffiti.to_string()); - } - - self.get(path).await - } - /// `GET v2/validator/blinded_blocks/{slot}` pub async fn get_validator_blinded_blocks>( &self, diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs index 1a0b46e38d..b4218c361a 100644 --- a/common/eth2/src/types.rs +++ b/common/eth2/src/types.rs @@ -897,6 +897,76 @@ pub struct SseLateHead { pub execution_optimistic: bool, } +#[superstruct( + variants(V1, V2), + variant_attributes(derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)) +)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)] +#[serde(untagged)] +pub struct SsePayloadAttributes { + #[superstruct(getter(copy))] + #[serde(with = "eth2_serde_utils::quoted_u64")] + pub timestamp: u64, + #[superstruct(getter(copy))] + pub prev_randao: Hash256, + #[superstruct(getter(copy))] + pub suggested_fee_recipient: Address, + #[superstruct(only(V2))] + pub withdrawals: Vec, +} + +#[derive(PartialEq, Debug, Deserialize, Serialize, Clone)] +pub struct SseExtendedPayloadAttributesGeneric { + pub proposal_slot: Slot, + #[serde(with = "eth2_serde_utils::quoted_u64")] + pub proposer_index: u64, + pub parent_block_root: Hash256, + pub parent_block_hash: ExecutionBlockHash, + pub payload_attributes: T, +} + +pub type SseExtendedPayloadAttributes = SseExtendedPayloadAttributesGeneric; +pub type VersionedSsePayloadAttributes = ForkVersionedResponse; + +impl ForkVersionDeserialize for SsePayloadAttributes { + fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>( + value: serde_json::value::Value, + fork_name: ForkName, + ) -> Result { + match fork_name { + ForkName::Merge => serde_json::from_value(value) + .map(Self::V1) + .map_err(serde::de::Error::custom), + ForkName::Capella => serde_json::from_value(value) + .map(Self::V2) + .map_err(serde::de::Error::custom), + ForkName::Base | ForkName::Altair => Err(serde::de::Error::custom(format!( + "SsePayloadAttributes deserialization for {fork_name} not implemented" + ))), + } + } +} + +impl ForkVersionDeserialize for SseExtendedPayloadAttributes { + fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>( + value: serde_json::value::Value, + fork_name: ForkName, + ) -> Result { + let helper: SseExtendedPayloadAttributesGeneric = + serde_json::from_value(value).map_err(serde::de::Error::custom)?; + Ok(Self { + proposal_slot: helper.proposal_slot, + proposer_index: helper.proposer_index, + parent_block_root: helper.parent_block_root, + parent_block_hash: helper.parent_block_hash, + payload_attributes: SsePayloadAttributes::deserialize_by_fork::( + helper.payload_attributes, + fork_name, + )?, + }) + } +} + #[derive(PartialEq, Debug, Serialize, Clone)] #[serde(bound = "T: EthSpec", untagged)] pub enum EventKind { @@ -910,6 +980,7 @@ pub enum EventKind { LateHead(SseLateHead), #[cfg(feature = "lighthouse")] BlockReward(BlockReward), + PayloadAttributes(VersionedSsePayloadAttributes), } impl EventKind { @@ -922,6 +993,7 @@ impl EventKind { EventKind::FinalizedCheckpoint(_) => "finalized_checkpoint", EventKind::ChainReorg(_) => "chain_reorg", EventKind::ContributionAndProof(_) => "contribution_and_proof", + EventKind::PayloadAttributes(_) => "payload_attributes", EventKind::LateHead(_) => "late_head", #[cfg(feature = "lighthouse")] EventKind::BlockReward(_) => "block_reward", @@ -977,6 +1049,11 @@ impl EventKind { ServerError::InvalidServerSentEvent(format!("Contribution and Proof: {:?}", e)) })?, ))), + "payload_attributes" => Ok(EventKind::PayloadAttributes( + serde_json::from_str(data).map_err(|e| { + ServerError::InvalidServerSentEvent(format!("Payload Attributes: {:?}", e)) + })?, + )), #[cfg(feature = "lighthouse")] "block_reward" => Ok(EventKind::BlockReward(serde_json::from_str(data).map_err( |e| ServerError::InvalidServerSentEvent(format!("Block Reward: {:?}", e)), @@ -1006,6 +1083,7 @@ pub enum EventTopic { ChainReorg, ContributionAndProof, LateHead, + PayloadAttributes, #[cfg(feature = "lighthouse")] BlockReward, } @@ -1022,6 +1100,7 @@ impl FromStr for EventTopic { "finalized_checkpoint" => Ok(EventTopic::FinalizedCheckpoint), "chain_reorg" => Ok(EventTopic::ChainReorg), "contribution_and_proof" => Ok(EventTopic::ContributionAndProof), + "payload_attributes" => Ok(EventTopic::PayloadAttributes), "late_head" => Ok(EventTopic::LateHead), #[cfg(feature = "lighthouse")] "block_reward" => Ok(EventTopic::BlockReward), @@ -1040,6 +1119,7 @@ impl fmt::Display for EventTopic { EventTopic::FinalizedCheckpoint => write!(f, "finalized_checkpoint"), EventTopic::ChainReorg => write!(f, "chain_reorg"), EventTopic::ContributionAndProof => write!(f, "contribution_and_proof"), + EventTopic::PayloadAttributes => write!(f, "payload_attributes"), EventTopic::LateHead => write!(f, "late_head"), #[cfg(feature = "lighthouse")] EventTopic::BlockReward => write!(f, "block_reward"), @@ -1114,38 +1194,6 @@ pub struct LivenessResponseData { pub is_live: bool, } -#[derive(PartialEq, Debug, Serialize, Deserialize)] -#[serde(bound = "T: EthSpec, Payload: AbstractExecPayload")] -pub struct BlocksAndBlobs> { - pub block: BeaconBlock, - pub blobs: Vec>, - pub kzg_aggregate_proof: KzgProof, -} - -impl> ForkVersionDeserialize - for BlocksAndBlobs -{ - fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>( - value: serde_json::value::Value, - fork_name: ForkName, - ) -> Result { - #[derive(Deserialize)] - #[serde(bound = "T: EthSpec")] - struct Helper { - block: serde_json::Value, - blobs: Vec>, - kzg_aggregate_proof: KzgProof, - } - let helper: Helper = serde_json::from_value(value).map_err(serde::de::Error::custom)?; - - Ok(Self { - block: BeaconBlock::deserialize_by_fork::<'de, D>(helper.block, fork_name)?, - blobs: helper.blobs, - kzg_aggregate_proof: helper.kzg_aggregate_proof, - }) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/common/eth2_config/src/lib.rs b/common/eth2_config/src/lib.rs index 7e3c025a83..7e5506667f 100644 --- a/common/eth2_config/src/lib.rs +++ b/common/eth2_config/src/lib.rs @@ -278,26 +278,6 @@ define_hardcoded_nets!( // directory. GENESIS_STATE_IS_KNOWN ), - ( - // Network name (must be unique among all networks). - kiln, - // The name of the directory in the `eth2_network_config/built_in_network_configs` - // directory where the configuration files are located for this network. - "kiln", - // Set to `true` if the genesis state can be found in the `built_in_network_configs` - // directory. - GENESIS_STATE_IS_KNOWN - ), - ( - // Network name (must be unique among all networks). - ropsten, - // The name of the directory in the `eth2_network_config/built_in_network_configs` - // directory where the configuration files are located for this network. - "ropsten", - // Set to `true` if the genesis state can be found in the `built_in_network_configs` - // directory. - GENESIS_STATE_IS_KNOWN - ), ( // Network name (must be unique among all networks). sepolia, diff --git a/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml b/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml index 6aa2c9590a..ca1d1e88a8 100644 --- a/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml @@ -39,9 +39,6 @@ BELLATRIX_FORK_EPOCH: 385536 # Capella CAPELLA_FORK_VERSION: 0x03000064 CAPELLA_FORK_EPOCH: 18446744073709551615 -# Eip4844 -EIP4844_FORK_VERSION: 0x04000064 -EIP4844_FORK_EPOCH: 18446744073709551615 # Sharding SHARDING_FORK_VERSION: 0x03000064 SHARDING_FORK_EPOCH: 18446744073709551615 diff --git a/common/eth2_network_config/built_in_network_configs/kiln/boot_enr.yaml b/common/eth2_network_config/built_in_network_configs/kiln/boot_enr.yaml deleted file mode 100644 index 4c03b0f19e..0000000000 --- a/common/eth2_network_config/built_in_network_configs/kiln/boot_enr.yaml +++ /dev/null @@ -1,3 +0,0 @@ -- enr:-Iq4QMCTfIMXnow27baRUb35Q8iiFHSIDBJh6hQM5Axohhf4b6Kr_cOCu0htQ5WvVqKvFgY28893DHAg8gnBAXsAVqmGAX53x8JggmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk -- enr:-KG4QFkPJUFWuONp5grM94OJvNht9wX6N36sA4wqucm6Z02ECWBQRmh6AzndaLVGYBHWre67mjK-E0uKt2CIbWrsZ_8DhGV0aDKQc6pfXHAAAHAyAAAAAAAAAIJpZIJ2NIJpcISl6LTmiXNlY3AyNTZrMaEDHlSNOgYrNWP8_l_WXqDMRvjv6gUAvHKizfqDDVc8feaDdGNwgiMog3VkcIIjKA -- enr:-MK4QI-wkVW1PxL4ksUM4H_hMgTTwxKMzvvDMfoiwPBuRxcsGkrGPLo4Kho3Ri1DEtJG4B6pjXddbzA9iF2gVctxv42GAX9v5WG5h2F0dG5ldHOIAAAAAAAAAACEZXRoMpBzql9ccAAAcDIAAAAAAAAAgmlkgnY0gmlwhKRcjMiJc2VjcDI1NmsxoQK1fc46pmVHKq8HNYLkSVaUv4uK2UBsGgjjGWU6AAhAY4hzeW5jbmV0cwCDdGNwgiMog3VkcIIjKA diff --git a/common/eth2_network_config/built_in_network_configs/kiln/config.yaml b/common/eth2_network_config/built_in_network_configs/kiln/config.yaml deleted file mode 100644 index 5631c8a0bf..0000000000 --- a/common/eth2_network_config/built_in_network_configs/kiln/config.yaml +++ /dev/null @@ -1,69 +0,0 @@ -# Extends the mainnet preset -CONFIG_NAME: 'kiln' -PRESET_BASE: 'mainnet' -# Genesis -# --------------------------------------------------------------- -MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 95000 -# Mar 11th, 2022, 14:00 UTC -MIN_GENESIS_TIME: 1647007200 -# Genesis fork -GENESIS_FORK_VERSION: 0x70000069 -# 300 seconds (5 min) -GENESIS_DELAY: 300 - - -# Forking -# --------------------------------------------------------------- -# Some forks are disabled for now: -# - These may be re-assigned to another fork-version later -# - Temporarily set to max uint64 value: 2**64 - 1 - -# Altair -ALTAIR_FORK_VERSION: 0x70000070 -ALTAIR_FORK_EPOCH: 50 -# Bellatrix -BELLATRIX_FORK_VERSION: 0x70000071 -BELLATRIX_FORK_EPOCH: 150 -TERMINAL_TOTAL_DIFFICULTY: 20000000000000 -TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000 -TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615 - -# Sharding -SHARDING_FORK_VERSION: 0x03000000 -SHARDING_FORK_EPOCH: 18446744073709551615 - - -# Time parameters -# --------------------------------------------------------------- -# 12 seconds -SECONDS_PER_SLOT: 12 -# 14 (estimate from Eth1 mainnet) -SECONDS_PER_ETH1_BLOCK: 14 -# 2**8 (= 256) epochs ~27 hours -MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 -# 2**8 (= 256) epochs ~27 hours -SHARD_COMMITTEE_PERIOD: 256 -# 16 blocks is ~190s -ETH1_FOLLOW_DISTANCE: 16 - - -# Validator cycle -# --------------------------------------------------------------- -# 2**2 (= 4) -INACTIVITY_SCORE_BIAS: 4 -# 2**4 (= 16) -INACTIVITY_SCORE_RECOVERY_RATE: 16 -# 2**4 * 10**9 (= 16,000,000,000) Gwei -EJECTION_BALANCE: 16000000000 -# 2**2 (= 4) -MIN_PER_EPOCH_CHURN_LIMIT: 4 -# 2**16 (= 65,536) -CHURN_LIMIT_QUOTIENT: 65536 - - -# Deposit contract -# --------------------------------------------------------------- -# Custom Ethereum testnet -DEPOSIT_CHAIN_ID: 1337802 -DEPOSIT_NETWORK_ID: 1337802 -DEPOSIT_CONTRACT_ADDRESS: 0x4242424242424242424242424242424242424242 diff --git a/common/eth2_network_config/built_in_network_configs/kiln/deploy_block.txt b/common/eth2_network_config/built_in_network_configs/kiln/deploy_block.txt deleted file mode 100644 index c227083464..0000000000 --- a/common/eth2_network_config/built_in_network_configs/kiln/deploy_block.txt +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/common/eth2_network_config/built_in_network_configs/kiln/genesis.ssz.zip b/common/eth2_network_config/built_in_network_configs/kiln/genesis.ssz.zip deleted file mode 100644 index 309b323a5b..0000000000 Binary files a/common/eth2_network_config/built_in_network_configs/kiln/genesis.ssz.zip and /dev/null differ diff --git a/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml b/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml index 83e6de7906..9d9852f627 100644 --- a/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/mainnet/config.yaml @@ -39,9 +39,6 @@ BELLATRIX_FORK_EPOCH: 144896 # Sept 6, 2022, 11:34:47am UTC # Capella CAPELLA_FORK_VERSION: 0x03000000 CAPELLA_FORK_EPOCH: 18446744073709551615 -# Eip4844 -EIP4844_FORK_VERSION: 0x04000000 -EIP4844_FORK_EPOCH: 18446744073709551615 # Sharding SHARDING_FORK_VERSION: 0x03000000 SHARDING_FORK_EPOCH: 18446744073709551615 diff --git a/common/eth2_network_config/built_in_network_configs/prater/config.yaml b/common/eth2_network_config/built_in_network_configs/prater/config.yaml index d173be20de..69d65ca8fc 100644 --- a/common/eth2_network_config/built_in_network_configs/prater/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/prater/config.yaml @@ -35,8 +35,11 @@ ALTAIR_FORK_EPOCH: 36660 # Merge BELLATRIX_FORK_VERSION: 0x02001020 BELLATRIX_FORK_EPOCH: 112260 +# Capella +CAPELLA_FORK_VERSION: 0x03001020 +CAPELLA_FORK_EPOCH: 162304 # Sharding -SHARDING_FORK_VERSION: 0x03001020 +SHARDING_FORK_VERSION: 0x04001020 SHARDING_FORK_EPOCH: 18446744073709551615 # TBD, 2**32 is a placeholder. Merge transition approach is in active R&D. diff --git a/common/eth2_network_config/built_in_network_configs/ropsten/boot_enr.yaml b/common/eth2_network_config/built_in_network_configs/ropsten/boot_enr.yaml deleted file mode 100644 index 27e6e53fc4..0000000000 --- a/common/eth2_network_config/built_in_network_configs/ropsten/boot_enr.yaml +++ /dev/null @@ -1,4 +0,0 @@ -# Pari -- enr:-Iq4QMCTfIMXnow27baRUb35Q8iiFHSIDBJh6hQM5Axohhf4b6Kr_cOCu0htQ5WvVqKvFgY28893DHAg8gnBAXsAVqmGAX53x8JggmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk -# Teku -- enr:-KG4QMJSJ7DHk6v2p-W8zQ3Xv7FfssZ_1E3p2eY6kN13staMObUonAurqyWhODoeY6edXtV8e9eL9RnhgZ9va2SMDRQMhGV0aDKQS-iVMYAAAHD0AQAAAAAAAIJpZIJ2NIJpcIQDhAAhiXNlY3AyNTZrMaEDXBVUZhhmdy1MYor1eGdRJ4vHYghFKDgjyHgt6sJ-IlCDdGNwgiMog3VkcIIjKA diff --git a/common/eth2_network_config/built_in_network_configs/ropsten/config.yaml b/common/eth2_network_config/built_in_network_configs/ropsten/config.yaml deleted file mode 100644 index 5dad3ff759..0000000000 --- a/common/eth2_network_config/built_in_network_configs/ropsten/config.yaml +++ /dev/null @@ -1,71 +0,0 @@ -# Extends the mainnet preset -PRESET_BASE: 'mainnet' -CONFIG_NAME: 'ropsten' - -# Genesis -# --------------------------------------------------------------- -MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 100000 -# Monday, May 30th, 2022 3:00:00 PM +UTC -MIN_GENESIS_TIME: 1653318000 -GENESIS_FORK_VERSION: 0x80000069 -GENESIS_DELAY: 604800 - - -# Forking -# --------------------------------------------------------------- -# Some forks are disabled for now: -# - These may be re-assigned to another fork-version later -# - Temporarily set to max uint64 value: 2**64 - 1 - -# Altair -ALTAIR_FORK_VERSION: 0x80000070 -ALTAIR_FORK_EPOCH: 500 -# Merge -BELLATRIX_FORK_VERSION: 0x80000071 -BELLATRIX_FORK_EPOCH: 750 -TERMINAL_TOTAL_DIFFICULTY: 50000000000000000 -TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000 -TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615 - -# Sharding -SHARDING_FORK_VERSION: 0x03001020 -SHARDING_FORK_EPOCH: 18446744073709551615 - -# Time parameters -# --------------------------------------------------------------- -# 12 seconds -SECONDS_PER_SLOT: 12 -# 14 (estimate from Eth1 mainnet) -SECONDS_PER_ETH1_BLOCK: 14 -# 2**8 (= 256) epochs ~27 hours -MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 -# 2**8 (= 256) epochs ~27 hours -SHARD_COMMITTEE_PERIOD: 256 -# 2**11 (= 2,048) Eth1 blocks ~8 hours -ETH1_FOLLOW_DISTANCE: 2048 - - -# Validator cycle -# --------------------------------------------------------------- -# 2**2 (= 4) -INACTIVITY_SCORE_BIAS: 4 -# 2**4 (= 16) -INACTIVITY_SCORE_RECOVERY_RATE: 16 -# 2**4 * 10**9 (= 16,000,000,000) Gwei -EJECTION_BALANCE: 16000000000 -# 2**2 (= 4) -MIN_PER_EPOCH_CHURN_LIMIT: 4 -# 2**16 (= 65,536) -CHURN_LIMIT_QUOTIENT: 65536 - - -# Fork choice -# --------------------------------------------------------------- -# 40% -PROPOSER_SCORE_BOOST: 40 - -# Deposit contract -# --------------------------------------------------------------- -DEPOSIT_CHAIN_ID: 3 -DEPOSIT_NETWORK_ID: 3 -DEPOSIT_CONTRACT_ADDRESS: 0x6f22fFbC56eFF051aECF839396DD1eD9aD6BBA9D diff --git a/common/eth2_network_config/built_in_network_configs/ropsten/deploy_block.txt b/common/eth2_network_config/built_in_network_configs/ropsten/deploy_block.txt deleted file mode 100644 index dd46f23b62..0000000000 --- a/common/eth2_network_config/built_in_network_configs/ropsten/deploy_block.txt +++ /dev/null @@ -1 +0,0 @@ -12269949 \ No newline at end of file diff --git a/common/eth2_network_config/built_in_network_configs/ropsten/genesis.ssz.zip b/common/eth2_network_config/built_in_network_configs/ropsten/genesis.ssz.zip deleted file mode 100644 index 5f83ed3b65..0000000000 Binary files a/common/eth2_network_config/built_in_network_configs/ropsten/genesis.ssz.zip and /dev/null differ diff --git a/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml b/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml index 4ba006ec94..2946572899 100644 --- a/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml +++ b/common/eth2_network_config/built_in_network_configs/sepolia/config.yaml @@ -32,10 +32,6 @@ TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615 CAPELLA_FORK_VERSION: 0x90000072 CAPELLA_FORK_EPOCH: 56832 -# Eip4844 -EIP4844_FORK_VERSION: 0x03001020 -EIP4844_FORK_EPOCH: 18446744073709551615 - # Sharding SHARDING_FORK_VERSION: 0x04001020 SHARDING_FORK_EPOCH: 18446744073709551615 diff --git a/common/lighthouse_version/src/lib.rs b/common/lighthouse_version/src/lib.rs index 8ad4aa86f3..10d1a8c325 100644 --- a/common/lighthouse_version/src/lib.rs +++ b/common/lighthouse_version/src/lib.rs @@ -17,8 +17,8 @@ pub const VERSION: &str = git_version!( // NOTE: using --match instead of --exclude for compatibility with old Git "--match=thiswillnevermatchlol" ], - prefix = "Lighthouse/v3.5.0-", - fallback = "Lighthouse/v3.5.0" + prefix = "Lighthouse/v3.5.1-", + fallback = "Lighthouse/v3.5.1" ); /// Returns `VERSION`, but with platform information appended to the end. diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index 590e151a85..566764195d 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -857,10 +857,7 @@ where (parent_justified, parent_finalized) } else { let justification_and_finalization_state = match block { - // TODO(eip4844): Ensure that the final specification - // does not substantially modify per epoch processing. - BeaconBlockRef::Eip4844(_) - | BeaconBlockRef::Capella(_) + BeaconBlockRef::Capella(_) | BeaconBlockRef::Merge(_) | BeaconBlockRef::Altair(_) => { let participation_cache = diff --git a/consensus/state_processing/src/common/slash_validator.rs b/consensus/state_processing/src/common/slash_validator.rs index 77cd1a3265..d4675f5ef5 100644 --- a/consensus/state_processing/src/common/slash_validator.rs +++ b/consensus/state_processing/src/common/slash_validator.rs @@ -50,12 +50,11 @@ pub fn slash_validator( validator_effective_balance.safe_div(spec.whistleblower_reward_quotient)?; let proposer_reward = match state { BeaconState::Base(_) => whistleblower_reward.safe_div(spec.proposer_reward_quotient)?, - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => whistleblower_reward - .safe_mul(PROPOSER_WEIGHT)? - .safe_div(WEIGHT_DENOMINATOR)?, + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { + whistleblower_reward + .safe_mul(PROPOSER_WEIGHT)? + .safe_div(WEIGHT_DENOMINATOR)? + } }; // Ensure the whistleblower index is in the validator registry. diff --git a/consensus/state_processing/src/genesis.rs b/consensus/state_processing/src/genesis.rs index 3f9328f4d5..68f04b554e 100644 --- a/consensus/state_processing/src/genesis.rs +++ b/consensus/state_processing/src/genesis.rs @@ -2,9 +2,7 @@ use super::per_block_processing::{ errors::BlockProcessingError, process_operations::process_deposit, }; use crate::common::DepositDataTree; -use crate::upgrade::{ - upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella, upgrade_to_eip4844, -}; +use crate::upgrade::{upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella}; use safe_arith::{ArithError, SafeArith}; use tree_hash::TreeHash; use types::DEPOSIT_TREE_DEPTH; @@ -93,23 +91,6 @@ pub fn initialize_beacon_state_from_eth1( } } - // Upgrade to eip4844 if configured from genesis - if spec - .eip4844_fork_epoch - .map_or(false, |fork_epoch| fork_epoch == T::genesis_epoch()) - { - upgrade_to_eip4844(&mut state, spec)?; - - // Remove intermediate Capella fork from `state.fork`. - state.fork_mut().previous_version = spec.eip4844_fork_version; - - // Override latest execution payload header. - // See https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#testing - if let Some(ExecutionPayloadHeader::Eip4844(header)) = execution_payload_header { - *state.latest_execution_payload_header_eip4844_mut()? = header; - } - } - // Now that we have our validators, initialize the caches (including the committees) state.build_all_caches(spec)?; diff --git a/consensus/state_processing/src/per_block_processing.rs b/consensus/state_processing/src/per_block_processing.rs index 4f686200b0..c564b98d66 100644 --- a/consensus/state_processing/src/per_block_processing.rs +++ b/consensus/state_processing/src/per_block_processing.rs @@ -13,7 +13,6 @@ pub use self::verify_attester_slashing::{ pub use self::verify_proposer_slashing::verify_proposer_slashing; pub use altair::sync_committee::process_sync_aggregate; pub use block_signature_verifier::{BlockSignatureVerifier, ParallelSignatureSets}; -pub use eip4844::eip4844::process_blob_kzg_commitments; pub use is_valid_indexed_attestation::is_valid_indexed_attestation; pub use process_operations::process_operations; pub use verify_attestation::{ @@ -27,7 +26,6 @@ pub use verify_exit::verify_exit; pub mod altair; pub mod block_signature_verifier; -pub mod eip4844; pub mod errors; mod is_valid_indexed_attestation; pub mod process_operations; @@ -180,12 +178,6 @@ pub fn per_block_processing>( )?; } - // Eip4844 specifications are not yet released so additional care is taken - // to ensure the code does not run in production. - if matches!(block, BeaconBlockRef::Eip4844(_)) { - process_blob_kzg_commitments(block.body())?; - } - Ok(()) } @@ -409,12 +401,6 @@ pub fn process_execution_payload>( _ => return Err(BlockProcessingError::IncorrectStateType), } } - ExecutionPayloadHeaderRefMut::Eip4844(header_mut) => { - match payload.to_execution_payload_header() { - ExecutionPayloadHeader::Eip4844(header) => *header_mut = header, - _ => return Err(BlockProcessingError::IncorrectStateType), - } - } } Ok(()) @@ -527,7 +513,7 @@ pub fn process_withdrawals>( ) -> Result<(), BlockProcessingError> { match state { BeaconState::Merge(_) => Ok(()), - BeaconState::Capella(_) | BeaconState::Eip4844(_) => { + BeaconState::Capella(_) => { let expected_withdrawals = get_expected_withdrawals(state, spec)?; let expected_root = expected_withdrawals.tree_hash_root(); let withdrawals_root = payload.withdrawals_root()?; diff --git a/consensus/state_processing/src/per_block_processing/eip4844.rs b/consensus/state_processing/src/per_block_processing/eip4844.rs deleted file mode 100644 index 23ab3c5c07..0000000000 --- a/consensus/state_processing/src/per_block_processing/eip4844.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[allow(clippy::module_inception)] -pub mod eip4844; diff --git a/consensus/state_processing/src/per_block_processing/eip4844/eip4844.rs b/consensus/state_processing/src/per_block_processing/eip4844/eip4844.rs deleted file mode 100644 index 7826057a43..0000000000 --- a/consensus/state_processing/src/per_block_processing/eip4844/eip4844.rs +++ /dev/null @@ -1,122 +0,0 @@ -use crate::BlockProcessingError; -use eth2_hashing::hash_fixed; -use itertools::{EitherOrBoth, Itertools}; -use safe_arith::SafeArith; -use ssz::Decode; -use ssz_types::VariableList; -use types::consts::eip4844::{BLOB_TX_TYPE, VERSIONED_HASH_VERSION_KZG}; -use types::{ - AbstractExecPayload, BeaconBlockBodyRef, EthSpec, ExecPayload, KzgCommitment, Transaction, - Transactions, VersionedHash, -}; - -pub fn process_blob_kzg_commitments>( - block_body: BeaconBlockBodyRef, -) -> Result<(), BlockProcessingError> { - if let (Ok(payload), Ok(kzg_commitments)) = ( - block_body.execution_payload(), - block_body.blob_kzg_commitments(), - ) { - if let Some(transactions) = payload.transactions() { - if !verify_kzg_commitments_against_transactions::(transactions, kzg_commitments)? { - return Err(BlockProcessingError::BlobVersionHashMismatch); - } - } - } - - Ok(()) -} - -pub fn verify_kzg_commitments_against_transactions( - transactions: &Transactions, - kzg_commitments: &VariableList, -) -> Result { - let nested_iter = transactions - .into_iter() - .filter(|tx| { - tx.first() - .map(|tx_type| *tx_type == BLOB_TX_TYPE) - .unwrap_or(false) - }) - .map(|tx| tx_peek_blob_versioned_hashes::(tx)); - - itertools::process_results(nested_iter, |iter| { - let zipped_iter = iter - .flatten() - // Need to use `itertools::zip_longest` here because just zipping hides if one iter is shorter - // and `itertools::zip_eq` panics. - .zip_longest(kzg_commitments.into_iter()) - .enumerate() - .map(|(index, next)| match next { - EitherOrBoth::Both(hash, commitment) => Ok((hash?, commitment)), - // The number of versioned hashes from the blob transactions exceeds the number of - // commitments in the block. - EitherOrBoth::Left(_) => Err(BlockProcessingError::BlobNumCommitmentsMismatch { - commitments_processed_in_block: index, - commitments_processed_in_transactions: index.safe_add(1)?, - }), - // The number of commitments in the block exceeds the number of versioned hashes - // in the blob transactions. - EitherOrBoth::Right(_) => Err(BlockProcessingError::BlobNumCommitmentsMismatch { - commitments_processed_in_block: index.safe_add(1)?, - commitments_processed_in_transactions: index, - }), - }); - - itertools::process_results(zipped_iter, |mut iter| { - iter.all(|(tx_versioned_hash, commitment)| { - tx_versioned_hash == kzg_commitment_to_versioned_hash(commitment) - }) - }) - })? -} - -/// Only transactions of type `BLOB_TX_TYPE` should be passed into this function. -fn tx_peek_blob_versioned_hashes( - opaque_tx: &Transaction, -) -> Result< - impl IntoIterator> + '_, - BlockProcessingError, -> { - let tx_len = opaque_tx.len(); - let message_offset = 1.safe_add(u32::from_ssz_bytes(opaque_tx.get(1..5).ok_or( - BlockProcessingError::BlobVersionHashIndexOutOfBounds { - length: tx_len, - index: 5, - }, - )?)?)?; - - let message_offset_usize = message_offset as usize; - - // field offset: 32 + 8 + 32 + 32 + 8 + 4 + 32 + 4 + 4 + 32 = 188 - let blob_versioned_hashes_offset = message_offset.safe_add(u32::from_ssz_bytes( - opaque_tx - .get(message_offset_usize.safe_add(188)?..message_offset_usize.safe_add(192)?) - .ok_or(BlockProcessingError::BlobVersionHashIndexOutOfBounds { - length: tx_len, - index: message_offset_usize.safe_add(192)?, - })?, - )?)?; - - let num_hashes = tx_len - .safe_sub(blob_versioned_hashes_offset as usize)? - .safe_div(32)?; - - Ok((0..num_hashes).into_iter().map(move |i| { - let next_version_hash_index = - (blob_versioned_hashes_offset as usize).safe_add(i.safe_mul(32)?)?; - let bytes = opaque_tx - .get(next_version_hash_index..next_version_hash_index.safe_add(32)?) - .ok_or(BlockProcessingError::BlobVersionHashIndexOutOfBounds { - length: tx_len, - index: (next_version_hash_index).safe_add(32)?, - })?; - Ok(VersionedHash::from_slice(bytes)) - })) -} - -fn kzg_commitment_to_versioned_hash(kzg_commitment: &KzgCommitment) -> VersionedHash { - let mut hashed_commitment = hash_fixed(&kzg_commitment.0); - hashed_commitment[0] = VERSIONED_HASH_VERSION_KZG; - VersionedHash::from(hashed_commitment) -} diff --git a/consensus/state_processing/src/per_block_processing/errors.rs b/consensus/state_processing/src/per_block_processing/errors.rs index 5c34afd593..1aaf298d69 100644 --- a/consensus/state_processing/src/per_block_processing/errors.rs +++ b/consensus/state_processing/src/per_block_processing/errors.rs @@ -82,18 +82,6 @@ pub enum BlockProcessingError { expected: Hash256, found: Hash256, }, - BlobVersionHashMismatch, - /// The number of commitments in blob transactions in the payload does not match the number - /// of commitments in the block. - BlobNumCommitmentsMismatch { - commitments_processed_in_block: usize, - /// This number depic - commitments_processed_in_transactions: usize, - }, - BlobVersionHashIndexOutOfBounds { - index: usize, - length: usize, - }, WithdrawalCredentialsInvalid, } diff --git a/consensus/state_processing/src/per_block_processing/process_operations.rs b/consensus/state_processing/src/per_block_processing/process_operations.rs index 8a6163f29b..7d04cad90b 100644 --- a/consensus/state_processing/src/per_block_processing/process_operations.rs +++ b/consensus/state_processing/src/per_block_processing/process_operations.rs @@ -256,8 +256,7 @@ pub fn process_attestations>( } BeaconBlockBodyRef::Altair(_) | BeaconBlockBodyRef::Merge(_) - | BeaconBlockBodyRef::Capella(_) - | BeaconBlockBodyRef::Eip4844(_) => { + | BeaconBlockBodyRef::Capella(_) => { altair::process_attestations( state, block_body.attestations(), diff --git a/consensus/state_processing/src/per_epoch_processing.rs b/consensus/state_processing/src/per_epoch_processing.rs index 996e39c27f..6350685f82 100644 --- a/consensus/state_processing/src/per_epoch_processing.rs +++ b/consensus/state_processing/src/per_epoch_processing.rs @@ -40,7 +40,7 @@ pub fn process_epoch( match state { BeaconState::Base(_) => base::process_epoch(state, spec), BeaconState::Altair(_) | BeaconState::Merge(_) => altair::process_epoch(state, spec), - BeaconState::Capella(_) | BeaconState::Eip4844(_) => capella::process_epoch(state, spec), + BeaconState::Capella(_) => capella::process_epoch(state, spec), } } diff --git a/consensus/state_processing/src/per_slot_processing.rs b/consensus/state_processing/src/per_slot_processing.rs index 8d2600bb41..ead06edbf5 100644 --- a/consensus/state_processing/src/per_slot_processing.rs +++ b/consensus/state_processing/src/per_slot_processing.rs @@ -1,6 +1,4 @@ -use crate::upgrade::{ - upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella, upgrade_to_eip4844, -}; +use crate::upgrade::{upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella}; use crate::{per_epoch_processing::EpochProcessingSummary, *}; use safe_arith::{ArithError, SafeArith}; use types::*; @@ -61,10 +59,6 @@ pub fn per_slot_processing( if spec.capella_fork_epoch == Some(state.current_epoch()) { upgrade_to_capella(state, spec)?; } - // Eip4844 - if spec.eip4844_fork_epoch == Some(state.current_epoch()) { - upgrade_to_eip4844(state, spec)?; - } } Ok(summary) diff --git a/consensus/state_processing/src/upgrade.rs b/consensus/state_processing/src/upgrade.rs index 01b6571056..a57d5923f8 100644 --- a/consensus/state_processing/src/upgrade.rs +++ b/consensus/state_processing/src/upgrade.rs @@ -1,9 +1,7 @@ pub mod altair; pub mod capella; -pub mod eip4844; pub mod merge; pub use altair::upgrade_to_altair; pub use capella::upgrade_to_capella; -pub use eip4844::upgrade_to_eip4844; pub use merge::upgrade_to_bellatrix; diff --git a/consensus/state_processing/src/upgrade/eip4844.rs b/consensus/state_processing/src/upgrade/eip4844.rs deleted file mode 100644 index 4f6ff9d194..0000000000 --- a/consensus/state_processing/src/upgrade/eip4844.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::mem; -use types::{BeaconState, BeaconStateEip4844, BeaconStateError as Error, ChainSpec, EthSpec, Fork}; - -/// Transform a `Capella` state into an `Eip4844` state. -pub fn upgrade_to_eip4844( - pre_state: &mut BeaconState, - spec: &ChainSpec, -) -> Result<(), Error> { - let epoch = pre_state.current_epoch(); - let pre = pre_state.as_capella_mut()?; - - let previous_fork_version = pre.fork.current_version; - - // 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`. - // - // Fixed size vectors get cloned because replacing them would require the same size - // allocation as cloning. - let post = BeaconState::Eip4844(BeaconStateEip4844 { - // Versioning - genesis_time: pre.genesis_time, - genesis_validators_root: pre.genesis_validators_root, - slot: pre.slot, - fork: Fork { - previous_version: previous_fork_version, - current_version: spec.eip4844_fork_version, - epoch, - }, - // History - latest_block_header: pre.latest_block_header.clone(), - block_roots: pre.block_roots.clone(), - state_roots: pre.state_roots.clone(), - historical_roots: mem::take(&mut pre.historical_roots), - // Eth1 - eth1_data: pre.eth1_data.clone(), - eth1_data_votes: mem::take(&mut pre.eth1_data_votes), - eth1_deposit_index: pre.eth1_deposit_index, - // Registry - validators: mem::take(&mut pre.validators), - balances: mem::take(&mut pre.balances), - // Randomness - randao_mixes: pre.randao_mixes.clone(), - // Slashings - slashings: pre.slashings.clone(), - // `Participation - previous_epoch_participation: mem::take(&mut pre.previous_epoch_participation), - current_epoch_participation: mem::take(&mut pre.current_epoch_participation), - // Finality - justification_bits: pre.justification_bits.clone(), - previous_justified_checkpoint: pre.previous_justified_checkpoint, - current_justified_checkpoint: pre.current_justified_checkpoint, - finalized_checkpoint: pre.finalized_checkpoint, - // Inactivity - inactivity_scores: mem::take(&mut pre.inactivity_scores), - // Sync committees - current_sync_committee: pre.current_sync_committee.clone(), - next_sync_committee: pre.next_sync_committee.clone(), - // Execution - latest_execution_payload_header: pre.latest_execution_payload_header.upgrade_to_eip4844(), - // Capella - next_withdrawal_index: pre.next_withdrawal_index, - next_withdrawal_validator_index: pre.next_withdrawal_validator_index, - historical_summaries: pre.historical_summaries.clone(), - // Caches - total_active_balance: pre.total_active_balance, - committee_caches: mem::take(&mut pre.committee_caches), - pubkey_cache: mem::take(&mut pre.pubkey_cache), - exit_cache: mem::take(&mut pre.exit_cache), - tree_hash_cache: mem::take(&mut pre.tree_hash_cache), - }); - - *pre_state = post; - - Ok(()) -} diff --git a/consensus/types/Cargo.toml b/consensus/types/Cargo.toml index 276077c7f1..46b88af66f 100644 --- a/consensus/types/Cargo.toml +++ b/consensus/types/Cargo.toml @@ -9,7 +9,6 @@ name = "benches" harness = false [dependencies] -serde-big-array = {version = "0.3.2", features = ["const-generics"]} merkle_proof = { path = "../../consensus/merkle_proof" } bls = { path = "../../crypto/bls", features = ["arbitrary"] } compare_fields = { path = "../../common/compare_fields" } diff --git a/consensus/types/src/beacon_block.rs b/consensus/types/src/beacon_block.rs index 0f26cd0e5e..4bf9e641c0 100644 --- a/consensus/types/src/beacon_block.rs +++ b/consensus/types/src/beacon_block.rs @@ -1,6 +1,6 @@ use crate::beacon_block_body::{ - BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyEip4844, BeaconBlockBodyMerge, - BeaconBlockBodyRef, BeaconBlockBodyRefMut, + BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyMerge, BeaconBlockBodyRef, + BeaconBlockBodyRefMut, }; use crate::test_utils::TestRandom; use crate::*; @@ -17,7 +17,7 @@ use tree_hash_derive::TreeHash; /// A block of the `BeaconChain`. #[superstruct( - variants(Base, Altair, Merge, Capella, Eip4844), + variants(Base, Altair, Merge, Capella), variant_attributes( derive( Debug, @@ -72,8 +72,6 @@ pub struct BeaconBlock = FullPayload pub body: BeaconBlockBodyMerge, #[superstruct(only(Capella), partial_getter(rename = "body_capella"))] pub body: BeaconBlockBodyCapella, - #[superstruct(only(Eip4844), partial_getter(rename = "body_eip4844"))] - pub body: BeaconBlockBodyEip4844, } pub type BlindedBeaconBlock = BeaconBlock>; @@ -126,9 +124,8 @@ impl> BeaconBlock { /// Usually it's better to prefer `from_ssz_bytes` which will decode the correct variant based /// on the fork slot. pub fn any_from_ssz_bytes(bytes: &[u8]) -> Result { - BeaconBlockEip4844::from_ssz_bytes(bytes) - .map(BeaconBlock::Eip4844) - .or_else(|_| BeaconBlockCapella::from_ssz_bytes(bytes).map(BeaconBlock::Capella)) + BeaconBlockCapella::from_ssz_bytes(bytes) + .map(BeaconBlock::Capella) .or_else(|_| BeaconBlockMerge::from_ssz_bytes(bytes).map(BeaconBlock::Merge)) .or_else(|_| BeaconBlockAltair::from_ssz_bytes(bytes).map(BeaconBlock::Altair)) .or_else(|_| BeaconBlockBase::from_ssz_bytes(bytes).map(BeaconBlock::Base)) @@ -206,7 +203,6 @@ impl<'a, T: EthSpec, Payload: AbstractExecPayload> BeaconBlockRef<'a, T, Payl BeaconBlockRef::Altair { .. } => ForkName::Altair, BeaconBlockRef::Merge { .. } => ForkName::Merge, BeaconBlockRef::Capella { .. } => ForkName::Capella, - BeaconBlockRef::Eip4844 { .. } => ForkName::Eip4844, }; if fork_at_slot == object_fork { @@ -560,36 +556,6 @@ impl> EmptyBlock for BeaconBlockCape } } -impl> EmptyBlock for BeaconBlockEip4844 { - /// Returns an empty Eip4844 block to be used during genesis. - fn empty(spec: &ChainSpec) -> Self { - BeaconBlockEip4844 { - slot: spec.genesis_slot, - proposer_index: 0, - parent_root: Hash256::zero(), - state_root: Hash256::zero(), - body: BeaconBlockBodyEip4844 { - randao_reveal: Signature::empty(), - eth1_data: Eth1Data { - deposit_root: Hash256::zero(), - block_hash: Hash256::zero(), - deposit_count: 0, - }, - graffiti: Graffiti::default(), - proposer_slashings: VariableList::empty(), - attester_slashings: VariableList::empty(), - attestations: VariableList::empty(), - deposits: VariableList::empty(), - voluntary_exits: VariableList::empty(), - sync_aggregate: SyncAggregate::empty(), - execution_payload: Payload::Eip4844::default(), - bls_to_execution_changes: VariableList::empty(), - blob_kzg_commitments: VariableList::empty(), - }, - } - } -} - // We can convert pre-Bellatrix blocks without payloads into blocks "with" payloads. impl From>> for BeaconBlockBase> @@ -669,7 +635,6 @@ impl_from!(BeaconBlockBase, >, >, |body: impl_from!(BeaconBlockAltair, >, >, |body: BeaconBlockBodyAltair<_, _>| body.into()); impl_from!(BeaconBlockMerge, >, >, |body: BeaconBlockBodyMerge<_, _>| body.into()); impl_from!(BeaconBlockCapella, >, >, |body: BeaconBlockBodyCapella<_, _>| body.into()); -impl_from!(BeaconBlockEip4844, >, >, |body: BeaconBlockBodyEip4844<_, _>| body.into()); // We can clone blocks with payloads to blocks without payloads, without cloning the payload. macro_rules! impl_clone_as_blinded { @@ -701,7 +666,6 @@ impl_clone_as_blinded!(BeaconBlockBase, >, >, >); impl_clone_as_blinded!(BeaconBlockMerge, >, >); impl_clone_as_blinded!(BeaconBlockCapella, >, >); -impl_clone_as_blinded!(BeaconBlockEip4844, >, >); // A reference to a full beacon block can be cloned into a blinded beacon block, without cloning the // execution payload. @@ -817,25 +781,6 @@ mod tests { }); } - #[test] - fn roundtrip_4844_block() { - let rng = &mut XorShiftRng::from_seed([42; 16]); - let spec = &ForkName::Eip4844.make_genesis_spec(MainnetEthSpec::default_spec()); - - let inner_block = BeaconBlockEip4844 { - slot: Slot::random_for_test(rng), - proposer_index: u64::random_for_test(rng), - parent_root: Hash256::random_for_test(rng), - state_root: Hash256::random_for_test(rng), - body: BeaconBlockBodyEip4844::random_for_test(rng), - }; - let block = BeaconBlock::Eip4844(inner_block.clone()); - - test_ssz_tree_hash_pair_with(&block, &inner_block, |bytes| { - BeaconBlock::from_ssz_bytes(bytes, spec) - }); - } - #[test] fn decode_base_and_altair() { type E = MainnetEthSpec; @@ -851,12 +796,9 @@ mod tests { let altair_slot = altair_epoch.start_slot(E::slots_per_epoch()); let capella_epoch = altair_fork_epoch + 1; let capella_slot = capella_epoch.start_slot(E::slots_per_epoch()); - let eip4844_epoch = capella_epoch + 1; - let eip4844_slot = eip4844_epoch.start_slot(E::slots_per_epoch()); spec.altair_fork_epoch = Some(altair_epoch); spec.capella_fork_epoch = Some(capella_epoch); - spec.eip4844_fork_epoch = Some(eip4844_epoch); // BeaconBlockBase { @@ -923,27 +865,5 @@ mod tests { BeaconBlock::from_ssz_bytes(&bad_block.as_ssz_bytes(), &spec) .expect_err("bad capella block cannot be decoded"); } - - // BeaconBlockEip4844 - { - let good_block = BeaconBlock::Eip4844(BeaconBlockEip4844 { - slot: eip4844_slot, - ..<_>::random_for_test(rng) - }); - // It's invalid to have an Capella block with a epoch lower than the fork epoch. - let bad_block = { - let mut bad = good_block.clone(); - *bad.slot_mut() = capella_slot; - bad - }; - - assert_eq!( - BeaconBlock::from_ssz_bytes(&good_block.as_ssz_bytes(), &spec) - .expect("good eip4844 block can be decoded"), - good_block - ); - BeaconBlock::from_ssz_bytes(&bad_block.as_ssz_bytes(), &spec) - .expect_err("bad eip4844 block cannot be decoded"); - } } } diff --git a/consensus/types/src/beacon_block_body.rs b/consensus/types/src/beacon_block_body.rs index 07c8f898b3..c0ba869410 100644 --- a/consensus/types/src/beacon_block_body.rs +++ b/consensus/types/src/beacon_block_body.rs @@ -1,4 +1,3 @@ -use crate::kzg_commitment::KzgCommitment; use crate::test_utils::TestRandom; use crate::*; use derivative::Derivative; @@ -14,7 +13,7 @@ use tree_hash_derive::TreeHash; /// /// This *superstruct* abstracts over the hard-fork. #[superstruct( - variants(Base, Altair, Merge, Capella, Eip4844), + variants(Base, Altair, Merge, Capella), variant_attributes( derive( Debug, @@ -52,7 +51,7 @@ pub struct BeaconBlockBody = FullPay pub attestations: VariableList, T::MaxAttestations>, pub deposits: VariableList, pub voluntary_exits: VariableList, - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub sync_aggregate: SyncAggregate, // We flatten the execution payload so that serde can use the name of the inner type, // either `execution_payload` for full payloads, or `execution_payload_header` for blinded @@ -63,14 +62,9 @@ pub struct BeaconBlockBody = FullPay #[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))] #[serde(flatten)] pub execution_payload: Payload::Capella, - #[superstruct(only(Eip4844), partial_getter(rename = "execution_payload_eip4844"))] - #[serde(flatten)] - pub execution_payload: Payload::Eip4844, - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] pub bls_to_execution_changes: VariableList, - #[superstruct(only(Eip4844))] - pub blob_kzg_commitments: VariableList, #[superstruct(only(Base, Altair))] #[ssz(skip_serializing, skip_deserializing)] #[tree_hash(skip_hashing)] @@ -91,7 +85,6 @@ impl<'a, T: EthSpec, Payload: AbstractExecPayload> BeaconBlockBodyRef<'a, T, Self::Base(_) | Self::Altair(_) => Err(Error::IncorrectStateVariant), Self::Merge(body) => Ok(Payload::Ref::from(&body.execution_payload)), Self::Capella(body) => Ok(Payload::Ref::from(&body.execution_payload)), - Self::Eip4844(body) => Ok(Payload::Ref::from(&body.execution_payload)), } } } @@ -104,7 +97,6 @@ impl<'a, T: EthSpec> BeaconBlockBodyRef<'a, T> { BeaconBlockBodyRef::Altair { .. } => ForkName::Altair, BeaconBlockBodyRef::Merge { .. } => ForkName::Merge, BeaconBlockBodyRef::Capella { .. } => ForkName::Capella, - BeaconBlockBodyRef::Eip4844 { .. } => ForkName::Eip4844, } } } @@ -329,50 +321,6 @@ impl From>> } } -impl From>> - for ( - BeaconBlockBodyEip4844>, - Option>, - ) -{ - fn from(body: BeaconBlockBodyEip4844>) -> Self { - let BeaconBlockBodyEip4844 { - randao_reveal, - eth1_data, - graffiti, - proposer_slashings, - attester_slashings, - attestations, - deposits, - voluntary_exits, - sync_aggregate, - execution_payload: FullPayloadEip4844 { execution_payload }, - bls_to_execution_changes, - blob_kzg_commitments, - } = body; - - ( - BeaconBlockBodyEip4844 { - randao_reveal, - eth1_data, - graffiti, - proposer_slashings, - attester_slashings, - attestations, - deposits, - voluntary_exits, - sync_aggregate, - execution_payload: BlindedPayloadEip4844 { - execution_payload_header: From::from(&execution_payload), - }, - bls_to_execution_changes, - blob_kzg_commitments, - }, - Some(execution_payload), - ) - } -} - // We can clone a full block into a blinded block, without cloning the payload. impl BeaconBlockBodyBase> { pub fn clone_as_blinded(&self) -> BeaconBlockBodyBase> { @@ -454,42 +402,6 @@ impl BeaconBlockBodyCapella> { } } -impl BeaconBlockBodyEip4844> { - pub fn clone_as_blinded(&self) -> BeaconBlockBodyEip4844> { - let BeaconBlockBodyEip4844 { - randao_reveal, - eth1_data, - graffiti, - proposer_slashings, - attester_slashings, - attestations, - deposits, - voluntary_exits, - sync_aggregate, - execution_payload: FullPayloadEip4844 { execution_payload }, - bls_to_execution_changes, - blob_kzg_commitments, - } = self; - - BeaconBlockBodyEip4844 { - randao_reveal: randao_reveal.clone(), - eth1_data: eth1_data.clone(), - graffiti: *graffiti, - proposer_slashings: proposer_slashings.clone(), - attester_slashings: attester_slashings.clone(), - attestations: attestations.clone(), - deposits: deposits.clone(), - voluntary_exits: voluntary_exits.clone(), - sync_aggregate: sync_aggregate.clone(), - execution_payload: BlindedPayloadEip4844 { - execution_payload_header: execution_payload.into(), - }, - bls_to_execution_changes: bls_to_execution_changes.clone(), - blob_kzg_commitments: blob_kzg_commitments.clone(), - } - } -} - impl From>> for ( BeaconBlockBody>, diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index c98df48d14..921dafbbc6 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -176,7 +176,7 @@ impl From for Hash256 { /// The state of the `BeaconChain` at some slot. #[superstruct( - variants(Base, Altair, Merge, Capella, Eip4844), + variants(Base, Altair, Merge, Capella), variant_attributes( derive( Derivative, @@ -256,9 +256,9 @@ where pub current_epoch_attestations: VariableList, T::MaxPendingAttestations>, // Participation (Altair and later) - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub previous_epoch_participation: VariableList, - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub current_epoch_participation: VariableList, // Finality @@ -273,13 +273,13 @@ where // Inactivity #[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")] - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub inactivity_scores: VariableList, // Light-client sync committees - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub current_sync_committee: Arc>, - #[superstruct(only(Altair, Merge, Capella, Eip4844))] + #[superstruct(only(Altair, Merge, Capella))] pub next_sync_committee: Arc>, // Execution @@ -293,21 +293,16 @@ where partial_getter(rename = "latest_execution_payload_header_capella") )] pub latest_execution_payload_header: ExecutionPayloadHeaderCapella, - #[superstruct( - only(Eip4844), - partial_getter(rename = "latest_execution_payload_header_eip4844") - )] - pub latest_execution_payload_header: ExecutionPayloadHeaderEip4844, // Capella - #[superstruct(only(Capella, Eip4844), partial_getter(copy))] + #[superstruct(only(Capella), partial_getter(copy))] #[serde(with = "eth2_serde_utils::quoted_u64")] pub next_withdrawal_index: u64, - #[superstruct(only(Capella, Eip4844), partial_getter(copy))] + #[superstruct(only(Capella), partial_getter(copy))] #[serde(with = "eth2_serde_utils::quoted_u64")] pub next_withdrawal_validator_index: u64, // Deep history valid from Capella onwards. - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] pub historical_summaries: VariableList, // Caching (not in the spec) @@ -420,7 +415,6 @@ impl BeaconState { BeaconState::Altair { .. } => ForkName::Altair, BeaconState::Merge { .. } => ForkName::Merge, BeaconState::Capella { .. } => ForkName::Capella, - BeaconState::Eip4844 { .. } => ForkName::Eip4844, }; if fork_at_slot == object_fork { @@ -720,9 +714,6 @@ impl BeaconState { BeaconState::Capella(state) => Ok(ExecutionPayloadHeaderRef::Capella( &state.latest_execution_payload_header, )), - BeaconState::Eip4844(state) => Ok(ExecutionPayloadHeaderRef::Eip4844( - &state.latest_execution_payload_header, - )), } } @@ -737,9 +728,6 @@ impl BeaconState { BeaconState::Capella(state) => Ok(ExecutionPayloadHeaderRefMut::Capella( &mut state.latest_execution_payload_header, )), - BeaconState::Eip4844(state) => Ok(ExecutionPayloadHeaderRefMut::Eip4844( - &mut state.latest_execution_payload_header, - )), } } @@ -1168,7 +1156,6 @@ impl BeaconState { BeaconState::Altair(state) => (&mut state.validators, &mut state.balances), BeaconState::Merge(state) => (&mut state.validators, &mut state.balances), BeaconState::Capella(state) => (&mut state.validators, &mut state.balances), - BeaconState::Eip4844(state) => (&mut state.validators, &mut state.balances), } } @@ -1366,7 +1353,6 @@ impl BeaconState { BeaconState::Altair(state) => Ok(&mut state.current_epoch_participation), BeaconState::Merge(state) => Ok(&mut state.current_epoch_participation), BeaconState::Capella(state) => Ok(&mut state.current_epoch_participation), - BeaconState::Eip4844(state) => Ok(&mut state.current_epoch_participation), } } else if epoch == self.previous_epoch() { match self { @@ -1374,7 +1360,6 @@ impl BeaconState { BeaconState::Altair(state) => Ok(&mut state.previous_epoch_participation), BeaconState::Merge(state) => Ok(&mut state.previous_epoch_participation), BeaconState::Capella(state) => Ok(&mut state.previous_epoch_participation), - BeaconState::Eip4844(state) => Ok(&mut state.previous_epoch_participation), } } else { Err(BeaconStateError::EpochOutOfBounds) @@ -1680,7 +1665,6 @@ impl BeaconState { BeaconState::Altair(inner) => BeaconState::Altair(inner.clone()), BeaconState::Merge(inner) => BeaconState::Merge(inner.clone()), BeaconState::Capella(inner) => BeaconState::Capella(inner.clone()), - BeaconState::Eip4844(inner) => BeaconState::Eip4844(inner.clone()), }; if config.committee_caches { *res.committee_caches_mut() = self.committee_caches().clone(); @@ -1849,7 +1833,6 @@ impl CompareFields for BeaconState { (BeaconState::Altair(x), BeaconState::Altair(y)) => x.compare_fields(y), (BeaconState::Merge(x), BeaconState::Merge(y)) => x.compare_fields(y), (BeaconState::Capella(x), BeaconState::Capella(y)) => x.compare_fields(y), - (BeaconState::Eip4844(x), BeaconState::Eip4844(y)) => x.compare_fields(y), _ => panic!("compare_fields: mismatched state variants",), } } diff --git a/consensus/types/src/blobs_sidecar.rs b/consensus/types/src/blobs_sidecar.rs deleted file mode 100644 index 227be3e2f8..0000000000 --- a/consensus/types/src/blobs_sidecar.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::kzg_proof::KzgProof; -use crate::{Blob, EthSpec, Hash256, SignedRoot, Slot}; -use serde_derive::{Deserialize, Serialize}; -use ssz::Encode; -use ssz_derive::{Decode, Encode}; -use ssz_types::VariableList; -use tree_hash_derive::TreeHash; - -#[derive( - Debug, - Clone, - Serialize, - Deserialize, - Encode, - Decode, - TreeHash, - PartialEq, - Default, - arbitrary::Arbitrary, -)] -#[serde(bound = "T: EthSpec")] -#[arbitrary(bound = "T: EthSpec")] -pub struct BlobsSidecar { - pub beacon_block_root: Hash256, - pub beacon_block_slot: Slot, - pub blobs: VariableList, T::MaxBlobsPerBlock>, - pub kzg_aggregate_proof: KzgProof, -} - -impl SignedRoot for BlobsSidecar {} - -impl BlobsSidecar { - pub fn empty() -> Self { - Self::default() - } - #[allow(clippy::integer_arithmetic)] - pub fn max_size() -> usize { - // Fixed part - Self::empty().as_ssz_bytes().len() - // Max size of variable length `blobs` field - + (T::max_blobs_per_block() * as Encode>::ssz_fixed_len()) - } -} diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index 1f947c9e7b..bbb0b9712b 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -14,7 +14,6 @@ pub enum Domain { BlsToExecutionChange, BeaconProposer, BeaconAttester, - BlobsSideCar, Randao, Deposit, VoluntaryExit, @@ -100,7 +99,6 @@ pub struct ChainSpec { */ pub(crate) domain_beacon_proposer: u32, pub(crate) domain_beacon_attester: u32, - pub(crate) domain_blobs_sidecar: u32, pub(crate) domain_randao: u32, pub(crate) domain_deposit: u32, pub(crate) domain_voluntary_exit: u32, @@ -161,12 +159,6 @@ pub struct ChainSpec { pub capella_fork_epoch: Option, pub max_validators_per_withdrawals_sweep: u64, - /* - * Eip4844 hard fork params - */ - pub eip4844_fork_version: [u8; 4], - pub eip4844_fork_epoch: Option, - /* * Networking */ @@ -255,16 +247,13 @@ impl ChainSpec { /// Returns the name of the fork which is active at `epoch`. pub fn fork_name_at_epoch(&self, epoch: Epoch) -> ForkName { - match self.eip4844_fork_epoch { - Some(fork_epoch) if epoch >= fork_epoch => ForkName::Eip4844, - _ => match self.capella_fork_epoch { - Some(fork_epoch) if epoch >= fork_epoch => ForkName::Capella, - _ => match self.bellatrix_fork_epoch { - Some(fork_epoch) if epoch >= fork_epoch => ForkName::Merge, - _ => match self.altair_fork_epoch { - Some(fork_epoch) if epoch >= fork_epoch => ForkName::Altair, - _ => ForkName::Base, - }, + match self.capella_fork_epoch { + Some(fork_epoch) if epoch >= fork_epoch => ForkName::Capella, + _ => match self.bellatrix_fork_epoch { + Some(fork_epoch) if epoch >= fork_epoch => ForkName::Merge, + _ => match self.altair_fork_epoch { + Some(fork_epoch) if epoch >= fork_epoch => ForkName::Altair, + _ => ForkName::Base, }, }, } @@ -277,7 +266,6 @@ impl ChainSpec { ForkName::Altair => self.altair_fork_version, ForkName::Merge => self.bellatrix_fork_version, ForkName::Capella => self.capella_fork_version, - ForkName::Eip4844 => self.eip4844_fork_version, } } @@ -288,7 +276,6 @@ impl ChainSpec { ForkName::Altair => self.altair_fork_epoch, ForkName::Merge => self.bellatrix_fork_epoch, ForkName::Capella => self.capella_fork_epoch, - ForkName::Eip4844 => self.eip4844_fork_epoch, } } @@ -299,7 +286,6 @@ impl ChainSpec { BeaconState::Altair(_) => self.inactivity_penalty_quotient_altair, BeaconState::Merge(_) => self.inactivity_penalty_quotient_bellatrix, BeaconState::Capella(_) => self.inactivity_penalty_quotient_bellatrix, - BeaconState::Eip4844(_) => self.inactivity_penalty_quotient_bellatrix, } } @@ -313,7 +299,6 @@ impl ChainSpec { BeaconState::Altair(_) => self.proportional_slashing_multiplier_altair, BeaconState::Merge(_) => self.proportional_slashing_multiplier_bellatrix, BeaconState::Capella(_) => self.proportional_slashing_multiplier_bellatrix, - BeaconState::Eip4844(_) => self.proportional_slashing_multiplier_bellatrix, } } @@ -327,7 +312,6 @@ impl ChainSpec { BeaconState::Altair(_) => self.min_slashing_penalty_quotient_altair, BeaconState::Merge(_) => self.min_slashing_penalty_quotient_bellatrix, BeaconState::Capella(_) => self.min_slashing_penalty_quotient_bellatrix, - BeaconState::Eip4844(_) => self.min_slashing_penalty_quotient_bellatrix, } } @@ -366,7 +350,6 @@ impl ChainSpec { match domain { Domain::BeaconProposer => self.domain_beacon_proposer, Domain::BeaconAttester => self.domain_beacon_attester, - Domain::BlobsSideCar => self.domain_blobs_sidecar, Domain::Randao => self.domain_randao, Domain::Deposit => self.domain_deposit, Domain::VoluntaryExit => self.domain_voluntary_exit, @@ -574,7 +557,6 @@ impl ChainSpec { domain_voluntary_exit: 4, domain_selection_proof: 5, domain_aggregate_and_proof: 6, - domain_blobs_sidecar: 10, // 0x0a000000 /* * Fork choice @@ -636,12 +618,6 @@ impl ChainSpec { capella_fork_epoch: None, max_validators_per_withdrawals_sweep: 16384, - /* - * Eip4844 hard fork params - */ - eip4844_fork_version: [0x04, 0x00, 0x00, 0x00], - eip4844_fork_epoch: None, - /* * Network specific */ @@ -709,9 +685,6 @@ impl ChainSpec { capella_fork_version: [0x03, 0x00, 0x00, 0x01], capella_fork_epoch: None, max_validators_per_withdrawals_sweep: 16, - // Eip4844 - eip4844_fork_version: [0x04, 0x00, 0x00, 0x01], - eip4844_fork_epoch: None, // Other network_id: 2, // lighthouse testnet network id deposit_chain_id: 5, @@ -809,7 +782,6 @@ impl ChainSpec { domain_voluntary_exit: 4, domain_selection_proof: 5, domain_aggregate_and_proof: 6, - domain_blobs_sidecar: 10, /* * Fork choice @@ -873,12 +845,6 @@ impl ChainSpec { capella_fork_epoch: None, max_validators_per_withdrawals_sweep: 16384, - /* - * Eip4844 hard fork params - */ - eip4844_fork_version: [0x04, 0x00, 0x00, 0x64], - eip4844_fork_epoch: None, - /* * Network specific */ @@ -970,14 +936,6 @@ pub struct Config { #[serde(deserialize_with = "deserialize_fork_epoch")] pub capella_fork_epoch: Option>, - #[serde(default = "default_eip4844_fork_version")] - #[serde(with = "eth2_serde_utils::bytes_4_hex")] - eip4844_fork_version: [u8; 4], - #[serde(default)] - #[serde(serialize_with = "serialize_fork_epoch")] - #[serde(deserialize_with = "deserialize_fork_epoch")] - pub eip4844_fork_epoch: Option>, - #[serde(with = "eth2_serde_utils::quoted_u64")] seconds_per_slot: u64, #[serde(with = "eth2_serde_utils::quoted_u64")] @@ -1020,11 +978,6 @@ fn default_capella_fork_version() -> [u8; 4] { [0xff, 0xff, 0xff, 0xff] } -fn default_eip4844_fork_version() -> [u8; 4] { - // This value shouldn't be used. - [0xff, 0xff, 0xff, 0xff] -} - /// Placeholder value: 2^256-2^10 (115792089237316195423570985008687907853269984665640564039457584007913129638912). /// /// Taken from https://github.com/ethereum/consensus-specs/blob/d5e4828aecafaf1c57ef67a5f23c4ae7b08c5137/configs/mainnet.yaml#L15-L16 @@ -1125,10 +1078,6 @@ impl Config { capella_fork_epoch: spec .capella_fork_epoch .map(|epoch| MaybeQuoted { value: epoch }), - eip4844_fork_version: spec.eip4844_fork_version, - eip4844_fork_epoch: spec - .eip4844_fork_epoch - .map(|epoch| MaybeQuoted { value: epoch }), seconds_per_slot: spec.seconds_per_slot, seconds_per_eth1_block: spec.seconds_per_eth1_block, @@ -1176,8 +1125,6 @@ impl Config { bellatrix_fork_version, capella_fork_epoch, capella_fork_version, - eip4844_fork_epoch, - eip4844_fork_version, seconds_per_slot, seconds_per_eth1_block, min_validator_withdrawability_delay, @@ -1210,8 +1157,6 @@ impl Config { bellatrix_fork_version, capella_fork_epoch: capella_fork_epoch.map(|q| q.value), capella_fork_version, - eip4844_fork_epoch: eip4844_fork_epoch.map(|q| q.value), - eip4844_fork_version, seconds_per_slot, seconds_per_eth1_block, min_validator_withdrawability_delay, @@ -1285,7 +1230,6 @@ mod tests { test_domain(Domain::BeaconProposer, spec.domain_beacon_proposer, &spec); test_domain(Domain::BeaconAttester, spec.domain_beacon_attester, &spec); - test_domain(Domain::BlobsSideCar, spec.domain_blobs_sidecar, &spec); test_domain(Domain::Randao, spec.domain_randao, &spec); test_domain(Domain::Deposit, spec.domain_deposit, &spec); test_domain(Domain::VoluntaryExit, spec.domain_voluntary_exit, &spec); @@ -1310,8 +1254,6 @@ mod tests { spec.domain_bls_to_execution_change, &spec, ); - - test_domain(Domain::BlobsSideCar, spec.domain_blobs_sidecar, &spec); } fn apply_bit_mask(domain_bytes: [u8; 4], spec: &ChainSpec) -> u32 { diff --git a/consensus/types/src/config_and_preset.rs b/consensus/types/src/config_and_preset.rs index ac93818b9c..b10ad7557b 100644 --- a/consensus/types/src/config_and_preset.rs +++ b/consensus/types/src/config_and_preset.rs @@ -78,7 +78,6 @@ pub fn get_extra_fields(spec: &ChainSpec) -> HashMap { "bls_withdrawal_prefix".to_uppercase() => u8_hex(spec.bls_withdrawal_prefix_byte), "domain_beacon_proposer".to_uppercase() => u32_hex(spec.domain_beacon_proposer), "domain_beacon_attester".to_uppercase() => u32_hex(spec.domain_beacon_attester), - "domain_blobs_sidecar".to_uppercase() => u32_hex(spec.domain_blobs_sidecar), "domain_randao".to_uppercase()=> u32_hex(spec.domain_randao), "domain_deposit".to_uppercase()=> u32_hex(spec.domain_deposit), "domain_voluntary_exit".to_uppercase() => u32_hex(spec.domain_voluntary_exit), diff --git a/consensus/types/src/consts.rs b/consensus/types/src/consts.rs index b13e3aa9c3..a9377bc3e0 100644 --- a/consensus/types/src/consts.rs +++ b/consensus/types/src/consts.rs @@ -22,17 +22,3 @@ pub mod altair { pub mod merge { pub const INTERVALS_PER_SLOT: u64 = 3; } -pub mod eip4844 { - use crate::Uint256; - - use lazy_static::lazy_static; - - lazy_static! { - pub static ref BLS_MODULUS: Uint256 = Uint256::from_dec_str( - "52435875175126190479447740508185965837690552500527637822603658699938581184513" - ) - .expect("should initialize BLS_MODULUS"); - } - pub const BLOB_TX_TYPE: u8 = 5; - pub const VERSIONED_HASH_VERSION_KZG: u8 = 1; -} diff --git a/consensus/types/src/eth_spec.rs b/consensus/types/src/eth_spec.rs index e45f5b392a..378e8d34b7 100644 --- a/consensus/types/src/eth_spec.rs +++ b/consensus/types/src/eth_spec.rs @@ -102,11 +102,6 @@ pub trait EthSpec: */ type MaxBlsToExecutionChanges: Unsigned + Clone + Sync + Send + Debug + PartialEq; type MaxWithdrawalsPerPayload: Unsigned + Clone + Sync + Send + Debug + PartialEq; - /* - * New in Eip4844 - */ - type MaxBlobsPerBlock: Unsigned + Clone + Sync + Send + Debug + PartialEq; - type FieldElementsPerBlob: Unsigned + Clone + Sync + Send + Debug + PartialEq; /* * Derived values (set these CAREFULLY) */ @@ -244,11 +239,6 @@ pub trait EthSpec: fn max_withdrawals_per_payload() -> usize { Self::MaxWithdrawalsPerPayload::to_usize() } - - /// Returns the `MAX_BLOBS_PER_BLOCK` constant for this specification. - fn max_blobs_per_block() -> usize { - Self::MaxBlobsPerBlock::to_usize() - } } /// Macro to inherit some type values from another EthSpec. @@ -288,8 +278,6 @@ impl EthSpec for MainnetEthSpec { type GasLimitDenominator = U1024; type MinGasLimit = U5000; type MaxExtraDataBytes = U32; - type MaxBlobsPerBlock = U16; // 2**4 = 16 - type FieldElementsPerBlob = U4096; 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 @@ -340,9 +328,7 @@ impl EthSpec for MinimalEthSpec { GasLimitDenominator, MinGasLimit, MaxExtraDataBytes, - MaxBlsToExecutionChanges, - MaxBlobsPerBlock, - FieldElementsPerBlob + MaxBlsToExecutionChanges }); fn default_spec() -> ChainSpec { @@ -388,8 +374,6 @@ impl EthSpec for GnosisEthSpec { type SlotsPerEth1VotingPeriod = U1024; // 64 epochs * 16 slots per epoch type MaxBlsToExecutionChanges = U16; type MaxWithdrawalsPerPayload = U16; - type MaxBlobsPerBlock = U16; // 2**4 = 16 - type FieldElementsPerBlob = U4096; fn default_spec() -> ChainSpec { ChainSpec::gnosis() diff --git a/consensus/types/src/execution_payload.rs b/consensus/types/src/execution_payload.rs index 6e055d0a79..c2b5295d67 100644 --- a/consensus/types/src/execution_payload.rs +++ b/consensus/types/src/execution_payload.rs @@ -15,7 +15,7 @@ pub type Transactions = VariableList< pub type Withdrawals = VariableList::MaxWithdrawalsPerPayload>; #[superstruct( - variants(Merge, Capella, Eip4844), + variants(Merge, Capella), variant_attributes( derive( Default, @@ -77,15 +77,11 @@ pub struct ExecutionPayload { #[serde(with = "eth2_serde_utils::quoted_u256")] #[superstruct(getter(copy))] pub base_fee_per_gas: Uint256, - #[superstruct(only(Eip4844))] - #[serde(with = "eth2_serde_utils::quoted_u256")] - #[superstruct(getter(copy))] - pub excess_data_gas: Uint256, #[superstruct(getter(copy))] pub block_hash: ExecutionBlockHash, #[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] pub transactions: Transactions, - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] pub withdrawals: Withdrawals, } @@ -107,7 +103,6 @@ impl ExecutionPayload { ))), ForkName::Merge => ExecutionPayloadMerge::from_ssz_bytes(bytes).map(Self::Merge), ForkName::Capella => ExecutionPayloadCapella::from_ssz_bytes(bytes).map(Self::Capella), - ForkName::Eip4844 => ExecutionPayloadEip4844::from_ssz_bytes(bytes).map(Self::Eip4844), } } @@ -134,19 +129,6 @@ impl ExecutionPayload { // Max size of variable length `withdrawals` field + (T::max_withdrawals_per_payload() * ::ssz_fixed_len()) } - - #[allow(clippy::integer_arithmetic)] - /// Returns the maximum size of an execution payload. - pub fn max_execution_payload_eip4844_size() -> usize { - // Fixed part - ExecutionPayloadEip4844::::default().as_ssz_bytes().len() - // Max size of variable length `extra_data` field - + (T::max_extra_data_bytes() * ::ssz_fixed_len()) - // Max size of variable length `transactions` field - + (T::max_transactions_per_payload() * (ssz::BYTES_PER_LENGTH_OFFSET + T::max_bytes_per_transaction())) - // Max size of variable length `withdrawals` field - + (T::max_withdrawals_per_payload() * ::ssz_fixed_len()) - } } impl ForkVersionDeserialize for ExecutionPayload { @@ -161,7 +143,6 @@ impl ForkVersionDeserialize for ExecutionPayload { Ok(match fork_name { ForkName::Merge => Self::Merge(serde_json::from_value(value).map_err(convert_err)?), ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?), - ForkName::Eip4844 => Self::Eip4844(serde_json::from_value(value).map_err(convert_err)?), ForkName::Base | ForkName::Altair => { return Err(serde::de::Error::custom(format!( "ExecutionPayload failed to deserialize: unsupported fork '{}'", diff --git a/consensus/types/src/execution_payload_header.rs b/consensus/types/src/execution_payload_header.rs index 4dc79ddc99..d193a6cd8e 100644 --- a/consensus/types/src/execution_payload_header.rs +++ b/consensus/types/src/execution_payload_header.rs @@ -9,7 +9,7 @@ use tree_hash_derive::TreeHash; use BeaconStateError; #[superstruct( - variants(Merge, Capella, Eip4844), + variants(Merge, Capella), variant_attributes( derive( Default, @@ -70,15 +70,11 @@ pub struct ExecutionPayloadHeader { #[serde(with = "eth2_serde_utils::quoted_u256")] #[superstruct(getter(copy))] pub base_fee_per_gas: Uint256, - #[superstruct(only(Eip4844))] - #[serde(with = "eth2_serde_utils::quoted_u256")] - #[superstruct(getter(copy))] - pub excess_data_gas: Uint256, #[superstruct(getter(copy))] pub block_hash: ExecutionBlockHash, #[superstruct(getter(copy))] pub transactions_root: Hash256, - #[superstruct(only(Capella, Eip4844))] + #[superstruct(only(Capella))] #[superstruct(getter(copy))] pub withdrawals_root: Hash256, } @@ -97,9 +93,6 @@ impl ExecutionPayloadHeader { ForkName::Capella => { ExecutionPayloadHeaderCapella::from_ssz_bytes(bytes).map(Self::Capella) } - ForkName::Eip4844 => { - ExecutionPayloadHeaderEip4844::from_ssz_bytes(bytes).map(Self::Eip4844) - } } } } @@ -135,30 +128,6 @@ impl ExecutionPayloadHeaderMerge { } } -impl ExecutionPayloadHeaderCapella { - pub fn upgrade_to_eip4844(&self) -> ExecutionPayloadHeaderEip4844 { - ExecutionPayloadHeaderEip4844 { - parent_hash: self.parent_hash, - fee_recipient: self.fee_recipient, - state_root: self.state_root, - receipts_root: self.receipts_root, - logs_bloom: self.logs_bloom.clone(), - prev_randao: self.prev_randao, - block_number: self.block_number, - gas_limit: self.gas_limit, - gas_used: self.gas_used, - timestamp: self.timestamp, - extra_data: self.extra_data.clone(), - base_fee_per_gas: self.base_fee_per_gas, - // TODO: verify if this is correct - excess_data_gas: Uint256::zero(), - block_hash: self.block_hash, - transactions_root: self.transactions_root, - withdrawals_root: self.withdrawals_root, - } - } -} - impl<'a, T: EthSpec> From<&'a ExecutionPayloadMerge> for ExecutionPayloadHeaderMerge { fn from(payload: &'a ExecutionPayloadMerge) -> Self { Self { @@ -201,29 +170,6 @@ impl<'a, T: EthSpec> From<&'a ExecutionPayloadCapella> for ExecutionPayloadHe } } -impl<'a, T: EthSpec> From<&'a ExecutionPayloadEip4844> for ExecutionPayloadHeaderEip4844 { - fn from(payload: &'a ExecutionPayloadEip4844) -> Self { - Self { - parent_hash: payload.parent_hash, - fee_recipient: payload.fee_recipient, - state_root: payload.state_root, - receipts_root: payload.receipts_root, - logs_bloom: payload.logs_bloom.clone(), - prev_randao: payload.prev_randao, - block_number: payload.block_number, - gas_limit: payload.gas_limit, - gas_used: payload.gas_used, - timestamp: payload.timestamp, - extra_data: payload.extra_data.clone(), - base_fee_per_gas: payload.base_fee_per_gas, - excess_data_gas: payload.excess_data_gas, - block_hash: payload.block_hash, - transactions_root: payload.transactions.tree_hash_root(), - withdrawals_root: payload.withdrawals.tree_hash_root(), - } - } -} - // These impls are required to work around an inelegance in `to_execution_payload_header`. // They only clone headers so they should be relatively cheap. impl<'a, T: EthSpec> From<&'a Self> for ExecutionPayloadHeaderMerge { @@ -238,12 +184,6 @@ impl<'a, T: EthSpec> From<&'a Self> for ExecutionPayloadHeaderCapella { } } -impl<'a, T: EthSpec> From<&'a Self> for ExecutionPayloadHeaderEip4844 { - fn from(payload: &'a Self) -> Self { - payload.clone() - } -} - impl<'a, T: EthSpec> From> for ExecutionPayloadHeader { fn from(payload: ExecutionPayloadRef<'a, T>) -> Self { map_execution_payload_ref_into_execution_payload_header!( @@ -274,17 +214,6 @@ impl TryFrom> for ExecutionPayloadHeaderCa } } } -impl TryFrom> for ExecutionPayloadHeaderEip4844 { - type Error = BeaconStateError; - fn try_from(header: ExecutionPayloadHeader) -> Result { - match header { - ExecutionPayloadHeader::Eip4844(execution_payload_header) => { - Ok(execution_payload_header) - } - _ => Err(BeaconStateError::IncorrectStateVariant), - } - } -} impl ForkVersionDeserialize for ExecutionPayloadHeader { fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>( @@ -301,7 +230,6 @@ impl ForkVersionDeserialize for ExecutionPayloadHeader { Ok(match fork_name { ForkName::Merge => Self::Merge(serde_json::from_value(value).map_err(convert_err)?), ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?), - ForkName::Eip4844 => Self::Eip4844(serde_json::from_value(value).map_err(convert_err)?), ForkName::Base | ForkName::Altair => { return Err(serde::de::Error::custom(format!( "ExecutionPayloadHeader failed to deserialize: unsupported fork '{}'", diff --git a/consensus/types/src/fork_context.rs b/consensus/types/src/fork_context.rs index f5221dd913..90d1fbc686 100644 --- a/consensus/types/src/fork_context.rs +++ b/consensus/types/src/fork_context.rs @@ -54,13 +54,6 @@ impl ForkContext { )); } - if spec.eip4844_fork_epoch.is_some() { - fork_to_digest.push(( - ForkName::Eip4844, - ChainSpec::compute_fork_digest(spec.eip4844_fork_version, genesis_validators_root), - )); - } - let fork_to_digest: HashMap = fork_to_digest.into_iter().collect(); let digest_to_fork = fork_to_digest diff --git a/consensus/types/src/fork_name.rs b/consensus/types/src/fork_name.rs index 89eaff7985..007d4c4daa 100644 --- a/consensus/types/src/fork_name.rs +++ b/consensus/types/src/fork_name.rs @@ -12,7 +12,6 @@ pub enum ForkName { Altair, Merge, Capella, - Eip4844, } impl ForkName { @@ -22,7 +21,6 @@ impl ForkName { ForkName::Altair, ForkName::Merge, ForkName::Capella, - ForkName::Eip4844, ] } @@ -35,35 +33,24 @@ impl ForkName { spec.altair_fork_epoch = None; spec.bellatrix_fork_epoch = None; spec.capella_fork_epoch = None; - spec.eip4844_fork_epoch = None; spec } ForkName::Altair => { spec.altair_fork_epoch = Some(Epoch::new(0)); spec.bellatrix_fork_epoch = None; spec.capella_fork_epoch = None; - spec.eip4844_fork_epoch = None; spec } ForkName::Merge => { spec.altair_fork_epoch = Some(Epoch::new(0)); spec.bellatrix_fork_epoch = Some(Epoch::new(0)); spec.capella_fork_epoch = None; - spec.eip4844_fork_epoch = None; spec } ForkName::Capella => { spec.altair_fork_epoch = Some(Epoch::new(0)); spec.bellatrix_fork_epoch = Some(Epoch::new(0)); spec.capella_fork_epoch = Some(Epoch::new(0)); - spec.eip4844_fork_epoch = None; - spec - } - ForkName::Eip4844 => { - spec.altair_fork_epoch = Some(Epoch::new(0)); - spec.bellatrix_fork_epoch = Some(Epoch::new(0)); - spec.capella_fork_epoch = Some(Epoch::new(0)); - spec.eip4844_fork_epoch = Some(Epoch::new(0)); spec } } @@ -78,7 +65,6 @@ impl ForkName { ForkName::Altair => Some(ForkName::Base), ForkName::Merge => Some(ForkName::Altair), ForkName::Capella => Some(ForkName::Merge), - ForkName::Eip4844 => Some(ForkName::Capella), } } @@ -90,8 +76,7 @@ impl ForkName { ForkName::Base => Some(ForkName::Altair), ForkName::Altair => Some(ForkName::Merge), ForkName::Merge => Some(ForkName::Capella), - ForkName::Capella => Some(ForkName::Eip4844), - ForkName::Eip4844 => None, + ForkName::Capella => None, } } } @@ -137,10 +122,6 @@ macro_rules! map_fork_name_with { let (value, extra_data) = $body; ($t::Capella(value), extra_data) } - ForkName::Eip4844 => { - let (value, extra_data) = $body; - ($t::Eip4844(value), extra_data) - } } }; } @@ -154,7 +135,6 @@ impl FromStr for ForkName { "altair" => ForkName::Altair, "bellatrix" | "merge" => ForkName::Merge, "capella" => ForkName::Capella, - "eip4844" => ForkName::Eip4844, _ => return Err(format!("unknown fork name: {}", fork_name)), }) } @@ -167,7 +147,6 @@ impl Display for ForkName { ForkName::Altair => "altair".fmt(f), ForkName::Merge => "bellatrix".fmt(f), ForkName::Capella => "capella".fmt(f), - ForkName::Eip4844 => "eip4844".fmt(f), } } } @@ -199,7 +178,7 @@ mod test { #[test] fn previous_and_next_fork_consistent() { - assert_eq!(ForkName::Eip4844.next_fork(), None); + assert_eq!(ForkName::Capella.next_fork(), None); assert_eq!(ForkName::Base.previous_fork(), None); for (prev_fork, fork) in ForkName::list_all().into_iter().tuple_windows() { diff --git a/consensus/types/src/kzg_commitment.rs b/consensus/types/src/kzg_commitment.rs deleted file mode 100644 index 4612af5de1..0000000000 --- a/consensus/types/src/kzg_commitment.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::test_utils::TestRandom; -use crate::*; -use derivative::Derivative; -use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use std::fmt; -use std::fmt::{Display, Formatter}; -use tree_hash::{PackedEncoding, TreeHash}; - -#[derive( - Derivative, Debug, Clone, Encode, Decode, Serialize, Deserialize, arbitrary::Arbitrary, -)] -#[derivative(PartialEq, Eq, Hash)] -#[ssz(struct_behaviour = "transparent")] -pub struct KzgCommitment(#[serde(with = "BigArray")] pub [u8; 48]); - -impl Display for KzgCommitment { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", eth2_serde_utils::hex::encode(self.0)) - } -} - -impl TreeHash for KzgCommitment { - fn tree_hash_type() -> tree_hash::TreeHashType { - <[u8; 48] as TreeHash>::tree_hash_type() - } - - fn tree_hash_packed_encoding(&self) -> PackedEncoding { - self.0.tree_hash_packed_encoding() - } - - fn tree_hash_packing_factor() -> usize { - <[u8; 48] as TreeHash>::tree_hash_packing_factor() - } - - fn tree_hash_root(&self) -> tree_hash::Hash256 { - self.0.tree_hash_root() - } -} - -impl TestRandom for KzgCommitment { - fn random_for_test(rng: &mut impl rand::RngCore) -> Self { - KzgCommitment(<[u8; 48] as TestRandom>::random_for_test(rng)) - } -} diff --git a/consensus/types/src/kzg_proof.rs b/consensus/types/src/kzg_proof.rs deleted file mode 100644 index 9c1136ce51..0000000000 --- a/consensus/types/src/kzg_proof.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::test_utils::{RngCore, TestRandom}; -use serde::{Deserialize, Serialize}; -use serde_big_array::BigArray; -use ssz_derive::{Decode, Encode}; -use std::fmt; -use tree_hash::{PackedEncoding, TreeHash}; - -const KZG_PROOF_BYTES_LEN: usize = 48; - -#[derive( - Debug, - PartialEq, - Hash, - Clone, - Copy, - Encode, - Decode, - Serialize, - Deserialize, - arbitrary::Arbitrary, -)] -#[serde(transparent)] -#[ssz(struct_behaviour = "transparent")] -pub struct KzgProof(#[serde(with = "BigArray")] pub [u8; KZG_PROOF_BYTES_LEN]); - -impl fmt::Display for KzgProof { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", eth2_serde_utils::hex::encode(self.0)) - } -} - -impl Default for KzgProof { - fn default() -> Self { - KzgProof([0; 48]) - } -} - -impl From<[u8; KZG_PROOF_BYTES_LEN]> for KzgProof { - fn from(bytes: [u8; KZG_PROOF_BYTES_LEN]) -> Self { - Self(bytes) - } -} - -impl Into<[u8; KZG_PROOF_BYTES_LEN]> for KzgProof { - fn into(self) -> [u8; KZG_PROOF_BYTES_LEN] { - self.0 - } -} - -impl TreeHash for KzgProof { - fn tree_hash_type() -> tree_hash::TreeHashType { - <[u8; KZG_PROOF_BYTES_LEN]>::tree_hash_type() - } - - fn tree_hash_packed_encoding(&self) -> PackedEncoding { - self.0.tree_hash_packed_encoding() - } - - fn tree_hash_packing_factor() -> usize { - <[u8; KZG_PROOF_BYTES_LEN]>::tree_hash_packing_factor() - } - - fn tree_hash_root(&self) -> tree_hash::Hash256 { - self.0.tree_hash_root() - } -} - -impl TestRandom for KzgProof { - fn random_for_test(rng: &mut impl RngCore) -> Self { - let mut bytes = [0; KZG_PROOF_BYTES_LEN]; - rng.fill_bytes(&mut bytes); - Self(bytes) - } -} diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 3760553b09..e51ccf1d29 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -100,10 +100,6 @@ pub mod slot_data; #[cfg(feature = "sqlite")] pub mod sqlite; -pub mod blobs_sidecar; -pub mod kzg_commitment; -pub mod kzg_proof; - use ethereum_types::{H160, H256}; pub use crate::aggregate_and_proof::AggregateAndProof; @@ -112,17 +108,16 @@ pub use crate::attestation_data::AttestationData; pub use crate::attestation_duty::AttestationDuty; pub use crate::attester_slashing::AttesterSlashing; pub use crate::beacon_block::{ - BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockCapella, BeaconBlockEip4844, - BeaconBlockMerge, BeaconBlockRef, BeaconBlockRefMut, BlindedBeaconBlock, EmptyBlock, + BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockCapella, BeaconBlockMerge, + BeaconBlockRef, BeaconBlockRefMut, BlindedBeaconBlock, EmptyBlock, }; pub use crate::beacon_block_body::{ BeaconBlockBody, BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyCapella, - BeaconBlockBodyEip4844, BeaconBlockBodyMerge, BeaconBlockBodyRef, BeaconBlockBodyRefMut, + BeaconBlockBodyMerge, BeaconBlockBodyRef, BeaconBlockBodyRefMut, }; pub use crate::beacon_block_header::BeaconBlockHeader; pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee}; pub use crate::beacon_state::{BeaconTreeHashCache, Error as BeaconStateError, *}; -pub use crate::blobs_sidecar::BlobsSidecar; pub use crate::bls_to_execution_change::BlsToExecutionChange; pub use crate::chain_spec::{ChainSpec, Config, Domain}; pub use crate::checkpoint::Checkpoint; @@ -140,12 +135,12 @@ pub use crate::eth_spec::EthSpecId; pub use crate::execution_block_hash::ExecutionBlockHash; pub use crate::execution_block_header::ExecutionBlockHeader; pub use crate::execution_payload::{ - ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadEip4844, ExecutionPayloadMerge, - ExecutionPayloadRef, Transaction, Transactions, Withdrawals, + ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadMerge, ExecutionPayloadRef, + Transaction, Transactions, Withdrawals, }; pub use crate::execution_payload_header::{ - ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderEip4844, - ExecutionPayloadHeaderMerge, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut, + ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderMerge, + ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut, }; pub use crate::fork::Fork; pub use crate::fork_context::ForkContext; @@ -157,16 +152,14 @@ pub use crate::fork_versioned_response::{ pub use crate::graffiti::{Graffiti, GRAFFITI_BYTES_LEN}; pub use crate::historical_batch::HistoricalBatch; pub use crate::indexed_attestation::IndexedAttestation; -pub use crate::kzg_commitment::KzgCommitment; -pub use crate::kzg_proof::KzgProof; pub use crate::light_client_finality_update::LightClientFinalityUpdate; pub use crate::light_client_optimistic_update::LightClientOptimisticUpdate; pub use crate::participation_flags::ParticipationFlags; pub use crate::participation_list::ParticipationList; pub use crate::payload::{ - AbstractExecPayload, BlindedPayload, BlindedPayloadCapella, BlindedPayloadEip4844, - BlindedPayloadMerge, BlindedPayloadRef, BlockType, ExecPayload, FullPayload, - FullPayloadCapella, FullPayloadEip4844, FullPayloadMerge, FullPayloadRef, OwnedExecPayload, + AbstractExecPayload, BlindedPayload, BlindedPayloadCapella, BlindedPayloadMerge, + BlindedPayloadRef, BlockType, ExecPayload, FullPayload, FullPayloadCapella, FullPayloadMerge, + FullPayloadRef, OwnedExecPayload, }; pub use crate::pending_attestation::PendingAttestation; pub use crate::preset::{AltairPreset, BasePreset, BellatrixPreset, CapellaPreset}; @@ -178,8 +171,7 @@ pub use crate::shuffling_id::AttestationShufflingId; pub use crate::signed_aggregate_and_proof::SignedAggregateAndProof; pub use crate::signed_beacon_block::{ SignedBeaconBlock, SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockCapella, - SignedBeaconBlockEip4844, SignedBeaconBlockHash, SignedBeaconBlockMerge, - SignedBlindedBeaconBlock, + SignedBeaconBlockHash, SignedBeaconBlockMerge, SignedBlindedBeaconBlock, }; pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader; pub use crate::signed_bls_to_execution_change::SignedBlsToExecutionChange; @@ -203,7 +195,6 @@ pub use crate::validator_subscription::ValidatorSubscription; pub use crate::voluntary_exit::VoluntaryExit; pub use crate::withdrawal::Withdrawal; pub use crate::withdrawal_credentials::WithdrawalCredentials; -use serde_big_array::BigArray; pub type CommitteeIndex = u64; pub type Hash256 = H256; @@ -211,7 +202,6 @@ pub type Uint256 = ethereum_types::U256; pub type Address = H160; pub type ForkVersion = [u8; 4]; pub type BLSFieldElement = Uint256; -pub type Blob = FixedVector::FieldElementsPerBlob>; pub type VersionedHash = Hash256; pub type Hash64 = ethereum_types::H64; diff --git a/consensus/types/src/payload.rs b/consensus/types/src/payload.rs index cc22bc3ab8..6c739c969d 100644 --- a/consensus/types/src/payload.rs +++ b/consensus/types/src/payload.rs @@ -81,13 +81,8 @@ pub trait AbstractExecPayload: + TryFrom> + TryInto + TryInto - + TryInto { - type Ref<'a>: ExecPayload - + Copy - + From<&'a Self::Merge> - + From<&'a Self::Capella> - + From<&'a Self::Eip4844>; + type Ref<'a>: ExecPayload + Copy + From<&'a Self::Merge> + From<&'a Self::Capella>; type Merge: OwnedExecPayload + Into @@ -97,16 +92,12 @@ pub trait AbstractExecPayload: + Into + for<'a> From>> + TryFrom>; - type Eip4844: OwnedExecPayload - + Into - + for<'a> From>> - + TryFrom>; fn default_at_fork(fork_name: ForkName) -> Result; } #[superstruct( - variants(Merge, Capella, Eip4844), + variants(Merge, Capella), variant_attributes( derive( Debug, @@ -145,8 +136,6 @@ pub struct FullPayload { pub execution_payload: ExecutionPayloadMerge, #[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))] pub execution_payload: ExecutionPayloadCapella, - #[superstruct(only(Eip4844), partial_getter(rename = "execution_payload_eip4844"))] - pub execution_payload: ExecutionPayloadEip4844, } impl From> for ExecutionPayload { @@ -250,9 +239,6 @@ impl ExecPayload for FullPayload { FullPayload::Capella(ref inner) => { Ok(inner.execution_payload.withdrawals.tree_hash_root()) } - FullPayload::Eip4844(ref inner) => { - Ok(inner.execution_payload.withdrawals.tree_hash_root()) - } } } @@ -359,9 +345,6 @@ impl<'b, T: EthSpec> ExecPayload for FullPayloadRef<'b, T> { FullPayloadRef::Capella(inner) => { Ok(inner.execution_payload.withdrawals.tree_hash_root()) } - FullPayloadRef::Eip4844(inner) => { - Ok(inner.execution_payload.withdrawals.tree_hash_root()) - } } } @@ -382,14 +365,12 @@ impl AbstractExecPayload for FullPayload { type Ref<'a> = FullPayloadRef<'a, T>; type Merge = FullPayloadMerge; type Capella = FullPayloadCapella; - type Eip4844 = FullPayloadEip4844; fn default_at_fork(fork_name: ForkName) -> Result { match fork_name { ForkName::Base | ForkName::Altair => Err(Error::IncorrectStateVariant), ForkName::Merge => Ok(FullPayloadMerge::default().into()), ForkName::Capella => Ok(FullPayloadCapella::default().into()), - ForkName::Eip4844 => Ok(FullPayloadEip4844::default().into()), } } } @@ -410,7 +391,7 @@ impl TryFrom> for FullPayload { } #[superstruct( - variants(Merge, Capella, Eip4844), + variants(Merge, Capella), variant_attributes( derive( Debug, @@ -448,8 +429,6 @@ pub struct BlindedPayload { pub execution_payload_header: ExecutionPayloadHeaderMerge, #[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))] pub execution_payload_header: ExecutionPayloadHeaderCapella, - #[superstruct(only(Eip4844), partial_getter(rename = "execution_payload_eip4844"))] - pub execution_payload_header: ExecutionPayloadHeaderEip4844, } impl<'a, T: EthSpec> From> for BlindedPayload { @@ -531,9 +510,6 @@ impl ExecPayload for BlindedPayload { BlindedPayload::Capella(ref inner) => { Ok(inner.execution_payload_header.withdrawals_root) } - BlindedPayload::Eip4844(ref inner) => { - Ok(inner.execution_payload_header.withdrawals_root) - } } } @@ -621,9 +597,6 @@ impl<'b, T: EthSpec> ExecPayload for BlindedPayloadRef<'b, T> { BlindedPayloadRef::Capella(inner) => { Ok(inner.execution_payload_header.withdrawals_root) } - BlindedPayloadRef::Eip4844(inner) => { - Ok(inner.execution_payload_header.withdrawals_root) - } } } @@ -887,26 +860,17 @@ impl_exec_payload_for_fork!( ExecutionPayloadCapella, Capella ); -impl_exec_payload_for_fork!( - BlindedPayloadEip4844, - FullPayloadEip4844, - ExecutionPayloadHeaderEip4844, - ExecutionPayloadEip4844, - Eip4844 -); impl AbstractExecPayload for BlindedPayload { type Ref<'a> = BlindedPayloadRef<'a, T>; type Merge = BlindedPayloadMerge; type Capella = BlindedPayloadCapella; - type Eip4844 = BlindedPayloadEip4844; fn default_at_fork(fork_name: ForkName) -> Result { match fork_name { ForkName::Base | ForkName::Altair => Err(Error::IncorrectStateVariant), ForkName::Merge => Ok(BlindedPayloadMerge::default().into()), ForkName::Capella => Ok(BlindedPayloadCapella::default().into()), - ForkName::Eip4844 => Ok(BlindedPayloadEip4844::default().into()), } } } @@ -935,11 +899,6 @@ impl From> for BlindedPayload { execution_payload_header, }) } - ExecutionPayloadHeader::Eip4844(execution_payload_header) => { - Self::Eip4844(BlindedPayloadEip4844 { - execution_payload_header, - }) - } } } } @@ -953,9 +912,6 @@ impl From> for ExecutionPayloadHeader { BlindedPayload::Capella(blinded_payload) => { ExecutionPayloadHeader::Capella(blinded_payload.execution_payload_header) } - BlindedPayload::Eip4844(blinded_payload) => { - ExecutionPayloadHeader::Eip4844(blinded_payload.execution_payload_header) - } } } } diff --git a/consensus/types/src/signed_beacon_block.rs b/consensus/types/src/signed_beacon_block.rs index 70fb28fbe7..5f623cf07a 100644 --- a/consensus/types/src/signed_beacon_block.rs +++ b/consensus/types/src/signed_beacon_block.rs @@ -37,7 +37,7 @@ impl From for Hash256 { /// A `BeaconBlock` and a signature from its proposer. #[superstruct( - variants(Base, Altair, Merge, Capella, Eip4844), + variants(Base, Altair, Merge, Capella), variant_attributes( derive( Debug, @@ -76,8 +76,6 @@ pub struct SignedBeaconBlock = FullP pub message: BeaconBlockMerge, #[superstruct(only(Capella), partial_getter(rename = "message_capella"))] pub message: BeaconBlockCapella, - #[superstruct(only(Eip4844), partial_getter(rename = "message_eip4844"))] - pub message: BeaconBlockEip4844, pub signature: Signature, } @@ -138,9 +136,6 @@ impl> SignedBeaconBlock BeaconBlock::Capella(message) => { SignedBeaconBlock::Capella(SignedBeaconBlockCapella { message, signature }) } - BeaconBlock::Eip4844(message) => { - SignedBeaconBlock::Eip4844(SignedBeaconBlockEip4844 { message, signature }) - } } } @@ -373,62 +368,6 @@ impl SignedBeaconBlockCapella> { } } -impl SignedBeaconBlockEip4844> { - pub fn into_full_block( - self, - execution_payload: ExecutionPayloadEip4844, - ) -> SignedBeaconBlockEip4844> { - let SignedBeaconBlockEip4844 { - message: - BeaconBlockEip4844 { - slot, - proposer_index, - parent_root, - state_root, - body: - BeaconBlockBodyEip4844 { - randao_reveal, - eth1_data, - graffiti, - proposer_slashings, - attester_slashings, - attestations, - deposits, - voluntary_exits, - sync_aggregate, - execution_payload: BlindedPayloadEip4844 { .. }, - bls_to_execution_changes, - blob_kzg_commitments, - }, - }, - signature, - } = self; - SignedBeaconBlockEip4844 { - message: BeaconBlockEip4844 { - slot, - proposer_index, - parent_root, - state_root, - body: BeaconBlockBodyEip4844 { - randao_reveal, - eth1_data, - graffiti, - proposer_slashings, - attester_slashings, - attestations, - deposits, - voluntary_exits, - sync_aggregate, - execution_payload: FullPayloadEip4844 { execution_payload }, - bls_to_execution_changes, - blob_kzg_commitments, - }, - }, - signature, - } - } -} - impl SignedBeaconBlock> { pub fn try_into_full_block( self, @@ -443,14 +382,10 @@ impl SignedBeaconBlock> { (SignedBeaconBlock::Capella(block), Some(ExecutionPayload::Capella(payload))) => { SignedBeaconBlock::Capella(block.into_full_block(payload)) } - (SignedBeaconBlock::Eip4844(block), Some(ExecutionPayload::Eip4844(payload))) => { - SignedBeaconBlock::Eip4844(block.into_full_block(payload)) - } // avoid wildcard matching forks so that compiler will // direct us here when a new fork has been added (SignedBeaconBlock::Merge(_), _) => return None, (SignedBeaconBlock::Capella(_), _) => return None, - (SignedBeaconBlock::Eip4844(_), _) => return None, }; Some(full_block) } diff --git a/lcli/Cargo.toml b/lcli/Cargo.toml index 93fe17506b..caceb99778 100644 --- a/lcli/Cargo.toml +++ b/lcli/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lcli" description = "Lighthouse CLI (modeled after zcli)" -version = "3.5.0" +version = "3.5.1" authors = ["Paul Hauner "] edition = "2021" diff --git a/lcli/src/create_payload_header.rs b/lcli/src/create_payload_header.rs index 7700f23d9d..6c0e8dcecf 100644 --- a/lcli/src/create_payload_header.rs +++ b/lcli/src/create_payload_header.rs @@ -5,8 +5,8 @@ use std::fs::File; use std::io::Write; use std::time::{SystemTime, UNIX_EPOCH}; use types::{ - EthSpec, ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderEip4844, - ExecutionPayloadHeaderMerge, ForkName, + EthSpec, ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderMerge, + ForkName, }; pub fn run(matches: &ArgMatches) -> Result<(), String> { @@ -40,14 +40,6 @@ pub fn run(matches: &ArgMatches) -> Result<(), String> { prev_randao: eth1_block_hash.into_root(), ..ExecutionPayloadHeaderCapella::default() }), - ForkName::Eip4844 => ExecutionPayloadHeader::Eip4844(ExecutionPayloadHeaderEip4844 { - gas_limit, - base_fee_per_gas, - timestamp: genesis_time, - block_hash: eth1_block_hash, - prev_randao: eth1_block_hash.into_root(), - ..ExecutionPayloadHeaderEip4844::default() - }), }; let mut file = File::create(file_name).map_err(|_| "Unable to create file".to_string())?; diff --git a/lcli/src/main.rs b/lcli/src/main.rs index d2e852ceca..cdf9cfa677 100644 --- a/lcli/src/main.rs +++ b/lcli/src/main.rs @@ -425,7 +425,7 @@ fn main() { .takes_value(true) .default_value("bellatrix") .help("The fork for which the execution payload header should be created.") - .possible_values(&["merge", "bellatrix", "capella", "eip4844"]) + .possible_values(&["merge", "bellatrix", "capella"]) ) ) .subcommand( diff --git a/lcli/src/new_testnet.rs b/lcli/src/new_testnet.rs index 4d194ff10b..5af22731f3 100644 --- a/lcli/src/new_testnet.rs +++ b/lcli/src/new_testnet.rs @@ -10,8 +10,7 @@ use std::path::PathBuf; use std::time::{SystemTime, UNIX_EPOCH}; use types::{ test_utils::generate_deterministic_keypairs, Address, Config, Epoch, EthSpec, - ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderEip4844, - ExecutionPayloadHeaderMerge, ForkName, + ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderMerge, ForkName, }; pub fn run(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Result<(), String> { @@ -94,10 +93,6 @@ pub fn run(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Resul ExecutionPayloadHeaderCapella::::from_ssz_bytes(bytes.as_slice()) .map(ExecutionPayloadHeader::Capella) } - ForkName::Eip4844 => { - ExecutionPayloadHeaderEip4844::::from_ssz_bytes(bytes.as_slice()) - .map(ExecutionPayloadHeader::Eip4844) - } } .map_err(|e| format!("SSZ decode failed: {:?}", e)) }) diff --git a/lighthouse/Cargo.toml b/lighthouse/Cargo.toml index 864cefa75e..07620ded02 100644 --- a/lighthouse/Cargo.toml +++ b/lighthouse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lighthouse" -version = "3.5.0" +version = "3.5.1" authors = ["Sigma Prime "] edition = "2021" autotests = false @@ -55,7 +55,7 @@ malloc_utils = { path = "../common/malloc_utils" } directory = { path = "../common/directory" } unused_port = { path = "../common/unused_port" } database_manager = { path = "../database_manager" } -slasher = { path = "../slasher" } +slasher = { path = "../slasher", default-features = false } validator_manager = { path = "../validator_manager" } [dev-dependencies] diff --git a/lighthouse/tests/beacon_node.rs b/lighthouse/tests/beacon_node.rs index a07502c58a..7f957b626d 100644 --- a/lighthouse/tests/beacon_node.rs +++ b/lighthouse/tests/beacon_node.rs @@ -182,6 +182,21 @@ fn prepare_payload_lookahead_shorter() { }); } +#[test] +fn always_prepare_payload_default() { + CommandLineTest::new() + .run_with_zero_port() + .with_config(|config| assert!(!config.chain.always_prepare_payload)); +} + +#[test] +fn always_prepare_payload_override() { + CommandLineTest::new() + .flag("always-prepare-payload", None) + .run_with_zero_port() + .with_config(|config| assert!(config.chain.always_prepare_payload)); +} + #[test] fn paranoid_block_proposal_default() { CommandLineTest::new() @@ -325,6 +340,21 @@ fn trusted_peers_flag() { }); } +#[test] +fn always_prefer_builder_payload_flag() { + CommandLineTest::new() + .flag("always-prefer-builder-payload", None) + .run_with_zero_port() + .with_config(|config| assert!(config.always_prefer_builder_payload)); +} + +#[test] +fn no_flag_sets_always_prefer_builder_payload_to_false() { + CommandLineTest::new() + .run_with_zero_port() + .with_config(|config| assert!(!config.always_prefer_builder_payload)); +} + // Tests for Eth1 flags. #[test] fn dummy_eth1_flag() { diff --git a/lighthouse/tests/validator_client.rs b/lighthouse/tests/validator_client.rs index 54ffb09c28..6cef8e597f 100644 --- a/lighthouse/tests/validator_client.rs +++ b/lighthouse/tests/validator_client.rs @@ -502,3 +502,28 @@ fn disable_run_on_all() { assert!(config.disable_run_on_all); }); } + +#[test] +fn latency_measurement_service() { + CommandLineTest::new().run().with_config(|config| { + assert!(config.enable_latency_measurement_service); + }); + CommandLineTest::new() + .flag("latency-measurement-service", None) + .run() + .with_config(|config| { + assert!(config.enable_latency_measurement_service); + }); + CommandLineTest::new() + .flag("latency-measurement-service", Some("true")) + .run() + .with_config(|config| { + assert!(config.enable_latency_measurement_service); + }); + CommandLineTest::new() + .flag("latency-measurement-service", Some("false")) + .run() + .with_config(|config| { + assert!(!config.enable_latency_measurement_service); + }); +} diff --git a/slasher/service/Cargo.toml b/slasher/service/Cargo.toml index 63cf1e4649..0a787defa2 100644 --- a/slasher/service/Cargo.toml +++ b/slasher/service/Cargo.toml @@ -9,7 +9,7 @@ beacon_chain = { path = "../../beacon_node/beacon_chain" } directory = { path = "../../common/directory" } lighthouse_network = { path = "../../beacon_node/lighthouse_network" } network = { path = "../../beacon_node/network" } -slasher = { path = ".." } +slasher = { path = "..", default-features = false } slog = "2.5.2" slot_clock = { path = "../../common/slot_clock" } state_processing = { path = "../../consensus/state_processing" } diff --git a/testing/ef_tests/Makefile b/testing/ef_tests/Makefile index 1feba41c86..fc3dea6e2f 100644 --- a/testing/ef_tests/Makefile +++ b/testing/ef_tests/Makefile @@ -1,4 +1,4 @@ -TESTS_TAG := v1.3.0-rc.1 +TESTS_TAG := v1.3.0-rc.3 TESTS = general minimal mainnet TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS)) diff --git a/testing/ef_tests/check_all_files_accessed.py b/testing/ef_tests/check_all_files_accessed.py index f8ddc0a9f2..b52d155224 100755 --- a/testing/ef_tests/check_all_files_accessed.py +++ b/testing/ef_tests/check_all_files_accessed.py @@ -41,8 +41,8 @@ excluded_paths = [ "tests/.*/.*/ssz_static/LightClientFinalityUpdate", # LightClientHeader "tests/.*/.*/ssz_static/LightClientHeader", - # Eip4844 tests are disabled for now. - "tests/.*/eip4844", + # Deneb (previously known as eip4844) tests are disabled for now. + "tests/.*/deneb", # One of the EF researchers likes to pack the tarballs on a Mac ".*\.DS_Store.*", # More Mac weirdness. @@ -55,9 +55,11 @@ excluded_paths = [ "bls12-381-tests/hash_to_G2" ] + def normalize_path(path): return path.split("consensus-spec-tests/")[1] + # Determine the list of filenames which were accessed during tests. passed = set() for line in open(accessed_files_filename, 'r').readlines(): @@ -90,4 +92,5 @@ for root, dirs, files in os.walk(tests_dir_filename): # Exit with an error if there were any files missed. assert len(missed) == 0, "{} missed files".format(len(missed)) -print("Accessed {} files ({} intentionally excluded)".format(accessed_files, excluded_files)) +print("Accessed {} files ({} intentionally excluded)".format( + accessed_files, excluded_files)) diff --git a/testing/ef_tests/src/cases/common.rs b/testing/ef_tests/src/cases/common.rs index cd980e374e..a59ccb34ad 100644 --- a/testing/ef_tests/src/cases/common.rs +++ b/testing/ef_tests/src/cases/common.rs @@ -66,7 +66,6 @@ pub fn previous_fork(fork_name: ForkName) -> ForkName { ForkName::Altair => ForkName::Base, ForkName::Merge => ForkName::Altair, // TODO: Check this when tests are released.. ForkName::Capella => ForkName::Merge, // TODO: Check this when tests are released.. - ForkName::Eip4844 => ForkName::Capella, // TODO: Check this when tests are released.. } } diff --git a/testing/ef_tests/src/cases/epoch_processing.rs b/testing/ef_tests/src/cases/epoch_processing.rs index 59a8ebd41c..6095e1be6b 100644 --- a/testing/ef_tests/src/cases/epoch_processing.rs +++ b/testing/ef_tests/src/cases/epoch_processing.rs @@ -101,10 +101,7 @@ impl EpochTransition for JustificationAndFinalization { justification_and_finalization_state.apply_changes_to_state(state); Ok(()) } - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => { + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { let justification_and_finalization_state = altair::process_justification_and_finalization( state, @@ -125,14 +122,13 @@ impl EpochTransition for RewardsAndPenalties { validator_statuses.process_attestations(state)?; base::process_rewards_and_penalties(state, &mut validator_statuses, spec) } - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => altair::process_rewards_and_penalties( - state, - &altair::ParticipationCache::new(state, spec).unwrap(), - spec, - ), + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { + altair::process_rewards_and_penalties( + state, + &altair::ParticipationCache::new(state, spec).unwrap(), + spec, + ) + } } } } @@ -155,10 +151,7 @@ impl EpochTransition for Slashings { spec, )?; } - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => { + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { process_slashings( state, altair::ParticipationCache::new(state, spec) @@ -210,9 +203,7 @@ impl EpochTransition for HistoricalRootsUpdate { impl EpochTransition for HistoricalSummariesUpdate { fn run(state: &mut BeaconState, _spec: &ChainSpec) -> Result<(), EpochProcessingError> { match state { - BeaconState::Capella(_) | BeaconState::Eip4844(_) => { - process_historical_summaries_update(state) - } + BeaconState::Capella(_) => process_historical_summaries_update(state), _ => Ok(()), } } @@ -232,10 +223,9 @@ impl EpochTransition for SyncCommitteeUpdates { fn run(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), EpochProcessingError> { match state { BeaconState::Base(_) => Ok(()), - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => altair::process_sync_committee_updates(state, spec), + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { + altair::process_sync_committee_updates(state, spec) + } } } } @@ -244,14 +234,13 @@ impl EpochTransition for InactivityUpdates { fn run(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), EpochProcessingError> { match state { BeaconState::Base(_) => Ok(()), - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => altair::process_inactivity_updates( - state, - &altair::ParticipationCache::new(state, spec).unwrap(), - spec, - ), + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { + altair::process_inactivity_updates( + state, + &altair::ParticipationCache::new(state, spec).unwrap(), + spec, + ) + } } } } @@ -260,10 +249,9 @@ impl EpochTransition for ParticipationFlagUpdates { fn run(state: &mut BeaconState, _: &ChainSpec) -> Result<(), EpochProcessingError> { match state { BeaconState::Base(_) => Ok(()), - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => altair::process_participation_flag_updates(state), + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { + altair::process_participation_flag_updates(state) + } } } } @@ -318,7 +306,6 @@ impl> Case for EpochProcessing { T::name() != "participation_record_updates" && T::name() != "historical_roots_update" } - ForkName::Eip4844 => false, // TODO: revisit when tests are out } } diff --git a/testing/ef_tests/src/cases/fork.rs b/testing/ef_tests/src/cases/fork.rs index f79e13005a..52157d32f8 100644 --- a/testing/ef_tests/src/cases/fork.rs +++ b/testing/ef_tests/src/cases/fork.rs @@ -62,7 +62,6 @@ impl Case for ForkTest { ForkName::Altair => upgrade_to_altair(&mut result_state, spec).map(|_| result_state), ForkName::Merge => upgrade_to_bellatrix(&mut result_state, spec).map(|_| result_state), ForkName::Capella => upgrade_to_capella(&mut result_state, spec).map(|_| result_state), - ForkName::Eip4844 => panic!("eip4844 not supported"), }; compare_beacon_state_results_without_caches(&mut result, &mut expected) diff --git a/testing/ef_tests/src/cases/operations.rs b/testing/ef_tests/src/cases/operations.rs index 71954405c0..5fd00285aa 100644 --- a/testing/ef_tests/src/cases/operations.rs +++ b/testing/ef_tests/src/cases/operations.rs @@ -95,10 +95,7 @@ impl Operation for Attestation { &mut ctxt, spec, ), - BeaconState::Altair(_) - | BeaconState::Merge(_) - | BeaconState::Capella(_) - | BeaconState::Eip4844(_) => { + BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Capella(_) => { altair::process_attestation(state, self, 0, &mut ctxt, VerifySignatures::True, spec) } } diff --git a/testing/ef_tests/src/cases/transition.rs b/testing/ef_tests/src/cases/transition.rs index fb7ccfea64..314e51d530 100644 --- a/testing/ef_tests/src/cases/transition.rs +++ b/testing/ef_tests/src/cases/transition.rs @@ -47,12 +47,6 @@ impl LoadCase for TransitionTest { spec.bellatrix_fork_epoch = Some(Epoch::new(0)); spec.capella_fork_epoch = Some(metadata.fork_epoch); } - ForkName::Eip4844 => { - spec.altair_fork_epoch = Some(Epoch::new(0)); - spec.bellatrix_fork_epoch = Some(Epoch::new(0)); - spec.capella_fork_epoch = Some(Epoch::new(0)); - spec.eip4844_fork_epoch = Some(metadata.fork_epoch); - } } // Load blocks diff --git a/testing/ef_tests/src/handler.rs b/testing/ef_tests/src/handler.rs index 07db7cd2a1..abf18b3506 100644 --- a/testing/ef_tests/src/handler.rs +++ b/testing/ef_tests/src/handler.rs @@ -24,11 +24,6 @@ pub trait Handler { fn run(&self) { for fork_name in ForkName::list_all() { - // FIXME(eip4844): enable eip4844 - if fork_name == ForkName::Eip4844 { - continue; - } - if self.is_enabled_for_fork(fork_name) { self.run_for_fork(fork_name) } @@ -650,6 +645,11 @@ impl Handler for MerkleProofValidityHandler { fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool { fork_name != ForkName::Base + // Test is skipped due to some changes in the Capella light client + // spec. + // + // https://github.com/sigp/lighthouse/issues/4022 + && fork_name != ForkName::Capella } } diff --git a/testing/ef_tests/src/type_name.rs b/testing/ef_tests/src/type_name.rs index 0239293e09..675388ee58 100644 --- a/testing/ef_tests/src/type_name.rs +++ b/testing/ef_tests/src/type_name.rs @@ -47,7 +47,6 @@ type_name_generic!(BeaconBlockBodyBase, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyAltair, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyMerge, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyCapella, "BeaconBlockBody"); -type_name_generic!(BeaconBlockBodyEip4844, "BeaconBlockBody"); type_name!(BeaconBlockHeader); type_name_generic!(BeaconState); type_name!(Checkpoint); @@ -59,12 +58,10 @@ type_name!(Eth1Data); type_name_generic!(ExecutionPayload); type_name_generic!(ExecutionPayloadMerge, "ExecutionPayload"); type_name_generic!(ExecutionPayloadCapella, "ExecutionPayload"); -type_name_generic!(ExecutionPayloadEip4844, "ExecutionPayload"); type_name_generic!(FullPayload, "ExecutionPayload"); type_name_generic!(ExecutionPayloadHeader); type_name_generic!(ExecutionPayloadHeaderMerge, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderCapella, "ExecutionPayloadHeader"); -type_name_generic!(ExecutionPayloadHeaderEip4844, "ExecutionPayloadHeader"); type_name_generic!(BlindedPayload, "ExecutionPayloadHeader"); type_name!(Fork); type_name!(ForkData); diff --git a/testing/execution_engine_integration/src/test_rig.rs b/testing/execution_engine_integration/src/test_rig.rs index bb416634e5..15e9f26018 100644 --- a/testing/execution_engine_integration/src/test_rig.rs +++ b/testing/execution_engine_integration/src/test_rig.rs @@ -427,7 +427,16 @@ impl TestRig { .notify_new_payload(&invalid_payload) .await .unwrap(); - assert!(matches!(status, PayloadStatus::InvalidBlockHash { .. })); + assert!(matches!( + status, + PayloadStatus::InvalidBlockHash { .. } + // Geth is returning `INVALID` with a `null` LVH to indicate it + // does not know the invalid ancestor. + | PayloadStatus::Invalid { + latest_valid_hash: None, + .. + } + )); /* * Execution Engine A: diff --git a/testing/web3signer_tests/src/lib.rs b/testing/web3signer_tests/src/lib.rs index 4f9a574f84..16bffd04f9 100644 --- a/testing/web3signer_tests/src/lib.rs +++ b/testing/web3signer_tests/src/lib.rs @@ -660,17 +660,17 @@ mod tests { } #[tokio::test] - async fn ropsten_base_types() { - test_base_types("ropsten", 4250).await + async fn sepolia_base_types() { + test_base_types("sepolia", 4250).await } #[tokio::test] - async fn ropsten_altair_types() { - test_altair_types("ropsten", 4251).await + async fn sepolia_altair_types() { + test_altair_types("sepolia", 4251).await } #[tokio::test] - async fn ropsten_merge_types() { - test_merge_types("ropsten", 4252).await + async fn sepolia_merge_types() { + test_merge_types("sepolia", 4252).await } } diff --git a/validator_client/src/beacon_node_fallback.rs b/validator_client/src/beacon_node_fallback.rs index 82f085c43f..3e667429b4 100644 --- a/validator_client/src/beacon_node_fallback.rs +++ b/validator_client/src/beacon_node_fallback.rs @@ -7,17 +7,20 @@ use crate::http_metrics::metrics::{inc_counter_vec, ENDPOINT_ERRORS, ENDPOINT_RE use environment::RuntimeContext; use eth2::BeaconNodeHttpClient; use futures::future; -use slog::{error, info, warn, Logger}; +use slog::{debug, error, info, warn, Logger}; use slot_clock::SlotClock; use std::fmt; use std::fmt::Debug; use std::future::Future; use std::marker::PhantomData; use std::sync::Arc; -use std::time::Duration; +use std::time::{Duration, Instant}; use tokio::{sync::RwLock, time::sleep}; use types::{ChainSpec, Config, EthSpec}; +/// Message emitted when the VC detects the BN is using a different spec. +const UPDATE_REQUIRED_LOG_HINT: &str = "this VC or the remote BN may need updating"; + /// The number of seconds *prior* to slot start that we will try and update the state of fallback /// nodes. /// @@ -27,6 +30,14 @@ use types::{ChainSpec, Config, EthSpec}; /// having the correct nodes up and running prior to the start of the slot. const SLOT_LOOKAHEAD: Duration = Duration::from_secs(1); +/// Indicates a measurement of latency between the VC and a BN. +pub struct LatencyMeasurement { + /// An identifier for the beacon node (e.g. the URL). + pub beacon_node_id: String, + /// The round-trip latency, if the BN responded successfully. + pub latency: Option, +} + /// Starts a service that will routinely try and update the status of the provided `beacon_nodes`. /// /// See `SLOT_LOOKAHEAD` for information about when this should run. @@ -262,6 +273,7 @@ impl CandidateBeaconNode { "Beacon node has mismatched Altair fork epoch"; "endpoint" => %self.beacon_node, "endpoint_altair_fork_epoch" => ?beacon_node_spec.altair_fork_epoch, + "hint" => UPDATE_REQUIRED_LOG_HINT, ); } else if beacon_node_spec.bellatrix_fork_epoch != spec.bellatrix_fork_epoch { warn!( @@ -269,6 +281,15 @@ impl CandidateBeaconNode { "Beacon node has mismatched Bellatrix fork epoch"; "endpoint" => %self.beacon_node, "endpoint_bellatrix_fork_epoch" => ?beacon_node_spec.bellatrix_fork_epoch, + "hint" => UPDATE_REQUIRED_LOG_HINT, + ); + } else if beacon_node_spec.capella_fork_epoch != spec.capella_fork_epoch { + warn!( + log, + "Beacon node has mismatched Capella fork epoch"; + "endpoint" => %self.beacon_node, + "endpoint_capella_fork_epoch" => ?beacon_node_spec.capella_fork_epoch, + "hint" => UPDATE_REQUIRED_LOG_HINT, ); } @@ -394,6 +415,47 @@ impl BeaconNodeFallback { let _ = future::join_all(futures).await; } + /// Concurrently send a request to all candidates (regardless of + /// offline/online) status and attempt to collect a rough reading on the + /// latency between the VC and candidate. + pub async fn measure_latency(&self) -> Vec { + let futures: Vec<_> = self + .candidates + .iter() + .map(|candidate| async { + let beacon_node_id = candidate.beacon_node.to_string(); + // The `node/version` endpoint is used since I imagine it would + // require the least processing in the BN and therefore measure + // the connection moreso than the BNs processing speed. + // + // I imagine all clients have the version string availble as a + // pre-computed string. + let response_instant = candidate + .beacon_node + .get_node_version() + .await + .ok() + .map(|_| Instant::now()); + (beacon_node_id, response_instant) + }) + .collect(); + + let request_instant = Instant::now(); + + // Send the request to all BNs at the same time. This might involve some + // queueing on the sending host, however I hope it will avoid bias + // caused by sending requests at different times. + future::join_all(futures) + .await + .into_iter() + .map(|(beacon_node_id, response_instant)| LatencyMeasurement { + beacon_node_id, + latency: response_instant + .and_then(|response| response.checked_duration_since(request_instant)), + }) + .collect() + } + /// Run `func` against each candidate in `self`, returning immediately if a result is found. /// Otherwise, return all the errors encountered along the way. /// @@ -409,10 +471,12 @@ impl BeaconNodeFallback { where F: Fn(&'a BeaconNodeHttpClient) -> R, R: Future>, + Err: Debug, { let mut errors = vec![]; let mut to_retry = vec![]; let mut retry_unsynced = vec![]; + let log = &self.log.clone(); // Run `func` using a `candidate`, returning the value or capturing errors. // @@ -427,6 +491,12 @@ impl BeaconNodeFallback { match func(&$candidate.beacon_node).await { Ok(val) => return Ok(val), Err(e) => { + debug!( + log, + "Request to beacon node failed"; + "node" => $candidate.beacon_node.to_string(), + "error" => ?e, + ); // If we have an error on this function, make the client as not-ready. // // There exists a race condition where the candidate may have been marked @@ -626,6 +696,7 @@ impl BeaconNodeFallback { where F: Fn(&'a BeaconNodeHttpClient) -> R, R: Future>, + Err: Debug, { if self.disable_run_on_all { self.first_success(require_synced, offline_on_failure, func) diff --git a/validator_client/src/block_service.rs b/validator_client/src/block_service.rs index 6fd519ebaf..3b37492377 100644 --- a/validator_client/src/block_service.rs +++ b/validator_client/src/block_service.rs @@ -407,17 +407,22 @@ impl BlockService { ) .await?; + let signing_timer = metrics::start_timer(&metrics::BLOCK_SIGNING_TIMES); let signed_block = self_ref .validator_store .sign_block::(*validator_pubkey_ref, block, current_slot) .await .map_err(|e| BlockError::Recoverable(format!("Unable to sign block: {:?}", e)))?; + let signing_time_ms = + Duration::from_secs_f64(signing_timer.map_or(0.0, |t| t.stop_and_record())).as_millis(); info!( log, "Publishing signed block"; "slot" => slot.as_u64(), + "signing_time_ms" => signing_time_ms, ); + // Publish block with first available beacon node. self.beacon_nodes .first_success( diff --git a/validator_client/src/cli.rs b/validator_client/src/cli.rs index dfea548735..171bc67af7 100644 --- a/validator_client/src/cli.rs +++ b/validator_client/src/cli.rs @@ -340,6 +340,15 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { set here moves too far from the previous block's gas limit. [default: 30,000,000]") .requires("builder-proposals"), ) + .arg( + Arg::with_name("latency-measurement-service") + .long("latency-measurement-service") + .value_name("BOOLEAN") + .help("Set to 'true' to enable a service that periodically attempts to measure latency to BNs. \ + Set to 'false' to disable.") + .default_value("true") + .takes_value(true), + ) /* * Experimental/development options. */ diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index a7dac22fce..d121bdecbb 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -73,6 +73,8 @@ pub struct Config { pub block_delay: Option, /// Disables publishing http api requests to all beacon nodes for select api calls. pub disable_run_on_all: bool, + /// Enables a service which attempts to measure latency between the VC and BNs. + pub enable_latency_measurement_service: bool, } impl Default for Config { @@ -111,6 +113,7 @@ impl Default for Config { builder_registration_timestamp_override: None, gas_limit: None, disable_run_on_all: false, + enable_latency_measurement_service: true, } } } @@ -365,6 +368,9 @@ impl Config { ); } + config.enable_latency_measurement_service = + parse_optional(cli_args, "latency-measurement-service")?.unwrap_or(true); + /* * Experimental */ diff --git a/validator_client/src/duties_service.rs b/validator_client/src/duties_service.rs index 6ba2a2d1fd..c335c67ab1 100644 --- a/validator_client/src/duties_service.rs +++ b/validator_client/src/duties_service.rs @@ -17,13 +17,14 @@ use crate::{ }; use environment::RuntimeContext; use eth2::types::{AttesterData, BeaconCommitteeSubscription, ProposerData, StateId, ValidatorId}; -use futures::future::join_all; +use futures::{stream, StreamExt}; use parking_lot::RwLock; use safe_arith::ArithError; use slog::{debug, error, info, warn, Logger}; use slot_clock::SlotClock; -use std::collections::{HashMap, HashSet}; +use std::collections::{hash_map, BTreeMap, HashMap, HashSet}; use std::sync::Arc; +use std::time::Duration; use sync::poll_sync_committee_duties; use sync::SyncDutiesMap; use tokio::{sync::mpsc::Sender, time::sleep}; @@ -40,6 +41,14 @@ const SUBSCRIPTION_BUFFER_SLOTS: u64 = 2; /// Only retain `HISTORICAL_DUTIES_EPOCHS` duties prior to the current epoch. const HISTORICAL_DUTIES_EPOCHS: u64 = 2; +/// Compute attestation selection proofs this many slots before they are required. +/// +/// At start-up selection proofs will be computed with less lookahead out of necessity. +const SELECTION_PROOF_SLOT_LOOKAHEAD: u64 = 8; + +/// Fraction of a slot at which selection proof signing should happen (2 means half way). +const SELECTION_PROOF_SCHEDULE_DENOM: u32 = 2; + /// Minimum number of validators for which we auto-enable per-validator metrics. /// For validators greater than this value, we need to manually set the `enable-per-validator-metrics` /// flag in the cli to enable collection of per validator metrics. @@ -71,7 +80,7 @@ pub struct DutyAndProof { impl DutyAndProof { /// Instantiate `Self`, computing the selection proof as well. - pub async fn new( + pub async fn new_with_selection_proof( duty: AttesterData, validator_store: &ValidatorStore, spec: &ChainSpec, @@ -99,6 +108,14 @@ impl DutyAndProof { selection_proof, }) } + + /// Create a new `DutyAndProof` with the selection proof waiting to be filled in. + pub fn new_without_selection_proof(duty: AttesterData) -> Self { + Self { + duty, + selection_proof: None, + } + } } /// To assist with readability, the dependent root for attester/proposer duties. @@ -471,7 +488,7 @@ async fn poll_validator_indices( /// 3. Push out any attestation subnet subscriptions to the BN. /// 4. Prune old entries from `duties_service.attesters`. async fn poll_beacon_attesters( - duties_service: &DutiesService, + duties_service: &Arc>, ) -> Result<(), Error> { let current_epoch_timer = metrics::start_timer_vec( &metrics::DUTIES_SERVICE_TIMES, @@ -634,7 +651,7 @@ async fn poll_beacon_attesters( /// For the given `local_indices` and `local_pubkeys`, download the duties for the given `epoch` and /// store them in `duties_service.attesters`. async fn poll_beacon_attesters_for_epoch( - duties_service: &DutiesService, + duties_service: &Arc>, epoch: Epoch, local_indices: &[u64], local_pubkeys: &HashSet, @@ -742,31 +759,16 @@ async fn poll_beacon_attesters_for_epoch( "num_new_duties" => new_duties.len(), ); - // Produce the `DutyAndProof` messages in parallel. - let duty_and_proof_results = join_all(new_duties.into_iter().map(|duty| { - DutyAndProof::new(duty, &duties_service.validator_store, &duties_service.spec) - })) - .await; - // Update the duties service with the new `DutyAndProof` messages. let mut attesters = duties_service.attesters.write(); let mut already_warned = Some(()); - for result in duty_and_proof_results { - let duty_and_proof = match result { - Ok(duty_and_proof) => duty_and_proof, - Err(e) => { - error!( - log, - "Failed to produce duty and proof"; - "error" => ?e, - "msg" => "may impair attestation duties" - ); - // Do not abort the entire batch for a single failure. - continue; - } - }; + for duty in &new_duties { + let attester_map = attesters.entry(duty.pubkey).or_default(); - let attester_map = attesters.entry(duty_and_proof.duty.pubkey).or_default(); + // Create initial entries in the map without selection proofs. We'll compute them in the + // background later to avoid creating a thundering herd of signing threads whenever new + // duties are computed. + let duty_and_proof = DutyAndProof::new_without_selection_proof(duty.clone()); if let Some((prior_dependent_root, _)) = attester_map.insert(epoch, (dependent_root, duty_and_proof)) @@ -785,9 +787,144 @@ async fn poll_beacon_attesters_for_epoch( } drop(attesters); + // Spawn the background task to compute selection proofs. + let subservice = duties_service.clone(); + duties_service.context.executor.spawn( + async move { + fill_in_selection_proofs(subservice, new_duties, dependent_root).await; + }, + "duties_service_selection_proofs_background", + ); + Ok(()) } +/// Compute the attestation selection proofs for the `duties` and add them to the `attesters` map. +/// +/// Duties are computed in batches each slot. If a re-org is detected then the process will +/// terminate early as it is assumed the selection proofs from `duties` are no longer relevant. +async fn fill_in_selection_proofs( + duties_service: Arc>, + duties: Vec, + dependent_root: Hash256, +) { + let log = duties_service.context.log(); + + // Sort duties by slot in a BTreeMap. + let mut duties_by_slot: BTreeMap> = BTreeMap::new(); + + for duty in duties { + duties_by_slot.entry(duty.slot).or_default().push(duty); + } + + // At halfway through each slot when nothing else is likely to be getting signed, sign a batch + // of selection proofs and insert them into the duties service `attesters` map. + let slot_clock = &duties_service.slot_clock; + let slot_offset = duties_service.slot_clock.slot_duration() / SELECTION_PROOF_SCHEDULE_DENOM; + + while !duties_by_slot.is_empty() { + if let Some(duration) = slot_clock.duration_to_next_slot() { + sleep(duration.saturating_sub(slot_offset)).await; + + let Some(current_slot) = slot_clock.now() else { + continue; + }; + + let lookahead_slot = current_slot + SELECTION_PROOF_SLOT_LOOKAHEAD; + + let mut relevant_duties = duties_by_slot.split_off(&lookahead_slot); + std::mem::swap(&mut relevant_duties, &mut duties_by_slot); + + let batch_size = relevant_duties.values().map(Vec::len).sum::(); + + if batch_size == 0 { + continue; + } + + let timer = metrics::start_timer_vec( + &metrics::DUTIES_SERVICE_TIMES, + &[metrics::ATTESTATION_SELECTION_PROOFS], + ); + + // Sign selection proofs (serially). + let duty_and_proof_results = stream::iter(relevant_duties.into_values().flatten()) + .then(|duty| async { + DutyAndProof::new_with_selection_proof( + duty, + &duties_service.validator_store, + &duties_service.spec, + ) + .await + }) + .collect::>() + .await; + + // Add to attesters store. + let mut attesters = duties_service.attesters.write(); + for result in duty_and_proof_results { + let duty_and_proof = match result { + Ok(duty_and_proof) => duty_and_proof, + Err(e) => { + error!( + log, + "Failed to produce duty and proof"; + "error" => ?e, + "msg" => "may impair attestation duties" + ); + // Do not abort the entire batch for a single failure. + continue; + } + }; + + let attester_map = attesters.entry(duty_and_proof.duty.pubkey).or_default(); + let epoch = duty_and_proof.duty.slot.epoch(E::slots_per_epoch()); + match attester_map.entry(epoch) { + hash_map::Entry::Occupied(mut entry) => { + // No need to update duties for which no proof was computed. + let Some(selection_proof) = duty_and_proof.selection_proof else { + continue; + }; + + let (existing_dependent_root, existing_duty) = entry.get_mut(); + + if *existing_dependent_root == dependent_root { + // Replace existing proof. + existing_duty.selection_proof = Some(selection_proof); + } else { + // Our selection proofs are no longer relevant due to a reorg, abandon + // this entire background process. + debug!( + log, + "Stopping selection proof background task"; + "reason" => "re-org" + ); + return; + } + } + hash_map::Entry::Vacant(entry) => { + entry.insert((dependent_root, duty_and_proof)); + } + } + } + drop(attesters); + + let time_taken_ms = + Duration::from_secs_f64(timer.map_or(0.0, |t| t.stop_and_record())).as_millis(); + debug!( + log, + "Computed attestation selection proofs"; + "batch_size" => batch_size, + "lookahead_slot" => lookahead_slot, + "time_taken_ms" => time_taken_ms + ); + } else { + // Just sleep for one slot if we are unable to read the system clock, this gives + // us an opportunity for the clock to eventually come good. + sleep(duties_service.slot_clock.slot_duration()).await; + } + } +} + /// Download the proposer duties for the current epoch and store them in `duties_service.proposers`. /// If there are any proposer for this slot, send out a notification to the block proposers. /// diff --git a/validator_client/src/http_metrics/metrics.rs b/validator_client/src/http_metrics/metrics.rs index 2d5b9b1db3..b4e400c3e7 100644 --- a/validator_client/src/http_metrics/metrics.rs +++ b/validator_client/src/http_metrics/metrics.rs @@ -32,6 +32,7 @@ pub const PROPOSER_DUTIES_HTTP_GET: &str = "proposer_duties_http_get"; pub const VALIDATOR_ID_HTTP_GET: &str = "validator_id_http_get"; pub const SUBSCRIPTIONS_HTTP_POST: &str = "subscriptions_http_post"; pub const UPDATE_PROPOSERS: &str = "update_proposers"; +pub const ATTESTATION_SELECTION_PROOFS: &str = "attestation_selection_proofs"; pub const SUBSCRIPTIONS: &str = "subscriptions"; pub const LOCAL_KEYSTORE: &str = "local_keystore"; pub const WEB3SIGNER: &str = "web3signer"; @@ -57,11 +58,6 @@ lazy_static::lazy_static! { "Total count of attempted block signings", &["status"] ); - pub static ref SIGNED_BLOBS_TOTAL: Result = try_create_int_counter_vec( - "vc_signed_beacon_blobs_total", - "Total count of attempted blob signings", - &["status"] - ); pub static ref SIGNED_ATTESTATIONS_TOTAL: Result = try_create_int_counter_vec( "vc_signed_attestations_total", "Total count of attempted Attestation signings", @@ -177,12 +173,28 @@ lazy_static::lazy_static! { "Duration to obtain a signature", &["type"] ); + pub static ref BLOCK_SIGNING_TIMES: Result = try_create_histogram( + "vc_block_signing_times_seconds", + "Duration to obtain a signature for a block", + ); pub static ref ATTESTATION_DUTY: Result = try_create_int_gauge_vec( "vc_attestation_duty_slot", "Attestation duty slot for all managed validators", &["validator"] ); + /* + * BN latency + */ + pub static ref VC_BEACON_NODE_LATENCY: Result = try_create_histogram_vec( + "vc_beacon_node_latency", + "Round-trip latency for a simple API endpoint on each BN", + &["endpoint"] + ); + pub static ref VC_BEACON_NODE_LATENCY_PRIMARY_ENDPOINT: Result = try_create_histogram( + "vc_beacon_node_latency_primary_endpoint", + "Round-trip latency for the primary BN endpoint", + ); } pub fn gather_prometheus_metrics( diff --git a/validator_client/src/http_metrics/mod.rs b/validator_client/src/http_metrics/mod.rs index c30d603447..31337491e8 100644 --- a/validator_client/src/http_metrics/mod.rs +++ b/validator_client/src/http_metrics/mod.rs @@ -121,7 +121,13 @@ pub fn serve( .and_then(|ctx: Arc>| async move { Ok::<_, warp::Rejection>( metrics::gather_prometheus_metrics(&ctx) - .map(|body| Response::builder().status(200).body(body).unwrap()) + .map(|body| { + Response::builder() + .status(200) + .header("Content-Type", "text/plain") + .body(body) + .unwrap() + }) .unwrap_or_else(|e| { Response::builder() .status(500) diff --git a/validator_client/src/latency.rs b/validator_client/src/latency.rs new file mode 100644 index 0000000000..7e752f2923 --- /dev/null +++ b/validator_client/src/latency.rs @@ -0,0 +1,64 @@ +use crate::{http_metrics::metrics, BeaconNodeFallback}; +use environment::RuntimeContext; +use slog::debug; +use slot_clock::SlotClock; +use std::sync::Arc; +use tokio::time::sleep; +use types::EthSpec; + +/// The latency service will run 11/12ths of the way through the slot. +pub const SLOT_DELAY_MULTIPLIER: u32 = 11; +pub const SLOT_DELAY_DENOMINATOR: u32 = 12; + +/// Starts a service that periodically checks the latency between the VC and the +/// candidate BNs. +pub fn start_latency_service( + context: RuntimeContext, + slot_clock: T, + beacon_nodes: Arc>, +) { + let log = context.log().clone(); + + let future = async move { + loop { + let sleep_time = slot_clock + .duration_to_next_slot() + .map(|next_slot| { + // This is 11/12ths through the next slot. On mainnet this + // will happen in the 11th second of each slot, one second + // before the next slot. + next_slot + (next_slot / SLOT_DELAY_DENOMINATOR) * SLOT_DELAY_MULTIPLIER + }) + // If we can't read the slot clock, just wait one slot. Running + // the measurement at a non-exact time is not a big issue. + .unwrap_or_else(|| slot_clock.slot_duration()); + + // Sleep until it's time to perform the measurement. + sleep(sleep_time).await; + + for (i, measurement) in beacon_nodes.measure_latency().await.iter().enumerate() { + if let Some(latency) = measurement.latency { + debug!( + log, + "Measured BN latency"; + "node" => &measurement.beacon_node_id, + "latency" => latency.as_millis(), + ); + metrics::observe_timer_vec( + &metrics::VC_BEACON_NODE_LATENCY, + &[&measurement.beacon_node_id], + latency, + ); + if i == 0 { + metrics::observe_duration( + &metrics::VC_BEACON_NODE_LATENCY_PRIMARY_ENDPOINT, + latency, + ); + } + } + } + } + }; + + context.executor.spawn(future, "latency"); +} diff --git a/validator_client/src/lib.rs b/validator_client/src/lib.rs index 2cbf58380d..6027427677 100644 --- a/validator_client/src/lib.rs +++ b/validator_client/src/lib.rs @@ -8,6 +8,7 @@ mod duties_service; mod graffiti_file; mod http_metrics; mod key_cache; +mod latency; mod notifier; mod preparation_service; mod signing_method; @@ -564,6 +565,14 @@ impl ProductionValidatorClient { None }; + if self.config.enable_latency_measurement_service { + latency::start_latency_service( + self.context.clone(), + self.duties_service.slot_clock.clone(), + self.duties_service.beacon_nodes.clone(), + ); + } + Ok(()) } } diff --git a/validator_client/src/signing_method/web3signer.rs b/validator_client/src/signing_method/web3signer.rs index 512cbc7d02..17e780304e 100644 --- a/validator_client/src/signing_method/web3signer.rs +++ b/validator_client/src/signing_method/web3signer.rs @@ -27,7 +27,6 @@ pub enum ForkName { Altair, Bellatrix, Capella, - Eip4844, } #[derive(Debug, PartialEq, Serialize)] @@ -97,11 +96,6 @@ impl<'a, T: EthSpec, Payload: AbstractExecPayload> Web3SignerObject<'a, T, Pa block: None, block_header: Some(block.block_header()), }), - BeaconBlock::Eip4844(_) => Ok(Web3SignerObject::BeaconBlock { - version: ForkName::Eip4844, - block: None, - block_header: Some(block.block_header()), - }), } }