From 4b220b9be81b7dd9f9f93e0bff14076f089e4db7 Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Wed, 10 Sep 2025 19:53:52 +0300 Subject: [PATCH] Update elastic scaling documentation (#9677) Closes https://github.com/paritytech/polkadot-sdk/pull/9677 Add docs and remove MVP. --------- Signed-off-by: Andrei Sandu Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Alexander Cyon Co-authored-by: Sebastian Kunert Co-authored-by: Alin Dima (cherry picked from commit 7af791f7594c61a97c31841c681666461e300563) --- docs/sdk/src/guides/enable_elastic_scaling.rs | 165 ++++++++++++++++++ .../src/guides/enable_elastic_scaling_mvp.rs | 144 --------------- docs/sdk/src/guides/mod.rs | 4 +- prdoc/pr_9677.prdoc | 7 + 4 files changed, 174 insertions(+), 146 deletions(-) create mode 100644 docs/sdk/src/guides/enable_elastic_scaling.rs delete mode 100644 docs/sdk/src/guides/enable_elastic_scaling_mvp.rs create mode 100644 prdoc/pr_9677.prdoc diff --git a/docs/sdk/src/guides/enable_elastic_scaling.rs b/docs/sdk/src/guides/enable_elastic_scaling.rs new file mode 100644 index 0000000000000..82e5f1189e273 --- /dev/null +++ b/docs/sdk/src/guides/enable_elastic_scaling.rs @@ -0,0 +1,165 @@ +//! # Enable elastic scaling for a parachain +//! +//!
This guide assumes full familiarity with Asynchronous Backing and its +//! terminology, as defined in the Polkadot SDK Docs. +//!
+//! +//! ## Quick introduction to Elastic Scaling +//! +//! [Elastic scaling](https://www.parity.io/blog/polkadot-web3-cloud) is a feature that enables parachains (rollups) to use multiple cores. +//! Parachains can adjust their usage of core resources on the fly to increase TPS and decrease +//! latency. +//! +//! ### When do you need Elastic Scaling? +//! +//! Depending on their use case, applications might have an increased need for the following: +//! - compute (CPU weight) +//! - bandwidth (proof size) +//! - lower latency (block time) +//! +//! ### High throughput (TPS) and lower latency +//! +//! If the main bottleneck is the CPU, then your parachain needs to maximize the compute usage of +//! each core while also achieving a lower latency. +//! 3 cores provide the best balance between CPU, bandwidth and latency: up to 6s of execution, +//! 5MB/s of DA bandwidth and fast block time of just 2 seconds. +//! +//! ### High bandwidth +//! +//! Useful for applications that are bottlenecked by bandwidth. +//! By using 6 cores, applications can make use of up to 6s of compute, 10MB/s of bandwidth +//! while also achieving 1 second block times. +//! +//! ### Ultra low latency +//! +//! When latency is the primary requirement, Elastic scaling is currently the only solution. The +//! caveat is the efficiency of core time usage decreases as more cores are used. +//! +//! For example, using 12 cores enables fast transaction confirmations with 500ms blocks and up to +//! 20 MB/s of DA bandwidth. +//! +//! ## Dependencies +//! +//! Prerequisites: Polkadot-SDK `2509` or newer. +//! +//! To ensure the security and reliability of your chain when using this feature you need the +//! following: +//! - An omni-node based collator. This has already become the default choice for collators. +//! - UMP signal support. +//! [RFC103](https://github.com/polkadot-fellows/RFCs/blob/main/text/0103-introduce-core-index-commitment.md). +//! This is mandatory protection against PoV replay attacks. +//! - Enabling the relay parent offset feature. This is required to ensure the parachain block times +//! and transaction in-block confidence are not negatively affected by relay chain forks. Read +//! [`crate::guides::handling_parachain_forks`] for more information. +//! - Block production configuration adjustments. +//! +//! ### Upgrade to Polkadot Omni node +//! +//! Your collators need to run `polkadot-parachain` or `polkadot-omni-node` with the `--authoring +//! slot-based` CLI argument. +//! To avoid potential issues and get best performance it is recommeneded to always run the +//! latest release on all of the collators. +//! +//! Further information about omni-node and how to upgrade is available: +//! - [high level docs](https://docs.polkadot.com/develop/toolkit/parachains/polkadot-omni-node/) +//! - [`crate::reference_docs::omni_node`] +//! +//! ### Enable UMP signals +//! +//! The only required change for the runtime is enabling the `experimental-ump-signals` feature of +//! the `parachain-system` pallet: +//! `cumulus-pallet-parachain-system = { workspace = true, features = ["experimental-ump-signals"] +//! }` +//! +//! You can find more technical details about UMP signals and their usage for elastic scaling +//! [here](https://github.com/polkadot-fellows/RFCs/blob/main/text/0103-introduce-core-index-commitment.md). +//! +//! ### Enable the relay parent offset feature +//! +//! It is recommended to use an offset of `1`, which is sufficient to eliminate any issues +//! with relay chain forks. +//! +//! Configure the relay parent offset like this: +//! ```ignore +//! /// Build with an offset of 1 behind the relay chain best block. +//! const RELAY_PARENT_OFFSET: u32 = 1; +//! +//! impl cumulus_pallet_parachain_system::Config for Runtime { +//! // ... +//! type RelayParentOffset = ConstU32; +//! } +//! ``` +//! +//! Implement the runtime API to retrieve the offset on the client side. +//! ```ignore +//! impl cumulus_primitives_core::RelayParentOffsetApi for Runtime { +//! fn relay_parent_offset() -> u32 { +//! RELAY_PARENT_OFFSET +//! } +//! } +//! ``` +//! +//! ### Block production configuration +//! +//! This configuration directly controls the minimum block time and maximum number of cores +//! the parachain can use. +//! +//! Example configuration for a 3 core parachain: +//! ```ignore +//! /// The upper limit of how many parachain blocks are processed by the relay chain per +//! /// parent. Limits the number of blocks authored per slot. This determines the minimum +//! /// block time of the parachain: +//! /// `RELAY_CHAIN_SLOT_DURATION_MILLIS/BLOCK_PROCESSING_VELOCITY` +//! const BLOCK_PROCESSING_VELOCITY: u32 = 3; +//! +//! /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included +//! /// into the relay chain. +//! const UNINCLUDED_SEGMENT_CAPACITY: u32 = (2 + RELAY_PARENT_OFFSET) * +//! BLOCK_PROCESSING_VELOCITY + 1; +//! +//! /// Relay chain slot duration, in milliseconds. +//! const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; +//! +//! type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< +//! Runtime, +//! RELAY_CHAIN_SLOT_DURATION_MILLIS, +//! BLOCK_PROCESSING_VELOCITY, +//! UNINCLUDED_SEGMENT_CAPACITY, +//! >; +//! +//! ``` +//! +//! ## Current limitations +//! +//! ### Maximum execution time per relay chain block. +//! +//! Since parachain block authoring is sequential, the next block can only be built after +//! the previous one has been imported. +//! At present, a core allows up to 2 seconds of execution per relay chain block. +//! +//! If we assume a 6s parachain slot, and each block takes the full 2 seconds to execute, +//! the parachain will not be able to fully utilize the compute resources of all 3 cores. +//! +//! If the collator hardware is faster, it can author and import full blocks more quickly, +//! making it possible to utilize even more than 3 cores efficiently. +//! +//! #### Why? +//! +//! Within a 6-second parachain slot, collators can author multiple parachain blocks. +//! Before building the first block in a slot, the new block author must import the last +//! block produced by the previous author. +//! If the import of the last block is not completed before the next relay chain slot starts, +//! the new author will build on its parent (assuming it was imported). This will create a fork +//! which degrades the parachain block confidence and block times. +//! +//! This means that, on reference hardware, a parachain with a slot time of 6s can +//! effectively utilize up to 4 seconds of execution per relay chain block, because it needs to +//! ensure the next block author has enough time to import the last block. +//! Hardware with higher single-core performance can enable a parachain to fully utilize more +//! cores. +//! +//! ### Fixed factor scaling. +//! +//! For true elasticity, a parachain needs to acquire more cores when needed in an automated +//! manner. This functionality is not yet available in the SDK, thus acquiring additional +//! on-demand or bulk cores has to be managed externally. diff --git a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs b/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs deleted file mode 100644 index 40b5f2828e362..0000000000000 --- a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs +++ /dev/null @@ -1,144 +0,0 @@ -//! # Enable elastic scaling MVP for a parachain -//! -//!
This guide assumes full familiarity with Asynchronous Backing and its -//! terminology, as defined in the Polkadot SDK Docs. -//! Furthermore, the parachain should have already been upgraded according to the guide.
-//! -//! ## Quick introduction to elastic scaling -//! -//! [Elastic scaling](https://polkadot.com/blog/elastic-scaling-streamling-growth-on-polkadot) -//! is a feature that will enable parachains to seamlessly scale up/down the number of used cores. -//! This can be desirable in order to increase the compute or storage throughput of a parachain or -//! to lower the latency between a transaction being submitted and it getting built in a parachain -//! block. -//! -//! At present, with Asynchronous Backing enabled, a parachain can only include a block on the relay -//! chain every 6 seconds, irregardless of how many cores the parachain acquires. Elastic scaling -//! builds further on the 10x throughput increase of Async Backing, enabling collators to submit up -//! to 3 parachain blocks per relay chain block, resulting in a further 3x throughput increase. -//! -//! ## Current limitations of the MVP -//! -//! The full implementation of elastic scaling spans across the entire relay/parachain stack and is -//! still [work in progress](https://github.com/paritytech/polkadot-sdk/issues/1829). -//! The MVP is still considered experimental software, so stability is not guaranteed. -//! If you encounter any problems, -//! [please open an issue](https://github.com/paritytech/polkadot-sdk/issues). -//! Below are described the current limitations of the MVP: -//! -//! 1. **Limited core count**. Parachain block authoring is sequential, so the second block will -//! start being built only after the previous block is imported. The current block production is -//! capped at 2 seconds of execution. Therefore, assuming the full 2 seconds are used, a -//! parachain can only utilise at most 3 cores in a relay chain slot of 6 seconds. If the full -//! execution time is not being used, higher core counts can be achieved. -//! 2. **Single collator requirement for consistently scaling beyond a core at full authorship -//! duration of 2 seconds per block.** Using the current implementation with multiple collators -//! adds additional latency to the block production pipeline. Assuming block execution takes -//! about the same as authorship, the additional overhead is equal the duration of the authorship -//! plus the block announcement. Each collator must first import the previous block before -//! authoring a new one, so it is clear that the highest throughput can be achieved using a -//! single collator. Experiments show that the peak performance using more than one collator -//! (measured up to 10 collators) is utilising 2 cores with authorship time of 1.3 seconds per -//! block, which leaves 400ms for networking overhead. This would allow for 2.6 seconds of -//! execution, compared to the 2 seconds async backing enabled. -//! [More experiments](https://github.com/paritytech/polkadot-sdk/issues/4696) are being -//! conducted in this space. -//! 3. **Trusted collator set.** The collator set needs to be trusted until there’s a mitigation -//! that would prevent or deter multiple collators from submitting the same collation to multiple -//! backing groups. A solution is being discussed -//! [here](https://github.com/polkadot-fellows/RFCs/issues/92). -//! 4. **Fixed scaling.** For true elasticity, the parachain must be able to seamlessly acquire or -//! sell coretime as the user demand grows and shrinks over time, in an automated manner. This is -//! currently lacking - a parachain can only scale up or down by “manually” acquiring coretime. -//! This is not in the scope of the relay chain functionality. Parachains can already start -//! implementing such autoscaling, but we aim to provide a framework/examples for developing -//! autoscaling strategies. -//! -//! Another hard limitation that is not envisioned to ever be lifted is that parachains which create -//! forks will generally not be able to utilise the full number of cores they acquire. -//! -//! ## Using elastic scaling MVP -//! -//! ### Prerequisites -//! -//! - Ensure Asynchronous Backing is enabled on the network and you have enabled it on the parachain -//! using [`crate::guides::async_backing_guide`]. -//! - Ensure the `AsyncBackingParams.max_candidate_depth` value is configured to a value that is at -//! least double the maximum targeted parachain velocity. For example, if the parachain will build -//! at most 3 candidates per relay chain block, the `max_candidate_depth` should be at least 6. -//! - Use a trusted single collator for maximum throughput. -//! - Ensure enough coretime is assigned to the parachain. For maximum throughput the upper bound is -//! 3 cores. -//! -//!
Phase 1 is NOT needed if using the polkadot-parachain or -//! polkadot-omni-node binary, or polkadot-omni-node-lib built from the -//! latest polkadot-sdk release! Simply pass the --authoring slot-based -//! ([`polkadot_omni_node_lib::cli::Cli::experimental_use_slot_based`]) parameter to the command -//! line and jump to Phase 2.
-//! -//! The following steps assume using the cumulus parachain template. -//! -//! ### Phase 1 - (For custom parachain node) Update Parachain Node -//! -//! This assumes you are using -//! [the latest parachain template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/parachain). -//! -//! This phase consists of plugging in the new slot-based collator. -//! -//! 1. In `node/src/service.rs` import the slot based collator instead of the lookahead collator. -#![doc = docify::embed!("../../cumulus/polkadot-omni-node/lib/src/nodes/aura.rs", slot_based_colator_import)] -//! -//! 2. In `start_consensus()` -//! - Remove the `overseer_handle` param (also remove the -//! `OverseerHandle` type import if it’s not used elsewhere). -//! - Rename `AuraParams` to `SlotBasedParams`, remove the `overseer_handle` field and add a -//! `slot_offset` field with a value of `Duration::from_secs(1)`. -//! - Replace the single future returned by `aura::run` with the two futures returned by it and -//! spawn them as separate tasks: -#![doc = docify::embed!("../../cumulus/polkadot-omni-node/lib/src/nodes/aura.rs", launch_slot_based_collator)] -//! -//! 3. In `start_parachain_node()` remove the `overseer_handle` param passed to `start_consensus`. -//! -//! ### Phase 2 - Activate fixed factor scaling in the runtime -//! -//! This phase consists of a couple of changes needed to be made to the parachain’s runtime in order -//! to utilise fixed factor scaling. -//! -//! First of all, you need to decide the upper limit to how many parachain blocks you need to -//! produce per relay chain block (in direct correlation with the number of acquired cores). This -//! should be either 1 (no scaling), 2 or 3. This is called the parachain velocity. -//! -//! If you configure a velocity which is different from the number of assigned cores, the measured -//! velocity in practice will be the minimum of these two. -//! -//! The chosen velocity will also be used to compute: -//! - The slot duration, by dividing the 6000 ms duration of the relay chain slot duration by the -//! velocity. -//! - The unincluded segment capacity, by multiplying the velocity with 2 and adding 1 to -//! it. -//! -//! Let’s assume a desired maximum velocity of 3 parachain blocks per relay chain block. The needed -//! changes would all be done in `runtime/src/lib.rs`: -//! -//! 1. Rename `BLOCK_PROCESSING_VELOCITY` to `MAX_BLOCK_PROCESSING_VELOCITY` and increase it to the -//! desired value. In this example, 3. -//! -//! ```ignore -//! const MAX_BLOCK_PROCESSING_VELOCITY: u32 = 3; -//! ``` -//! -//! 2. Set the `MILLISECS_PER_BLOCK` to the desired value. -//! -//! ```ignore -//! const MILLISECS_PER_BLOCK: u32 = -//! RELAY_CHAIN_SLOT_DURATION_MILLIS / MAX_BLOCK_PROCESSING_VELOCITY; -//! ``` -//! Note: for a parachain which measures time in terms of its own block number, changing block -//! time may cause complications, requiring additional changes. See here more information: -//! [`crate::guides::async_backing_guide#timing-by-block-number`]. -//! -//! 3. Increase the `UNINCLUDED_SEGMENT_CAPACITY` to the desired value. -//! -//! ```ignore -//! const UNINCLUDED_SEGMENT_CAPACITY: u32 = 2 * MAX_BLOCK_PROCESSING_VELOCITY + 1; -//! ``` diff --git a/docs/sdk/src/guides/mod.rs b/docs/sdk/src/guides/mod.rs index 156311b94cc12..c75370ba35ec0 100644 --- a/docs/sdk/src/guides/mod.rs +++ b/docs/sdk/src/guides/mod.rs @@ -43,8 +43,8 @@ pub mod async_backing_guide; /// How to enable metadata hash verification in the runtime. pub mod enable_metadata_hash; -/// How to enable elastic scaling MVP on a parachain. -pub mod enable_elastic_scaling_mvp; +/// How to enable elastic scaling on a parachain. +pub mod enable_elastic_scaling; /// How to parameterize parachain forking in relation to relay chain forking. pub mod handling_parachain_forks; diff --git a/prdoc/pr_9677.prdoc b/prdoc/pr_9677.prdoc new file mode 100644 index 0000000000000..973b538b04a46 --- /dev/null +++ b/prdoc/pr_9677.prdoc @@ -0,0 +1,7 @@ +title: 'Update elastic scaling documentation' +doc: +- audience: [Runtime Dev, Node Dev] + description: Updated elastic scaling guide. Removes the guide for the MVP version. +crates: + - name: polkadot-sdk-docs + bump: major