Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
853a9df
Extend submission result types
AndreiEres Nov 25, 2025
c6d8e87
Remove NetworkPriority (which was never used)
AndreiEres Nov 28, 2025
1cc5ae9
Add Invalid result
AndreiEres Nov 28, 2025
550d9fa
Handle encoding_too_large
AndreiEres Nov 28, 2025
b153d0f
Add rejected variant
AndreiEres Nov 28, 2025
32b198b
Update from github-actions[bot] running command 'prdoc --audience nod…
github-actions[bot] Nov 28, 2025
31a606b
Update
AndreiEres Nov 28, 2025
bc77940
Update
AndreiEres Nov 28, 2025
67d915f
Update PR doc
AndreiEres Nov 28, 2025
068364a
Fix PR doc
AndreiEres Nov 28, 2025
4b6cc03
Update substrate/client/rpc-api/src/statement/mod.rs
AndreiEres Dec 1, 2025
89c3c37
Fix assertion
AndreiEres Dec 1, 2025
a3a0a90
Don't copy types
AndreiEres Dec 2, 2025
534ec44
statement-store: api changes
alexggh Dec 2, 2025
b3d1b36
Merge remote-tracking branch 'origin/AndreiEres/sss-rpc-types' into o…
alexggh Dec 2, 2025
6ef12d3
Merge remote-tracking branch 'origin/master' into alexggh/api-consoli…
alexggh Dec 3, 2025
af1be1d
remove replacement_preference_mask
alexggh Dec 3, 2025
c394914
remove unused
alexggh Dec 3, 2025
3ad1478
remove unused
alexggh Dec 3, 2025
31d3f53
remove unused
alexggh Dec 3, 2025
03fcc46
Merge remote-tracking branch 'origin/master' into alexggh/api-consoli…
alexggh Dec 9, 2025
acf0103
address feedback
alexggh Dec 9, 2025
65cd2ec
fixup documentation
alexggh Dec 9, 2025
e97cb8f
fix documentation
alexggh Dec 9, 2025
eca03c7
remove non-api changes for now
alexggh Dec 9, 2025
f43fc81
fix typos
alexggh Dec 9, 2025
849c17f
remove original api
alexggh Dec 9, 2025
dad2bd3
statement-store: implement new api
alexggh Dec 9, 2025
ec178a0
update and use statement_store_bench
alexggh Jan 7, 2026
af3d636
send existing statements
alexggh Jan 8, 2026
1ddc597
added more tests
alexggh Jan 8, 2026
4138d92
bench configure connections properly
alexggh Jan 8, 2026
fa73bd7
add periodical expiration of statements
alexggh Jan 8, 2026
54be894
Merge remote-tracking branch 'origin/master' into alexggh/api-consoli…
alexggh Jan 8, 2026
c157a26
make clippy happy
alexggh Jan 9, 2026
55b7c28
fix build
alexggh Jan 9, 2026
cf81c8a
Merge remote-tracking branch 'origin/master' into pr-10690
alexggh Jan 9, 2026
a7e65cd
make clippy happy
alexggh Jan 12, 2026
004f80b
remove unused function
alexggh Jan 12, 2026
4ec4df4
review feedback
alexggh Jan 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 11 additions & 14 deletions cumulus/parachains/runtimes/people/people-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1152,8 +1152,10 @@ impl_runtime_apis! {
_source: StatementSource,
statement: Statement,
) -> Result<ValidStatement, InvalidStatement> {
let account = match statement.verify_signature() {
SignatureVerificationResult::Valid(account) => account.into(),
match statement.verify_signature() {
SignatureVerificationResult::Valid(account) => {
tracing::debug!(target: "runtime", "Valid statement signature from account: {:?}", account);
},
SignatureVerificationResult::Invalid => {
tracing::debug!(target: "runtime", "Bad statement signature.");
return Err(InvalidStatement::BadProof)
Expand All @@ -1164,19 +1166,14 @@ impl_runtime_apis! {
},
};

// For now just allow validators to store some statements.
// For now just allow a small quota to everyone to help with testing.
// Later we will have more sophisticated checks here.
// In the future we will allow people.
if pallet_session::Validators::<Runtime>::get().contains(&account) {
Ok(ValidStatement {
max_count: 2,
max_size: 1024,
})
} else {
Ok(ValidStatement {
max_count: 0,
max_size: 0,
})
}
Ok(ValidStatement {
max_count: 2 * 1024,
max_size: 1024 * 10,
})

}
}
}
Expand Down
4 changes: 3 additions & 1 deletion cumulus/polkadot-omni-node/lib/src/common/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub(crate) trait BuildRpcExtensions<Client, Backend, Pool, StatementStore> {
backend: Arc<Backend>,
pool: Arc<Pool>,
statement_store: Option<Arc<StatementStore>>,
spawn_handle: Arc<dyn sp_core::traits::SpawnNamed>,
) -> sc_service::error::Result<RpcExtension>;
}

