referrerpolicy=no-referrer-when-downgrade

cumulus_client_consensus_aura/collators/slot_based/
mod.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5// Cumulus is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9
10// Cumulus is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with Cumulus. If not, see <https://www.gnu.org/licenses/>.
17
18//! # Architecture Overview
19//!
20//! The block building mechanism operates through two coordinated tasks:
21//!
22//! 1. **Block Builder Task**: Orchestrates the timing and execution of parachain block production
23//! 2. **Collator Task**: Processes built blocks into collations for relay chain submission
24//!
25//! # Block Builder Task Details
26//!
27//! The block builder task manages block production timing and execution through an iterative
28//! process:
29//!
30//! 1. Awaits the next production signal from the internal timer
31//! 2. Retrieves the current best relay chain block and identifies a valid parent block (see
32//!    [find_parent_for_building][cumulus_client_consensus_common::find_parent_for_building] for
33//!    parent selection criteria)
34//! 3. Validates that:
35//!    - The parachain has an assigned core on the relay chain
36//!    - No block has been previously built on the target core
37//! 4. Executes block building and import operations
38//! 5. Transmits the completed block to the collator task
39//!
40//! # Block Production Timing
41//!
42//! When a block is produced is determined by the following parameters:
43//!
44//! - Parachain slot duration
45//! - Number of assigned parachain cores
46//! - The `target_block_rate` runtime API, which determines how many blocks to produce per relay
47//!   chain slot. When this API is unavailable, the block builder falls back to one block per core.
48//!   When the target exceeds the number of cores, multiple blocks are bundled per core.
49//!
50//! ## Timing Examples
51//!
52//! The following table demonstrates various timing configurations and their effects. The "AURA
53//! Slot" column shows which author is responsible for the block.
54//!
55//! | Slot Duration (ms) | Cores | Production Attempts (ms) | AURA Slot  |
56//! |-------------------|--------|-------------------------|------------|
57//! | 2000              | 3      | 0, 2000, 4000, 6000    | 0, 1, 2, 3 |
58//! | 6000              | 1      | 0, 6000, 12000, 18000  | 0, 1, 2, 3 |
59//! | 6000              | 3      | 0, 2000, 4000, 6000    | 0, 0, 0, 1 |
60//! | 12000             | 1      | 0, 6000, 12000, 18000  | 0, 0, 1, 1 |
61//! | 12000             | 3      | 0, 2000, 4000, 6000    | 0, 0, 0, 0 |
62//!
63//! # Collator Task Details
64//!
65//! The collator task receives built blocks from the block builder task and performs two primary
66//! functions:
67//!
68//! 1. Block compression
69//! 2. Submission to the collation-generation subsystem
70
71use self::{block_builder_task::run_block_builder, collation_task::run_collation_task};
72pub use block_import::{SlotBasedBlockImport, SlotBasedBlockImportHandle};
73use codec::Codec;
74use cumulus_client_collator::service::ServiceInterface as CollatorServiceInterface;
75use cumulus_client_consensus_common::{self as consensus_common, ParachainBlockImportMarker};
76use cumulus_client_proof_size_recording::register_proof_size_recording_cleanup;
77use cumulus_primitives_aura::AuraUnincludedSegmentApi;
78use cumulus_primitives_core::{
79	KeyToIncludeInRelayProof, RelayParentOffsetApi, SchedulingV3EnabledApi, TargetBlockRate,
80};
81use cumulus_relay_chain_interface::RelayChainInterface;
82use futures::FutureExt;
83use polkadot_primitives::{CollatorPair, Id as ParaId};
84use sc_client_api::{
85	backend::AuxStore, client::PreCommitActions, BlockBackend, BlockOf, BlockchainEvents,
86	UsageProvider,
87};
88use sc_consensus::BlockImport;
89use sc_network_types::PeerId;
90use sc_utils::mpsc::tracing_unbounded;
91use sp_api::ProvideRuntimeApi;
92use sp_application_crypto::AppPublic;
93use sp_block_builder::BlockBuilder;
94use sp_blockchain::HeaderBackend;
95use sp_consensus::Environment;
96use sp_consensus_aura::AuraApi;
97use sp_core::{crypto::Pair, traits::SpawnEssentialNamed};
98use sp_inherents::CreateInherentDataProviders;
99use sp_keystore::KeystorePtr;
100use sp_runtime::traits::{Block as BlockT, Member};
101use std::{path::PathBuf, sync::Arc, time::Duration};
102
103mod block_builder_task;
104mod block_import;
105mod collation_task;
106mod message;
107mod relay_chain_data_cache;
108mod resubmission;
109mod resubmittable_segment;
110mod scheduling;
111mod slot_timer;
112
113#[cfg(test)]
114mod tests;
115
116/// Parameters for [`run`].
117pub struct Params<Block, BI, CIDP, Client, Backend, RClient, CHP, Proposer, CS, Spawner> {
118	/// Inherent data providers. Only non-consensus inherent data should be provided, i.e.
119	/// the timestamp, slot, and paras inherents should be omitted, as they are set by this
120	/// collator.
121	pub create_inherent_data_providers: CIDP,
122	/// Used to actually import blocks.
123	pub block_import: BI,
124	/// The underlying para client.
125	pub para_client: Arc<Client>,
126	/// The para client's backend, used to access the database.
127	pub para_backend: Arc<Backend>,
128	/// A handle to the relay-chain client.
129	pub relay_client: RClient,
130	/// A validation code hash provider, used to get the current validation code hash.
131	pub code_hash_provider: CHP,
132	/// The underlying keystore, which should contain Aura consensus keys.
133	pub keystore: KeystorePtr,
134	/// The collator key used to sign collations before submitting to validators.
135	pub collator_key: CollatorPair,
136	/// The collator network peer id.
137	pub collator_peer_id: PeerId,
138	/// The para's ID.
139	pub para_id: ParaId,
140	/// The proposer for building blocks.
141	pub proposer: Proposer,
142	/// The generic collator service used to plug into this consensus engine.
143	pub collator_service: CS,
144	/// Whether we should reinitialize the collator config (i.e. we are transitioning to aura).
145	pub reinitialize: bool,
146	/// Offset slots by a fixed duration. This can be used to create more preferrable authoring
147	/// timings.
148	pub slot_offset: Duration,
149	/// The handle returned by [`SlotBasedBlockImport`].
150	pub block_import_handle: SlotBasedBlockImportHandle<Block>,
151	/// Spawner for spawning futures.
152	pub spawner: Spawner,
153	/// Slot duration of the relay chain
154	pub relay_chain_slot_duration: Duration,
155	/// When set, the collator will export every produced `POV` to this folder.
156	pub export_pov: Option<PathBuf>,
157	/// The maximum percentage of the maximum PoV size that the collator can use.
158	/// It will be removed once <https://github.com/paritytech/polkadot-sdk/issues/6020> is fixed.
159	pub max_pov_percentage: Option<u32>,
160}
161
162/// Run aura-based block building and collation task.
163pub fn run<Block, P, BI, CIDP, Client, Backend, RClient, CHP, Proposer, CS, Spawner>(
164	params: Params<Block, BI, CIDP, Client, Backend, RClient, CHP, Proposer, CS, Spawner>,
165) where
166	Block: BlockT,
167	Client: ProvideRuntimeApi<Block>
168		+ BlockOf
169		+ AuxStore
170		+ HeaderBackend<Block>
171		+ BlockBackend<Block>
172		+ UsageProvider<Block>
173		+ PreCommitActions<Block>
174		+ BlockchainEvents<Block>
175		+ Send
176		+ Sync
177		+ 'static,
178	Client::Api: AuraApi<Block, P::Public>
179		+ AuraUnincludedSegmentApi<Block>
180		+ RelayParentOffsetApi<Block>
181		+ TargetBlockRate<Block>
182		+ BlockBuilder<Block>
183		+ KeyToIncludeInRelayProof<Block>
184		+ SchedulingV3EnabledApi<Block>,
185	Backend: sc_client_api::Backend<Block> + 'static,
186	RClient: RelayChainInterface + Clone + 'static,
187	CIDP: CreateInherentDataProviders<Block, ()> + 'static,
188	CIDP::InherentDataProviders: Send,
189	BI: BlockImport<Block> + ParachainBlockImportMarker + Send + Sync + 'static,
190	Proposer: Environment<Block> + Send + Sync + 'static,
191	CS: CollatorServiceInterface<Block> + Send + Sync + Clone + 'static,
192	CHP: consensus_common::ValidationCodeHashProvider<Block::Hash> + Send + Sync + 'static,
193	P: Pair + Send + Sync + 'static,
194	P::Public: AppPublic + Member + Codec,
195	P::Signature: TryFrom<Vec<u8>> + Member + Codec,
196	Spawner: SpawnEssentialNamed + Clone + 'static,
197{
198	let Params {
199		create_inherent_data_providers,
200		block_import,
201		para_client,
202		para_backend,
203		relay_client,
204		code_hash_provider,
205		keystore,
206		collator_key,
207		collator_peer_id,
208		para_id,
209		proposer,
210		collator_service,
211		reinitialize,
212		slot_offset,
213		block_import_handle,
214		spawner,
215		export_pov,
216		relay_chain_slot_duration,
217		max_pov_percentage,
218	} = params;
219
220	// Initialize proof size recording cleanup
221	register_proof_size_recording_cleanup(para_client.clone());
222
223	let resubmission_backfill_fut = resubmission::run_resubmission_backfill(
224		block_import_handle,
225		relay_client.clone(),
226		para_client.clone(),
227		para_id,
228	);
229
230	let (tx, rx) = tracing_unbounded("mpsc_builder_to_collator", 100);
231	let collator_task_params = collation_task::Params {
232		relay_client: relay_client.clone(),
233		collator_key,
234		para_id,
235		reinitialize,
236		collator_service: collator_service.clone(),
237		collator_receiver: rx,
238		export_pov,
239	};
240
241	let collation_task_fut = run_collation_task::<Block, _, _>(collator_task_params);
242
243	let block_builder_params = block_builder_task::BuilderTaskParams {
244		create_inherent_data_providers,
245		block_import,
246		para_client,
247		para_backend,
248		relay_client,
249		code_hash_provider,
250		keystore,
251		collator_peer_id,
252		para_id,
253		proposer,
254		collator_service,
255		collator_sender: tx,
256		relay_chain_slot_duration,
257		slot_offset,
258		max_pov_percentage,
259	};
260
261	let block_builder_fut =
262		run_block_builder::<Block, P, _, _, _, _, _, _, _, _>(block_builder_params);
263
264	spawner.spawn_essential_blocking(
265		"slot-based-block-builder",
266		Some("slot-based-collator"),
267		block_builder_fut.boxed(),
268	);
269	spawner.spawn_essential_blocking(
270		"slot-based-collation",
271		Some("slot-based-collator"),
272		collation_task_fut.boxed(),
273	);
274	spawner.spawn_essential_blocking(
275		"slot-based-resubmission-backfill",
276		Some("slot-based-collator"),
277		resubmission_backfill_fut.boxed(),
278	);
279}