diff --git a/Cargo.lock b/Cargo.lock index 786568aab6405..af9f75d379f28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4642,6 +4642,7 @@ dependencies = [ "sc-service", "sc-sysinfo", "sc-telemetry", + "sc-tracing", "sc-transaction-pool", "sc-utils", "sp-api", @@ -4651,6 +4652,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-transaction-pool", + "sp-trie", ] [[package]] diff --git a/cumulus/client/service/Cargo.toml b/cumulus/client/service/Cargo.toml index 3ea36d70b42b6..c7e953a33d0a6 100644 --- a/cumulus/client/service/Cargo.toml +++ b/cumulus/client/service/Cargo.toml @@ -1,4 +1,5 @@ [package] + name = "cumulus-client-service" version = "0.7.0" authors.workspace = true @@ -26,6 +27,7 @@ sc-rpc = { workspace = true, default-features = true } sc-service = { workspace = true, default-features = true } sc-sysinfo = { workspace = true, default-features = true } sc-telemetry = { workspace = true, default-features = true } +sc-tracing = { workspace = true, default-features = true } sc-transaction-pool = { workspace = true, default-features = true } sc-utils = { workspace = true, default-features = true } sp-api = { workspace = true, default-features = true } @@ -35,6 +37,7 @@ sp-core = { workspace = true, default-features = true } sp-io = { workspace = true, default-features = true } sp-runtime = { workspace = true, default-features = true } sp-transaction-pool = { workspace = true, default-features = true } +sp-trie = { workspace = true, default-features = true } # Polkadot polkadot-primitives = { workspace = true, default-features = true } diff --git a/cumulus/client/service/src/lib.rs b/cumulus/client/service/src/lib.rs index 501212eb971a3..979e2c0df365a 100644 --- a/cumulus/client/service/src/lib.rs +++ b/cumulus/client/service/src/lib.rs @@ -45,14 +45,16 @@ use sc_network_sync::SyncingService; use sc_network_transactions::TransactionsHandlerController; use sc_service::{Configuration, SpawnTaskHandle, TaskManager, WarpSyncConfig}; use sc_telemetry::{log, TelemetryWorkerHandle}; +use sc_tracing::block::TracingExecuteBlock; use sc_utils::mpsc::TracingUnboundedSender; -use sp_api::ProvideRuntimeApi; +use sp_api::{ApiExt, Core, ProofRecorder, ProvideRuntimeApi}; use sp_blockchain::{HeaderBackend, HeaderMetadata}; use sp_core::Decode; use sp_runtime::{ traits::{Block as BlockT, BlockIdTo, Header}, SaturatedConversion, Saturating, }; +use sp_trie::proof_size_extension::ProofSizeExt; use std::{ sync::Arc, time::{Duration, Instant}, @@ -597,3 +599,36 @@ impl ParachainInformantMetrics { }) } } + +/// Implementation of [`TracingExecuteBlock`] for parachains. +/// +/// Ensures that all the required extensions required by parachain runtimes are registered and +/// available. +pub struct ParachainTracingExecuteBlock { + client: Arc, +} + +impl ParachainTracingExecuteBlock { + /// Creates a new instance of `self`. + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +impl TracingExecuteBlock for ParachainTracingExecuteBlock +where + Block: BlockT, + Client: ProvideRuntimeApi + Send + Sync, + Client::Api: Core, +{ + fn execute_block(&self, _: Block::Hash, block: Block) -> sp_blockchain::Result<()> { + let mut runtime_api = self.client.runtime_api(); + let storage_proof_recorder = ProofRecorder::::default(); + runtime_api.register_extension(ProofSizeExt::new(storage_proof_recorder.clone())); + runtime_api.record_proof_with_recorder(storage_proof_recorder); + + runtime_api + .execute_block(*block.header().parent_hash(), block) + .map_err(Into::into) + } +} diff --git a/cumulus/polkadot-omni-node/lib/src/common/spec.rs b/cumulus/polkadot-omni-node/lib/src/common/spec.rs index 30e5fd587941b..686e2cc4e1669 100644 --- a/cumulus/polkadot-omni-node/lib/src/common/spec.rs +++ b/cumulus/polkadot-omni-node/lib/src/common/spec.rs @@ -31,7 +31,8 @@ use cumulus_client_bootnodes::{start_bootnode_tasks, StartBootnodeTasksParams}; use cumulus_client_cli::CollatorOptions; use cumulus_client_service::{ build_network, build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks, - BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams, + BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, ParachainTracingExecuteBlock, + StartRelayChainTasksParams, }; use cumulus_primitives_core::{BlockT, GetParachainInfo, ParaId}; use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; @@ -455,6 +456,9 @@ pub(crate) trait NodeSpec: BaseNodeSpec { system_rpc_tx, tx_handler_controller, telemetry: telemetry.as_mut(), + tracing_execute_block: Some(Arc::new(ParachainTracingExecuteBlock::new( + client.clone(), + ))), })?; if let Some(hwbench) = hwbench { diff --git a/cumulus/polkadot-omni-node/lib/src/nodes/aura.rs b/cumulus/polkadot-omni-node/lib/src/nodes/aura.rs index 797f8d47c5af8..ec4eb36689dcc 100644 --- a/cumulus/polkadot-omni-node/lib/src/nodes/aura.rs +++ b/cumulus/polkadot-omni-node/lib/src/nodes/aura.rs @@ -358,6 +358,7 @@ where sync_service, config, telemetry: telemetry.as_mut(), + tracing_execute_block: None, })?; Ok(task_manager) diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs index d0d2325c21b6c..0bc1f21dcdf39 100644 --- a/cumulus/test/service/src/lib.rs +++ b/cumulus/test/service/src/lib.rs @@ -52,7 +52,8 @@ use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImpo use cumulus_client_pov_recovery::{RecoveryDelayRange, RecoveryHandle}; use cumulus_client_service::{ build_network, prepare_node_config, start_relay_chain_tasks, BuildNetworkParams, - CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams, + CollatorSybilResistance, DARecoveryProfile, ParachainTracingExecuteBlock, + StartRelayChainTasksParams, }; use cumulus_primitives_core::{relay_chain::ValidationCode, GetParachainInfo, ParaId}; use cumulus_relay_chain_inprocess_interface::RelayChainInProcessInterface; @@ -389,6 +390,7 @@ where system_rpc_tx, tx_handler_controller, telemetry: None, + tracing_execute_block: Some(Arc::new(ParachainTracingExecuteBlock::new(client.clone()))), })?; let announce_block = { diff --git a/polkadot/node/service/src/builder/mod.rs b/polkadot/node/service/src/builder/mod.rs index c4e9a6668ed3e..9d52617cc8da9 100644 --- a/polkadot/node/service/src/builder/mod.rs +++ b/polkadot/node/service/src/builder/mod.rs @@ -506,6 +506,7 @@ where system_rpc_tx, tx_handler_controller, telemetry: telemetry.as_mut(), + tracing_execute_block: None, })?; if let Some(hwbench) = hwbench { diff --git a/prdoc/pr_9871.prdoc b/prdoc/pr_9871.prdoc new file mode 100644 index 0000000000000..0693259867564 --- /dev/null +++ b/prdoc/pr_9871.prdoc @@ -0,0 +1,20 @@ +title: '`trace_block`: Support overwriting `execute_block`' +doc: +- audience: Node Dev + description: |- + This is required for example for parachains that require special extensions to be registered (e.g. `ProofSizeExt`) to succeed the block execution. + + This pull request changes the signature of `spawn_tasks` which now requires a `tracing_execute_block` parameter. If your chain is a solochain, just set the parameter to `None` or overwrite it if you need any special handling. For parachain builders, this value can be set to `cumulus_service::ParachainTracingExecuteBlock`. +crates: +- name: cumulus-client-service + bump: major +- name: polkadot-omni-node-lib + bump: major +- name: polkadot-service + bump: major +- name: sc-rpc + bump: major +- name: sc-service + bump: major +- name: sc-tracing + bump: major diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index 8db5cf24ea22a..89a5ef151df30 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -568,6 +568,7 @@ pub fn new_full_base::Hash>>( tx_handler_controller, sync_service: sync_service.clone(), telemetry: telemetry.as_mut(), + tracing_execute_block: None, })?; if let Some(hwbench) = hwbench { diff --git a/substrate/client/rpc/src/state/mod.rs b/substrate/client/rpc/src/state/mod.rs index d8989b3e1bee7..2d3986432603f 100644 --- a/substrate/client/rpc/src/state/mod.rs +++ b/substrate/client/rpc/src/state/mod.rs @@ -30,6 +30,7 @@ use sc_client_api::{ Backend, BlockBackend, BlockchainEvents, ExecutorProvider, ProofProvider, StorageProvider, }; use sc_rpc_api::{check_if_safe, DenyUnsafe}; +use sc_tracing::block::TracingExecuteBlock; use sp_api::{CallApiAt, Metadata, ProvideRuntimeApi}; use sp_blockchain::{HeaderBackend, HeaderMetadata}; use sp_core::{ @@ -164,6 +165,7 @@ where pub fn new_full( client: Arc, executor: SubscriptionTaskExecutor, + execute_block: Option>>, ) -> (State, ChildState) where Block: BlockT + 'static, @@ -183,9 +185,13 @@ where + 'static, Client::Api: Metadata, { - let child_backend = - Box::new(self::state_full::FullState::new(client.clone(), executor.clone())); - let backend = Box::new(self::state_full::FullState::new(client, executor)); + let child_backend = Box::new(self::state_full::FullState::new( + client.clone(), + executor.clone(), + execute_block.clone(), + )); + let backend = + Box::new(self::state_full::FullState::new(client, executor, execute_block.clone())); (State { backend }, ChildState { backend: child_backend }) } diff --git a/substrate/client/rpc/src/state/state_full.rs b/substrate/client/rpc/src/state/state_full.rs index 7703936f8115d..ed04d510fd118 100644 --- a/substrate/client/rpc/src/state/state_full.rs +++ b/substrate/client/rpc/src/state/state_full.rs @@ -37,6 +37,7 @@ use sc_client_api::{ StorageProvider, }; use sc_rpc_api::state::ReadProof; +use sc_tracing::block::TracingExecuteBlock; use sp_api::{CallApiAt, Metadata, ProvideRuntimeApi}; use sp_blockchain::{ CachedHeaderMetadata, Error as ClientError, HeaderBackend, HeaderMetadata, @@ -55,7 +56,7 @@ use sp_version::RuntimeVersion; /// The maximum time allowed for an RPC call when running without unsafe RPC enabled. const MAXIMUM_SAFE_RPC_CALL_TIMEOUT: Duration = Duration::from_secs(30); -/// Ranges to query in state_queryStorage. +/// Ranges to query in `state_queryStorage`. struct QueryStorageRange { /// Hashes of all the blocks in the range. pub hashes: Vec, @@ -65,7 +66,8 @@ struct QueryStorageRange { pub struct FullState { client: Arc, executor: SubscriptionTaskExecutor, - _phantom: PhantomData<(BE, Block)>, + execute_block: Option>>, + _phantom: PhantomData, } impl FullState @@ -78,8 +80,12 @@ where Block: BlockT + 'static, { /// Create new state API backend for full nodes. - pub fn new(client: Arc, executor: SubscriptionTaskExecutor) -> Self { - Self { client, executor, _phantom: PhantomData } + pub fn new( + client: Arc, + executor: SubscriptionTaskExecutor, + execute_block: Option>>, + ) -> Self { + Self { client, executor, execute_block, _phantom: PhantomData } } /// Returns given block hash or best block hash if None is passed. @@ -479,6 +485,7 @@ where targets, storage_keys, methods, + self.execute_block.clone(), ) .trace_block() .map_err(|e| invalid_block::(block, None, e.to_string())) diff --git a/substrate/client/rpc/src/state/tests.rs b/substrate/client/rpc/src/state/tests.rs index c02f0d0b759bf..c35d9efa42b58 100644 --- a/substrate/client/rpc/src/state/tests.rs +++ b/substrate/client/rpc/src/state/tests.rs @@ -53,7 +53,7 @@ async fn should_return_storage() { .add_extra_storage(b":map:acc2".to_vec(), vec![1, 2, 3]) .build(); let genesis_hash = client.genesis_hash(); - let (client, child) = new_full(Arc::new(client), test_executor()); + let (client, child) = new_full(Arc::new(client), test_executor(), None); let key = StorageKey(KEY.to_vec()); let ext = allow_unsafe(); @@ -106,7 +106,7 @@ async fn should_return_storage_entries() { .add_extra_child_storage(&child_info, KEY2.to_vec(), CHILD_VALUE2.to_vec()) .build(); let genesis_hash = client.genesis_hash(); - let (_client, child) = new_full(Arc::new(client), test_executor()); + let (_client, child) = new_full(Arc::new(client), test_executor(), None); let keys = &[StorageKey(KEY1.to_vec()), StorageKey(KEY2.to_vec())]; assert_eq!( @@ -137,7 +137,7 @@ async fn should_return_child_storage() { .build(), ); let genesis_hash = client.genesis_hash(); - let (_client, child) = new_full(client, test_executor()); + let (_client, child) = new_full(client, test_executor(), None); let child_key = prefixed_storage_key(); let key = StorageKey(b"key".to_vec()); @@ -168,7 +168,7 @@ async fn should_return_child_storage_entries() { .build(), ); let genesis_hash = client.genesis_hash(); - let (_client, child) = new_full(client, test_executor()); + let (_client, child) = new_full(client, test_executor(), None); let child_key = prefixed_storage_key(); let keys = vec![StorageKey(b"key1".to_vec()), StorageKey(b"key2".to_vec())]; @@ -199,7 +199,7 @@ async fn should_return_child_storage_entries() { async fn should_call_contract() { let client = Arc::new(substrate_test_runtime_client::new()); let genesis_hash = client.genesis_hash(); - let (client, _child) = new_full(client, test_executor()); + let (client, _child) = new_full(client, test_executor(), None); assert_matches!( client.call("balanceOf".into(), Bytes(vec![1, 2, 3]), Some(genesis_hash).into()), @@ -211,7 +211,7 @@ async fn should_call_contract() { async fn should_notify_about_storage_changes() { let mut sub = { let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client.clone(), test_executor()); + let (api, _child) = new_full(client.clone(), test_executor(), None); let mut api_rpc = api.into_rpc(); api_rpc.extensions_mut().insert(DenyUnsafe::No); @@ -250,7 +250,7 @@ async fn should_notify_about_storage_changes() { async fn should_send_initial_storage_changes_and_notifications() { let mut sub = { let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client.clone(), test_executor()); + let (api, _child) = new_full(client.clone(), test_executor(), None); let alice_balance_key = [ sp_crypto_hashing::twox_128(b"System"), @@ -300,7 +300,7 @@ async fn should_send_initial_storage_changes_and_notifications() { #[tokio::test] async fn should_query_storage() { async fn run_tests(client: Arc) { - let (api, _child) = new_full(client.clone(), test_executor()); + let (api, _child) = new_full(client.clone(), test_executor(), None); let add_block = |index| { let mut builder = BlockBuilderBuilder::new(&*client) @@ -468,7 +468,7 @@ async fn should_query_storage() { #[tokio::test] async fn should_return_runtime_version() { let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client.clone(), test_executor()); + let (api, _child) = new_full(client.clone(), test_executor(), None); // it is basically json-encoded substrate_test_runtime_client::runtime::VERSION let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ @@ -491,7 +491,7 @@ async fn should_return_runtime_version() { async fn should_notify_on_runtime_version_initially() { let mut sub = { let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client, test_executor()); + let (api, _child) = new_full(client, test_executor(), None); let mut api_rpc = api.into_rpc(); api_rpc.extensions_mut().insert(DenyUnsafe::No); @@ -518,7 +518,7 @@ fn should_deserialize_storage_key() { #[tokio::test] async fn wildcard_storage_subscriptions_are_rpc_unsafe() { let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client, test_executor()); + let (api, _child) = new_full(client, test_executor(), None); let mut api_rpc = api.into_rpc(); api_rpc.extensions_mut().insert(DenyUnsafe::Yes); @@ -529,7 +529,7 @@ async fn wildcard_storage_subscriptions_are_rpc_unsafe() { #[tokio::test] async fn concrete_storage_subscriptions_are_rpc_safe() { let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client, test_executor()); + let (api, _child) = new_full(client, test_executor(), None); let mut api_rpc = api.into_rpc(); api_rpc.extensions_mut().insert(DenyUnsafe::Yes); diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs index 74d94c30cd69b..3813fce66143c 100644 --- a/substrate/client/service/src/builder.rs +++ b/substrate/client/service/src/builder.rs @@ -81,6 +81,7 @@ use sc_rpc_spec_v2::{ transaction::{TransactionApiServer, TransactionBroadcastApiServer}, }; use sc_telemetry::{telemetry, ConnectionMessage, Telemetry, TelemetryHandle, SUBSTRATE_INFO}; +use sc_tracing::block::TracingExecuteBlock; use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_api::{CallApiAt, ProvideRuntimeApi}; @@ -461,11 +462,29 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { pub sync_service: Arc>, /// Telemetry instance for this node. pub telemetry: Option<&'a mut Telemetry>, + /// Optional [`TracingExecuteBlock`] handle. + /// + /// Will be used by the `trace_block` RPC to execute the actual block. + pub tracing_execute_block: Option>>, } /// Spawn the tasks that are required to run a node. pub fn spawn_tasks( - params: SpawnTasksParams, + SpawnTasksParams { + mut config, + task_manager, + client, + backend, + keystore, + transaction_pool, + rpc_builder, + network, + system_rpc_tx, + tx_handler_controller, + sync_service, + telemetry, + tracing_execute_block: execute_block, + }: SpawnTasksParams, ) -> Result where TCl: ProvideRuntimeApi @@ -492,21 +511,6 @@ where TBackend: 'static + sc_client_api::backend::Backend + Send, TExPool: MaintainedTransactionPool::Hash> + 'static, { - let SpawnTasksParams { - mut config, - task_manager, - client, - backend, - keystore, - transaction_pool, - rpc_builder, - network, - system_rpc_tx, - tx_handler_controller, - sync_service, - telemetry, - } = params; - let chain_info = client.usage_info().chain; sp_session::generate_initial_session_keys( @@ -603,21 +607,22 @@ where .transpose()?; let gen_rpc_module = || { - gen_rpc_module( - task_manager.spawn_handle(), - client.clone(), - transaction_pool.clone(), - keystore.clone(), - system_rpc_tx.clone(), - config.impl_name.clone(), - config.impl_version.clone(), - config.chain_spec.as_ref(), - &config.state_pruning, - config.blocks_pruning, - backend.clone(), - &*rpc_builder, - rpc_v2_metrics.clone(), - ) + gen_rpc_module(GenRpcModuleParams { + spawn_handle: task_manager.spawn_handle(), + client: client.clone(), + transaction_pool: transaction_pool.clone(), + keystore: keystore.clone(), + system_rpc_tx: system_rpc_tx.clone(), + impl_name: config.impl_name.clone(), + impl_version: config.impl_version.clone(), + chain_spec: config.chain_spec.as_ref(), + state_pruning: &config.state_pruning, + blocks_pruning: config.blocks_pruning, + backend: backend.clone(), + rpc_builder: &*rpc_builder, + metrics: rpc_v2_metrics.clone(), + tracing_execute_block: execute_block.clone(), + }) }; let rpc_server_handle = start_rpc_servers( @@ -750,21 +755,58 @@ where Ok(telemetry.handle()) } +/// Parameters for [`gen_rpc_module`]. +pub struct GenRpcModuleParams<'a, TBl: BlockT, TBackend, TCl, TRpc, TExPool> { + /// The handle to spawn tasks. + pub spawn_handle: SpawnTaskHandle, + /// Access to the client. + pub client: Arc, + /// The transaction pool. + pub transaction_pool: Arc, + /// Keystore handle. + pub keystore: KeystorePtr, + /// Sender for system requests. + pub system_rpc_tx: TracingUnboundedSender>, + /// Implementation name of this node. + pub impl_name: String, + /// Implementation version of this node. + pub impl_version: String, + /// The chain spec. + pub chain_spec: &'a dyn ChainSpec, + /// Enabled pruning mode for this node. + pub state_pruning: &'a Option, + /// Enabled blocks pruning mode. + pub blocks_pruning: BlocksPruning, + /// Backend of the node. + pub backend: Arc, + /// RPC builder. + pub rpc_builder: &'a (dyn Fn(SubscriptionTaskExecutor) -> Result, Error>), + /// Transaction metrics handle. + pub metrics: Option, + /// Optional [`TracingExecuteBlock`] handle. + /// + /// Will be used by the `trace_block` RPC to execute the actual block. + pub tracing_execute_block: Option>>, +} + /// Generate RPC module using provided configuration pub fn gen_rpc_module( - spawn_handle: SpawnTaskHandle, - client: Arc, - transaction_pool: Arc, - keystore: KeystorePtr, - system_rpc_tx: TracingUnboundedSender>, - impl_name: String, - impl_version: String, - chain_spec: &dyn ChainSpec, - state_pruning: &Option, - blocks_pruning: BlocksPruning, - backend: Arc, - rpc_builder: &(dyn Fn(SubscriptionTaskExecutor) -> Result, Error>), - metrics: Option, + GenRpcModuleParams { + spawn_handle, + client, + transaction_pool, + keystore, + system_rpc_tx, + impl_name, + impl_version, + chain_spec, + state_pruning, + blocks_pruning, + backend, + rpc_builder, + metrics, + tracing_execute_block: execute_block, + }: GenRpcModuleParams, ) -> Result, Error> where TBl: BlockT, @@ -799,7 +841,8 @@ where let (chain, state, child_state) = { let chain = sc_rpc::chain::new_full(client.clone(), task_executor.clone()).into_rpc(); - let (state, child_state) = sc_rpc::state::new_full(client.clone(), task_executor.clone()); + let (state, child_state) = + sc_rpc::state::new_full(client.clone(), task_executor.clone(), execute_block); let state = state.into_rpc(); let child_state = child_state.into_rpc(); diff --git a/substrate/client/tracing/src/block/mod.rs b/substrate/client/tracing/src/block/mod.rs index 3ebbc3d97e171..f39fa6142b5f2 100644 --- a/substrate/client/tracing/src/block/mod.rs +++ b/substrate/client/tracing/src/block/mod.rs @@ -36,7 +36,7 @@ use tracing::{ use crate::{SpanDatum, TraceEvent, Values}; use sc_client_api::BlockBackend; -use sp_api::{Core, Metadata, ProvideRuntimeApi}; +use sp_api::{Core, ProvideRuntimeApi}; use sp_blockchain::HeaderBackend; use sp_core::hexdisplay::HexDisplay; use sp_rpc::tracing::{BlockTrace, Span, TraceBlockResponse}; @@ -52,6 +52,47 @@ const TRACE_TARGET: &str = "block_trace"; // The name of a field required for all events. const REQUIRED_EVENT_FIELD: &str = "method"; +/// Something that can execute a block in a tracing context. +pub trait TracingExecuteBlock: Send + Sync { + /// Execute the given `block`. + /// + /// The `block` is prepared to be executed right away, this means that any `Seal` was already + /// removed from the header. As this changes the `hash` of the block, `orig_hash` is passed + /// alongside to the callee. + /// + /// The execution should be done sync on the same thread, because the caller will register + /// special tracing collectors. + fn execute_block(&self, orig_hash: Block::Hash, block: Block) -> sp_blockchain::Result<()>; +} + +/// Default implementation of [`ExecuteBlock`]. +/// +/// Uses [`Core::execute_block`] to directly execute a block. +struct DefaultExecuteBlock { + client: Arc, +} + +impl DefaultExecuteBlock { + /// Creates a new instance. + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +impl TracingExecuteBlock for DefaultExecuteBlock +where + Client: ProvideRuntimeApi + Send + Sync + 'static, + Client::Api: Core, + Block: BlockT, +{ + fn execute_block(&self, _: Block::Hash, block: Block) -> sp_blockchain::Result<()> { + self.client + .runtime_api() + .execute_block(*block.header().parent_hash(), block) + .map_err(Into::into) + } +} + /// Tracing Block Result type alias pub type TraceBlockResult = Result; @@ -96,11 +137,13 @@ impl Subscriber for BlockSubscriber { if !metadata.is_span() && metadata.fields().field(REQUIRED_EVENT_FIELD).is_none() { return false } + for (target, level) in &self.targets { if metadata.level() <= level && metadata.target().starts_with(target) { return true } } + false } @@ -167,6 +210,7 @@ pub struct BlockExecutor { targets: Option, storage_keys: Option, methods: Option, + execute_block: Arc>, } impl BlockExecutor @@ -178,7 +222,7 @@ where + Send + Sync + 'static, - Client::Api: Metadata, + Client::Api: Core, { /// Create a new `BlockExecutor` pub fn new( @@ -187,8 +231,17 @@ where targets: Option, storage_keys: Option, methods: Option, + execute_block: Option>>, ) -> Self { - Self { client, block, targets, storage_keys, methods } + Self { + client: client.clone(), + block, + targets, + storage_keys, + methods, + execute_block: execute_block + .unwrap_or_else(|| Arc::new(DefaultExecuteBlock::new(client))), + } } /// Execute block, record all spans and events belonging to `Self::targets` @@ -228,7 +281,7 @@ where if let Err(e) = dispatcher::with_default(&dispatch, || { let span = tracing::info_span!(target: TRACE_TARGET, "trace_block"); let _enter = span.enter(); - self.client.runtime_api().execute_block(parent_hash, block) + self.execute_block.execute_block(self.block, block) }) { return Err(Error::Dispatch(format!( "Failed to collect traces and execute block: {}", @@ -311,6 +364,7 @@ fn patch_and_filter(mut span: SpanDatum, targets: &str) -> Option { return None } } + Some(span.into()) } @@ -321,6 +375,7 @@ fn check_target(targets: &str, target: &str, level: &Level) -> bool { return true } } + false } diff --git a/substrate/frame/revive/dev-node/node/src/service.rs b/substrate/frame/revive/dev-node/node/src/service.rs index 5cee6586da51d..4f53173627d70 100644 --- a/substrate/frame/revive/dev-node/node/src/service.rs +++ b/substrate/frame/revive/dev-node/node/src/service.rs @@ -186,6 +186,7 @@ pub fn new_full::Ha sync_service, config, telemetry: telemetry.as_mut(), + tracing_execute_block: None, })?; let proposer = sc_basic_authorship::ProposerFactory::new( diff --git a/templates/minimal/node/src/service.rs b/templates/minimal/node/src/service.rs index 5988dbf3ce6ed..cd68ba6fd767b 100644 --- a/templates/minimal/node/src/service.rs +++ b/templates/minimal/node/src/service.rs @@ -194,6 +194,7 @@ pub fn new_full::Ha sync_service, config, telemetry: telemetry.as_mut(), + tracing_execute_block: None, })?; let proposer = sc_basic_authorship::ProposerFactory::new( diff --git a/templates/parachain/node/src/service.rs b/templates/parachain/node/src/service.rs index 4ce1bba376e8d..7d95673eafdc9 100644 --- a/templates/parachain/node/src/service.rs +++ b/templates/parachain/node/src/service.rs @@ -9,7 +9,7 @@ use parachain_template_runtime::{ opaque::{Block, Hash}, }; -use polkadot_sdk::*; +use polkadot_sdk::{cumulus_client_service::ParachainTracingExecuteBlock, *}; // Cumulus Imports use cumulus_client_bootnodes::{start_bootnode_tasks, StartBootnodeTasksParams}; @@ -347,6 +347,7 @@ pub async fn start_parachain_node( system_rpc_tx, tx_handler_controller, telemetry: telemetry.as_mut(), + tracing_execute_block: Some(Arc::new(ParachainTracingExecuteBlock::new(client.clone()))), })?; if let Some(hwbench) = hwbench { diff --git a/templates/solochain/node/src/service.rs b/templates/solochain/node/src/service.rs index 79d97fbab8dfa..dd932b2974945 100644 --- a/templates/solochain/node/src/service.rs +++ b/templates/solochain/node/src/service.rs @@ -234,6 +234,7 @@ pub fn new_full< sync_service: sync_service.clone(), config, telemetry: telemetry.as_mut(), + tracing_execute_block: None, })?; if role.is_authority() {