Substrate statement store implementation
License: GPL-3.0-or-later WITH Classpath-exception-2.0
The statement store is an off-chain, decentralized data store for cryptographically signed statements. It enables accounts to publish arbitrary data that can be queried and propagated across the network without consuming on-chain storage. Statement store designed around two fundamental pillars: Scalability and Graceful Degradation. It expressly avoids the properties of centralized data structures. Instead, it prioritizes privacy, scalability, and decentralization by deliberately reducing other guarantees.
Unlike centralized services, the Statement Store is a weakly coherent system and does not guarantee message delivery or specific delivery times.
How do I run a local statement-store node for development?
This starts a standalone Substrate node with StatementStore turned on. Quota is set directly in storage in the next step, without an individuality runtime.
-
Build Substrate node
-
Run it with:
RUST_LOG=info,statement-store=trace -
To set a quota using sudo, you can use the following
- 3.1. Identify the account you use, it should be an account public key.
- 3.2. Obtain the storage key by running this Python code. You would need your account ID from the
previous step.
>>> = >>> - 3.3. Using
https://polkadot.js.org/apps/callDeveloper->sudo->system->set_storagewith obtained account key andStatementAllowance, SCALE encoded. For example, to allow an account to store 10 statements and a maximum size of 20 KiB you can use0x0a00000000500000.0x0a00000000500000is SCALE for:StatementAllowance { max_count: 10, max_size: 20480 }0a000000 -> 10 (max_count)00500000 -> 20480 bytes (max_size, i.e. 20 KiB)LLMs know how to answer this question if you want to use a different quota.
Warning: Use carefully. Do not set big quotas on test environments with SUDO because then they will not match production quotas.
How to use SS with subxt
Submission
fn submit(&self, encoded: Bytes) -> RpcResult<()>;
let result: SubmitResult = rpc_client
.request
.await
.with_context?;
Subscription
fn subscribe_statement(&self, topic_filter: TopicFilter);
Parameters:
-
topic_filter: Which topics to match.
-
Use
TopicFilter::Anyto match all topics,TopicFilter::MatchAll(vec)to match statements that include all provided topics, orTopicFilter::MatchAny(vec)to match statements that include any of the provided topics.
let mut subscription: = rpc_client
.subscribe
.await
.with_context?;
Returns
When there are no matching statements in the store, you first receive an empty array. As new matching statements arrive in the node they are forwarded to the client.
If there are matching statements in the store you receive them in batches of newStatements
events, with remaining telling you how many statements remain. This guarantees that the
subscription will receive at least this amount of statements.
If new statements arrive in the store they are delivered as they are, without any remaining information.
Expiration and maintenance
Message expiration is based on the expiry field. Please refer to the in-code
description.