mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-17 18:58:23 +00:00
WIP: Gloas full/empty child fork harness + tests + Option B sketch
Harness/tests (foundation): - make_gloas_block_with_status: produce a gloas block with explicit parent payload status (builds FULL vs EMPTY children); returns its data columns. - TestRig::build_full_empty_fork: G(full) -> A(full) -> B(FULL child), A -> C(EMPTY). - SimulateConfig::return_no_envelope_for_block: withhold a block's payload envelope. - Tests: gloas_build_full_empty_fork_shape (shape), gloas_full_empty_children_ retain_parent_for_payload (happy path), gloas_empty_child_continues_while_ parent_payload_withheld (red: C must complete, B+A retained while payload withheld). Option B sketch (untested, mod.rs) -- to be implemented properly: - continue_child_lookups on a SingleBlock Imported result (children re-evaluate on parent block import, before its payload). - retain a failed lookup while another lookup awaits it (is_awaited).
This commit is contained in:
@@ -509,6 +509,13 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
"Received lookup processing result"
|
||||
);
|
||||
|
||||
let block_root = lookup.block_root();
|
||||
// Gloas: a block imports into fork choice on block + columns, *before* its payload
|
||||
// envelope. Children awaiting it must re-evaluate at that point: an EMPTY child can import
|
||||
// on the parent block alone, while a FULL child re-awaits the parent's payload.
|
||||
let block_imported = matches!(process_type, BlockProcessType::SingleBlock { .. })
|
||||
&& matches!(result, BlockProcessingResult::Imported(..));
|
||||
|
||||
let lookup_result = match process_type {
|
||||
BlockProcessType::SingleBlock { .. } => lookup.on_block_processing_result(result, cx),
|
||||
BlockProcessType::SingleCustodyColumn(_) => {
|
||||
@@ -519,6 +526,9 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
}
|
||||
};
|
||||
self.on_lookup_result(lookup_id, lookup_result, "processing_result", cx);
|
||||
if block_imported {
|
||||
self.continue_child_lookups(block_root, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_external_processing_result(
|
||||
@@ -657,6 +667,22 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
// update metrics because the lookup does not exist.
|
||||
Err(LookupRequestError::UnknownLookup) => false,
|
||||
Err(error) => {
|
||||
// Retain a failed lookup while another lookup awaits it: a FULL Gloas child awaits
|
||||
// its parent's payload, so the parent's failed payload download must not cascade-
|
||||
// drop the child. The parent stays until its payload arrives (or it is reaped as
|
||||
// stuck).
|
||||
if let Some(block_root) = self.single_block_lookups.get(&id).map(|l| l.block_root())
|
||||
&& self.is_awaited(block_root)
|
||||
{
|
||||
debug!(
|
||||
id,
|
||||
source,
|
||||
?error,
|
||||
?block_root,
|
||||
"Retaining failed lookup awaited by a child"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
debug!(id, source, ?error, "Dropping lookup on request error");
|
||||
self.drop_lookup_and_children(id, error.into());
|
||||
self.update_metrics();
|
||||
@@ -665,6 +691,13 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if any lookup is awaiting `block_root` as its parent.
|
||||
fn is_awaited(&self, block_root: Hash256) -> bool {
|
||||
self.single_block_lookups
|
||||
.values()
|
||||
.any(|lookup| lookup.awaiting_parent() == Some(block_root))
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
/// Drops all the single block requests and returns how many requests were dropped.
|
||||
|
||||
Reference in New Issue
Block a user