Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,669 changes: 988 additions & 681 deletions Cargo.lock

Large diffs are not rendered by default.

293 changes: 147 additions & 146 deletions Cargo.toml

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion client/consensus/nimbus-consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,17 @@ sp-runtime = { workspace = true }
sp-version = { workspace = true }
sp-trie = { workspace = true }
sp-state-machine = { workspace = true }
sp-externalities = { workspace = true }
sc-basic-authorship = { workspace = true }
sc-block-builder = { workspace = true }
sc-transaction-pool-api = { workspace = true }
substrate-prometheus-endpoint = { workspace = true }
anyhow = { workspace = true }
thiserror = { workspace = true }

# Cumulus dependencies
cumulus-client-collator = { workspace = true }
cumulus-client-consensus-common = { workspace = true }
cumulus-client-consensus-proposer = { workspace = true }
cumulus-client-parachain-inherent = { workspace = true }
cumulus-primitives-core = { workspace = true }
cumulus-primitives-parachain-inherent = { workspace = true }
Expand Down
33 changes: 27 additions & 6 deletions client/consensus/nimbus-consensus/src/collator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

use cumulus_client_collator::service::ServiceInterface as CollatorServiceInterface;
use cumulus_client_consensus_common::{ParachainBlockImportMarker, ParachainCandidate};
use cumulus_client_consensus_proposer::ProposerInterface;
use crate::ProposerInterface;
use cumulus_client_parachain_inherent::{ParachainInherentData, ParachainInherentDataProvider};
use cumulus_primitives_core::{
relay_chain::Hash as PHash, DigestItem, ParachainBlockData, PersistedValidationData,
Expand Down Expand Up @@ -124,6 +124,17 @@ where
collator_peer_id: PeerId,
cidp_context: CIDPContext,
) -> Result<(ParachainInherentData, InherentData), Box<dyn Error + Send + Sync + 'static>> {
// stable2603 introduced `RelayProofRequest` (cumulus_primitives_core)
// which wraps a typed list of relay-chain storage keys; previously the
// API took a raw `Vec<Vec<u8>>` of top-level keys. We faithfully
// translate every key as `RelayStorageKey::Top` since the call sites
// only ever passed top-level keys.
let relay_proof_request = cumulus_primitives_core::RelayProofRequest {
keys: additional_relay_state_keys
.into_iter()
.map(cumulus_primitives_core::RelayStorageKey::Top)
.collect(),
};
let paras_inherent_data = ParachainInherentDataProvider::create_at(
relay_parent,
&self.relay_client,
Expand All @@ -132,7 +143,7 @@ where
relay_parent_descendants
.map(RelayParentData::into_inherent_descendant_list)
.unwrap_or_default(),
additional_relay_state_keys,
relay_proof_request,
collator_peer_id,
)
.await;
Expand Down Expand Up @@ -202,6 +213,15 @@ where
)];
logs.extend(additional_pre_digest.into().unwrap_or_default());

// Caller now owns the proof recorder and the runtime extensions; see
// paritytech/polkadot-sdk#9947. Register `ProofSizeExt` so the runtime
// can observe its own PoV growth during block production.
let storage_proof_recorder = sp_api::ProofRecorder::<Block>::default();
let mut extra_extensions = sp_externalities::Extensions::new();
extra_extensions.register(sp_trie::proof_size_extension::ProofSizeExt::new(
storage_proof_recorder.clone(),
));

let maybe_proposal = self
.proposer
.propose(
Expand All @@ -211,6 +231,8 @@ where
Digest { logs },
proposal_duration,
Some(max_pov_size),
Some(storage_proof_recorder.clone()),
extra_extensions,
)
.await
.map_err(|e| Box::new(e) as Box<dyn Error + Send>)?;
Expand All @@ -220,6 +242,8 @@ where
Some(p) => p,
};

let proof = storage_proof_recorder.drain_storage_proof();

