Skip to content

Commit 93e0649

Browse files
authored
Notify lookup sync of gossip processing results (#5722)
* Notify lookup sync of gossip processing results * Add tests * Add GossipBlockProcessResult event * Re-add dropped comments * Update beacon_node/network/src/network_beacon_processor/sync_methods.rs * update test_lookup_disconnection_peer_left
1 parent 6d792b4 commit 93e0649

File tree

12 files changed

+398
-93
lines changed

12 files changed

+398
-93
lines changed

beacon_node/beacon_chain/src/block_verification_types.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,26 @@ pub struct BlockImportData<E: EthSpec> {
314314
pub consensus_context: ConsensusContext<E>,
315315
}
316316

317+
impl<E: EthSpec> BlockImportData<E> {
318+
pub fn __new_for_test(
319+
block_root: Hash256,
320+
state: BeaconState<E>,
321+
parent_block: SignedBeaconBlock<E, BlindedPayload<E>>,
322+
) -> Self {
323+
Self {
324+
block_root,
325+
state,
326+
parent_block,
327+
parent_eth1_finalization_data: Eth1FinalizationData {
328+
eth1_data: <_>::default(),
329+
eth1_deposit_index: 0,
330+
},
331+
confirmed_state_roots: vec![],
332+
consensus_context: ConsensusContext::new(Slot::new(0)),
333+
}
334+
}
335+
}
336+
317337
pub type GossipVerifiedBlockContents<E> =
318338
(GossipVerifiedBlock<E>, Option<GossipVerifiedBlobList<E>>);
319339

beacon_node/beacon_chain/src/data_availability_checker.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,11 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
8484
})
8585
}
8686

