diff --git a/substrate/client/rpc-api/src/state/mod.rs b/substrate/client/rpc-api/src/state/mod.rs index 5b8e0ffc7a..620a000c50 100644 --- a/substrate/client/rpc-api/src/state/mod.rs +++ b/substrate/client/rpc-api/src/state/mod.rs @@ -222,17 +222,55 @@ pub trait StateApi { /// /// ### `curl` example /// + /// - Get tracing spans and events /// ```text /// curl \ /// -H "Content-Type: application/json" \ /// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \ - /// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264"]}' \ + /// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "pallet,frame,state", "", ""]}' \ + /// http://localhost:9933/ + /// ``` + /// + /// - Get tracing events with all `storage_keys` + /// ```text + /// curl \ + /// -H "Content-Type: application/json" \ + /// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \ + /// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "", ""]}' \ + /// http://localhost:9933/ + /// ``` + /// + /// - Get tracing events with `storage_keys` ('f0c365c3cf59d671eb72da0e7a4113c4') + /// ```text + /// curl \ + /// -H "Content-Type: application/json" \ + /// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \ + /// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "f0c365c3cf59d671eb72da0e7a4113c4", ""]}' \ + /// http://localhost:9933/ + /// ``` + /// + /// - Get tracing events with `storage_keys` ('f0c365c3cf59d671eb72da0e7a4113c4') and method + /// ('Put') + /// ```text + /// curl \ + /// -H "Content-Type: application/json" \ + /// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \ + /// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "f0c365c3cf59d671eb72da0e7a4113c4", "Put"]}' \ + /// http://localhost:9933/ + /// ``` + /// + /// - Get tracing events with all `storage_keys` and method ('Put') + /// ```text + /// curl \ + /// -H "Content-Type: application/json" \ + /// -d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \ + /// "params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "", "Put"]}' \ /// http://localhost:9933/ /// ``` /// /// ### Params /// - /// - `block_hash` (param index 0): Hash of the block to trace. + /// - `block` (param index 0): Hash of the block to trace. /// - `targets` (param index 1): String of comma separated (no spaces) targets. Specified /// targets match with trace targets by prefix (i.e if a target is in the beginning /// of a trace target it is considered a match). If an empty string is specified no @@ -251,6 +289,10 @@ pub trait StateApi { /// which is a map from `AccountId` to `AccountInfo`. The key filter for this would be /// the storage prefix for the map: /// `26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9` + /// - `methods` (param index 3): String of comma separated (no spaces) tracing event method. + /// If an empty string is specified no events will be filtered out. If anything other than + /// an empty string is specified, events will be filtered by method (so non-method events will + /// **not** show up). /// /// Additionally you would want to track the extrinsic index, which is under the /// `:extrinsic_index` key. The key for this would be the aforementioned string as bytes @@ -277,5 +319,6 @@ pub trait StateApi { block: Hash, targets: Option, storage_keys: Option, + methods: Option, ) -> FutureResult; } diff --git a/substrate/client/rpc/src/state/mod.rs b/substrate/client/rpc/src/state/mod.rs index 042225042d..5413264de4 100644 --- a/substrate/client/rpc/src/state/mod.rs +++ b/substrate/client/rpc/src/state/mod.rs @@ -178,6 +178,7 @@ where block: Block::Hash, targets: Option, storage_keys: Option, + methods: Option, ) -> FutureResult; } @@ -413,12 +414,13 @@ where block: Block::Hash, targets: Option, storage_keys: Option, + methods: Option, ) -> FutureResult { if let Err(err) = self.deny_unsafe.check_if_safe() { return async move { Err(err.into()) }.boxed() } - self.backend.trace_block(block, targets, storage_keys) + self.backend.trace_block(block, targets, storage_keys, methods) } } diff --git a/substrate/client/rpc/src/state/state_full.rs b/substrate/client/rpc/src/state/state_full.rs index 0d9a35fd26..54124ad958 100644 --- a/substrate/client/rpc/src/state/state_full.rs +++ b/substrate/client/rpc/src/state/state_full.rs @@ -581,12 +581,14 @@ where block: Block::Hash, targets: Option, storage_keys: Option, + methods: Option, ) -> FutureResult { let block_executor = sc_tracing::block::BlockExecutor::new( self.client.clone(), block, targets, storage_keys, + methods, self.rpc_max_payload, ); let r = block_executor diff --git a/substrate/client/rpc/src/state/state_light.rs b/substrate/client/rpc/src/state/state_light.rs index cdb3a77e8d..b89b0638ba 100644 --- a/substrate/client/rpc/src/state/state_light.rs +++ b/substrate/client/rpc/src/state/state_light.rs @@ -449,6 +449,7 @@ where _block: Block::Hash, _targets: Option, _storage_keys: Option, + _methods: Option, ) -> FutureResult { async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() } diff --git a/substrate/client/tracing/src/block/mod.rs b/substrate/client/tracing/src/block/mod.rs index d439e70f8a..8280d4613a 100644 --- a/substrate/client/tracing/src/block/mod.rs +++ b/substrate/client/tracing/src/block/mod.rs @@ -181,6 +181,7 @@ pub struct BlockExecutor { block: Block::Hash, targets: Option, storage_keys: Option, + methods: Option, rpc_max_payload: usize, } @@ -201,12 +202,13 @@ where block: Block::Hash, targets: Option, storage_keys: Option, + methods: Option, rpc_max_payload: Option, ) -> Self { let rpc_max_payload = rpc_max_payload .map(|mb| mb.saturating_mul(MEGABYTE)) .unwrap_or(RPC_MAX_PAYLOAD_DEFAULT); - Self { client, block, targets, storage_keys, rpc_max_payload } + Self { client, block, targets, storage_keys, methods, rpc_max_payload } } /// Execute block, record all spans and events belonging to `Self::targets` @@ -274,7 +276,13 @@ where .filter(|e| { self.storage_keys .as_ref() - .map(|keys| event_key_filter(e, keys)) + .map(|keys| event_values_filter(e, "key", keys)) + .unwrap_or(false) + }) + .filter(|e| { + self.methods + .as_ref() + .map(|methods| event_values_filter(e, "method", methods)) .unwrap_or(false) }) .map(|s| s.into()) @@ -292,6 +300,7 @@ where parent_hash: block_id_as_string(parent_id), tracing_targets: targets.to_string(), storage_keys: self.storage_keys.clone().unwrap_or_default(), + methods: self.methods.clone().unwrap_or_default(), spans, events, }) @@ -301,12 +310,12 @@ where } } -fn event_key_filter(event: &TraceEvent, storage_keys: &str) -> bool { +fn event_values_filter(event: &TraceEvent, filter_kind: &str, values: &str) -> bool { event .values .string_values - .get("key") - .and_then(|key| Some(check_target(storage_keys, key, &event.level))) + .get(filter_kind) + .and_then(|value| Some(check_target(values, value, &event.level))) .unwrap_or(false) } diff --git a/substrate/primitives/rpc/src/tracing.rs b/substrate/primitives/rpc/src/tracing.rs index 7e05cd84a7..737ace2410 100644 --- a/substrate/primitives/rpc/src/tracing.rs +++ b/substrate/primitives/rpc/src/tracing.rs @@ -35,6 +35,9 @@ pub struct BlockTrace { /// Storage key targets used to filter out events that do not have one of the storage keys. /// Empty string means do not filter out any events. pub storage_keys: String, + /// Method targets used to filter out events that do not have one of the event method. + /// Empty string means do not filter out any events. + pub methods: String, /// Vec of tracing spans pub spans: Vec, /// Vec of tracing events