let sealed_importable = seal::<_, P>(
proposal.block,
proposal.storage_changes,
Expand All @@ -242,10 +266,7 @@ where
.map_err(|e| Box::new(e) as Box<dyn Error + Send>)
.await?;

Ok(Some(ParachainCandidate {
block,
proof: proposal.proof,
}))
Ok(Some(ParachainCandidate { block, proof }))
}

/// Propose, seal, import a block and packaging it into a collation.
Expand Down
43 changes: 18 additions & 25 deletions client/consensus/nimbus-consensus/src/collators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub mod slot_based;
use crate::{collator::SlotClaim, *};
use async_backing_primitives::Slot;
use async_backing_primitives::UnincludedSegmentApi;
use cumulus_client_consensus_common::{ParentSearchParams, PotentialParent};
use cumulus_client_consensus_common::ParentSearchParams;
use cumulus_primitives_core::{
relay_chain::{Header as RelayHeader, OccupiedCoreAssumption, ValidationCodeHash},
ParaId,
Expand Down Expand Up @@ -240,15 +240,14 @@ async fn scheduling_lookahead(
}
}

/// Use [`cumulus_client_consensus_common::find_potential_parents`] to find parachain blocks that
/// we can build on. Once a list of potential parents is retrieved, return the last one of the
/// longest chain.
/// Use [`cumulus_client_consensus_common::find_parent_for_building`] to find the best parachain
/// block to build on. Returns the included block header alongside the best parent header.
async fn find_parent<Block>(
relay_parent: RelayHash,
para_id: ParaId,
para_backend: &impl sc_client_api::Backend<Block>,
relay_client: &impl RelayChainInterface,
) -> Option<(<Block as BlockT>::Header, PotentialParent<Block>)>
) -> Option<(<Block as BlockT>::Header, <Block as BlockT>::Header)>
where
Block: BlockT,
{
Expand All @@ -259,40 +258,34 @@ where
.await
.unwrap_or(polkadot_primitives::DEFAULT_SCHEDULING_LOOKAHEAD)
.saturating_sub(1) as usize,
max_depth: PARENT_SEARCH_DEPTH,
ignore_alternative_branches: true,
};

let potential_parents = cumulus_client_consensus_common::find_potential_parents::<Block>(
match cumulus_client_consensus_common::find_parent_for_building::<Block>(
parent_search_params,
para_backend,
relay_client,
)
.await;

let potential_parents = match potential_parents {
.await
{
Ok(Some(result)) => Some((result.included_header, result.best_parent_header)),
Ok(None) => {
tracing::warn!(
target: crate::LOG_TARGET,
?relay_parent,
"Could not find parent to build upon.",
);
None
}
Err(e) => {
tracing::error!(
target: crate::LOG_TARGET,
?relay_parent,
err = ?e,
"Could not fetch potential parents to build upon"
);

return None;
None
}
Ok(x) => x,
};

let included_block = potential_parents
.iter()
.find(|x| x.depth == 0)?
.header
.clone();
potential_parents
.into_iter()
.max_by_key(|a| a.depth)
.map(|parent| (included_block, parent))
}
}

/// Helper for managing pre-connections to backing groups.
Expand Down
2 changes: 1 addition & 1 deletion client/consensus/nimbus-consensus/src/collators/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use crate::*;
use cumulus_client_collator::service::ServiceInterface as CollatorServiceInterface;
use cumulus_client_consensus_common::{self as consensus_common, ParachainBlockImportMarker};
use cumulus_client_consensus_proposer::ProposerInterface;
use crate::ProposerInterface;
use cumulus_primitives_core::{
relay_chain::{BlockId as RBlockId, Hash as PHash, ValidationCode},
CollectCollationInfo, ParaId, PersistedValidationData,
Expand Down
48 changes: 23 additions & 25 deletions client/consensus/nimbus-consensus/src/collators/lookahead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use cumulus_client_consensus_common::{
self as consensus_common, load_abridged_host_configuration, ParachainBlockImportMarker,
ParentSearchParams,
};
use cumulus_client_consensus_proposer::ProposerInterface;
use crate::ProposerInterface;
use cumulus_primitives_core::{
relay_chain::{AsyncBackingParams, CoreIndex, Hash as PHash},
CollectCollationInfo, ParaId,
Expand All @@ -43,6 +43,7 @@ use sp_core::Encode;
use sp_inherents::CreateInherentDataProviders;
use sp_keystore::KeystorePtr;
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use sp_runtime::Saturating;
use std::{sync::Arc, time::Duration};

/// Parameters for [`run`].
Expand Down Expand Up @@ -273,9 +274,13 @@ where
}
};

