From 7f0bb12fbd904aae267079b1d0bad275159a0523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 13 Nov 2025 21:11:00 +0100 Subject: [PATCH] Rename `SlotSchedule` to `TargetBlockRate` This renames the `SlotSchedule` runtime api to `TargetBlockRate`. It also changes the signature to only returning the target block rate. As discussed at the retreat, we don't need the block time returned as part of this runtime api. --- .../assets/asset-hub-rococo/src/lib.rs | 6 +- .../assets/asset-hub-westend/src/lib.rs | 6 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 6 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 6 +- .../collectives-westend/src/lib.rs | 6 +- .../coretime/coretime-rococo/src/lib.rs | 6 +- .../coretime/coretime-westend/src/lib.rs | 6 +- .../glutton/glutton-westend/src/lib.rs | 6 +- .../runtimes/people/people-rococo/src/lib.rs | 6 +- .../runtimes/people/people-westend/src/lib.rs | 6 +- .../lib/src/fake_runtime_api/utils.rs | 4 +- cumulus/primitives/core/src/lib.rs | 162 ++---------------- cumulus/test/runtime/src/lib.rs | 6 +- 13 files changed, 46 insertions(+), 186 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 747842c2254e9..bde01f335b19c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -2069,9 +2069,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index e00258f7a4f2b..6ee07f6fe0a8a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1755,9 +1755,9 @@ pallet_revive::impl_runtime_apis_plus_revive_traits!( } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 68cfd2b6c21ac..7dbcbb0975eb4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -1577,9 +1577,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index cc8449131c343..6e55033bc20ba 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -1439,9 +1439,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index ac168d694e77f..85521a8db084e 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -1347,9 +1347,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index aea5eff47a9b9..8e59eda372c01 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -1187,9 +1187,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 17b1023cc07d8..671ccb8c9c0d5 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -1204,9 +1204,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } } diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 39c0c57820b69..ac563cb4912dd 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -510,9 +510,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 5b3f7ba903c71..dec1be2786bd2 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -1118,9 +1118,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index bee243cca5982..ed613f38589b8 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -1136,9 +1136,9 @@ impl_runtime_apis! { } } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_num_cores: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } diff --git a/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs index 085f7ff3e5027..db4c88033da9b 100644 --- a/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs +++ b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs @@ -242,8 +242,8 @@ macro_rules! impl_node_runtime_apis { } } - impl cumulus_primitives_core::SlotSchedule<$block> for $runtime { - fn next_slot_schedule(_: u32) -> cumulus_primitives_core::NextSlotSchedule { + impl cumulus_primitives_core::TargetBlockRate<$block> for $runtime { + fn target_block_rate() -> u32 { unimplemented!() } } diff --git a/cumulus/primitives/core/src/lib.rs b/cumulus/primitives/core/src/lib.rs index e06a92dcef8bc..9fc245aab43f7 100644 --- a/cumulus/primitives/core/src/lib.rs +++ b/cumulus/primitives/core/src/lib.rs @@ -22,7 +22,6 @@ extern crate alloc; use alloc::vec::Vec; use codec::{Compact, Decode, DecodeAll, DecodeWithMemTracking, Encode, MaxEncodedLen}; -use core::time::Duration; use polkadot_parachain_primitives::primitives::HeadData; use scale_info::TypeInfo; use sp_runtime::RuntimeDebug; @@ -467,46 +466,6 @@ pub struct CollationInfo { pub head_data: HeadData, } -/// The schedule for the next relay chain slot. -/// -/// Returns the maximum number of parachain blocks to produce and the block time per block to use. -#[derive(Clone, Debug, codec::Decode, codec::Encode, PartialEq, TypeInfo)] -pub struct NextSlotSchedule { - /// The maximum number of blocks to produce in the relay chain slot. - /// - /// The node is free to produce less blocks. - pub number_of_blocks: u32, - /// The target block time in wall clock time for each block. - /// - /// The maximum should be [`REF_TIME_PER_CORE_IN_SECS`] or otherwise blocks may fail to - /// validate on the relay chain. - pub block_time: Duration, -} - -impl NextSlotSchedule { - /// Creates a schedule that produces one block, occupying an entire core. - pub fn one_block_using_one_core() -> Self { - Self { number_of_blocks: 1, block_time: Duration::from_secs(REF_TIME_PER_CORE_IN_SECS) } - } - - /// A schedule that maps `x` blocks onto `y` cores. - pub fn x_blocks_using_y_cores(blocks: u32, cores: u32) -> Self { - let ref_time_per_core = Duration::from_secs(REF_TIME_PER_CORE_IN_SECS); - - if blocks == 0 || cores == 0 { - return Self { number_of_blocks: 0, block_time: Duration::from_secs(0) } - } - - // In wall clock time we can not go above `6s` (relay chain slot duration), so we need to - // cap there. - let block_time = (ref_time_per_core * cores).min(Duration::from_secs(6)) / blocks; - // One block can at max occupy one core. - let block_time = block_time.min(ref_time_per_core); - - Self { block_time, number_of_blocks: blocks } - } -} - sp_api::decl_runtime_apis! { /// Runtime api to collect information about a collation. /// @@ -540,117 +499,18 @@ sp_api::decl_runtime_apis! { fn relay_parent_offset() -> u32; } - /// API for parachain slot scheduling. + /// API for parachain target block rate. /// - /// This runtime API allows the parachain runtime to communicate the block interval - /// to the node side. The node will call this API every relay chain slot (~6 seconds) - /// to get the scheduled parachain block interval. - pub trait SlotSchedule { - /// Get the block production schedule for the next relay chain slot. - /// - /// - `num_cores`: The number of cores assigned to this parachain + /// This runtime API allows the parachain runtime to communicate the target block rate + /// to the node side. The target block rate is always valid for the next relay chain slot. + /// + /// The runtime can not enforce this target block rate. It only acts as a maximum, but not more. + /// In the end it depends on the collator how many blocks will be produced. If there are no cores + /// available or the collator is offline, no blocks at all will be produced. + pub trait TargetBlockRate { + /// Get the target block rate for this parachain. /// - /// Returns a [`NextSlotSchedule`]. - fn next_slot_schedule(num_cores: u32) -> NextSlotSchedule; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn one_block_using_one_core_works() { - let schedule = NextSlotSchedule::one_block_using_one_core(); - assert_eq!(schedule.number_of_blocks, 1); - assert_eq!(schedule.block_time, Duration::from_secs(REF_TIME_PER_CORE_IN_SECS)); - } - - #[test] - fn x_blocks_using_y_cores_basic_functionality() { - // 2 blocks using 1 core: each block gets 1 second - let schedule = NextSlotSchedule::x_blocks_using_y_cores(2, 1); - assert_eq!(schedule.number_of_blocks, 2); - assert_eq!(schedule.block_time, Duration::from_secs(1)); - - // 4 blocks using 2 cores: each block gets 1 second - let schedule = NextSlotSchedule::x_blocks_using_y_cores(4, 2); - assert_eq!(schedule.number_of_blocks, 4); - assert_eq!(schedule.block_time, Duration::from_secs(1)); - - // 2 blocks using 2 cores: each block gets 2 seconds (max) - let schedule = NextSlotSchedule::x_blocks_using_y_cores(2, 2); - assert_eq!(schedule.number_of_blocks, 2); - assert_eq!(schedule.block_time, Duration::from_secs(2)); - } - - #[test] - fn x_blocks_using_y_cores_caps_block_time_at_ref_time() { - let schedule = NextSlotSchedule::x_blocks_using_y_cores(2, 10); - assert_eq!(schedule.number_of_blocks, 2); - assert_eq!(schedule.block_time, Duration::from_secs(REF_TIME_PER_CORE_IN_SECS)); - - let schedule = NextSlotSchedule::x_blocks_using_y_cores(1, 5); - assert_eq!(schedule.number_of_blocks, 1); - assert_eq!(schedule.block_time, Duration::from_secs(REF_TIME_PER_CORE_IN_SECS)); - } - - #[test] - fn x_blocks_using_y_cores_edge_cases() { - // Zero blocks - let schedule = NextSlotSchedule::x_blocks_using_y_cores(0, 1); - assert_eq!(schedule.number_of_blocks, 0); - assert_eq!(schedule.block_time, Duration::from_secs(0)); - - // Zero cores (should not panic, though not realistic) - let schedule = NextSlotSchedule::x_blocks_using_y_cores(2, 0); - assert_eq!(schedule.number_of_blocks, 0); - assert_eq!(schedule.block_time, Duration::from_secs(0)); - - // Large numbers - let schedule = NextSlotSchedule::x_blocks_using_y_cores(100, 50); - assert_eq!(schedule.number_of_blocks, 100); - assert_eq!(schedule.block_time, Duration::from_millis(60)); - } - - #[test] - fn x_blocks_using_y_cores_various_ratios() { - // 6 blocks, 3 cores: each block gets 1 second - let schedule = NextSlotSchedule::x_blocks_using_y_cores(6, 3); - assert_eq!(schedule.number_of_blocks, 6); - assert_eq!(schedule.block_time, Duration::from_secs(1)); - - // 8 blocks, 4 cores: each block gets 1 second - let schedule = NextSlotSchedule::x_blocks_using_y_cores(8, 4); - assert_eq!(schedule.number_of_blocks, 8); - assert_eq!(schedule.block_time, Duration::from_millis(750)); - - // 4 blocks, 8 cores: each block gets 2 seconds (capped) - let schedule = NextSlotSchedule::x_blocks_using_y_cores(4, 8); - assert_eq!(schedule.number_of_blocks, 4); - assert_eq!(schedule.block_time, Duration::from_millis(1500)); - - // 10 blocks, 2 cores: each block gets `400ms` - let schedule = NextSlotSchedule::x_blocks_using_y_cores(10, 2); - assert_eq!(schedule.number_of_blocks, 10); - assert_eq!(schedule.block_time, Duration::from_millis(400)); - } - - #[test] - fn x_blocks_using_y_cores_fractional_seconds() { - // 6 blocks, 1 core: each block gets `333.333... ms (2000ms / 6)` - let schedule = NextSlotSchedule::x_blocks_using_y_cores(6, 1); - assert_eq!(schedule.number_of_blocks, 6); - assert_eq!(schedule.block_time, Duration::from_nanos(333_333_333)); - - // 8 blocks, 1 core: each block gets `250ms` - let schedule = NextSlotSchedule::x_blocks_using_y_cores(8, 1); - assert_eq!(schedule.number_of_blocks, 8); - assert_eq!(schedule.block_time, Duration::from_millis(250)); - - // 12 blocks, 1 core: each block gets `~166.666ms` - let schedule = NextSlotSchedule::x_blocks_using_y_cores(12, 1); - assert_eq!(schedule.number_of_blocks, 12); - assert_eq!(schedule.block_time, Duration::from_nanos(166_666_666)); + /// Returns the target number of blocks per relay chain slot. + fn target_block_rate() -> u32; } } diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index feb5d2cb8199b..75859680b5199 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -631,9 +631,9 @@ impl_runtime_apis! { } - impl cumulus_primitives_core::SlotSchedule for Runtime { - fn next_slot_schedule(_: u32) -> cumulus_primitives_core::NextSlotSchedule { - cumulus_primitives_core::NextSlotSchedule::one_block_using_one_core() + impl cumulus_primitives_core::TargetBlockRate for Runtime { + fn target_block_rate() -> u32 { + 1 } } }