diff --git a/client/api/src/execution_extensions.rs b/client/api/src/execution_extensions.rs index 351e9c8914043..1a986a23a47dc 100644 --- a/client/api/src/execution_extensions.rs +++ b/client/api/src/execution_extensions.rs @@ -62,6 +62,18 @@ impl Default for ExecutionStrategies { } } +/// Generate the starting set of ExternalitiesExtensions based upon the given capabilities +pub trait ExtensionsFactory: Send + Sync { + /// Make `Extensions` for given Capapbilities + fn extensions_for(&self, capabilities: offchain::Capabilities) -> Extensions; +} + +impl ExtensionsFactory for () { + fn extensions_for(&self, _capabilities: offchain::Capabilities) -> Extensions { + Extensions::new() + } +} + /// A producer of execution extensions for offchain calls. /// /// This crate aggregates extensions available for the offchain calls @@ -70,7 +82,10 @@ impl Default for ExecutionStrategies { pub struct ExecutionExtensions { strategies: ExecutionStrategies, keystore: Option, + // FIXME: these two are only RwLock because of https://github.com/paritytech/substrate/issues/4587 + // remove when fixed. transaction_pool: RwLock>>>, + extensions_factory: RwLock>, } impl Default for ExecutionExtensions { @@ -79,6 +94,7 @@ impl Default for ExecutionExtensions { strategies: Default::default(), keystore: None, transaction_pool: RwLock::new(None), + extensions_factory: RwLock::new(Box::new(())), } } } @@ -90,7 +106,8 @@ impl ExecutionExtensions { keystore: Option, ) -> Self { let transaction_pool = RwLock::new(None); - Self { strategies, keystore, transaction_pool } + let extensions_factory = Box::new(()); + Self { strategies, keystore, extensions_factory: RwLock::new(extensions_factory), transaction_pool } } /// Get a reference to the execution strategies. @@ -98,6 +115,11 @@ impl ExecutionExtensions { &self.strategies } + /// Set the new extensions_factory + pub fn set_extensions_factory(&self, maker: Box) { + *self.extensions_factory.write() = maker; + } + /// Register transaction pool extension. /// /// To break retain cycle between `Client` and `TransactionPool` we require this @@ -135,7 +157,7 @@ impl ExecutionExtensions { let capabilities = context.capabilities(); - let mut extensions = Extensions::new(); + let mut extensions = self.extensions_factory.read().extensions_for(capabilities); if capabilities.has(offchain::Capability::Keystore) { if let Some(keystore) = self.keystore.as_ref() { diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 6eb0259b7928c..0160da9bbed8d 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -22,6 +22,7 @@ use sc_client_api::{ self, BlockchainEvents, backend::RemoteBackend, light::RemoteBlockchain, + execution_extensions::ExtensionsFactory, }; use sc_client::Client; use sc_chain_spec::{RuntimeGenesis, Extension}; @@ -746,6 +747,13 @@ ServiceBuilder< + TransactionPoolMaintainer::Hash>, TRpc: sc_rpc::RpcExtension + Clone, { + + /// Set an ExecutionExtensionsFactory + pub fn with_execution_extensions_factory(self, execution_extensions_factory: Box) -> Result { + self.client.execution_extensions().set_extensions_factory(execution_extensions_factory); + Ok(self) + } + /// Builds the service. pub fn build(self) -> Result