diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index ba5b855db9a65cabee3da43a16063e2c51513b0f..d0578a77a91e960b2a7b3e78aaaa87c6167172d2 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -10159,6 +10159,7 @@ dependencies = [
  "parity-db",
  "parking_lot 0.12.1",
  "sc-client-api",
+ "sc-keystore",
  "sp-api",
  "sp-blockchain",
  "sp-core",
@@ -11592,8 +11593,14 @@ dependencies = [
 name = "sp-statement-store"
 version = "4.0.0-dev"
 dependencies = [
+ "aes-gcm 0.10.2",
+ "curve25519-dalek 3.2.0",
+ "ed25519-dalek",
+ "hkdf",
  "parity-scale-codec",
+ "rand 0.8.5",
  "scale-info",
+ "sha2 0.10.6",
  "sp-api",
  "sp-application-crypto",
  "sp-core",
@@ -11602,6 +11609,7 @@ dependencies = [
  "sp-runtime-interface",
  "sp-std",
  "thiserror",
+ "x25519-dalek 2.0.0-pre.1",
 ]
 
 [[package]]
diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs
index 5fb5e77c0601271be34da38374ca3c8a9efb76b6..99608c04d38b55f6710021d13037d5994f8ac436 100644
--- a/substrate/bin/node/cli/src/service.rs
+++ b/substrate/bin/node/cli/src/service.rs
@@ -241,6 +241,7 @@ pub fn new_partial(
 		&config.data_path,
 		Default::default(),
 		client.clone(),
+		keystore_container.local_keystore(),
 		config.prometheus_registry(),
 		&task_manager.spawn_handle(),
 	)
diff --git a/substrate/client/cli/src/runner.rs b/substrate/client/cli/src/runner.rs
index c96f494354f9a39e45468746e722e164cf4750da..59f53200a192bce80a0e5b151ce78db26f87c195 100644
--- a/substrate/client/cli/src/runner.rs
+++ b/substrate/client/cli/src/runner.rs
@@ -400,7 +400,7 @@ mod tests {
 			},
 		);
 
-		let Some(output) = output else { return } ;
+		let Some(output) = output else { return };
 
 		let stderr = dbg!(String::from_utf8(output.stderr).unwrap());
 
diff --git a/substrate/client/keystore/src/lib.rs b/substrate/client/keystore/src/lib.rs
index 4151f8c4dc1a483d24f4e6a27bb3220e202a90cf..2d353f3ceba5d715d7c9b01e9a1f04e7a9a86c4e 100644
--- a/substrate/client/keystore/src/lib.rs
+++ b/substrate/client/keystore/src/lib.rs
@@ -26,6 +26,7 @@ use std::io;
 /// Local keystore implementation
 mod local;
 pub use local::LocalKeystore;
+pub use sp_keystore::Keystore;
 
 /// Keystore error.
 #[derive(Debug, thiserror::Error)]
diff --git a/substrate/client/network/src/discovery.rs b/substrate/client/network/src/discovery.rs
index b6cb29584658f14d2026effb34001c41029fec86..d9fad538443463a5a6474cc3b90e8e954203f086 100644
--- a/substrate/client/network/src/discovery.rs
+++ b/substrate/client/network/src/discovery.rs
@@ -548,7 +548,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
 		addresses: &[Multiaddr],
 		effective_role: Endpoint,
 	) -> Result<Vec<Multiaddr>, ConnectionDenied> {
-		let Some(peer_id) = maybe_peer else { return Ok(Vec::new()); };
+		let Some(peer_id) = maybe_peer else { return Ok(Vec::new()) };
 
 		let mut list = self
 			.permanent_addresses
diff --git a/substrate/client/network/src/protocol_controller.rs b/substrate/client/network/src/protocol_controller.rs
index 9a77881c63320dccf7c8b68cb5e748bb8522e7d9..5b421e1485d69e8e6c3f9c493210f20a8bebb522 100644
--- a/substrate/client/network/src/protocol_controller.rs
+++ b/substrate/client/network/src/protocol_controller.rs
@@ -658,9 +658,7 @@ impl ProtocolController {
 	/// disconnected, `Ok(false)` if it wasn't found, `Err(PeerId)`, if the peer found, but not in
 	/// connected state.
 	fn drop_reserved_peer(&mut self, peer_id: &PeerId) -> Result<bool, PeerId> {
-		let Some(state) = self.reserved_nodes.get_mut(peer_id) else {
-			return Ok(false)
-		};
+		let Some(state) = self.reserved_nodes.get_mut(peer_id) else { return Ok(false) };
 
 		if let PeerState::Connected(direction) = state {
 			trace!(
@@ -678,9 +676,7 @@ impl ProtocolController {
 	/// Try dropping the peer as a regular peer. Return `true` if the peer was found and
 	/// disconnected, `false` if it wasn't found.
 	fn drop_regular_peer(&mut self, peer_id: &PeerId) -> bool {
-		let Some(direction) = self.nodes.remove(peer_id) else {
-			return false
-		};
+		let Some(direction) = self.nodes.remove(peer_id) else { return false };
 
 		trace!(
 			target: LOG_TARGET,
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs b/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs
index bb3599c0e4ae59325b7c25831509c7767999ca3c..a61406b8d53b83769224ec93e10c5e5ce7096e45 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs
@@ -162,7 +162,8 @@ where
 			},
 		};
 		// Keep track of the subscription.
-		let Some(rx_stop) = self.subscriptions.insert_subscription(sub_id.clone(), with_runtime) else {
+		let Some(rx_stop) = self.subscriptions.insert_subscription(sub_id.clone(), with_runtime)
+		else {
 			// Inserting the subscription can only fail if the JsonRPSee
 			// generated a duplicate subscription ID.
 			debug!(target: LOG_TARGET, "[follow][id={:?}] Subscription already accepted", sub_id);
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs b/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs
index cb6af8bd590b3a5a0252ff91acf39a510e252a5a..799978be532ae20632aec2b77a5920c2e34996de 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs
@@ -339,9 +339,7 @@ where
 		let mut events = Vec::new();
 
 		// Nothing to be done if no finalized hashes are provided.
-		let Some(first_hash) = finalized_block_hashes.get(0) else {
-			return Ok(Default::default())
-		};
+		let Some(first_hash) = finalized_block_hashes.get(0) else { return Ok(Default::default()) };
 
 		// Find the parent header.
 		let Some(first_header) = self.client.header(*first_hash)? else {
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs b/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs
index adab64a01c875372f9ed538f29489c0f41c04586..be8b8f46a28440d7408696f5550895ba641c501f 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs
@@ -328,9 +328,7 @@ impl<Block: BlockT, BE: Backend<Block>> SubscriptionsInner<Block, BE> {
 
 	/// Remove the subscription ID with associated pinned blocks.
 	pub fn remove_subscription(&mut self, sub_id: &str) {
-		let Some(mut sub) = self.subs.remove(sub_id) else {
-			return
-		};
+		let Some(mut sub) = self.subs.remove(sub_id) else { return };
 
 		// The `Stop` event can be generated only once.
 		sub.stop();
diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs
index c987c2471907d65d125470eaa40737b136007c87..0961967f9ca20a039e12b560b3ba6cb6cea24659 100644
--- a/substrate/client/service/src/lib.rs
+++ b/substrate/client/service/src/lib.rs
@@ -237,7 +237,7 @@ pub async fn build_system_rpc_future<
 		// Answer incoming RPC requests.
 		let Some(req) = rpc_rx.next().await else {
 			debug!("RPC requests stream has terminated, shutting down the system RPC future.");
-			return;
+			return
 		};
 
 		match req {
diff --git a/substrate/client/statement-store/Cargo.toml b/substrate/client/statement-store/Cargo.toml
index bb2d7aa2feaa53e6ee7ecf706c827130bd8b9d7e..8668dbfa8ba03a2e6e514507ba8089b6b9233d77 100644
--- a/substrate/client/statement-store/Cargo.toml
+++ b/substrate/client/statement-store/Cargo.toml
@@ -24,6 +24,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" }
 sp-core = { version = "21.0.0", path = "../../primitives/core" }
 sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" }
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
+sc-keystore = { version = "4.0.0-dev", path = "../../client/keystore" }
 
 [dev-dependencies]
 tempfile = "3.1.0"
diff --git a/substrate/client/statement-store/src/lib.rs b/substrate/client/statement-store/src/lib.rs
index 3b42641d9c5ab1fbd907f7805451a858b7e3e695..da0af08b45402a9e2df83dbd6f9f91e4d4d99311 100644
--- a/substrate/client/statement-store/src/lib.rs
+++ b/substrate/client/statement-store/src/lib.rs
@@ -54,9 +54,10 @@ pub use sp_statement_store::{Error, StatementStore, MAX_TOPICS};
 use metrics::MetricsLink as PrometheusMetrics;
 use parking_lot::RwLock;
 use prometheus_endpoint::Registry as PrometheusRegistry;
+use sc_keystore::LocalKeystore;
 use sp_api::ProvideRuntimeApi;
 use sp_blockchain::HeaderBackend;
-use sp_core::{hexdisplay::HexDisplay, traits::SpawnNamed, Decode, Encode};
+use sp_core::{crypto::UncheckedFrom, hexdisplay::HexDisplay, traits::SpawnNamed, Decode, Encode};
 use sp_runtime::traits::Block as BlockT;
 use sp_statement_store::{
 	runtime_api::{
@@ -201,6 +202,7 @@ pub struct Store {
 			+ Send
 			+ Sync,
 	>,
+	keystore: Arc<LocalKeystore>,
 	// Used for testing
 	time_override: Option<u64>,
 	metrics: PrometheusMetrics,
@@ -479,6 +481,7 @@ impl Store {
 		path: &std::path::Path,
 		options: Options,
 		client: Arc<Client>,
+		keystore: Arc<LocalKeystore>,
 		prometheus: Option<&PrometheusRegistry>,
 		task_spawner: &dyn SpawnNamed,
 	) -> Result<Arc<Store>>
@@ -493,7 +496,7 @@ impl Store {
 			+ 'static,
 		Client::Api: ValidateStatement<Block>,
 	{
-		let store = Arc::new(Self::new(path, options, client, prometheus)?);
+		let store = Arc::new(Self::new(path, options, client, keystore, prometheus)?);
 
 		// Perform periodic statement store maintenance
 		let worker_store = store.clone();
@@ -518,6 +521,7 @@ impl Store {
 		path: &std::path::Path,
 		options: Options,
 		client: Arc<Client>,
+		keystore: Arc<LocalKeystore>,
 		prometheus: Option<&PrometheusRegistry>,
 	) -> Result<Store>
 	where
@@ -566,6 +570,7 @@ impl Store {
 			db,
 			index: RwLock::new(Index::new(options)),
 			validate_fn,
+			keystore,
 			time_override: None,
 			metrics: PrometheusMetrics::new(prometheus),
 		};
@@ -768,7 +773,45 @@ impl StatementStore for Store {
 	/// Return the decrypted data of all known statements whose decryption key is identified as
 	/// `dest`. The key must be available to the client.
 	fn posted_clear(&self, match_all_topics: &[Topic], dest: [u8; 32]) -> Result<Vec<Vec<u8>>> {
-		self.collect_statements(Some(dest), match_all_topics, |statement| statement.into_data())
+		self.collect_statements(Some(dest), match_all_topics, |statement| {
+			if let (Some(key), Some(_)) = (statement.decryption_key(), statement.data()) {
+				let public: sp_core::ed25519::Public = UncheckedFrom::unchecked_from(key);
+				let public: sp_statement_store::ed25519::Public = public.into();
+				match self.keystore.key_pair::<sp_statement_store::ed25519::Pair>(&public) {
+					Err(e) => {
+						log::debug!(
+							target: LOG_TARGET,
+							"Keystore error: {:?}, for statement {:?}",
+							e,
+							HexDisplay::from(&statement.hash())
+						);
+						None
+					},
+					Ok(None) => {
+						log::debug!(
+							target: LOG_TARGET,
+							"Keystore is missing key for statement {:?}",
+							HexDisplay::from(&statement.hash())
+						);
+						None
+					},
+					Ok(Some(pair)) => match statement.decrypt_private(&pair.into_inner()) {
+						Ok(r) => r,
+						Err(e) => {
+							log::debug!(
+								target: LOG_TARGET,
+								"Decryption error: {:?}, for statement {:?}",
+								e,
+								HexDisplay::from(&statement.hash())
+							);
+							None
+						},
+					},
+				}
+			} else {
+				None
+			}
+		})
 	}
 
 	/// Submit a statement to the store. Validates the statement and returns validation result.
@@ -887,6 +930,7 @@ impl StatementStore for Store {
 #[cfg(test)]
 mod tests {
 	use crate::Store;
+	use sc_keystore::Keystore;
 	use sp_core::Pair;
 	use sp_statement_store::{
 		runtime_api::{InvalidStatement, ValidStatement, ValidateStatement},
@@ -916,6 +960,7 @@ mod tests {
 			RuntimeApi { _inner: self.clone() }.into()
 		}
 	}
+
 	sp_api::mock_impl_runtime_apis! {
 		impl ValidateStatement<Block> for RuntimeApi {
 			fn validate_statement(
@@ -983,7 +1028,8 @@ mod tests {
 		let client = std::sync::Arc::new(TestClient);
 		let mut path: std::path::PathBuf = temp_dir.path().into();
 		path.push("db");
-		let store = Store::new(&path, Default::default(), client, None).unwrap();
+		let keystore = std::sync::Arc::new(sc_keystore::LocalKeystore::in_memory());
+		let store = Store::new(&path, Default::default(), client, keystore, None).unwrap();
 		(store, temp_dir) // return order is important. Store must be dropped before TempDir
 	}
 
@@ -1086,12 +1132,13 @@ mod tests {
 		assert_eq!(store.statements().unwrap().len(), 3);
 		assert_eq!(store.broadcasts(&[]).unwrap().len(), 3);
 		assert_eq!(store.statement(&statement1.hash()).unwrap(), Some(statement1.clone()));
+		let keystore = store.keystore.clone();
 		drop(store);
 
 		let client = std::sync::Arc::new(TestClient);
 		let mut path: std::path::PathBuf = temp.path().into();
 		path.push("db");
-		let store = Store::new(&path, Default::default(), client, None).unwrap();
+		let store = Store::new(&path, Default::default(), client, keystore, None).unwrap();
 		assert_eq!(store.statements().unwrap().len(), 3);
 		assert_eq!(store.broadcasts(&[]).unwrap().len(), 3);
 		assert_eq!(store.statement(&statement1.hash()).unwrap(), Some(statement1));
@@ -1196,7 +1243,6 @@ mod tests {
 			statement(2, 4, None, 1000).hash(),
 			statement(3, 4, Some(3), 300).hash(),
 			statement(3, 5, None, 500).hash(),
-			//statement(4, 6, None, 100).hash(),
 		];
 		expected_statements.sort();
 		let mut statements: Vec<_> =
@@ -1220,13 +1266,31 @@ mod tests {
 		store.set_time(DEFAULT_PURGE_AFTER_SEC + 1);
 		store.maintain();
 		assert_eq!(store.index.read().expired.len(), 0);
+		let keystore = store.keystore.clone();
 		drop(store);
 
 		let client = std::sync::Arc::new(TestClient);
 		let mut path: std::path::PathBuf = temp.path().into();
 		path.push("db");
-		let store = Store::new(&path, Default::default(), client, None).unwrap();
+		let store = Store::new(&path, Default::default(), client, keystore, None).unwrap();
 		assert_eq!(store.statements().unwrap().len(), 0);
 		assert_eq!(store.index.read().expired.len(), 0);
 	}
+
+	#[test]
+	fn posted_clear_decrypts() {
+		let (store, _temp) = test_store();
+		let public = store
+			.keystore
+			.ed25519_generate_new(sp_core::crypto::key_types::STATEMENT, None)
+			.unwrap();
+		let statement1 = statement(1, 1, None, 100);
+		let mut statement2 = statement(1, 2, None, 0);
+		let plain = b"The most valuable secret".to_vec();
+		statement2.encrypt(&plain, &public).unwrap();
+		store.submit(statement1, StatementSource::Network);
+		store.submit(statement2, StatementSource::Network);
+		let posted_clear = store.posted_clear(&[], public.into()).unwrap();
+		assert_eq!(posted_clear, vec![plain]);
+	}
 }
diff --git a/substrate/frame/glutton/src/lib.rs b/substrate/frame/glutton/src/lib.rs
index ae3e4f87f0e80cf3669f061dc258fd468c2ad59d..838bd9b67d2965ae2bf66ec5102213b441883f4e 100644
--- a/substrate/frame/glutton/src/lib.rs
+++ b/substrate/frame/glutton/src/lib.rs
@@ -271,9 +271,7 @@ pub mod pallet {
 		///
 		/// Tries to come as close to the limit as possible.
 		pub(crate) fn waste_at_most_proof_size(meter: &mut WeightMeter) {
-			let Ok(n) = Self::calculate_proof_size_iters(&meter) else {
-				return;
-			};
+			let Ok(n) = Self::calculate_proof_size_iters(&meter) else { return };
 
 			meter.defensive_saturating_accrue(T::WeightInfo::waste_proof_size_some(n));
 
@@ -303,9 +301,7 @@ pub mod pallet {
 		///
 		/// Tries to come as close to the limit as possible.
 		pub(crate) fn waste_at_most_ref_time(meter: &mut WeightMeter) {
-			let Ok(n) = Self::calculate_ref_time_iters(&meter) else {
-				return;
-			};
+			let Ok(n) = Self::calculate_ref_time_iters(&meter) else { return };
 			meter.defensive_saturating_accrue(T::WeightInfo::waste_ref_time_iter(n));
 
 			let clobber = Self::waste_ref_time_iter(vec![0u8; 64], n);
diff --git a/substrate/frame/support/procedural/src/benchmark.rs b/substrate/frame/support/procedural/src/benchmark.rs
index 18d672b9b0508ddc3daf65efb9ba916f20385875..9f28e7129d2e1b1e2d38b4f55de5a795677d2824 100644
--- a/substrate/frame/support/procedural/src/benchmark.rs
+++ b/substrate/frame/support/procedural/src/benchmark.rs
@@ -166,11 +166,11 @@ fn ensure_valid_return_type(item_fn: &ItemFn) -> Result<()> {
 	if let ReturnType::Type(_, typ) = &item_fn.sig.output {
 		let non_unit = |span| return Err(Error::new(span, "expected `()`"));
 		let Type::Path(TypePath { path, qself: _ }) = &**typ else {
-				return Err(Error::new(
+			return Err(Error::new(
 					typ.span(),
 					"Only `Result<(), BenchmarkError>` or a blank return type is allowed on benchmark function definitions",
 				))
-			};
+		};
 		let seg = path
 			.segments
 			.last()
@@ -780,7 +780,7 @@ fn expand_benchmark(
 			let call_name = match *expr_call.func {
 				Expr::Path(expr_path) => {
 					// normal function call
-					let Some(segment) = expr_path.path.segments.last() else { return call_err(); };
+					let Some(segment) = expr_path.path.segments.last() else { return call_err() };
 					segment.ident.to_string()
 				},
 				Expr::Infer(_) => {
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs
index 544f63be2bfa14dc2076831bdb6609ad3c8ad342..b78360d5fc052200e0fcd09942f9882406785109 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs
@@ -100,9 +100,7 @@ pub fn expand_outer_enum(
 	let enum_name_ident = Ident::new(enum_ty.struct_name(), Span::call_site());
 
 	for pallet_decl in pallet_decls {
-		let Some(pallet_entry) = pallet_decl.find_part(enum_name_str) else {
-			continue
-		};
+		let Some(pallet_entry) = pallet_decl.find_part(enum_name_str) else { continue };
 
 		let path = &pallet_decl.path;
 		let pallet_name = &pallet_decl.name;
diff --git a/substrate/primitives/api/proc-macro/src/runtime_metadata.rs b/substrate/primitives/api/proc-macro/src/runtime_metadata.rs
index d027e86fac4ef36c219a531a22fbc05d96a9b632..41849401291e633924e6f530ffc5bc3474ba6283 100644
--- a/substrate/primitives/api/proc-macro/src/runtime_metadata.rs
+++ b/substrate/primitives/api/proc-macro/src/runtime_metadata.rs
@@ -88,9 +88,7 @@ pub fn generate_decl_runtime_metadata(decl: &ItemTrait) -> TokenStream2 {
 	let mut where_clause = Vec::new();
 	for item in &decl.items {
 		// Collect metadata for methods only.
-		let syn::TraitItem::Fn(method) = item else {
-			continue
-		};
+		let syn::TraitItem::Fn(method) = item else { continue };
 
 		// Collect metadata only for the latest methods.
 		let is_changed_in =
@@ -103,9 +101,7 @@ pub fn generate_decl_runtime_metadata(decl: &ItemTrait) -> TokenStream2 {
 		let signature = &method.sig;
 		for input in &signature.inputs {
 			// Exclude `self` from metadata collection.
-			let syn::FnArg::Typed(typed) = input else {
-				continue
-			};
+			let syn::FnArg::Typed(typed) = input else { continue };
 
 			let pat = &typed.pat;
 			let name = quote!(#pat).to_string();
@@ -153,9 +149,7 @@ pub fn generate_decl_runtime_metadata(decl: &ItemTrait) -> TokenStream2 {
 	// The trait generics where already extended with `Block: BlockT`.
 	let mut generics = decl.generics.clone();
 	for generic_param in generics.params.iter_mut() {
-		let syn::GenericParam::Type(ty) = generic_param else {
-			continue
-		};
+		let syn::GenericParam::Type(ty) = generic_param else { continue };
 
 		// Default type parameters are not allowed in functions.
 		ty.eq_token = None;
diff --git a/substrate/primitives/api/proc-macro/src/utils.rs b/substrate/primitives/api/proc-macro/src/utils.rs
index 7b580ee6f099e31c4f4568e3e2b47b5595de64c5..c9389154bbf40ff780f97e5d096dcaee7f1c1ce2 100644
--- a/substrate/primitives/api/proc-macro/src/utils.rs
+++ b/substrate/primitives/api/proc-macro/src/utils.rs
@@ -266,9 +266,7 @@ pub fn get_doc_literals(attrs: &[syn::Attribute]) -> Vec<syn::Lit> {
 	attrs
 		.iter()
 		.filter_map(|attr| {
-			let syn::Meta::NameValue(meta) = &attr.meta else {
-				return None
-			};
+			let syn::Meta::NameValue(meta) = &attr.meta else { return None };
 			let Ok(lit) = syn::parse2::<syn::Lit>(meta.value.to_token_stream()) else {
 				unreachable!("non-lit doc attribute values do not exist");
 			};
diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs
index 46f59719f9c294bc70523badac30c8ea9b203313..95a25c11a717d2e88d8f3f62203b509603f573a8 100644
--- a/substrate/primitives/application-crypto/src/lib.rs
+++ b/substrate/primitives/application-crypto/src/lib.rs
@@ -179,6 +179,13 @@ macro_rules! app_crypto_pair {
 		impl $crate::AppPair for Pair {
 			type Generic = $pair;
 		}
+
+		impl Pair {
+			/// Convert into wrapped generic key pair type.
+			pub fn into_inner(self) -> $pair {
+				self.0
+			}
+		}
 	};
 }
 
diff --git a/substrate/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs b/substrate/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs
index e9a3208a738efdee8a7333380658954b3ffd9f87..5f3f675c971f21503944a5474bd053faf7dd4873 100644
--- a/substrate/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs
+++ b/substrate/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs
@@ -52,9 +52,7 @@ fn check<N>(f: N, n: N, d: N, r: Rounding)
 where
 	N: MultiplyRational + Into<u128> + Copy + core::fmt::Debug,
 {
-	let Some(got) = f.multiply_rational(n, d, r) else {
-		return;
-	};
+	let Some(got) = f.multiply_rational(n, d, r) else { return };
 
 	let (ae, be, ce) =
 		(Fraction::from(f.into()), Fraction::from(n.into()), Fraction::from(d.into()));
diff --git a/substrate/primitives/blockchain/src/backend.rs b/substrate/primitives/blockchain/src/backend.rs
index e9278be1d5d3c4c1d213fbf61db350831c604572..8208f9128e714511c2a3604d7d754e4d87d62530 100644
--- a/substrate/primitives/blockchain/src/backend.rs
+++ b/substrate/primitives/blockchain/src/backend.rs
@@ -196,9 +196,7 @@ pub trait Backend<Block: BlockT>:
 		base_hash: Block::Hash,
 		import_lock: &RwLock<()>,
 	) -> Result<Option<Block::Hash>> {
-		let Some(base_header) = self.header(base_hash)? else {
-			return Ok(None)
-		};
+		let Some(base_header) = self.header(base_hash)? else { return Ok(None) };
 
 		let leaves = {
 			// ensure no blocks are imported during this code block.
diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml
index f0da73e8ec7891241950773c6f995385ce8fa0e7..f02489a09f05eee1b72fdf1c155fed7df798d657 100644
--- a/substrate/primitives/core/Cargo.toml
+++ b/substrate/primitives/core/Cargo.toml
@@ -57,7 +57,6 @@ sp-runtime-interface = { version = "17.0.0", default-features = false, path = ".
 w3f-bls = { version = "0.1.3", default-features = false, optional = true}
 
 [dev-dependencies]
-rand = "0.8.5"
 criterion = "0.4.0"
 serde_json = "1.0"
 sp-core-hashing-proc-macro = { version = "9.0.0", path = "./hashing/proc-macro" }
diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs
index 9d948a5bcea66915c64bced01c56e04cbe7d04ca..d46f2b5043d61a9d3ddb3f6f4d4a53bf642ee930 100644
--- a/substrate/primitives/core/src/ed25519.rs
+++ b/substrate/primitives/core/src/ed25519.rs
@@ -422,12 +422,8 @@ impl TraitPair for Pair {
 	///
 	/// Returns true if the signature is good.
 	fn verify<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, public: &Self::Public) -> bool {
-		let Ok(public) = VerificationKey::try_from(public.as_slice()) else {
-			return false
-		};
-		let Ok(signature) = ed25519_zebra::Signature::try_from(sig.as_ref()) else {
-			return false
-		};
+		let Ok(public) = VerificationKey::try_from(public.as_slice()) else { return false };
+		let Ok(signature) = ed25519_zebra::Signature::try_from(sig.as_ref()) else { return false };
 		public.verify(&signature, message.as_ref()).is_ok()
 	}
 
diff --git a/substrate/primitives/core/src/sr25519.rs b/substrate/primitives/core/src/sr25519.rs
index 1c040f6ccf7be9be102487d003e07e85c53dfa4b..bcd64ed1cc3cf4d4a4ed79301e5dcc44d1acb925 100644
--- a/substrate/primitives/core/src/sr25519.rs
+++ b/substrate/primitives/core/src/sr25519.rs
@@ -505,12 +505,8 @@ impl TraitPair for Pair {
 	}
 
 	fn verify<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool {
-		let Ok(signature) = schnorrkel::Signature::from_bytes(sig.as_ref()) else {
-			return false
-		};
-		let Ok(public) = PublicKey::from_bytes(pubkey.as_ref()) else {
-			return false
-		};
+		let Ok(signature) = schnorrkel::Signature::from_bytes(sig.as_ref()) else { return false };
+		let Ok(public) = PublicKey::from_bytes(pubkey.as_ref()) else { return false };
 		public.verify_simple(SIGNING_CTX, message.as_ref(), &signature).is_ok()
 	}
 
diff --git a/substrate/primitives/io/src/lib.rs b/substrate/primitives/io/src/lib.rs
index 750b5d592463742cfc55b942034da21be1c80e60..bd20ee0c917aac13feabe73485cc1366c461b472 100644
--- a/substrate/primitives/io/src/lib.rs
+++ b/substrate/primitives/io/src/lib.rs
@@ -776,9 +776,7 @@ pub trait Crypto {
 				return false
 			};
 
-			let Ok(sig) = ed25519_dalek::Signature::from_bytes(&sig.0) else {
-				return false
-			};
+			let Ok(sig) = ed25519_dalek::Signature::from_bytes(&sig.0) else { return false };
 
 			public_key.verify(msg, &sig).is_ok()
 		} else {
diff --git a/substrate/primitives/statement-store/Cargo.toml b/substrate/primitives/statement-store/Cargo.toml
index c0e1a494ab23af28a31003e0fb3f4b6095eb1131..02ee6f4c15521d1fcc7d8702566c1e50b0d03b54 100644
--- a/substrate/primitives/statement-store/Cargo.toml
+++ b/substrate/primitives/statement-store/Cargo.toml
@@ -24,6 +24,15 @@ sp-runtime-interface = { version = "17.0.0", default-features = false, path = ".
 sp-externalities = { version = "0.19.0", default-features = false, path = "../externalities" }
 thiserror = { version = "1.0", optional = true }
 
+# ECIES dependencies
+ed25519-dalek = { version = "1.0", optional = true }
+x25519-dalek = { version = "2.0.0-pre.1", optional = true }
+curve25519-dalek = { version = "3.2", optional = true }
+aes-gcm = { version = "0.10", optional = true }
+hkdf = { version = "0.12.0", optional = true }
+sha2 = { version = "0.10.0", optional = true }
+rand = { version = "0.8.5", features = ["small_rng"],  optional = true }
+
 [features]
 default = ["std"]
 std = [
@@ -36,6 +45,14 @@ std = [
 	"sp-api/std",
 	"sp-application-crypto/std",
 	"thiserror",
+
+	"ed25519-dalek",
+	"x25519-dalek",
+	"curve25519-dalek",
+	"aes-gcm",
+	"hkdf",
+	"sha2",
+	"rand",
 ]
 serde = [
         "scale-info/serde",
diff --git a/substrate/primitives/statement-store/src/ecies.rs b/substrate/primitives/statement-store/src/ecies.rs
new file mode 100644
index 0000000000000000000000000000000000000000..4afd583e03c80165f3f6716054d6181489105f0e
--- /dev/null
+++ b/substrate/primitives/statement-store/src/ecies.rs
@@ -0,0 +1,174 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// tag::description[]
+//! ECIES encryption scheme using x25519 key exchange and AEAD.
+// end::description[]
+
+use aes_gcm::{aead::Aead, AeadCore, KeyInit};
+use rand::rngs::OsRng;
+use sha2::Digest;
+use sp_core::crypto::Pair;
+
+/// x25519 secret key.
+pub type SecretKey = x25519_dalek::StaticSecret;
+/// x25519 public key.
+pub type PublicKey = x25519_dalek::PublicKey;
+
+/// Encryption or decryption error.
+#[derive(Debug, PartialEq, Eq, thiserror::Error)]
+pub enum Error {
+	/// Generic AES encryption error.
+	#[error("Encryption error")]
+	Encryption,
+	/// Generic AES decryption error.
+	#[error("Decryption error")]
+	Decryption,
+	/// Error reading key data. Not enough data in the buffer.
+	#[error("Bad cypher text")]
+	BadData,
+}
+
+const NONCE_LEN: usize = 12;
+const PK_LEN: usize = 32;
+const AES_KEY_LEN: usize = 32;
+
+fn aes_encrypt(key: &[u8; AES_KEY_LEN], nonce: &[u8], plaintext: &[u8]) -> Result<Vec<u8>, Error> {
+	let enc = aes_gcm::Aes256Gcm::new(key.into());
+
+	enc.encrypt(nonce.into(), aes_gcm::aead::Payload { msg: plaintext, aad: b"" })
+		.map_err(|_| Error::Encryption)
+}
+
+fn aes_decrypt(key: &[u8; AES_KEY_LEN], nonce: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
+	let dec = aes_gcm::Aes256Gcm::new(key.into());
+	dec.decrypt(nonce.into(), aes_gcm::aead::Payload { msg: ciphertext, aad: b"" })
+		.map_err(|_| Error::Decryption)
+}
+
+fn kdf(shared_secret: &[u8]) -> [u8; AES_KEY_LEN] {
+	let hkdf = hkdf::Hkdf::<sha2::Sha256>::new(None, shared_secret);
+	let mut aes_key = [0u8; AES_KEY_LEN];
+	hkdf.expand(b"", &mut aes_key)
+		.expect("There's always enough data for derivation. qed.");
+	aes_key
+}
+
+/// Encrypt `plaintext` with the given public x25519 public key. Decryption can be performed with
+/// the matching secret key.
+pub fn encrypt_x25519(pk: &PublicKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
+	let ephemeral_sk = x25519_dalek::StaticSecret::new(OsRng);
+	let ephemeral_pk = x25519_dalek::PublicKey::from(&ephemeral_sk);
+
+	let mut shared_secret = ephemeral_sk.diffie_hellman(pk).to_bytes().to_vec();
+	shared_secret.extend_from_slice(ephemeral_pk.as_bytes());
+
+	let aes_key = kdf(&shared_secret);
+
+	let nonce = aes_gcm::Aes256Gcm::generate_nonce(OsRng);
+	let ciphertext = aes_encrypt(&aes_key, &nonce, plaintext)?;
+
+	let mut out = Vec::with_capacity(ciphertext.len() + PK_LEN + NONCE_LEN);
+	out.extend_from_slice(ephemeral_pk.as_bytes());
+	out.extend_from_slice(nonce.as_slice());
+	out.extend_from_slice(ciphertext.as_slice());
+
+	Ok(out)
+}
+
+/// Encrypt `plaintext` with the given ed25519 public key. Decryption can be performed with the
+/// matching secret key.
+pub fn encrypt_ed25519(pk: &sp_core::ed25519::Public, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
+	let ed25519 = curve25519_dalek::edwards::CompressedEdwardsY(pk.0);
+	let x25519 = ed25519.decompress().ok_or(Error::BadData)?.to_montgomery();
+	let montgomery = x25519_dalek::PublicKey::from(x25519.to_bytes());
+	encrypt_x25519(&montgomery, plaintext)
+}
+
+/// Decrypt with the given x25519 secret key.
+pub fn decrypt_x25519(sk: &SecretKey, encrypted: &[u8]) -> Result<Vec<u8>, Error> {
+	if encrypted.len() < PK_LEN + NONCE_LEN {
+		return Err(Error::BadData)
+	}
+	let mut ephemeral_pk: [u8; PK_LEN] = Default::default();
+	ephemeral_pk.copy_from_slice(&encrypted[0..PK_LEN]);
+	let ephemeral_pk = PublicKey::from(ephemeral_pk);
+
+	let mut shared_secret = sk.diffie_hellman(&ephemeral_pk).to_bytes().to_vec();
+	shared_secret.extend_from_slice(ephemeral_pk.as_bytes());
+
+	let aes_key = kdf(&shared_secret);
+
+	let nonce = &encrypted[PK_LEN..PK_LEN + NONCE_LEN];
+	aes_decrypt(&aes_key, &nonce, &encrypted[PK_LEN + NONCE_LEN..])
+}
+
+/// Decrypt with the given ed25519 key pair.
+pub fn decrypt_ed25519(pair: &sp_core::ed25519::Pair, encrypted: &[u8]) -> Result<Vec<u8>, Error> {
+	let raw = pair.to_raw_vec();
+	let hash: [u8; 32] = sha2::Sha512::digest(&raw).as_slice()[..32]
+		.try_into()
+		.map_err(|_| Error::Decryption)?;
+	let secret = x25519_dalek::StaticSecret::from(hash);
+	decrypt_x25519(&secret, encrypted)
+}
+
+#[cfg(test)]
+mod test {
+	use super::*;
+	use rand::rngs::OsRng;
+	use sp_core::crypto::Pair;
+
+	#[test]
+	fn basic_x25519_encryption() {
+		let sk = SecretKey::new(OsRng);
+		let pk = PublicKey::from(&sk);
+
+		let plain_message = b"An important secret message";
+		let encrypted = encrypt_x25519(&pk, plain_message).unwrap();
+
+		let decrypted = decrypt_x25519(&sk, &encrypted).unwrap();
+		assert_eq!(plain_message, decrypted.as_slice());
+	}
+
+	#[test]
+	fn basic_ed25519_encryption() {
+		let (pair, _) = sp_core::ed25519::Pair::generate();
+		let pk = pair.into();
+
+		let plain_message = b"An important secret message";
+		let encrypted = encrypt_ed25519(&pk, plain_message).unwrap();
+
+		let decrypted = decrypt_ed25519(&pair, &encrypted).unwrap();
+		assert_eq!(plain_message, decrypted.as_slice());
+	}
+
+	#[test]
+	fn fails_on_bad_data() {
+		let sk = SecretKey::new(OsRng);
+		let pk = PublicKey::from(&sk);
+
+		let plain_message = b"An important secret message";
+		let encrypted = encrypt_x25519(&pk, plain_message).unwrap();
+
+		assert_eq!(decrypt_x25519(&sk, &[]), Err(Error::BadData));
+		assert_eq!(
+			decrypt_x25519(&sk, &encrypted[0..super::PK_LEN + super::NONCE_LEN - 1]),
+			Err(Error::BadData)
+		);
+	}
+}
diff --git a/substrate/primitives/statement-store/src/lib.rs b/substrate/primitives/statement-store/src/lib.rs
index e5c642d24e2b30973d37441d09a7d8a3e6fa472e..67e7a7b3896b5df81c27539c52135669778882ae 100644
--- a/substrate/primitives/statement-store/src/lib.rs
+++ b/substrate/primitives/statement-store/src/lib.rs
@@ -49,6 +49,8 @@ pub use store_api::{
 	Error, NetworkPriority, Result, StatementSource, StatementStore, SubmitResult,
 };
 
+#[cfg(feature = "std")]
+mod ecies;
 pub mod runtime_api;
 #[cfg(feature = "std")]
 mod store_api;
@@ -61,12 +63,17 @@ mod sr25519 {
 	pub type Public = app_sr25519::Public;
 }
 
-mod ed25519 {
+/// Statement-store specific ed25519 crypto primitives.
+pub mod ed25519 {
 	mod app_ed25519 {
 		use sp_application_crypto::{app_crypto, ed25519, key_types::STATEMENT};
 		app_crypto!(ed25519, STATEMENT);
 	}
+	/// Statement-store specific ed25519 public key.
 	pub type Public = app_ed25519::Public;
+	/// Statement-store specific ed25519 key pair.
+	#[cfg(feature = "std")]
+	pub type Pair = app_ed25519::Pair;
 }
 
 mod ecdsa {
@@ -507,6 +514,28 @@ impl Statement {
 		}
 		output
 	}
+
+	/// Encrypt give data with given key and store both in the statements.
+	#[cfg(feature = "std")]
+	pub fn encrypt(
+		&mut self,
+		data: &[u8],
+		key: &sp_core::ed25519::Public,
+	) -> core::result::Result<(), ecies::Error> {
+		let encrypted = ecies::encrypt_ed25519(key, data)?;
+		self.data = Some(encrypted);
+		self.decryption_key = Some((*key).into());
+		Ok(())
+	}
+
+	/// Decrypt data (if any) with the given private key.
+	#[cfg(feature = "std")]
+	pub fn decrypt_private(
+		&self,
+		key: &sp_core::ed25519::Pair,
+	) -> core::result::Result<Option<Vec<u8>>, ecies::Error> {
+		self.data.as_ref().map(|d| ecies::decrypt_ed25519(key, d)).transpose()
+	}
 }
 
 #[cfg(test)]
@@ -615,4 +644,18 @@ mod test {
 		statement.remove_proof();
 		assert_eq!(statement.verify_signature(), SignatureVerificationResult::NoSignature);
 	}
+
+	#[test]
+	fn encrypt_decrypt() {
+		let mut statement = Statement::new();
+		let (pair, _) = sp_core::ed25519::Pair::generate();
+		let plain = b"test data".to_vec();
+
+		//let sr25519_kp = sp_core::sr25519::Pair::from_string("//Alice", None).unwrap();
+		statement.encrypt(&plain, &pair.public()).unwrap();
+		assert_ne!(plain.as_slice(), statement.data().unwrap().as_slice());
+
+		let decrypted = statement.decrypt_private(&pair).unwrap();
+		assert_eq!(decrypted, Some(plain));
+	}
 }
diff --git a/substrate/utils/wasm-builder/src/lib.rs b/substrate/utils/wasm-builder/src/lib.rs
index 8405b5a0bda9e8759d56495cae37c1d42ca80e9f..c9011f97be711d9338c3cd572f4c105a910ca581 100644
--- a/substrate/utils/wasm-builder/src/lib.rs
+++ b/substrate/utils/wasm-builder/src/lib.rs
@@ -222,7 +222,7 @@ fn get_rustup_command() -> Option<CargoCommand> {
 			continue
 		}
 
-		let Some(cargo_version) = cmd.version() else { continue; };
+		let Some(cargo_version) = cmd.version() else { continue };
 
 		versions.push((cargo_version, rustup_version.to_string()));
 	}