Handle unknown head during attestation publishing (#5010)

* Handle unknown head during attestation publishing

* Merge remote-tracking branch 'origin/unstable' into queue-http-attestations

* Simplify task spawner

* Improve logging

* Add a test

* Improve error logging

* Merge remote-tracking branch 'origin/unstable' into queue-http-attestations

* Fix beta compiler warnings
This commit is contained in:
Michael Sproul
2024-02-15 23:24:47 +11:00
committed by GitHub
parent 49536ff103
commit f17fb291b7
7 changed files with 455 additions and 140 deletions

View File

@@ -4,6 +4,7 @@ use beacon_chain::{
test_utils::{AttestationStrategy, BlockStrategy, SyncCommitteeStrategy},
ChainConfig,
};
use beacon_processor::work_reprocessing_queue::ReprocessQueueMessage;
use eth2::types::ProduceBlockV3Response;
use eth2::types::{DepositContractData, StateId};
use execution_layer::{ForkchoiceState, PayloadAttributes};
@@ -840,3 +841,78 @@ pub async fn fork_choice_before_proposal() {
// D's parent is B.
assert_eq!(block_d.parent_root(), block_root_b.into());
}
// Test that attestations to unknown blocks are requeued and processed when their block arrives.
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn queue_attestations_from_http() {
let validator_count = 128;
let all_validators = (0..validator_count).collect::<Vec<_>>();
let tester = InteractiveTester::<E>::new(None, validator_count).await;
let harness = &tester.harness;
let client = tester.client.clone();
let num_initial = 5;
// Slot of the block attested to.
let attestation_slot = Slot::new(num_initial) + 1;
// Make some initial blocks.
harness.advance_slot();
harness
.extend_chain(
num_initial as usize,
BlockStrategy::OnCanonicalHead,
AttestationStrategy::AllValidators,
)
.await;
harness.advance_slot();
assert_eq!(harness.get_current_slot(), attestation_slot);
// Make the attested-to block without applying it.
let pre_state = harness.get_current_state();
let (block, post_state) = harness.make_block(pre_state, attestation_slot).await;
let block_root = block.0.canonical_root();
// Make attestations to the block and POST them to the beacon node on a background thread.
let attestations = harness
.make_unaggregated_attestations(
&all_validators,
&post_state,
block.0.state_root(),
block_root.into(),
attestation_slot,
)
.into_iter()
.flat_map(|attestations| attestations.into_iter().map(|(att, _subnet)| att))
.collect::<Vec<_>>();
let attestation_future = tokio::spawn(async move {
client
.post_beacon_pool_attestations(&attestations)
.await
.expect("attestations should be processed successfully")
});
// In parallel, apply the block. We need to manually notify the reprocess queue, because the
// `beacon_chain` does not know about the queue and will not update it for us.
let parent_root = block.0.parent_root();
harness
.process_block(attestation_slot, block_root, block)
.await
.unwrap();
tester
.ctx
.beacon_processor_reprocess_send
.as_ref()
.unwrap()
.send(ReprocessQueueMessage::BlockImported {
block_root,
parent_root,
})
.await
.unwrap();
attestation_future.await.unwrap();
}