87-
/// Checks if the block root is currenlty in the availability cache awaiting processing because
87+
/// Checks if the block root is currenlty in the availability cache awaiting import because
8888
/// of missing components.
89-
pub fn has_block(&self, block_root: &Hash256) -> bool {
90-
self.availability_cache.has_block(block_root)
89+
pub fn has_execution_valid_block(&self, block_root: &Hash256) -> bool {
90+
self.availability_cache
91+
.has_execution_valid_block(block_root)
9192
}
9293

9394
/// Return the required blobs `block_root` expects if the block is currenlty in the cache.

beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -432,11 +432,6 @@ impl<T: BeaconChainTypes> Critical<T> {
432432
Ok(())
433433
}
434434

435-
/// Returns true if the block root is known, without altering the LRU ordering
436-
pub fn has_block(&self, block_root: &Hash256) -> bool {
437-
self.in_memory.peek(block_root).is_some() || self.store_keys.contains(block_root)
438-
}
439-
440435
/// This only checks for the blobs in memory
441436
pub fn peek_blob(
442437
&self,
@@ -549,8 +544,12 @@ impl<T: BeaconChainTypes> OverflowLRUCache<T> {
549544
}
550545

551546
/// Returns true if the block root is known, without altering the LRU ordering
552-
pub fn has_block(&self, block_root: &Hash256) -> bool {
553-
self.critical.read().has_block(block_root)
547+
pub fn has_execution_valid_block(&self, block_root: &Hash256) -> bool {
548+
if let Some(pending_components) = self.critical.read().peek_pending_components(block_root) {
549+
pending_components.executed_block.is_some()
550+
} else {
551+
false
552+
}
554553
}
555554

556555
/// Fetch a blob from the cache without affecting the LRU ordering

beacon_node/network/src/network_beacon_processor/gossip_methods.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,19 +1187,18 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
11871187
"block_root" => %block_root,
11881188
);
11891189
}
1190-
Err(BlockError::ParentUnknown(block)) => {
1191-
// Inform the sync manager to find parents for this block
1192-
// This should not occur. It should be checked by `should_forward_block`
1190+
Err(BlockError::ParentUnknown(_)) => {
1191+
// This should not occur. It should be checked by `should_forward_block`.
1192+
// Do not send sync message UnknownParentBlock to prevent conflicts with the
1193+
// BlockComponentProcessed message below. If this error ever happens, lookup sync
1194+
// can recover by receiving another block / blob / attestation referencing the
1195+
// chain that includes this block.
11931196
error!(
11941197
self.log,
11951198
"Block with unknown parent attempted to be processed";
1199+
"block_root" => %block_root,
11961200
"peer_id" => %peer_id
11971201
);
1198-
self.send_sync_message(SyncMessage::UnknownParentBlock(
1199-
peer_id,
1200-
block.clone(),
1201-
block_root,
1202-
));
12031202
}
12041203
Err(ref e @ BlockError::ExecutionPayloadError(ref epe)) if !epe.penalize_peer() => {
12051204
debug!(
@@ -1263,6 +1262,11 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
12631262
&self.log,
12641263
);
12651264
}
1265+
1266+
self.send_sync_message(SyncMessage::GossipBlockProcessResult {
1267+
block_root,
1268+
imported: matches!(result, Ok(AvailabilityProcessingStatus::Imported(_))),
1269+
});
12661270
}
12671271

12681272
pub fn process_gossip_voluntary_exit(

beacon_node/network/src/network_beacon_processor/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
use crate::{
2-
service::NetworkMessage,
3-
sync::{manager::BlockProcessType, SyncMessage},
4-
};
1+
use crate::sync::manager::BlockProcessType;
2+
use crate::{service::NetworkMessage, sync::manager::SyncMessage};
53
use beacon_chain::block_verification_types::RpcBlock;
64
use beacon_chain::{builder::Witness, eth1_chain::CachingEth1Backend, BeaconChain};
75
use beacon_chain::{BeaconChainTypes, NotifyExecutionLayer};

beacon_node/network/src/network_beacon_processor/sync_methods.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,17 +170,15 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
170170
if reprocess_tx.try_send(reprocess_msg).is_err() {
171171
error!(self.log, "Failed to inform block import"; "source" => "rpc", "block_root" => %hash)
172172
};
173-
if matches!(process_type, BlockProcessType::SingleBlock { .. }) {
174-
self.chain.block_times_cache.write().set_time_observed(
175-
hash,
176-
slot,
177-
seen_timestamp,
178-
None,
179-
None,
180-
);
173+
self.chain.block_times_cache.write().set_time_observed(
174+
hash,
175+
slot,
176+
seen_timestamp,
177+
None,
178+
None,
179+
);
181180

182-
self.chain.recompute_head_at_current_slot().await;
183-
}
181+
self.chain.recompute_head_at_current_slot().await;
184182
}
185183
// Sync handles these results
186184
self.send_sync_message(SyncMessage::BlockComponentProcessed {

beacon_node/network/src/sync/block_lookups/common.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::sync::block_lookups::single_block_lookup::{
22
LookupRequestError, SingleBlockLookup, SingleLookupRequestState,
33
};
44
use crate::sync::block_lookups::{BlobRequestState, BlockRequestState, PeerId};
5-
use crate::sync::manager::{BlockProcessType, Id, SLOT_IMPORT_TOLERANCE};
6-
use crate::sync::network_context::SyncNetworkContext;
5+
use crate::sync::manager::{Id, SLOT_IMPORT_TOLERANCE};
6+
use crate::sync::network_context::{LookupRequestResult, SyncNetworkContext};
77
use beacon_chain::block_verification_types::RpcBlock;
88
use beacon_chain::BeaconChainTypes;
99
use std::sync::Arc;
@@ -45,7 +45,7 @@ pub trait RequestState<T: BeaconChainTypes> {
4545
peer_id: PeerId,
4646
downloaded_block_expected_blobs: Option<usize>,
4747
cx: &mut SyncNetworkContext<T>,
48-
) -> Result<bool, LookupRequestError>;
48+
) -> Result<LookupRequestResult, LookupRequestError>;
4949

5050
/* Response handling methods */
5151

@@ -80,7 +80,7 @@ impl<T: BeaconChainTypes> RequestState<T> for BlockRequestState<T::EthSpec> {
8080
peer_id: PeerId,
8181
_: Option<usize>,
8282
cx: &mut SyncNetworkContext<T>,
83-
) -> Result<bool, LookupRequestError> {
83+
) -> Result<LookupRequestResult, LookupRequestError> {
8484
cx.block_lookup_request(id, peer_id, self.requested_block_root)
8585
.map_err(LookupRequestError::SendFailed)
8686
}
@@ -97,10 +97,10 @@ impl<T: BeaconChainTypes> RequestState<T> for BlockRequestState<T::EthSpec> {
9797
peer_id: _,
9898
} = download_result;
9999
cx.send_block_for_processing(
100+
id,
100101
block_root,
101102
RpcBlock::new_without_blobs(Some(block_root), value),
102103
seen_timestamp,
103-
BlockProcessType::SingleBlock { id },
104104
)
105105
.map_err(LookupRequestError::SendFailed)
106106
}
@@ -128,7 +128,7 @@ impl<T: BeaconChainTypes> RequestState<T> for BlobRequestState<T::EthSpec> {
128128
peer_id: PeerId,
129129
downloaded_block_expected_blobs: Option<usize>,
130130
cx: &mut SyncNetworkContext<T>,
131-
) -> Result<bool, LookupRequestError> {
131+
) -> Result<LookupRequestResult, LookupRequestError> {
132132
cx.blob_lookup_request(
133133
id,
134134
peer_id,
@@ -149,13 +149,8 @@ impl<T: BeaconChainTypes> RequestState<T> for BlobRequestState<T::EthSpec> {
149149
seen_timestamp,
150150
peer_id: _,
151151
} = download_result;
152-
cx.send_blobs_for_processing(
153-
block_root,
154-
value,
155-
seen_timestamp,
156-
BlockProcessType::SingleBlob { id },
157-
)
158-
.map_err(LookupRequestError::SendFailed)
152+
cx.send_blobs_for_processing(id, block_root, value, seen_timestamp)
153+
.map_err(LookupRequestError::SendFailed)
159154
}
160155

161156
fn response_type() -> ResponseType {

beacon_node/network/src/sync/block_lookups/mod.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,10 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
408408
self.on_processing_result_inner::<BlobRequestState<T::EthSpec>>(id, result, cx)
409409
}
410410
};
411-
self.on_lookup_result(process_type.id(), lookup_result, "processing_result", cx);
411+
let id = match process_type {
412+
BlockProcessType::SingleBlock { id } | BlockProcessType::SingleBlob { id } => id,
413+
};
414+
self.on_lookup_result(id, lookup_result, "processing_result", cx);
412415
}
413416

