collation-generation + collator-protocol: collate on multiple assigned cores (#3795)

This works only for collators that implement the `collator_fn` allowing
`collation-generation` subsystem to pull collations triggered on new
heads.

Also enables
`request_v2::CollationFetchingResponse::CollationWithParentHeadData` for
test adder/undying collators.

TODO:
- [x] fix tests
- [x] new tests
- [x] PR doc

---------

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>
This commit is contained in:
Andrei Sandu
2024-03-27 16:44:10 +02:00
committed by GitHub
parent 25af0adf78
commit 417c54c61c
15 changed files with 556 additions and 140 deletions
@@ -49,7 +49,7 @@ use polkadot_node_subsystem::messages::{
CollationGenerationMessage, RuntimeApiMessage, RuntimeApiRequest,
};
use polkadot_overseer::Handle as OverseerHandle;
use polkadot_primitives::{CollatorPair, Id as ParaId, OccupiedCoreAssumption};
use polkadot_primitives::{CollatorPair, CoreIndex, Id as ParaId, OccupiedCoreAssumption};
use futures::{channel::oneshot, prelude::*};
use sc_client_api::{backend::AuxStore, BlockBackend, BlockOf};
@@ -184,7 +184,15 @@ where
while let Some(relay_parent_header) = import_notifications.next().await {
let relay_parent = relay_parent_header.hash();
if !is_para_scheduled(relay_parent, params.para_id, &mut params.overseer_handle).await {
// TODO: Currently we use just the first core here, but for elastic scaling
// we iterate and build on all of the cores returned.
let core_index = if let Some(core_index) =
cores_scheduled_for_para(relay_parent, params.para_id, &mut params.overseer_handle)
.await
.get(0)
{
*core_index
} else {
tracing::trace!(
target: crate::LOG_TARGET,
?relay_parent,
@@ -193,7 +201,7 @@ where
);
continue
}
};
let max_pov_size = match params
.relay_client
@@ -396,6 +404,7 @@ where
parent_head: parent_header.encode().into(),
validation_code_hash,
result_sender: None,
core_index,
},
),
"SubmitCollation",
@@ -480,14 +489,12 @@ async fn max_ancestry_lookback(
}
}
// Checks if there exists a scheduled core for the para at the provided relay parent.
//
// Falls back to `false` in case of an error.
async fn is_para_scheduled(
// Return all the cores assigned to the para at the provided relay parent.
async fn cores_scheduled_for_para(
relay_parent: PHash,
para_id: ParaId,
overseer_handle: &mut OverseerHandle,
) -> bool {
) -> Vec<CoreIndex> {
let (tx, rx) = oneshot::channel();
let request = RuntimeApiRequest::AvailabilityCores(tx);
overseer_handle
@@ -503,7 +510,7 @@ async fn is_para_scheduled(
?relay_parent,
"Failed to query availability cores runtime API",
);
return false
return Vec::new()
},
Err(oneshot::Canceled) => {
tracing::error!(
@@ -511,9 +518,19 @@ async fn is_para_scheduled(
?relay_parent,
"Sender for availability cores runtime request dropped",
);
return false
return Vec::new()
},
};
cores.iter().any(|core| core.para_id() == Some(para_id))
cores
.iter()
.enumerate()
.filter_map(|(index, core)| {
if core.para_id() == Some(para_id) {
Some(CoreIndex(index as u32))
} else {
None
}
})
.collect()
}