pub trait StateApiClient<Hash>: SubscriptionClientTwhere
    Hash: Send + Sync + 'static + Serialize + DeserializeOwned,{
Show 15 methods // Provided methods fn call<'life0, 'async_trait>( &'life0 self, name: String, bytes: Bytes, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Bytes>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn storage_keys<'life0, 'async_trait>( &'life0 self, prefix: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageKey>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn storage_pairs<'life0, 'async_trait>( &'life0 self, prefix: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<(StorageKey, StorageData)>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn storage_keys_paged<'life0, 'async_trait>( &'life0 self, prefix: Option<StorageKey>, count: u32, start_key: Option<StorageKey>, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageKey>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn storage<'life0, 'async_trait>( &'life0 self, key: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Option<StorageData>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn storage_hash<'life0, 'async_trait>( &'life0 self, key: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Option<Hash>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn storage_size<'life0, 'async_trait>( &'life0 self, key: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Option<u64>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn metadata<'life0, 'async_trait>( &'life0 self, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Bytes>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn runtime_version<'life0, 'async_trait>( &'life0 self, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<RuntimeVersion>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn query_storage<'life0, 'async_trait>( &'life0 self, keys: Vec<StorageKey>, block: Hash, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageChangeSet<Hash>>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn query_storage_at<'life0, 'async_trait>( &'life0 self, keys: Vec<StorageKey>, at: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageChangeSet<Hash>>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn read_proof<'life0, 'async_trait>( &'life0 self, keys: Vec<StorageKey>, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<ReadProof<Hash>>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn trace_block<'life0, 'async_trait>( &'life0 self, block: Hash, targets: Option<String>, storage_keys: Option<String>, methods: Option<String> ) -> Pin<Box<dyn Future<Output = RpcResult<TraceBlockResponse>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn subscribe_runtime_version<'life0, 'async_trait>( &'life0 self ) -> Pin<Box<dyn Future<Output = Result<Subscription<RuntimeVersion>, Error>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... } fn subscribe_storage<'life0, 'async_trait>( &'life0 self, keys: Option<Vec<StorageKey>> ) -> Pin<Box<dyn Future<Output = Result<Subscription<StorageChangeSet<Hash>>, Error>> + Send + 'async_trait>> where Self: Sync + 'async_trait, 'life0: 'async_trait { ... }
}
Expand description

Client implementation for the StateApi RPC API.

Provided Methods§

source