414417
pub fn on_processing_result_inner<R: RequestState<T>>(
@@ -521,6 +524,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
521524
}
522525
other => {
523526
debug!(self.log, "Invalid lookup component"; "block_root" => ?block_root, "component" => ?R::response_type(), "error" => ?other);
527+
524528
let peer_id = request_state.on_processing_failure()?;
525529
cx.report_peer(
526530
peer_id,
@@ -561,6 +565,30 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
561565
}
562566
}
563567

568+
pub fn on_external_processing_result(
569+
&mut self,
570+
block_root: Hash256,
571+
imported: bool,
572+
cx: &mut SyncNetworkContext<T>,
573+
) {
574+
let Some((id, lookup)) = self
575+
.single_block_lookups
576+
.iter_mut()
577+
.find(|(_, lookup)| lookup.is_for_block(block_root))
578+
else {
579+
// Ok to ignore gossip process events
580+
return;
581+
};
582+
583+
let lookup_result = if imported {
584+
Ok(LookupResult::Completed)
585+
} else {
586+
lookup.continue_requests(cx)
587+
};
588+
let id = *id;
589+
self.on_lookup_result(id, lookup_result, "external_processing_result", cx);
590+
}
591+
564592
/// Makes progress on the immediate children of `block_root`
565593
pub fn continue_child_lookups(&mut self, block_root: Hash256, cx: &mut SyncNetworkContext<T>) {
566594
let mut lookup_results = vec![]; // < need to buffer lookup results to not re-borrow &mut self

beacon_node/network/src/sync/block_lookups/single_block_lookup.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::common::ResponseType;
22
use super::{BlockComponent, PeerId, SINGLE_BLOCK_LOOKUP_MAX_ATTEMPTS};
33
use crate::sync::block_lookups::common::RequestState;
44
use crate::sync::block_lookups::Id;
5-
use crate::sync::network_context::SyncNetworkContext;
5+
use crate::sync::network_context::{LookupRequestResult, SyncNetworkContext};
66
use beacon_chain::BeaconChainTypes;
77
use itertools::Itertools;
88
use rand::seq::IteratorRandom;
@@ -179,11 +179,13 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
179179
.use_rand_available_peer()
180180
.ok_or(LookupRequestError::NoPeers)?;
181181

182-
// make_request returns true only if a request needs to be made
183-
if request.make_request(id, peer_id, downloaded_block_expected_blobs, cx)? {
184-
request.get_state_mut().on_download_start()?;
185-
} else {
186-
request.get_state_mut().on_completed_request()?;
182+
match request.make_request(id, peer_id, downloaded_block_expected_blobs, cx)? {
183+
LookupRequestResult::RequestSent => request.get_state_mut().on_download_start()?,
184+
LookupRequestResult::NoRequestNeeded => {
185+
request.get_state_mut().on_completed_request()?
186+
}
187+
// Sync will receive a future event to make progress on the request, do nothing now
188+
LookupRequestResult::Pending => return Ok(()),
187189
}
188190

189191
// Otherwise, attempt to progress awaiting processing
@@ -262,12 +264,16 @@ pub struct DownloadResult<T: Clone> {
262264
pub peer_id: PeerId,
263265
}
264266

265-
#[derive(Debug, PartialEq, Eq)]
267+
#[derive(Debug, PartialEq, Eq, IntoStaticStr)]
266268
pub enum State<T: Clone> {
267269
AwaitingDownload,
268270
Downloading,
269271
AwaitingProcess(DownloadResult<T>),
272+
/// Request is processing, sent by lookup sync
270273
Processing(DownloadResult<T>),
274+
/// Request is processed:
275+
/// - `Processed(Some)` if lookup sync downloaded and sent to process this request
276+
/// - `Processed(None)` if another source (i.e. gossip) sent this component for processing
271277
Processed(Option<PeerId>),
272278
}
273279

@@ -428,12 +434,11 @@ impl<T: Clone> SingleLookupRequestState<T> {
428434
}
429435
}
430436

431-
pub fn on_processing_success(&mut self) -> Result<PeerId, LookupRequestError> {
437+
pub fn on_processing_success(&mut self) -> Result<(), LookupRequestError> {
432438
match &self.state {
433439
State::Processing(result) => {
434-
let peer_id = result.peer_id;
435-
self.state = State::Processed(Some(peer_id));
436-
Ok(peer_id)
440+
self.state = State::Processed(Some(result.peer_id));
441+
Ok(())
437442
}
438443
other => Err(LookupRequestError::BadState(format!(
439444
"Bad state on_processing_success expected Processing got {other}"
@@ -514,12 +519,6 @@ impl<T: Clone> SingleLookupRequestState<T> {
514519

515520
impl<T: Clone> std::fmt::Display for State<T> {
516521
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
517-
match self {
518-
State::AwaitingDownload => write!(f, "AwaitingDownload"),
519-
State::Downloading { .. } => write!(f, "Downloading"),
520-
State::AwaitingProcess { .. } => write!(f, "AwaitingProcessing"),
521-
State::Processing { .. } => write!(f, "Processing"),
522-
State::Processed { .. } => write!(f, "Processed"),
523-
}
522+
write!(f, "{}", Into::<&'static str>::into(self))
524523
}
525524
}

0 commit comments

Comments
 (0)