// Search potential parents to build upon
let mut potential_parents =
match cumulus_client_consensus_common::find_potential_parents::<Block>(
// Find the best parent to build upon. The new
// `find_parent_for_building` returns the included block plus the
// deepest descendant that fits within the ancestry lookback (the
// stable2603 replacement for the old `find_potential_parents`
// + manual depth filtering).
let (included_header, initial_parent_header) =
match cumulus_client_consensus_common::find_parent_for_building::<Block>(
ParentSearchParams {
relay_parent,
para_id: params.para_id,
Expand All @@ -284,8 +289,6 @@ where
&params.relay_client,
)
.await,
max_depth: PARENT_SEARCH_DEPTH,
ignore_alternative_branches: true,
},
&*params.para_backend,
&params.relay_client,
Expand All @@ -302,39 +305,30 @@ where

continue;
}
Ok(potential_parents) => potential_parents,
Ok(None) => continue,
Ok(Some(result)) => (result.included_header, result.best_parent_header),
};

// Search the first potential parent parablock that is already included in the relay
let included_block = match potential_parents.iter().find(|x| x.depth == 0) {
None => continue, // also serves as an `is_empty` check.
Some(b) => b.hash,
};
let included_block = included_header.hash();

// At this point, we found a potential parent parablock that is already included in the relay.
//
// Sort by depth, ascending, to choose the longest chain. If the longest chain has space,
// build upon that. Otherwise, don't build at all.
potential_parents.sort_by_key(|a| a.depth);
let initial_parent = match potential_parents.pop() {
None => continue,
Some(initial_parent) => initial_parent,
};
// Distance from included block to best parent (unincluded segment length).
let initial_parent_depth = (*initial_parent_header.number())
.saturating_sub(*included_header.number());

// Build in a loop until not allowed. Note that the selected collators can change
// at any block, so we need to re-claim our slot every time.
// This needs to change to support elastic scaling, but for continuously
// scheduled chains this ensures that the backlog will grow steadily.
let mut parent_hash = initial_parent.hash;
let mut parent_header = initial_parent.header;
let mut parent_hash = initial_parent_header.hash();
let mut parent_header = initial_parent_header;
let overseer_handle = &mut params.overseer_handle;

// Proactively connect to backing groups. This is especially important for single
// collator setups where we always own the slot and thus would never trigger
// pre-connection through the normal code path.
connection_helper.update(slot_now).await;

for n_built in 0..2 {
for n_built in 0..2u32 {
// Ask to the runtime if we are authorized to create a new parablock on top of this parent.
// (This will claim the slot internally)
let para_client = &*params.para_client;
Expand All @@ -358,7 +352,7 @@ where
target: crate::LOG_TARGET,
?slot_now,
?relay_parent,
unincluded_segment_len = initial_parent.depth + n_built,
unincluded_segment_len = ?initial_parent_depth.saturating_add(n_built.into()),
"Slot claimed. Building"
);

Expand Down Expand Up @@ -475,6 +469,10 @@ where
validation_code_hash,
result_sender: None,
core_index,
// `None` keeps V2 candidate-descriptor semantics
// (the relay parent is used as the scheduling
// parent). Set to `Some(hash)` to opt into V3.
scheduling_parent: None,
},
),
"SubmitCollation",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ use parity_scale_codec::{Codec, Encode};