fn call<'life0, 'async_trait>( &'life0 self, name: String, bytes: Bytes, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Bytes>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Call a contract at a block’s state.

source

fn storage_keys<'life0, 'async_trait>( &'life0 self, prefix: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageKey>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

👎Deprecated since 2.0.0: Please use getKeysPaged with proper paging support

Returns the keys with prefix, leave empty to get all the keys.

source

fn storage_pairs<'life0, 'async_trait>( &'life0 self, prefix: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<(StorageKey, StorageData)>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Returns the keys with prefix, leave empty to get all the keys

source

fn storage_keys_paged<'life0, 'async_trait>( &'life0 self, prefix: Option<StorageKey>, count: u32, start_key: Option<StorageKey>, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageKey>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Returns the keys with prefix with pagination support. Up to count keys will be returned. If start_key is passed, return next keys in storage in lexicographic order.

source

fn storage<'life0, 'async_trait>( &'life0 self, key: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Option<StorageData>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Returns a storage entry at a specific block’s state.

source

fn storage_hash<'life0, 'async_trait>( &'life0 self, key: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Option<Hash>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Returns the hash of a storage entry at a block’s state.

source

fn storage_size<'life0, 'async_trait>( &'life0 self, key: StorageKey, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Option<u64>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Returns the size of a storage entry at a block’s state.

source

fn metadata<'life0, 'async_trait>( &'life0 self, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Bytes>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Returns the runtime metadata as an opaque blob.

source

fn runtime_version<'life0, 'async_trait>( &'life0 self, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<RuntimeVersion>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Get the runtime version.

source

fn query_storage<'life0, 'async_trait>( &'life0 self, keys: Vec<StorageKey>, block: Hash, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageChangeSet<Hash>>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Query historical storage entries (by key) starting from a block given as the second parameter.

NOTE This first returned result contains the initial state of storage for all keys. Subsequent values in the vector represent changes to the previous state (diffs).

source

fn query_storage_at<'life0, 'async_trait>( &'life0 self, keys: Vec<StorageKey>, at: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<Vec<StorageChangeSet<Hash>>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Query storage entries (by key) starting at block hash given as the second parameter.

source

fn read_proof<'life0, 'async_trait>( &'life0 self, keys: Vec<StorageKey>, hash: Option<Hash> ) -> Pin<Box<dyn Future<Output = RpcResult<ReadProof<Hash>>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

Returns proof of storage entries at a specific block’s state.

source

fn trace_block<'life0, 'async_trait>( &'life0 self, block: Hash, targets: Option<String>, storage_keys: Option<String>, methods: Option<String> ) -> Pin<Box<dyn Future<Output = RpcResult<TraceBlockResponse>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

The traceBlock RPC provides a way to trace the re-execution of a single block, collecting Spans and Events from both the client and the relevant WASM runtime. The Spans and Events are conceptually equivalent to those from the Tracing crate.

The structure of the traces follows that of the block execution pipeline, so meaningful interpretation of the traces requires an understanding of the Substrate chain’s block execution.

Link to conceptual map of trace structure for Polkadot and Kusama block execution.

Node requirements
  • Fully synced archive node (i.e. a node that is not actively doing a “major” sync).
  • Tracing enabled WASM runtimes for all runtime versions for which tracing is desired.
Node recommendations
  • Use fast SSD disk storage.
  • Run node flags to increase DB read speed (i.e. --state-cache-size, --db-cache).
Creating tracing enabled WASM runtimes
  • Checkout commit of chain version to compile with WASM traces
  • diener can help to peg commit of substrate to what the chain expects.
  • Navigate to the runtime folder/package of the chain
  • Add feature with-tracing = ["frame-executive/with-tracing", "sp-io/with-tracing"] under [features] to the runtime packages’ Cargo.toml.
  • Compile the runtime with cargo build --release --features with-tracing
  • Tracing-enabled WASM runtime should be found in ./target/release/wbuild/{{chain}}-runtime and be called something like {{your_chain}}_runtime.compact.wasm. This can be renamed/modified however you like, as long as it retains the .wasm extension.
  • Run the node with the wasm blob overrides by placing them in a folder with all your runtimes, and passing the path of this folder to your chain, e.g.:
  • ./target/release/polkadot --wasm-runtime-overrides /home/user/my-custom-wasm-runtimes

You can also find some pre-built tracing enabled wasm runtimes in substrate-archive

Source.

RPC Usage

The RPC allows for two filtering mechanisms: tracing targets and storage key prefixes. The filtering of spans and events takes place after they are all collected; so while filters do not reduce time for actual block re-execution, they reduce the response payload size.

Note: storage events primarily come from primitives/state-machine/src/ext.rs. The default filters can be overridden, see the params section for details.

curl example
  • Get tracing spans and events
curl \
	-H "Content-Type: application/json" \
	-d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \
		"params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "pallet,frame,state", "", ""]}' \
	http://localhost:9933/
  • Get tracing events with all storage_keys
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’)
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’)
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’)
curl \
	-H "Content-Type: application/json" \
	-d '{"id":1, "jsonrpc":"2.0", "method": "state_traceBlock", \
		"params": ["0xb246acf1adea1f801ce15c77a5fa7d8f2eb8fed466978bcee172cc02cf64e264", "state", "", "Put"]}' \
	http://localhost:9933/
Params
  • 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 targets will be filtered out. The majority of targets correspond to Rust module names, and the ones that do not are typically “hardcoded” into span or event location somewhere in the Substrate source code. (“Non-hardcoded” targets typically come from frame support macros.)
  • storage_keys (param index 2): String of comma separated (no spaces) hex encoded (no 0x prefix) storage keys. 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 storage key (so non-storage events will not show up). You can specify any length of a storage key prefix (i.e. if a specified storage key is in the beginning of an events storage key it is considered a match). Example: for balance tracking on Polkadot & Kusama you would likely want to track changes to account balances with the frame_system::Account storage item, 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 in hex: 3a65787472696e7369635f696e646578. The following are some resources to learn more about storage keys in substrate: substrate storage, transparent keys in substrate, querying substrate storage via rpc.

Maximum payload size

The maximum payload size allowed is 15mb. Payloads over this size will return a object with a simple error message. If you run into issues with payload size you can narrow down the traces using a smaller set of targets and/or storage keys.

If you are having issues with maximum payload size you can use the flag -ltracing=trace to get some logging during tracing.

source

fn subscribe_runtime_version<'life0, 'async_trait>( &'life0 self ) -> Pin<Box<dyn Future<Output = Result<Subscription<RuntimeVersion>, Error>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

New runtime version subscription

source

fn subscribe_storage<'life0, 'async_trait>( &'life0 self, keys: Option<Vec<StorageKey>> ) -> Pin<Box<dyn Future<Output = Result<Subscription<StorageChangeSet<Hash>>, Error>> + Send + 'async_trait>>where Self: Sync + 'async_trait, 'life0: 'async_trait,

New storage subscription

Implementors§

source§

impl<TypeJsonRpseeInteral, Hash> StateApiClient<Hash> for TypeJsonRpseeInteralwhere TypeJsonRpseeInteral: SubscriptionClientT, Hash: Send + Sync + 'static + Serialize + DeserializeOwned,