Expand All @@ -66,6 +67,7 @@ where
sc_transaction_pool::TransactionPoolHandle<Block, ParachainClient<Block, RuntimeApi>>,
>,
statement_store: Option<Arc<sc_statement_store::Store>>,
spawn_handle: Arc<dyn sp_core::traits::SpawnNamed>,
) -> sc_service::error::Result<RpcExtension> {
let build = || -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>> {
let mut module = RpcExtension::new(());
Expand All @@ -74,7 +76,7 @@ where
module.merge(TransactionPayment::new(client.clone()).into_rpc())?;
module.merge(StateMigration::new(client.clone(), backend).into_rpc())?;
if let Some(statement_store) = statement_store {
module.merge(StatementStore::new(statement_store).into_rpc())?;
module.merge(StatementStore::new(statement_store, spawn_handle).into_rpc())?;
}
module.merge(Dev::new(client).into_rpc())?;

Expand Down
4 changes: 3 additions & 1 deletion cumulus/polkadot-omni-node/lib/src/common/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,18 +449,20 @@ pub(crate) trait NodeSpec: BaseNodeSpec {
);
}

let spawn_handle = Arc::new(task_manager.spawn_handle());

let rpc_builder = {
let client = client.clone();
let transaction_pool = transaction_pool.clone();
let backend_for_rpc = backend.clone();
let statement_store = statement_store.clone();

Box::new(move |_| {
Self::BuildRpcExtensions::build_rpc_extensions(
client.clone(),
backend_for_rpc.clone(),
transaction_pool.clone(),
statement_store.clone(),
spawn_handle.clone(),
)
})
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub(crate) fn build_statement_store<
client,
local_keystore,
parachain_config.prometheus_registry(),
&task_manager.spawn_handle(),
Box::new(task_manager.spawn_handle()),
)
.map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;
let statement_protocol_executor = {
Expand Down
3 changes: 2 additions & 1 deletion cumulus/polkadot-omni-node/lib/src/nodes/aura.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ where
);
},
}

let spawn_handle = Arc::new(task_manager.spawn_handle());
let rpc_extensions_builder = {
let client = client.clone();
let transaction_pool = transaction_pool.clone();
Expand All @@ -363,6 +363,7 @@ where
backend_for_rpc.clone(),
transaction_pool.clone(),
None,
spawn_handle.clone(),
)?;
Ok(module)
})
Expand Down
2 changes: 1 addition & 1 deletion cumulus/zombienet/zombienet-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ zombienet-orchestrator = { workspace = true }
zombienet-configuration = { workspace = true }
cumulus-zombienet-sdk-helpers = { workspace = true }
cumulus-test-runtime = { workspace = true }
sp-statement-store = { workspace = true, default-features = true }
sp-statement-store = { workspace = true, features = ["serde"], default-features = true }
sc-statement-store = { workspace = true, default-features = true }
sp-keyring = { workspace = true, default-features = true }
sp-core = { workspace = true, default-features = true }
Expand Down
59 changes: 32 additions & 27 deletions cumulus/zombienet/zombienet-sdk/tests/zombie_ci/statement_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
// Test that people-westend enables the statement store in the node and that statements are
// propagated to peers.

