diff --git a/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs b/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs index a473b3bced02..38a4f58e0930 100644 --- a/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs +++ b/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs @@ -369,6 +369,10 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient { async fn node_features(&self, at: Hash) -> Result { Ok(self.rpc_client.parachain_host_node_features(at).await?) } + + async fn bulk_core_count(&self, at: Hash) -> Result { + Ok(self.rpc_client.parachain_host_bulk_core_count(at).await?) + } } #[async_trait::async_trait] diff --git a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs index cc993c6ff9f6..0f60e40ffe2e 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs @@ -607,6 +607,14 @@ impl RelayChainRpcClient { .await } + pub async fn parachain_host_bulk_core_count( + &self, + at: RelayHash + ) -> Result { + self.call_remote_runtime_function("ParachainHost_bulk_core_count", at, None::<()>) + .await + } + pub async fn parachain_host_disabled_validators( &self, at: RelayHash, diff --git a/polkadot/node/core/runtime-api/src/cache.rs b/polkadot/node/core/runtime-api/src/cache.rs index 8a7a3dc08b81..dadd56266bad 100644 --- a/polkadot/node/core/runtime-api/src/cache.rs +++ b/polkadot/node/core/runtime-api/src/cache.rs @@ -68,6 +68,7 @@ pub(crate) struct RequestResultCache { para_backing_state: LruMap<(Hash, ParaId), Option>, async_backing_params: LruMap, node_features: LruMap, + bulk_core_count: LruMap, } impl Default for RequestResultCache { @@ -102,6 +103,7 @@ impl Default for RequestResultCache { para_backing_state: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), async_backing_params: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), node_features: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), + bulk_core_count: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), } } } @@ -507,6 +509,21 @@ impl RequestResultCache { ) { self.async_backing_params.insert(key, value); } + + pub(crate) fn bulk_core_count( + &mut self, + session_index: SessionIndex, + ) -> Option<&u16> { + self.bulk_core_count.get(&session_index).map(|v| &*v) + } + + pub(crate) fn cache_bulk_core_count( + &mut self, + session_index: SessionIndex, + value: u16, + ) { + self.bulk_core_count.insert(session_index, value); + } } pub(crate) enum RequestResult { @@ -558,4 +575,5 @@ pub(crate) enum RequestResult { ParaBackingState(Hash, ParaId, Option), AsyncBackingParams(Hash, async_backing::AsyncBackingParams), NodeFeatures(SessionIndex, vstaging::NodeFeatures), + BulkCoreCount(SessionIndex, u16), } diff --git a/polkadot/node/core/runtime-api/src/lib.rs b/polkadot/node/core/runtime-api/src/lib.rs index 8689355c4139..7803d5bcf08a 100644 --- a/polkadot/node/core/runtime-api/src/lib.rs +++ b/polkadot/node/core/runtime-api/src/lib.rs @@ -175,6 +175,8 @@ where self.requests_cache.cache_async_backing_params(relay_parent, params), NodeFeatures(session_index, params) => self.requests_cache.cache_node_features(session_index, params), + BulkCoreCount(session_index, count) => + self.requests_cache.cache_bulk_core_count(session_index, count) } } @@ -324,6 +326,14 @@ where Some(Request::NodeFeatures(index, sender)) } }, + Request::BulkCoreCount(index, sender) => { + if let Some(value) = self.requests_cache.bulk_core_count(index) { + self.metrics.on_cached_request(); + let _ = sender.send(Ok(value.clone())); + None + } else { + Some(Request::BulkCoreCount(index, sender)) + } } } @@ -612,5 +622,12 @@ where sender, result = (index) ), + Request::BulkCoreCount(index, sender) => query!( + BulkCoreCount, + bulk_core_count(), + ver = Request::BULK_CORE_COUNT_RUNTIME_REQUIREMENT, + sender, + result = (index) + ), } } diff --git a/polkadot/node/core/runtime-api/src/tests.rs b/polkadot/node/core/runtime-api/src/tests.rs index b939bffb0e7f..34e6fb542adb 100644 --- a/polkadot/node/core/runtime-api/src/tests.rs +++ b/polkadot/node/core/runtime-api/src/tests.rs @@ -276,6 +276,10 @@ impl RuntimeApiSubsystemClient for MockSubsystemClient { async fn disabled_validators(&self, _: Hash) -> Result, ApiError> { todo!("Not required for tests") } + + async fn bulk_core_count(&self, _: Hash) -> Result { + todo!("Not required for tests") + } } #[test] diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 43456daec302..0d5c60736275 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -720,6 +720,8 @@ pub enum RuntimeApiRequest { AsyncBackingParams(RuntimeApiSender), /// Get the node features. NodeFeatures(SessionIndex, RuntimeApiSender), + /// Get the bulk core count + BulkCoreCount(SessionIndex, RuntimeApiSender), } impl RuntimeApiRequest { @@ -751,6 +753,9 @@ impl RuntimeApiRequest { /// `Node features` pub const NODE_FEATURES_RUNTIME_REQUIREMENT: u32 = 9; + + /// `BulkCoreCount` + pub const BULK_CORE_COUNT_RUNTIME_REQUIREMENT: u32 = 10; } /// A message to the Runtime API subsystem. diff --git a/polkadot/node/subsystem-types/src/runtime_client.rs b/polkadot/node/subsystem-types/src/runtime_client.rs index 8369fd215f4f..1a6f04b6cd36 100644 --- a/polkadot/node/subsystem-types/src/runtime_client.rs +++ b/polkadot/node/subsystem-types/src/runtime_client.rs @@ -265,6 +265,11 @@ pub trait RuntimeApiSubsystemClient { /// Get the node features. async fn node_features(&self, at: Hash) -> Result; + + // === v10 === + + /// Get the bulk core count + async fn bulk_core_count(&self, at: Hash) -> Result; } /// Default implementation of [`RuntimeApiSubsystemClient`] using the client. @@ -521,4 +526,11 @@ where async fn disabled_validators(&self, at: Hash) -> Result, ApiError> { self.client.runtime_api().disabled_validators(at) } + + async fn bulk_core_count( + &self, + at: Hash, + ) -> Result { + self.client.runtime_api().bulk_core_count(at) + } } diff --git a/polkadot/node/subsystem-util/src/runtime/mod.rs b/polkadot/node/subsystem-util/src/runtime/mod.rs index aada7a5d77ab..a597549817a2 100644 --- a/polkadot/node/subsystem-util/src/runtime/mod.rs +++ b/polkadot/node/subsystem-util/src/runtime/mod.rs @@ -536,3 +536,32 @@ pub async fn request_node_features( res.map(Some) } } + +/// Request current bulk core count +/// Pass in the session index for caching purposes, as it should only change on session boundaries. +/// Prior to runtime API version 10, just return 0. +pub async fn request_bulk_core_count( + parent: Hash, + session_index: SessionIndex, + sender: &mut impl overseer::SubsystemSender, +) -> Result { + let res = recv_runtime( + request_from_runtime(parent, sender, |tx| { + RuntimeApiRequest::BulkCoreCount(session_index, tx) + }) + .await, + ) + .await; + + if let Err(Error::RuntimeRequest(RuntimeApiError::NotSupported { .. })) = res { + gum::trace!( + target: LOG_TARGET, + ?parent, + "Querying the bulk core count from the runtime is not supported by the current Runtime API", + ); + + Ok(0u16) + } else { + res.map(Some) + } +} \ No newline at end of file diff --git a/polkadot/primitives/src/runtime_api.rs b/polkadot/primitives/src/runtime_api.rs index e4c1d590f457..0e50b45603d9 100644 --- a/polkadot/primitives/src/runtime_api.rs +++ b/polkadot/primitives/src/runtime_api.rs @@ -271,5 +271,11 @@ sp_api::decl_runtime_apis! { /// This is a staging method! Do not use on production runtimes! #[api_version(9)] fn node_features() -> vstaging::NodeFeatures; + + /***** Added in v10 *****/ + + /// Get bulk core count + #[api_version(10)] + fn bulk_core_count() -> u16 } } diff --git a/polkadot/runtime/parachains/src/configuration.rs b/polkadot/runtime/parachains/src/configuration.rs index bff9cc34b4fb..f38a47bb7c4b 100644 --- a/polkadot/runtime/parachains/src/configuration.rs +++ b/polkadot/runtime/parachains/src/configuration.rs @@ -263,6 +263,8 @@ pub struct HostConfiguration { pub minimum_backing_votes: u32, /// Node features enablement. pub node_features: NodeFeatures, + /// Bulk core count + pub bulk_core_count: u16, } impl> Default for HostConfiguration { @@ -315,6 +317,7 @@ impl> Default for HostConfiguration /// v8-v9: /// v9-v10: + const STORAGE_VERSION: StorageVersion = StorageVersion::new(10); #[pallet::pallet]