use cumulus_client_collator::service::ServiceInterface as CollatorServiceInterface;
use cumulus_client_consensus_common::{self as consensus_common, ParachainBlockImportMarker};
use cumulus_client_consensus_proposer::ProposerInterface;
use crate::ProposerInterface;
use cumulus_relay_chain_interface::RelayChainInterface;
use sp_consensus_slots::SlotDuration;
use sp_runtime::SaturatedConversion;
use sp_runtime::{SaturatedConversion, Saturating};

use super::CollatorMessage;
use crate::{
Expand Down Expand Up @@ -250,15 +250,19 @@ where
let relay_parent = rp_data.relay_parent().hash();
let relay_parent_header = rp_data.relay_parent().clone();

let Some((included_header, parent)) =
let Some((included_header, parent_header)) =
crate::collators::find_parent(relay_parent, para_id, &*para_backend, &relay_client)
.await
else {
continue;
};

let parent_hash = parent.hash;
let parent_header = &parent.header;
let parent_hash = parent_header.hash();
let parent_header = &parent_header;
// Distance from included block to best parent (unincluded segment length).
let unincluded_segment_len = parent_header
.number()
.saturating_sub(*included_header.number());

// Retrieve the core.
let core = match determine_core(
Expand Down Expand Up @@ -352,7 +356,7 @@ where
None => {
tracing::debug!(
target: crate::LOG_TARGET,
unincluded_segment_len = parent.depth,
unincluded_segment_len = ?unincluded_segment_len,
relay_parent = ?relay_parent,
relay_parent_num = %relay_parent_header.number(),
included_hash = ?included_header_hash,
Expand All @@ -367,7 +371,7 @@ where

tracing::debug!(
target: crate::LOG_TARGET,
unincluded_segment_len = parent.depth,
unincluded_segment_len = ?unincluded_segment_len,
relay_parent = %relay_parent,
relay_parent_num = %relay_parent_header.number(),
relay_parent_offset,
Expand Down Expand Up @@ -438,7 +442,7 @@ where
let Some(adjusted_authoring_duration) = adjusted_authoring_duration else {
tracing::debug!(
target: crate::LOG_TARGET,
unincluded_segment_len = parent.depth,
unincluded_segment_len = ?unincluded_segment_len,
relay_parent = ?relay_parent,
relay_parent_num = %relay_parent_header.number(),
included_hash = ?included_header_hash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ async fn handle_collation_message<Block: BlockT, RClient: RelayChainInterface +
validation_code_hash,
core_index,
result_sender: None,
// `None` keeps V2 candidate-descriptor semantics; set to
// `Some(hash)` to opt into V3 with a custom scheduling parent.
scheduling_parent: None,
}),
"SubmitCollation",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub use block_import::{SlotBasedBlockImport, SlotBasedBlockImportHandle};
use consensus_common::ParachainCandidate;
use cumulus_client_collator::service::ServiceInterface as CollatorServiceInterface;
use cumulus_client_consensus_common::{self as consensus_common, ParachainBlockImportMarker};
use cumulus_client_consensus_proposer::ProposerInterface;
use crate::ProposerInterface;
use cumulus_primitives_core::RelayParentOffsetApi;
use cumulus_relay_chain_interface::RelayChainInterface;
use futures::FutureExt;
Expand Down
2 changes: 2 additions & 0 deletions client/consensus/nimbus-consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ pub mod collators;

mod import_queue;
mod manual_seal;
mod proposer;

pub use import_queue::import_queue;
pub use manual_seal::NimbusManualSealConsensusDataProvider;
pub use proposer::{Error as ProposerError, ProposerInterface};

use cumulus_primitives_core::{relay_chain::Header as PHeader, PersistedValidationData};
use log::{info, warn};
Expand Down
Loading
Loading