use std::time::Duration;

use anyhow::anyhow;
use sp_core::{Bytes, Encode};
use sp_statement_store::{SubmitResult, TopicFilter};
use zombienet_sdk::{subxt::ext::subxt_rpcs::rpc_params, NetworkConfigBuilder};

#[tokio::test(flavor = "multi_thread")]
Expand Down Expand Up @@ -36,7 +39,7 @@ async fn statement_store() -> Result<(), anyhow::Error> {
.with_chain("people-westend-local")
.with_default_args(vec![
"--force-authoring".into(),
"-lparachain=debug".into(),
"-linfo,statement-gossip=debug,statement-store=debug".into(),
"--enable-statement-store".into(),
])
.with_collator(|n| n.with_name("charlie"))
Expand Down Expand Up @@ -64,40 +67,42 @@ async fn statement_store() -> Result<(), anyhow::Error> {

// Create the statement "1,2,3" signed by dave.
let mut statement = sp_statement_store::Statement::new();
let topic = [0u8; 32]; // just a dummy topic
statement.set_plain_data(vec![1, 2, 3]);
statement.set_topic(0, topic);
statement.set_expiry_from_parts(u32::MAX, 0);
let dave = sp_keyring::Sr25519Keyring::Dave;
statement.sign_sr25519_private(&dave.pair());
let statement: Bytes = statement.encode().into();
// Subscribe to statements with topic "topic" to dave.
let stop_after_secs = 20;
let mut subscription = dave_rpc
.subscribe::<Bytes>(
"statement_subscribeStatement",
rpc_params![TopicFilter::MatchAll(vec![topic.to_vec().into()])],
"statement_unsubscribeStatement",
)
.await?;

// Submit the statement to charlie.
let _: () = charlie_rpc.request("statement_submit", rpc_params![statement.clone()]).await?;

// Ensure that charlie stored the statement.
let charlie_dump: Vec<Bytes> = charlie_rpc.request("statement_dump", rpc_params![]).await?;
if charlie_dump != vec![statement.clone()] {
return Err(anyhow!("Charlie did not store the statement"));
}

// Query dave until it receives the statement, stop if 20 seconds passed.
let query_start_time = std::time::SystemTime::now();
let stop_after_secs = 20;
loop {
let dave_dump: Vec<Bytes> = dave_rpc.request("statement_dump", rpc_params![]).await?;
if !dave_dump.is_empty() {
if dave_dump != vec![statement.clone()] {
return Err(anyhow!("Dave statement store is not the expected one"));
}
break;
}
let _: SubmitResult =
charlie_rpc.request("statement_submit", rpc_params![statement.clone()]).await?;

let elapsed =
query_start_time.elapsed().map_err(|_| anyhow!("Failed to get elapsed time"))?;
if elapsed.as_secs() > stop_after_secs {
return Err(anyhow!("Dave did not receive the statement in time"));
}
let statement_bytes =
tokio::time::timeout(Duration::from_secs(stop_after_secs), subscription.next())
.await
.expect("Should not timeout")
.expect("Should receive")
.expect("Should not error");

tokio::time::sleep(core::time::Duration::from_secs(1)).await;
}
assert_eq!(statement_bytes, statement);
// Now make sure no more statements are received.
assert!(tokio::time::timeout(Duration::from_secs(stop_after_secs), subscription.next())
.await
.is_err());
log::info!("Statement store test passed");
log::info!("Keeping network alive");

tokio::time::sleep(Duration::from_hours(24)).await;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we need hang the test for 24h?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is there for App guys to have a node setup they can run locally, will remove it before merge.

Ok(())
}
Loading