diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 0cdf5b9fe95..e8df5b811ed 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -722,7 +722,7 @@ impl IntoGossipVerifiedBlockContents for PublishBlockReq Ok::<_, BlockContentsError>(gossip_verified_blobs) }) .transpose()?; - let gossip_verified_block = GossipVerifiedBlock::new(Arc::new(block), chain)?; + let gossip_verified_block = GossipVerifiedBlock::new(block, chain)?; Ok((gossip_verified_block, gossip_verified_blobs)) } diff --git a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs index 8b8368022ac..34c9bc76f6e 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs @@ -952,7 +952,7 @@ mod test { }; let availability_pending_block = AvailabilityPendingExecutedBlock { - block: Arc::new(block), + block, import_data, payload_verification_outcome, }; diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 7a66a6bdb4b..6b85c8e4931 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -822,7 +822,7 @@ where slot: Slot, ) -> (SignedBlindedBeaconBlock, BeaconState) { let (unblinded, new_state) = self.make_block(state, slot).await; - (unblinded.0.into(), new_state) + ((*unblinded.0).clone().into(), new_state) } /// Returns a newly created block, signed by the proposer for the given slot. @@ -866,14 +866,14 @@ where panic!("Should always be a full payload response"); }; - let signed_block = block_response.block.sign( + let signed_block = Arc::new(block_response.block.sign( &self.validator_keypairs[proposer_index].sk, &block_response.state.fork(), block_response.state.genesis_validators_root(), &self.spec, - ); + )); - let block_contents: SignedBlockContentsTuple = match &signed_block { + let block_contents: SignedBlockContentsTuple = match *signed_block { SignedBeaconBlock::Base(_) | SignedBeaconBlock::Altair(_) | SignedBeaconBlock::Merge(_) @@ -928,14 +928,14 @@ where panic!("Should always be a full payload response"); }; - let signed_block = block_response.block.sign( + let signed_block = Arc::new(block_response.block.sign( &self.validator_keypairs[proposer_index].sk, &block_response.state.fork(), block_response.state.genesis_validators_root(), &self.spec, - ); + )); - let block_contents: SignedBlockContentsTuple = match &signed_block { + let block_contents: SignedBlockContentsTuple = match *signed_block { SignedBeaconBlock::Base(_) | SignedBeaconBlock::Altair(_) | SignedBeaconBlock::Merge(_) @@ -1742,7 +1742,7 @@ where let ((block, blobs), state) = self.make_block_return_pre_state(state, slot).await; - let (mut block, _) = block.deconstruct(); + let (mut block, _) = (*block).clone().deconstruct(); block_modifier(&mut block); @@ -1754,7 +1754,7 @@ where state.genesis_validators_root(), &self.spec, ); - ((signed_block, blobs), state) + ((Arc::new(signed_block), blobs), state) } pub async fn make_blob_with_modifier( @@ -1768,7 +1768,7 @@ where let ((block, mut blobs), state) = self.make_block_return_pre_state(state, slot).await; - let (block, _) = block.deconstruct(); + let (block, _) = (*block).clone().deconstruct(); blob_modifier(&mut blobs.as_mut().unwrap().1); @@ -1780,7 +1780,7 @@ where state.genesis_validators_root(), &self.spec, ); - ((signed_block, blobs), state) + ((Arc::new(signed_block), blobs), state) } pub fn make_deposits<'a>( @@ -1873,7 +1873,7 @@ where .chain .process_block( block_root, - RpcBlock::new(Some(block_root), Arc::new(block), sidecars).unwrap(), + RpcBlock::new(Some(block_root), block, sidecars).unwrap(), NotifyExecutionLayer::Yes, || Ok(()), ) @@ -1899,7 +1899,7 @@ where .chain .process_block( block_root, - RpcBlock::new(Some(block_root), Arc::new(block), sidecars).unwrap(), + RpcBlock::new(Some(block_root), block, sidecars).unwrap(), NotifyExecutionLayer::Yes, || Ok(()), ) diff --git a/beacon_node/beacon_chain/tests/block_verification.rs b/beacon_node/beacon_chain/tests/block_verification.rs index 4344013b3ce..541e97436db 100644 --- a/beacon_node/beacon_chain/tests/block_verification.rs +++ b/beacon_node/beacon_chain/tests/block_verification.rs @@ -1142,11 +1142,7 @@ async fn verify_block_for_gossip_slashing_detection() { let ((block1, blobs1), _) = harness.make_block(state.clone(), Slot::new(1)).await; let ((block2, _blobs2), _) = harness.make_block(state, Slot::new(1)).await; - let verified_block = harness - .chain - .verify_block_for_gossip(Arc::new(block1)) - .await - .unwrap(); + let verified_block = harness.chain.verify_block_for_gossip(block1).await.unwrap(); if let Some((kzg_proofs, blobs)) = blobs1 { let sidecars = @@ -1174,12 +1170,7 @@ async fn verify_block_for_gossip_slashing_detection() { ) .await .unwrap(); - unwrap_err( - harness - .chain - .verify_block_for_gossip(Arc::new(block2)) - .await, - ); + unwrap_err(harness.chain.verify_block_for_gossip(block2).await); // Slasher should have been handed the two conflicting blocks and crafted a slashing. slasher.process_queued(Epoch::new(0)).unwrap(); @@ -1198,11 +1189,7 @@ async fn verify_block_for_gossip_doppelganger_detection() { let state = harness.get_current_state(); let ((block, _), _) = harness.make_block(state.clone(), Slot::new(1)).await; - let verified_block = harness - .chain - .verify_block_for_gossip(Arc::new(block)) - .await - .unwrap(); + let verified_block = harness.chain.verify_block_for_gossip(block).await.unwrap(); let attestations = verified_block.block.message().body().attestations().clone(); harness .chain @@ -1564,7 +1551,6 @@ async fn import_duplicate_block_unrealized_justification() { let slot = harness.get_current_slot(); let (block_contents, _) = harness.make_block(state.clone(), slot).await; let (block, _) = block_contents; - let block = Arc::new(block); let block_root = block.canonical_root(); // Create two verified variants of the block, representing the same block being processed in diff --git a/beacon_node/beacon_chain/tests/payload_invalidation.rs b/beacon_node/beacon_chain/tests/payload_invalidation.rs index 5076a6c1a92..a0b7fbd365a 100644 --- a/beacon_node/beacon_chain/tests/payload_invalidation.rs +++ b/beacon_node/beacon_chain/tests/payload_invalidation.rs @@ -319,7 +319,7 @@ impl InvalidPayloadRig { .get_full_block(&block_root) .unwrap() .unwrap(), - block, + *block, "block from db must match block imported" ); } @@ -700,7 +700,7 @@ async fn invalidates_all_descendants() { .chain .process_block( fork_block.canonical_root(), - Arc::new(fork_block), + fork_block, NotifyExecutionLayer::Yes, || Ok(()), ) @@ -800,7 +800,7 @@ async fn switches_heads() { .chain .process_block( fork_block.canonical_root(), - Arc::new(fork_block), + fork_block, NotifyExecutionLayer::Yes, || Ok(()), ) @@ -1044,8 +1044,7 @@ async fn invalid_parent() { // Produce another block atop the parent, but don't import yet. let slot = parent_block.slot() + 1; rig.harness.set_current_slot(slot); - let (block_tuple, state) = rig.harness.make_block(parent_state, slot).await; - let block = Arc::new(block_tuple.0); + let ((block, _), state) = rig.harness.make_block(parent_state, slot).await; let block_root = block.canonical_root(); assert_eq!(block.parent_root(), parent_root); @@ -1865,7 +1864,7 @@ impl InvalidHeadSetup { .state_at_slot(slot - 1, StateSkipConfig::WithStateRoots) .unwrap(); let (fork_block_tuple, _) = rig.harness.make_block(parent_state, slot).await; - opt_fork_block = Some(Arc::new(fork_block_tuple.0)); + opt_fork_block = Some(fork_block_tuple.0); } else { // Skipped slot. }; diff --git a/beacon_node/beacon_chain/tests/store_tests.rs b/beacon_node/beacon_chain/tests/store_tests.rs index 28770b93e24..9b832bd7646 100644 --- a/beacon_node/beacon_chain/tests/store_tests.rs +++ b/beacon_node/beacon_chain/tests/store_tests.rs @@ -2268,17 +2268,17 @@ async fn garbage_collect_temp_states_from_failed_block() { let block_slot = Slot::new(2 * slots_per_epoch); let ((signed_block, _), state) = harness.make_block(genesis_state, block_slot).await; - let (mut block, _) = signed_block.deconstruct(); + let (mut block, _) = (*signed_block).clone().deconstruct(); // Mutate the block to make it invalid, and re-sign it. *block.state_root_mut() = Hash256::repeat_byte(0xff); let proposer_index = block.proposer_index() as usize; - let block = block.sign( + let block = Arc::new(block.sign( &harness.validator_keypairs[proposer_index].sk, &state.fork(), state.genesis_validators_root(), &harness.spec, - ); + )); // The block should be rejected, but should store a bunch of temporary states. harness.set_current_slot(block_slot); @@ -2677,7 +2677,7 @@ async fn process_blocks_and_attestations_for_unaligned_checkpoint() { .chain .process_block( invalid_fork_block.canonical_root(), - Arc::new(invalid_fork_block.clone()), + invalid_fork_block.clone(), NotifyExecutionLayer::Yes, || Ok(()), ) @@ -2690,7 +2690,7 @@ async fn process_blocks_and_attestations_for_unaligned_checkpoint() { .chain .process_block( valid_fork_block.canonical_root(), - Arc::new(valid_fork_block.clone()), + valid_fork_block.clone(), NotifyExecutionLayer::Yes, || Ok(()), ) diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index 02ea9518c69..3777e61420b 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -1410,7 +1410,7 @@ pub fn serve( .and(network_tx_filter.clone()) .and(log_filter.clone()) .then( - move |block_contents: SignedBlindedBeaconBlock, + move |block_contents: Arc>, task_spawner: TaskSpawner, chain: Arc>, network_tx: UnboundedSender>, @@ -1450,6 +1450,7 @@ pub fn serve( &block_bytes, &chain.spec, ) + .map(Arc::new) .map_err(|e| { warp_utils::reject::custom_bad_request(format!("invalid SSZ: {e:?}")) })?; @@ -1478,7 +1479,7 @@ pub fn serve( .and(log_filter.clone()) .then( move |validation_level: api_types::BroadcastValidationQuery, - blinded_block: SignedBlindedBeaconBlock, + blinded_block: Arc>, task_spawner: TaskSpawner, chain: Arc>, network_tx: UnboundedSender>, @@ -1519,6 +1520,7 @@ pub fn serve( &block_bytes, &chain.spec, ) + .map(Arc::new) .map_err(|e| { warp_utils::reject::custom_bad_request(format!("invalid SSZ: {e:?}")) })?; diff --git a/beacon_node/http_api/src/publish_blocks.rs b/beacon_node/http_api/src/publish_blocks.rs index 8b037715405..8b85c2ac951 100644 --- a/beacon_node/http_api/src/publish_blocks.rs +++ b/beacon_node/http_api/src/publish_blocks.rs @@ -194,7 +194,7 @@ pub async fn publish_block { info!( @@ -291,7 +290,7 @@ pub async fn publish_block( - blinded_block: SignedBlindedBeaconBlock, + blinded_block: Arc>, chain: Arc>, network_tx: &UnboundedSender>, log: Logger, @@ -319,7 +318,7 @@ pub async fn publish_blinded_block( pub async fn reconstruct_block( chain: Arc>, block_root: Hash256, - block: SignedBlindedBeaconBlock, + block: Arc>, log: Logger, ) -> Result>, Rejection> { let full_payload_opt = if let Ok(payload_header) = block.message().body().execution_payload() { @@ -380,6 +379,10 @@ pub async fn reconstruct_block( None }; + // Perf: cloning the block here to unblind it is a little sub-optimal. This is considered an + // acceptable tradeoff to avoid passing blocks around on the stack (unarced), which blows up + // the size of futures. + let block = (*block).clone(); match full_payload_opt { // A block without a payload is pre-merge and we consider it locally // built. diff --git a/beacon_node/http_api/tests/broadcast_validation_tests.rs b/beacon_node/http_api/tests/broadcast_validation_tests.rs index 2d42371a7c9..6a3f7947e6b 100644 --- a/beacon_node/http_api/tests/broadcast_validation_tests.rs +++ b/beacon_node/http_api/tests/broadcast_validation_tests.rs @@ -3,7 +3,7 @@ use beacon_chain::{ GossipVerifiedBlock, IntoGossipVerifiedBlockContents, }; use eth2::reqwest::StatusCode; -use eth2::types::{BroadcastValidation, PublishBlockRequest, SignedBeaconBlock}; +use eth2::types::{BroadcastValidation, PublishBlockRequest}; use http_api::test_utils::InteractiveTester; use http_api::{publish_blinded_block, publish_block, reconstruct_block, ProvenancedBlock}; use std::sync::Arc; @@ -63,7 +63,7 @@ pub async fn gossip_invalid() { tester.harness.advance_slot(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = tester + let ((block, blobs), _) = tester .harness .make_block_with_modifier(chain_state_before, slot, |b| { *b.state_root_mut() = Hash256::zero(); @@ -115,7 +115,7 @@ pub async fn gossip_partial_pass() { tester.harness.advance_slot(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = tester + let ((block, blobs), _) = tester .harness .make_block_with_modifier(chain_state_before, slot, |b| { *b.state_root_mut() = Hash256::random() @@ -161,8 +161,7 @@ pub async fn gossip_full_pass() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = - tester.harness.make_block(state_a, slot_b).await; + let ((block, blobs), _) = tester.harness.make_block(state_a, slot_b).await; let response: Result<(), eth2::Error> = tester .client @@ -252,7 +251,7 @@ pub async fn consensus_invalid() { tester.harness.advance_slot(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = tester + let ((block, blobs), _) = tester .harness .make_block_with_modifier(chain_state_before, slot, |b| { *b.state_root_mut() = Hash256::zero(); @@ -304,7 +303,7 @@ pub async fn consensus_gossip() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = tester + let ((block, blobs), _) = tester .harness .make_block_with_modifier(state_a, slot_b, |b| *b.state_root_mut() = Hash256::zero()) .await; @@ -418,8 +417,7 @@ pub async fn consensus_full_pass() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = - tester.harness.make_block(state_a, slot_b).await; + let ((block, blobs), _) = tester.harness.make_block(state_a, slot_b).await; let response: Result<(), eth2::Error> = tester .client @@ -465,7 +463,7 @@ pub async fn equivocation_invalid() { tester.harness.advance_slot(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = tester + let ((block, blobs), _) = tester .harness .make_block_with_modifier(chain_state_before, slot, |b| { *b.state_root_mut() = Hash256::zero(); @@ -518,10 +516,9 @@ pub async fn equivocation_consensus_early_equivocation() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block_a, blobs_a), state_after_a): ((SignedBeaconBlock, _), _) = + let ((block_a, blobs_a), state_after_a) = tester.harness.make_block(state_a.clone(), slot_b).await; - let ((block_b, blobs_b), state_after_b): ((SignedBeaconBlock, _), _) = - tester.harness.make_block(state_a, slot_b).await; + let ((block_b, blobs_b), state_after_b) = tester.harness.make_block(state_a, slot_b).await; /* check for `make_block` curios */ assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); @@ -590,7 +587,7 @@ pub async fn equivocation_gossip() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = tester + let ((block, blobs), _) = tester .harness .make_block_with_modifier(state_a, slot_b, |b| *b.state_root_mut() = Hash256::zero()) .await; @@ -645,10 +642,9 @@ pub async fn equivocation_consensus_late_equivocation() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block_a, blobs_a), state_after_a): ((SignedBeaconBlock, _), _) = + let ((block_a, blobs_a), state_after_a) = tester.harness.make_block(state_a.clone(), slot_b).await; - let ((block_b, blobs_b), state_after_b): ((SignedBeaconBlock, _), _) = - tester.harness.make_block(state_a, slot_b).await; + let ((block_b, blobs_b), state_after_b) = tester.harness.make_block(state_a, slot_b).await; /* check for `make_block` curios */ assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); @@ -716,8 +712,7 @@ pub async fn equivocation_full_pass() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block, blobs), _): ((SignedBeaconBlock, _), _) = - tester.harness.make_block(state_a, slot_b).await; + let ((block, blobs), _) = tester.harness.make_block(state_a, slot_b).await; let response: Result<(), eth2::Error> = tester .client @@ -1269,6 +1264,7 @@ pub async fn blinded_equivocation_consensus_late_equivocation() { .make_blinded_block(state_a.clone(), slot_b) .await; let (block_b, state_after_b) = tester.harness.make_blinded_block(state_a, slot_b).await; + let block_b = Arc::new(block_b); /* check for `make_blinded_block` curios */ assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); @@ -1278,7 +1274,7 @@ pub async fn blinded_equivocation_consensus_late_equivocation() { let unblinded_block_a = reconstruct_block( tester.harness.chain.clone(), block_a.canonical_root(), - block_a, + Arc::new(block_a), test_logger.clone(), ) .await @@ -1301,15 +1297,11 @@ pub async fn blinded_equivocation_consensus_late_equivocation() { ProvenancedBlock::Builder(b, _) => b, }; - let gossip_block_b = GossipVerifiedBlock::new( - Arc::new(inner_block_b.clone().deconstruct().0), - &tester.harness.chain, - ); + let gossip_block_b = + GossipVerifiedBlock::new(inner_block_b.clone().deconstruct().0, &tester.harness.chain); assert!(gossip_block_b.is_ok()); - let gossip_block_a = GossipVerifiedBlock::new( - Arc::new(inner_block_a.clone().deconstruct().0), - &tester.harness.chain, - ); + let gossip_block_a = + GossipVerifiedBlock::new(inner_block_a.clone().deconstruct().0, &tester.harness.chain); assert!(gossip_block_a.is_err()); let channel = tokio::sync::mpsc::unbounded_channel(); diff --git a/beacon_node/http_api/tests/interactive_tests.rs b/beacon_node/http_api/tests/interactive_tests.rs index 210c4d2550c..6fb197b41ab 100644 --- a/beacon_node/http_api/tests/interactive_tests.rs +++ b/beacon_node/http_api/tests/interactive_tests.rs @@ -632,7 +632,7 @@ pub async fn proposer_boost_re_org_test( panic!("Should not be a blinded block"); } }; - let block_c = harness.sign_beacon_block(unsigned_block_c, &state_b); + let block_c = Arc::new(harness.sign_beacon_block(unsigned_block_c, &state_b)); if should_re_org { // Block C should build on A. diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index 300c5a10600..4e0b4d761e6 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -2597,7 +2597,7 @@ impl ApiTester { let signed_block = block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec); let signed_block_contents = - PublishBlockRequest::try_from(signed_block.clone()).unwrap(); + PublishBlockRequest::try_from(Arc::new(signed_block.clone())).unwrap(); self.client .post_beacon_blocks(&signed_block_contents) @@ -2670,8 +2670,8 @@ impl ApiTester { .unwrap(); assert_eq!( - self.chain.head_beacon_block().as_ref(), - signed_block_contents.signed_block() + self.chain.head_beacon_block(), + *signed_block_contents.signed_block() ); self.chain.slot_clock.set_slot(slot.as_u64() + 1); @@ -2763,8 +2763,8 @@ impl ApiTester { .unwrap(); assert_eq!( - self.chain.head_beacon_block().as_ref(), - signed_block_contents.signed_block() + self.chain.head_beacon_block(), + *signed_block_contents.signed_block() ); self.chain.slot_clock.set_slot(slot.as_u64() + 1); @@ -2994,7 +2994,7 @@ impl ApiTester { .data; let signed_block = signed_block_contents.signed_block(); - assert_eq!(&head_block, signed_block); + assert_eq!(head_block, **signed_block); self.chain.slot_clock.set_slot(slot.as_u64() + 1); } diff --git a/beacon_node/network/src/network_beacon_processor/tests.rs b/beacon_node/network/src/network_beacon_processor/tests.rs index 48c5334357e..dd58eb83555 100644 --- a/beacon_node/network/src/network_beacon_processor/tests.rs +++ b/beacon_node/network/src/network_beacon_processor/tests.rs @@ -250,7 +250,7 @@ impl TestRig { }; Self { chain, - next_block: Arc::new(block), + next_block: block, next_blobs: blob_sidecars, attestations, next_block_attestations, diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs index 3e8d0c60795..a301055f34c 100644 --- a/common/eth2/src/types.rs +++ b/common/eth2/src/types.rs @@ -15,6 +15,7 @@ use ssz_derive::{Decode, Encode}; use std::convert::TryFrom; use std::fmt::{self, Display}; use std::str::{from_utf8, FromStr}; +use std::sync::Arc; use std::time::Duration; use types::beacon_block_body::KzgCommitments; pub use types::*; @@ -1479,10 +1480,10 @@ mod tests { type E = MainnetEthSpec; let spec = ForkName::Capella.make_genesis_spec(E::default_spec()); - let block: PublishBlockRequest = SignedBeaconBlock::from_block( + let block: PublishBlockRequest = Arc::new(SignedBeaconBlock::from_block( BeaconBlock::::Capella(BeaconBlockCapella::empty(&spec)), Signature::empty(), - ) + )) .try_into() .expect("should convert into signed block contents"); @@ -1503,7 +1504,8 @@ mod tests { ); let blobs = BlobsList::::from(vec![Blob::::default()]); let kzg_proofs = KzgProofs::::from(vec![KzgProof::empty()]); - let signed_block_contents = PublishBlockRequest::new(block, Some((kzg_proofs, blobs))); + let signed_block_contents = + PublishBlockRequest::new(Arc::new(block), Some((kzg_proofs, blobs))); let decoded: PublishBlockRequest = PublishBlockRequest::from_ssz_bytes( &signed_block_contents.as_ssz_bytes(), @@ -1644,7 +1646,7 @@ impl FullBlockContents { ) -> PublishBlockRequest { let (block, maybe_blobs) = self.deconstruct(); let signed_block = block.sign(secret_key, fork, genesis_validators_root, spec); - PublishBlockRequest::new(signed_block, maybe_blobs) + PublishBlockRequest::new(Arc::new(signed_block), maybe_blobs) } } @@ -1675,7 +1677,10 @@ impl Into> for FullBlockContents { } } -pub type SignedBlockContentsTuple = (SignedBeaconBlock, Option<(KzgProofs, BlobsList)>); +pub type SignedBlockContentsTuple = ( + Arc>, + Option<(KzgProofs, BlobsList)>, +); fn parse_required_header( headers: &HeaderMap, @@ -1730,12 +1735,12 @@ impl TryFrom<&HeaderMap> for ProduceBlockV3Metadata { #[ssz(enum_behaviour = "transparent")] pub enum PublishBlockRequest { BlockContents(SignedBlockContents), - Block(SignedBeaconBlock), + Block(Arc>), } impl PublishBlockRequest { pub fn new( - block: SignedBeaconBlock, + block: Arc>, blob_items: Option<(KzgProofs, BlobsList)>, ) -> Self { match blob_items { @@ -1753,7 +1758,7 @@ impl PublishBlockRequest { match fork_name { ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => { SignedBeaconBlock::from_ssz_bytes_for_fork(bytes, fork_name) - .map(|block| PublishBlockRequest::Block(block)) + .map(|block| PublishBlockRequest::Block(Arc::new(block))) } ForkName::Deneb => { let mut builder = ssz::SszDecoderBuilder::new(bytes); @@ -1767,12 +1772,15 @@ impl PublishBlockRequest { })?; let kzg_proofs = decoder.decode_next()?; let blobs = decoder.decode_next()?; - Ok(PublishBlockRequest::new(block, Some((kzg_proofs, blobs)))) + Ok(PublishBlockRequest::new( + Arc::new(block), + Some((kzg_proofs, blobs)), + )) } } } - pub fn signed_block(&self) -> &SignedBeaconBlock { + pub fn signed_block(&self) -> &Arc> { match self { PublishBlockRequest::BlockContents(block_and_sidecars) => { &block_and_sidecars.signed_block @@ -1802,14 +1810,14 @@ pub fn into_full_block_and_blobs( let signed_block = blinded_block .try_into_full_block(None) .ok_or("Failed to build full block with payload".to_string())?; - Ok(PublishBlockRequest::new(signed_block, None)) + Ok(PublishBlockRequest::new(Arc::new(signed_block), None)) } // This variant implies a pre-deneb block Some(FullPayloadContents::Payload(execution_payload)) => { let signed_block = blinded_block .try_into_full_block(Some(execution_payload)) .ok_or("Failed to build full block with payload".to_string())?; - Ok(PublishBlockRequest::new(signed_block, None)) + Ok(PublishBlockRequest::new(Arc::new(signed_block), None)) } // This variant implies a post-deneb block Some(FullPayloadContents::PayloadAndBlobs(payload_and_blobs)) => { @@ -1818,7 +1826,7 @@ pub fn into_full_block_and_blobs( .ok_or("Failed to build full block with payload".to_string())?; Ok(PublishBlockRequest::new( - signed_block, + Arc::new(signed_block), Some(( payload_and_blobs.blobs_bundle.proofs, payload_and_blobs.blobs_bundle.blobs, @@ -1828,10 +1836,10 @@ pub fn into_full_block_and_blobs( } } -impl TryFrom> for PublishBlockRequest { +impl TryFrom>> for PublishBlockRequest { type Error = &'static str; - fn try_from(block: SignedBeaconBlock) -> Result { - match block { + fn try_from(block: Arc>) -> Result { + match *block { SignedBeaconBlock::Base(_) | SignedBeaconBlock::Altair(_) | SignedBeaconBlock::Merge(_) @@ -1852,7 +1860,7 @@ impl From> for PublishBlockRequest { #[derive(Debug, Clone, Serialize, Deserialize, Encode)] #[serde(bound = "T: EthSpec")] pub struct SignedBlockContents { - pub signed_block: SignedBeaconBlock, + pub signed_block: Arc>, pub kzg_proofs: KzgProofs, #[serde(with = "ssz_types::serde_utils::list_of_hex_fixed_vec")] pub blobs: BlobsList, diff --git a/consensus/fork_choice/tests/tests.rs b/consensus/fork_choice/tests/tests.rs index c21b8ed567f..649fbcc5559 100644 --- a/consensus/fork_choice/tests/tests.rs +++ b/consensus/fork_choice/tests/tests.rs @@ -323,8 +323,9 @@ impl ForkChoiceTest { ) .unwrap(); let slot = self.harness.get_current_slot(); - let (mut block_tuple, mut state) = self.harness.make_block(state, slot).await; - func(&mut block_tuple.0, &mut state); + let ((block_arc, _block_blobs), mut state) = self.harness.make_block(state, slot).await; + let mut block = (*block_arc).clone(); + func(&mut block, &mut state); let current_slot = self.harness.get_current_slot(); self.harness .chain @@ -332,8 +333,8 @@ impl ForkChoiceTest { .fork_choice_write_lock() .on_block( current_slot, - block_tuple.0.message(), - block_tuple.0.canonical_root(), + block.message(), + block.canonical_root(), Duration::from_secs(0), &state, PayloadVerificationStatus::Verified, @@ -366,8 +367,9 @@ impl ForkChoiceTest { ) .unwrap(); let slot = self.harness.get_current_slot(); - let (mut block_tuple, mut state) = self.harness.make_block(state, slot).await; - mutation_func(&mut block_tuple.0, &mut state); + let ((block_arc, _block_blobs), mut state) = self.harness.make_block(state, slot).await; + let mut block = (*block_arc).clone(); + mutation_func(&mut block, &mut state); let current_slot = self.harness.get_current_slot(); let err = self .harness @@ -376,8 +378,8 @@ impl ForkChoiceTest { .fork_choice_write_lock() .on_block( current_slot, - block_tuple.0.message(), - block_tuple.0.canonical_root(), + block.message(), + block.canonical_root(), Duration::from_secs(0), &state, PayloadVerificationStatus::Verified, diff --git a/consensus/state_processing/src/per_block_processing/tests.rs b/consensus/state_processing/src/per_block_processing/tests.rs index 75eb438967c..83fd0f232ca 100644 --- a/consensus/state_processing/src/per_block_processing/tests.rs +++ b/consensus/state_processing/src/per_block_processing/tests.rs @@ -90,7 +90,7 @@ async fn invalid_block_header_state_slot() { let slot = state.slot() + Slot::new(1); let ((signed_block, _), mut state) = harness.make_block_return_pre_state(state, slot).await; - let (mut block, signature) = signed_block.deconstruct(); + let (mut block, signature) = (*signed_block).clone().deconstruct(); *block.slot_mut() = slot + Slot::new(1); let mut ctxt = ConsensusContext::new(block.slot()); @@ -123,7 +123,7 @@ async fn invalid_parent_block_root() { let ((signed_block, _), mut state) = harness .make_block_return_pre_state(state, slot + Slot::new(1)) .await; - let (mut block, signature) = signed_block.deconstruct(); + let (mut block, signature) = (*signed_block).clone().deconstruct(); *block.parent_root_mut() = Hash256::from([0xAA; 32]); let mut ctxt = ConsensusContext::new(block.slot()); @@ -158,7 +158,7 @@ async fn invalid_block_signature() { let ((signed_block, _), mut state) = harness .make_block_return_pre_state(state, slot + Slot::new(1)) .await; - let (block, _) = signed_block.deconstruct(); + let (block, _) = (*signed_block).clone().deconstruct(); let mut ctxt = ConsensusContext::new(block.slot()); let result = per_block_processing( diff --git a/testing/state_transition_vectors/src/exit.rs b/testing/state_transition_vectors/src/exit.rs index 29f5c015e38..50b98d3066d 100644 --- a/testing/state_transition_vectors/src/exit.rs +++ b/testing/state_transition_vectors/src/exit.rs @@ -57,7 +57,7 @@ impl ExitTest { block_modifier(&harness, block); }) .await; - (signed_block.0, state) + ((*signed_block.0).clone(), state) } fn process( diff --git a/validator_client/src/block_service.rs b/validator_client/src/block_service.rs index b65e301de86..e0c98660e27 100644 --- a/validator_client/src/block_service.rs +++ b/validator_client/src/block_service.rs @@ -450,12 +450,13 @@ impl BlockService { self.validator_store .sign_block(*validator_pubkey, block, slot) .await - .map(|b| SignedBlock::Full(PublishBlockRequest::new(b, maybe_blobs))) + .map(|b| SignedBlock::Full(PublishBlockRequest::new(Arc::new(b), maybe_blobs))) } UnsignedBlock::Blinded(block) => self .validator_store .sign_block(*validator_pubkey, block, slot) .await + .map(Arc::new) .map(SignedBlock::Blinded), }; @@ -870,7 +871,7 @@ impl UnsignedBlock { pub enum SignedBlock { Full(PublishBlockRequest), - Blinded(SignedBlindedBeaconBlock), + Blinded(Arc>), } impl SignedBlock {