diff --git a/Cargo.lock b/Cargo.lock
index e213136785be5..df4247cd6a8f9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -20793,6 +20793,7 @@ dependencies = [
name = "sc-statement-store"
version = "10.0.0"
dependencies = [
+ "criterion",
"log",
"parity-db",
"parking_lot 0.12.3",
diff --git a/prdoc/pr_9884.prdoc b/prdoc/pr_9884.prdoc
new file mode 100644
index 0000000000000..12fe580a2c3a6
--- /dev/null
+++ b/prdoc/pr_9884.prdoc
@@ -0,0 +1,14 @@
+title: Add criterion benches for statement-store
+doc:
+- audience: Node Dev
+ description: |-
+ # Description
+
+ Adds micro benches simulating concurrent work with the statement-store.
+
+ ## Integration
+
+ This PR does not not affect downstream projects.
+crates:
+- name: sc-statement-store
+ bump: none
diff --git a/substrate/client/statement-store/Cargo.toml b/substrate/client/statement-store/Cargo.toml
index c0219b294cede..04edc6d0e74b9 100644
--- a/substrate/client/statement-store/Cargo.toml
+++ b/substrate/client/statement-store/Cargo.toml
@@ -30,5 +30,11 @@ sp-statement-store = { workspace = true, default-features = true }
tokio = { features = ["time"], workspace = true, default-features = true }
[dev-dependencies]
+criterion = { workspace = true, default-features = true }
sp-tracing = { workspace = true }
tempfile = { workspace = true }
+
+[[bench]]
+name = "statement_store"
+harness = false
+required-features = []
diff --git a/substrate/client/statement-store/benches/statement_store.rs b/substrate/client/statement-store/benches/statement_store.rs
new file mode 100644
index 0000000000000..6d8cc3ca51c26
--- /dev/null
+++ b/substrate/client/statement-store/benches/statement_store.rs
@@ -0,0 +1,411 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use criterion::{criterion_group, criterion_main, Criterion};
+use sc_statement_store::Store;
+use sp_core::Pair;
+use sp_statement_store::{
+ runtime_api::{InvalidStatement, ValidStatement, ValidateStatement},
+ DecryptionKey, Proof, SignatureVerificationResult, Statement, StatementSource, StatementStore,
+ SubmitResult, Topic,
+};
+use std::sync::Arc;
+
+type Extrinsic = sp_runtime::OpaqueExtrinsic;
+type Hash = sp_core::H256;
+type Hashing = sp_runtime::traits::BlakeTwo256;
+type BlockNumber = u64;
+type Header = sp_runtime::generic::Header;
+type Block = sp_runtime::generic::Block;
+
+const CORRECT_BLOCK_HASH: [u8; 32] = [1u8; 32];
+const STATEMENT_DATA_SIZE: usize = 256;
+const INITIAL_STATEMENTS: usize = 1_000;
+const NUM_THREADS: usize = 64;
+const OPS_PER_THREAD: usize = 10;
+const TOTAL_OPS: usize = NUM_THREADS * OPS_PER_THREAD;
+
+#[derive(Clone)]
+struct TestClient;
+
+struct RuntimeApi {
+ _inner: TestClient,
+}
+
+impl sp_api::ProvideRuntimeApi for TestClient {
+ type Api = RuntimeApi;
+ fn runtime_api(&self) -> sp_api::ApiRef {
+ RuntimeApi { _inner: self.clone() }.into()
+ }
+}
+
+sp_api::mock_impl_runtime_apis! {
+ impl ValidateStatement for RuntimeApi {
+ fn validate_statement(
+ _source: StatementSource,
+ statement: Statement,
+ ) -> std::result::Result {
+ match statement.verify_signature() {
+ SignatureVerificationResult::Valid(_) =>
+ Ok(ValidStatement { max_count: 100_000, max_size: 1_000_000 }),
+ SignatureVerificationResult::Invalid => Err(InvalidStatement::BadProof),
+ SignatureVerificationResult::NoSignature => {
+ if let Some(Proof::OnChain { block_hash, .. }) = statement.proof() {
+ if block_hash == &CORRECT_BLOCK_HASH {
+ Ok(ValidStatement { max_count: 100_000, max_size: 1_000_000 })
+ } else {
+ Err(InvalidStatement::BadProof)
+ }
+ } else {
+ Err(InvalidStatement::BadProof)
+ }
+ },
+ }
+ }
+ }
+}
+
+impl sp_blockchain::HeaderBackend for TestClient {
+ fn header(&self, _hash: Hash) -> sp_blockchain::Result