From 553b32ff846da0bbc13c640a466703a22b3fc934 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 5 Apr 2023 17:24:04 +0200 Subject: [PATCH 1/6] Added ECIES encryption --- Cargo.lock | 8 ++ bin/node/cli/src/service.rs | 1 + client/keystore/src/local.rs | 15 ++ client/statement-store/Cargo.toml | 1 + client/statement-store/src/lib.rs | 67 ++++++++- primitives/core/Cargo.toml | 1 - primitives/keystore/src/lib.rs | 11 ++ primitives/keystore/src/testing.rs | 14 ++ primitives/statement-store/Cargo.toml | 17 +++ primitives/statement-store/src/ecies.rs | 178 ++++++++++++++++++++++++ primitives/statement-store/src/lib.rs | 38 +++++ 11 files changed, 343 insertions(+), 8 deletions(-) create mode 100644 primitives/statement-store/src/ecies.rs diff --git a/Cargo.lock b/Cargo.lock index 37f18f2cd2d77..32b6f0849c4d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10137,6 +10137,7 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-core", + "sp-keystore", "sp-runtime", "sp-statement-store", "sp-tracing", @@ -11573,9 +11574,15 @@ dependencies = [ name = "sp-statement-store" version = "4.0.0-dev" dependencies = [ + "aes-gcm 0.10.2", + "curve25519-dalek 3.2.0", + "ed25519-dalek", + "hkdf", "log", "parity-scale-codec", + "rand 0.8.5", "scale-info", + "sha2 0.10.6", "sp-api", "sp-application-crypto", "sp-core", @@ -11584,6 +11591,7 @@ dependencies = [ "sp-runtime-interface", "sp-std", "thiserror", + "x25519-dalek 2.0.0-pre.1", ] [[package]] diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 8fc44c7c5eddf..a02e2478e89eb 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -233,6 +233,7 @@ pub fn new_partial( &config.data_path, Default::default(), client.clone(), + keystore_container.keystore(), config.prometheus_registry(), &task_manager.spawn_handle(), ) diff --git a/client/keystore/src/local.rs b/client/keystore/src/local.rs index 4167e486ecf62..1222f224aa963 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -196,6 +196,21 @@ impl Keystore for LocalKeystore { self.sign::(key_type, public, msg) } + fn with_ed25519_key( + &self, + key_type: KeyTypeId, + public: &ed25519::Public, + f: &mut dyn FnMut(&ed25519::Pair), + ) -> std::result::Result { + let pair = self.0.read().key_pair_by_type::(public, key_type)?; + Ok(if let Some(pair) = pair { + f(&pair); + true + } else { + false + }) + } + fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec { self.public_keys::(key_type) } diff --git a/client/statement-store/Cargo.toml b/client/statement-store/Cargo.toml index f5abcba33bae2..75f1de85fab5e 100644 --- a/client/statement-store/Cargo.toml +++ b/client/statement-store/Cargo.toml @@ -26,6 +26,7 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0. sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "21.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.27.0", path = "../../primitives/keystore" } sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" } sp-tracing = { version = "10.0.0", path = "../../primitives/tracing" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/statement-store/src/lib.rs b/client/statement-store/src/lib.rs index 4acb89a05f7d1..6dc6c36f1ea6f 100644 --- a/client/statement-store/src/lib.rs +++ b/client/statement-store/src/lib.rs @@ -56,7 +56,8 @@ use parking_lot::RwLock; use prometheus_endpoint::Registry as PrometheusRegistry; 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_keystore::Keystore; use sp_runtime::traits::Block as BlockT; use sp_statement_store::{ runtime_api::{InvalidStatement, StatementSource, ValidStatement, ValidateStatement}, @@ -199,6 +200,7 @@ pub struct Store { + Send + Sync, >, + keystore: Arc, // Used for testing time_override: Option, metrics: PrometheusMetrics, @@ -477,6 +479,7 @@ impl Store { path: &std::path::Path, options: Options, client: Arc, + keystore: Arc, prometheus: Option<&PrometheusRegistry>, task_spawner: &dyn SpawnNamed, ) -> Result> @@ -491,7 +494,7 @@ impl Store { + 'static, Client::Api: ValidateStatement, { - let store = Arc::new(Self::new(path, options, client.clone(), prometheus)?); + let store = Arc::new(Self::new(path, options, client.clone(), keystore, prometheus)?); client.execution_extensions().register_statement_store(store.clone()); // Perform periodic statement store maintenance @@ -517,6 +520,7 @@ impl Store { path: &std::path::Path, options: Options, client: Arc, + keystore: Arc, prometheus: Option<&PrometheusRegistry>, ) -> Result where @@ -565,6 +569,7 @@ impl Store { db, index: RwLock::new(Index::new(options)), validate_fn, + keystore, time_override: None, metrics: PrometheusMetrics::new(prometheus), }; @@ -762,7 +767,35 @@ 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>> { - 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 = UncheckedFrom::unchecked_from(key); + let mut out = None; + if let Err(e) = self.keystore.with_ed25519_key( + sp_core::crypto::key_types::STATEMENT, + &public, + &mut |pair| match statement.decrypt_private(pair) { + Ok(r) => out = r, + Err(e) => log::debug!( + target: LOG_TARGET, + "Decryption error: {:?}, for statement {:?}", + e, + HexDisplay::from(&statement.hash()) + ), + }, + ) { + log::debug!( + target: LOG_TARGET, + "Keystore error error: {:?}, for statement {:?}", + e, + HexDisplay::from(&statement.hash()) + ) + } + out + } else { + None + } + }) } /// Submit a statement to the store. Validates the statement and returns validation result. @@ -910,6 +943,7 @@ mod tests { RuntimeApi { _inner: self.clone() }.into() } } + sp_api::mock_impl_runtime_apis! { impl ValidateStatement for RuntimeApi { fn validate_statement( @@ -977,7 +1011,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(sp_keystore::testing::MemoryKeystore::new()); + let store = Store::new(&path, Default::default(), client, keystore, None).unwrap(); (store, temp_dir) // return order is important. Store must be dropped before TempDir } @@ -1080,12 +1115,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)); @@ -1190,7 +1226,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<_> = @@ -1214,13 +1249,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/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 6c043d5a21499..950c29dfb024b 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -56,7 +56,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/primitives/keystore/src/lib.rs b/primitives/keystore/src/lib.rs index 1d2a27cb8726c..ac1ed86b9d376 100644 --- a/primitives/keystore/src/lib.rs +++ b/primitives/keystore/src/lib.rs @@ -307,6 +307,17 @@ pub trait Keystore: Send + Sync { }; Ok(signature) } + + /// Call a custom function with an ed25519 private key that matches given public key. + /// + /// Returns `Ok(true)` if the key is found and `f` was called. `Ok(false)` if the key is missing + /// and an error when something has failed. + fn with_ed25519_key( + &self, + key_type: KeyTypeId, + public: &ed25519::Public, + f: &mut dyn FnMut(&ed25519::Pair), + ) -> std::result::Result; } /// A shared pointer to a keystore implementation. diff --git a/primitives/keystore/src/testing.rs b/primitives/keystore/src/testing.rs index e18931a7af883..6aba901548a68 100644 --- a/primitives/keystore/src/testing.rs +++ b/primitives/keystore/src/testing.rs @@ -286,6 +286,20 @@ impl Keystore for MemoryKeystore { .iter() .all(|(k, t)| self.keys.read().get(t).and_then(|s| s.get(k)).is_some()) } + + fn with_ed25519_key( + &self, + key_type: KeyTypeId, + public: &ed25519::Public, + f: &mut dyn FnMut(&ed25519::Pair), + ) -> std::result::Result { + Ok(if let Some(pair) = self.pair::(key_type, public) { + f(&pair); + true + } else { + false + }) + } } impl Into for MemoryKeystore { diff --git a/primitives/statement-store/Cargo.toml b/primitives/statement-store/Cargo.toml index cf1ef208490b1..7439608f01754 100644 --- a/primitives/statement-store/Cargo.toml +++ b/primitives/statement-store/Cargo.toml @@ -25,6 +25,15 @@ sp-externalities = { version = "0.19.0", default-features = false, path = "../ex thiserror = { version = "1.0", optional = true } log = { version = "0.4.17", 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 = [ @@ -38,6 +47,14 @@ std = [ "sp-application-crypto/std", "thiserror", "log", + + "ed25519-dalek", + "x25519-dalek", + "curve25519-dalek", + "aes-gcm", + "hkdf", + "sha2", + "rand", ] serde = [ "scale-info/serde", diff --git a/primitives/statement-store/src/ecies.rs b/primitives/statement-store/src/ecies.rs new file mode 100644 index 0000000000000..5948373e18296 --- /dev/null +++ b/primitives/statement-store/src/ecies.rs @@ -0,0 +1,178 @@ +// 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, KeyInit}; +use rand::{rngs::OsRng, RngCore}; +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, 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, 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::::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."); + 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, 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 mut nonce = [0u8; NONCE_LEN]; + OsRng.fill_bytes(&mut nonce); + 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, Error> { + let ed25519 = curve25519_dalek::edwards::CompressedEdwardsY(pk.0); + let x25519 = ed25519 + .decompress() + .ok_or(Error::BadData) + .expect("The compressed point is invalid") + .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, 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, Error> { + let raw = pair.to_raw_vec(); + let hash: [u8; 32] = + sha2::Sha512::digest(&raw).as_slice()[..32].try_into().expect("Hashing error"); + 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/primitives/statement-store/src/lib.rs b/primitives/statement-store/src/lib.rs index e5c642d24e2b3..42ac24c6dddde 100644 --- a/primitives/statement-store/src/lib.rs +++ b/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; @@ -507,6 +509,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.clone().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>, ecies::Error> { + self.data.as_ref().map(|d| ecies::decrypt_ed25519(key, d)).transpose() + } } #[cfg(test)] @@ -615,4 +639,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)); + } } From d0e0059f006c5f5e557178f3b2e358c5e47146f6 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 22 Jun 2023 11:02:51 +0200 Subject: [PATCH 2/6] tweaks --- primitives/statement-store/src/ecies.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/primitives/statement-store/src/ecies.rs b/primitives/statement-store/src/ecies.rs index 5948373e18296..1fd6811261252 100644 --- a/primitives/statement-store/src/ecies.rs +++ b/primitives/statement-store/src/ecies.rs @@ -19,8 +19,8 @@ //! ECIES encryption scheme using x25519 key exchange and AEAD. // end::description[] -use aes_gcm::{aead::Aead, KeyInit}; -use rand::{rngs::OsRng, RngCore}; +use aes_gcm::{aead::Aead, KeyInit, AeadCore}; +use rand::rngs::OsRng; use sha2::Digest; use sp_core::crypto::Pair; @@ -79,8 +79,7 @@ pub fn encrypt_x25519(pk: &PublicKey, plaintext: &[u8]) -> Result, Error let aes_key = kdf(&shared_secret); - let mut nonce = [0u8; NONCE_LEN]; - OsRng.fill_bytes(&mut nonce); + 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); @@ -97,8 +96,7 @@ pub fn encrypt_ed25519(pk: &sp_core::ed25519::Public, plaintext: &[u8]) -> Resul let ed25519 = curve25519_dalek::edwards::CompressedEdwardsY(pk.0); let x25519 = ed25519 .decompress() - .ok_or(Error::BadData) - .expect("The compressed point is invalid") + .ok_or(Error::BadData)? .to_montgomery(); let montgomery = x25519_dalek::PublicKey::from(x25519.to_bytes()); encrypt_x25519(&montgomery, plaintext) @@ -126,7 +124,7 @@ pub fn decrypt_x25519(sk: &SecretKey, encrypted: &[u8]) -> Result, Error pub fn decrypt_ed25519(pair: &sp_core::ed25519::Pair, encrypted: &[u8]) -> Result, Error> { let raw = pair.to_raw_vec(); let hash: [u8; 32] = - sha2::Sha512::digest(&raw).as_slice()[..32].try_into().expect("Hashing error"); + sha2::Sha512::digest(&raw).as_slice()[..32].try_into().map_err(|_| Error::Decryption)?; let secret = x25519_dalek::StaticSecret::from(hash); decrypt_x25519(&secret, encrypted) } From 08e220ff41c780aa56698b06425040a69d68de59 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 22 Jun 2023 11:09:54 +0200 Subject: [PATCH 3/6] fmt --- primitives/statement-store/src/ecies.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/primitives/statement-store/src/ecies.rs b/primitives/statement-store/src/ecies.rs index 1fd6811261252..a955b2a40b861 100644 --- a/primitives/statement-store/src/ecies.rs +++ b/primitives/statement-store/src/ecies.rs @@ -19,7 +19,7 @@ //! ECIES encryption scheme using x25519 key exchange and AEAD. // end::description[] -use aes_gcm::{aead::Aead, KeyInit, AeadCore}; +use aes_gcm::{aead::Aead, AeadCore, KeyInit}; use rand::rngs::OsRng; use sha2::Digest; use sp_core::crypto::Pair; @@ -94,10 +94,7 @@ pub fn encrypt_x25519(pk: &PublicKey, plaintext: &[u8]) -> Result, Error /// matching secret key. pub fn encrypt_ed25519(pk: &sp_core::ed25519::Public, plaintext: &[u8]) -> Result, Error> { let ed25519 = curve25519_dalek::edwards::CompressedEdwardsY(pk.0); - let x25519 = ed25519 - .decompress() - .ok_or(Error::BadData)? - .to_montgomery(); + let x25519 = ed25519.decompress().ok_or(Error::BadData)?.to_montgomery(); let montgomery = x25519_dalek::PublicKey::from(x25519.to_bytes()); encrypt_x25519(&montgomery, plaintext) } @@ -123,8 +120,9 @@ pub fn decrypt_x25519(sk: &SecretKey, encrypted: &[u8]) -> Result, Error /// Decrypt with the given ed25519 key pair. pub fn decrypt_ed25519(pair: &sp_core::ed25519::Pair, encrypted: &[u8]) -> Result, 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 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) } From 26fc2425cd00c57976cfc6d0c61b374f97b919a9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 22 Jun 2023 11:28:56 +0200 Subject: [PATCH 4/6] Make clippy happy --- primitives/statement-store/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/statement-store/src/lib.rs b/primitives/statement-store/src/lib.rs index 42ac24c6dddde..ca7f6fca7aa56 100644 --- a/primitives/statement-store/src/lib.rs +++ b/primitives/statement-store/src/lib.rs @@ -519,7 +519,7 @@ impl Statement { ) -> core::result::Result<(), ecies::Error> { let encrypted = ecies::encrypt_ed25519(key, data)?; self.data = Some(encrypted); - self.decryption_key = Some(key.clone().into()); + self.decryption_key = Some((*key).into()); Ok(()) } From 72c16bfdbebdc6fda460794f269ce475045a2384 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 3 Jul 2023 14:37:58 +0200 Subject: [PATCH 5/6] Use local keystore --- Cargo.lock | 2 +- bin/node/cli/src/service.rs | 2 +- client/cli/src/runner.rs | 2 +- client/keystore/src/lib.rs | 1 + client/keystore/src/local.rs | 15 ----- client/network/src/discovery.rs | 2 +- client/network/src/protocol_controller.rs | 8 +-- .../rpc-spec-v2/src/chain_head/chain_head.rs | 3 +- .../src/chain_head/chain_head_follow.rs | 4 +- .../src/chain_head/subscription/inner.rs | 4 +- client/service/src/lib.rs | 2 +- client/statement-store/Cargo.toml | 2 +- client/statement-store/src/lib.rs | 57 +++++++++++-------- frame/contracts/src/migration/v11.rs | 4 +- frame/glutton/src/lib.rs | 8 +-- frame/support/procedural/src/benchmark.rs | 6 +- .../construct_runtime/expand/outer_enums.rs | 4 +- .../api/proc-macro/src/runtime_metadata.rs | 12 +--- primitives/api/proc-macro/src/utils.rs | 4 +- primitives/application-crypto/src/lib.rs | 7 +++ .../src/multiply_by_rational_with_rounding.rs | 4 +- primitives/blockchain/src/backend.rs | 4 +- primitives/core/src/ed25519.rs | 8 +-- primitives/core/src/sr25519.rs | 8 +-- primitives/io/src/lib.rs | 4 +- primitives/keystore/src/lib.rs | 11 ---- primitives/keystore/src/testing.rs | 14 ----- primitives/statement-store/src/lib.rs | 7 ++- utils/wasm-builder/src/lib.rs | 2 +- 29 files changed, 81 insertions(+), 130 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c6c30900956c..37fab7aee3c1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10011,10 +10011,10 @@ dependencies = [ "parity-db", "parking_lot 0.12.1", "sc-client-api", + "sc-keystore", "sp-api", "sp-blockchain", "sp-core", - "sp-keystore", "sp-runtime", "sp-statement-store", "substrate-prometheus-endpoint", diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index c1631e2e7f349..bcfc705044f81 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -233,7 +233,7 @@ pub fn new_partial( &config.data_path, Default::default(), client.clone(), - keystore_container.keystore(), + keystore_container.local_keystore(), config.prometheus_registry(), &task_manager.spawn_handle(), ) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 7b534b37192ad..1b8db03c2713b 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -423,7 +423,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/client/keystore/src/lib.rs b/client/keystore/src/lib.rs index 4151f8c4dc1a4..2d353f3ceba5d 100644 --- a/client/keystore/src/lib.rs +++ b/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/client/keystore/src/local.rs b/client/keystore/src/local.rs index 1222f224aa963..4167e486ecf62 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -196,21 +196,6 @@ impl Keystore for LocalKeystore { self.sign::(key_type, public, msg) } - fn with_ed25519_key( - &self, - key_type: KeyTypeId, - public: &ed25519::Public, - f: &mut dyn FnMut(&ed25519::Pair), - ) -> std::result::Result { - let pair = self.0.read().key_pair_by_type::(public, key_type)?; - Ok(if let Some(pair) = pair { - f(&pair); - true - } else { - false - }) - } - fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec { self.public_keys::(key_type) } diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index b6cb29584658f..d9fad53844346 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -548,7 +548,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { addresses: &[Multiaddr], effective_role: Endpoint, ) -> Result, 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/client/network/src/protocol_controller.rs b/client/network/src/protocol_controller.rs index 9a77881c63320..5b421e1485d69 100644 --- a/client/network/src/protocol_controller.rs +++ b/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 { - 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/client/rpc-spec-v2/src/chain_head/chain_head.rs b/client/rpc-spec-v2/src/chain_head/chain_head.rs index 0f2d55f100929..0884646196021 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head.rs +++ b/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/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs b/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs index cb6af8bd590b3..799978be532ae 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs +++ b/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/client/rpc-spec-v2/src/chain_head/subscription/inner.rs b/client/rpc-spec-v2/src/chain_head/subscription/inner.rs index bdb14e8de7172..ba7f117f4fccd 100644 --- a/client/rpc-spec-v2/src/chain_head/subscription/inner.rs +++ b/client/rpc-spec-v2/src/chain_head/subscription/inner.rs @@ -328,9 +328,7 @@ impl> SubscriptionsInner { /// 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/client/service/src/lib.rs b/client/service/src/lib.rs index 4a896ecc87263..e3feb45ee9fbc 100644 --- a/client/service/src/lib.rs +++ b/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/client/statement-store/Cargo.toml b/client/statement-store/Cargo.toml index 7b2e337ffb545..8668dbfa8ba03 100644 --- a/client/statement-store/Cargo.toml +++ b/client/statement-store/Cargo.toml @@ -22,9 +22,9 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0. sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "21.0.0", path = "../../primitives/core" } -sp-keystore = { version = "0.27.0", path = "../../primitives/keystore" } 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/client/statement-store/src/lib.rs b/client/statement-store/src/lib.rs index 6dc6c36f1ea6f..1f8567896dfc9 100644 --- a/client/statement-store/src/lib.rs +++ b/client/statement-store/src/lib.rs @@ -54,10 +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::{crypto::UncheckedFrom, hexdisplay::HexDisplay, traits::SpawnNamed, Decode, Encode}; -use sp_keystore::Keystore; use sp_runtime::traits::Block as BlockT; use sp_statement_store::{ runtime_api::{InvalidStatement, StatementSource, ValidStatement, ValidateStatement}, @@ -200,7 +200,7 @@ pub struct Store { + Send + Sync, >, - keystore: Arc, + keystore: Arc, // Used for testing time_override: Option, metrics: PrometheusMetrics, @@ -479,7 +479,7 @@ impl Store { path: &std::path::Path, options: Options, client: Arc, - keystore: Arc, + keystore: Arc, prometheus: Option<&PrometheusRegistry>, task_spawner: &dyn SpawnNamed, ) -> Result> @@ -520,7 +520,7 @@ impl Store { path: &std::path::Path, options: Options, client: Arc, - keystore: Arc, + keystore: Arc, prometheus: Option<&PrometheusRegistry>, ) -> Result where @@ -769,29 +769,39 @@ impl StatementStore for Store { fn posted_clear(&self, match_all_topics: &[Topic], dest: [u8; 32]) -> Result>> { self.collect_statements(Some(dest), match_all_topics, |statement| { if let (Some(key), Some(_)) = (statement.decryption_key(), statement.data()) { - let public = UncheckedFrom::unchecked_from(key); - let mut out = None; - if let Err(e) = self.keystore.with_ed25519_key( - sp_core::crypto::key_types::STATEMENT, - &public, - &mut |pair| match statement.decrypt_private(pair) { - Ok(r) => out = r, - Err(e) => log::debug!( + let public: sp_core::ed25519::Public = UncheckedFrom::unchecked_from(key); + let public: sp_statement_store::ed25519::Public = public.into(); + match self.keystore.key_pair::(&public) { + Err(e) => { + log::debug!( target: LOG_TARGET, - "Decryption error: {:?}, for statement {:?}", + "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 + }, }, - ) { - log::debug!( - target: LOG_TARGET, - "Keystore error error: {:?}, for statement {:?}", - e, - HexDisplay::from(&statement.hash()) - ) } - out } else { None } @@ -914,6 +924,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}, @@ -1011,7 +1022,7 @@ mod tests { let client = std::sync::Arc::new(TestClient); let mut path: std::path::PathBuf = temp_dir.path().into(); path.push("db"); - let keystore = std::sync::Arc::new(sp_keystore::testing::MemoryKeystore::new()); + 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 } diff --git a/frame/contracts/src/migration/v11.rs b/frame/contracts/src/migration/v11.rs index 67740cfaf6c80..8123d73aee560 100644 --- a/frame/contracts/src/migration/v11.rs +++ b/frame/contracts/src/migration/v11.rs @@ -80,7 +80,9 @@ impl MigrationStep for Migration { } fn step(&mut self) -> (IsFinished, Weight) { - let Some(old_queue) = old::DeletionQueue::::take() else { return (IsFinished::Yes, Weight::zero()) }; + let Some(old_queue) = old::DeletionQueue::::take() else { + return (IsFinished::Yes, Weight::zero()) + }; let len = old_queue.len(); log::debug!( diff --git a/frame/glutton/src/lib.rs b/frame/glutton/src/lib.rs index c02a14810d0b2..544a8d8a05af7 100644 --- a/frame/glutton/src/lib.rs +++ b/frame/glutton/src/lib.rs @@ -269,9 +269,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)); @@ -301,9 +299,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/frame/support/procedural/src/benchmark.rs b/frame/support/procedural/src/benchmark.rs index 18d672b9b0508..9f28e7129d2e1 100644 --- a/frame/support/procedural/src/benchmark.rs +++ b/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/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs b/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs index 544f63be2bfa1..b78360d5fc052 100644 --- a/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs +++ b/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/primitives/api/proc-macro/src/runtime_metadata.rs b/primitives/api/proc-macro/src/runtime_metadata.rs index 458248cbd3d16..8dd88e2ef702b 100644 --- a/primitives/api/proc-macro/src/runtime_metadata.rs +++ b/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/primitives/api/proc-macro/src/utils.rs b/primitives/api/proc-macro/src/utils.rs index 6716be142febc..5df3ee1dec74b 100644 --- a/primitives/api/proc-macro/src/utils.rs +++ b/primitives/api/proc-macro/src/utils.rs @@ -263,9 +263,7 @@ pub fn get_doc_literals(attrs: &[syn::Attribute]) -> Vec { 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::(meta.value.to_token_stream()) else { unreachable!("non-lit doc attribute values do not exist"); }; diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index 46f59719f9c29..95a25c11a717d 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/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/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs b/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs index e9a3208a738ef..5f3f675c971f2 100644 --- a/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs +++ b/primitives/arithmetic/fuzzer/src/multiply_by_rational_with_rounding.rs @@ -52,9 +52,7 @@ fn check(f: N, n: N, d: N, r: Rounding) where N: MultiplyRational + Into + 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/primitives/blockchain/src/backend.rs b/primitives/blockchain/src/backend.rs index e9278be1d5d3c..8208f9128e714 100644 --- a/primitives/blockchain/src/backend.rs +++ b/primitives/blockchain/src/backend.rs @@ -196,9 +196,7 @@ pub trait Backend: base_hash: Block::Hash, import_lock: &RwLock<()>, ) -> Result> { - 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/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index ba947990e1c0b..de085e590b996 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -422,12 +422,8 @@ impl TraitPair for Pair { /// /// Returns true if the signature is good. fn verify>(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/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 963ca1c3fedc3..36c1c3251488c 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -505,12 +505,8 @@ impl TraitPair for Pair { } fn verify>(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/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 750b5d5924637..bd20ee0c917aa 100644 --- a/primitives/io/src/lib.rs +++ b/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/primitives/keystore/src/lib.rs b/primitives/keystore/src/lib.rs index ac1ed86b9d376..1d2a27cb8726c 100644 --- a/primitives/keystore/src/lib.rs +++ b/primitives/keystore/src/lib.rs @@ -307,17 +307,6 @@ pub trait Keystore: Send + Sync { }; Ok(signature) } - - /// Call a custom function with an ed25519 private key that matches given public key. - /// - /// Returns `Ok(true)` if the key is found and `f` was called. `Ok(false)` if the key is missing - /// and an error when something has failed. - fn with_ed25519_key( - &self, - key_type: KeyTypeId, - public: &ed25519::Public, - f: &mut dyn FnMut(&ed25519::Pair), - ) -> std::result::Result; } /// A shared pointer to a keystore implementation. diff --git a/primitives/keystore/src/testing.rs b/primitives/keystore/src/testing.rs index 6aba901548a68..e18931a7af883 100644 --- a/primitives/keystore/src/testing.rs +++ b/primitives/keystore/src/testing.rs @@ -286,20 +286,6 @@ impl Keystore for MemoryKeystore { .iter() .all(|(k, t)| self.keys.read().get(t).and_then(|s| s.get(k)).is_some()) } - - fn with_ed25519_key( - &self, - key_type: KeyTypeId, - public: &ed25519::Public, - f: &mut dyn FnMut(&ed25519::Pair), - ) -> std::result::Result { - Ok(if let Some(pair) = self.pair::(key_type, public) { - f(&pair); - true - } else { - false - }) - } } impl Into for MemoryKeystore { diff --git a/primitives/statement-store/src/lib.rs b/primitives/statement-store/src/lib.rs index ca7f6fca7aa56..67e7a7b3896b5 100644 --- a/primitives/statement-store/src/lib.rs +++ b/primitives/statement-store/src/lib.rs @@ -63,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 { diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index 8405b5a0bda9e..c9011f97be711 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -222,7 +222,7 @@ fn get_rustup_command() -> Option { 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())); } From 57c8ea6574fb1dc16c4b215971e862a4d2f0257a Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 16 Jul 2023 13:37:22 +0200 Subject: [PATCH 6/6] qed --- primitives/statement-store/src/ecies.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/statement-store/src/ecies.rs b/primitives/statement-store/src/ecies.rs index a955b2a40b861..4afd583e03c80 100644 --- a/primitives/statement-store/src/ecies.rs +++ b/primitives/statement-store/src/ecies.rs @@ -64,7 +64,7 @@ fn kdf(shared_secret: &[u8]) -> [u8; AES_KEY_LEN] { let hkdf = hkdf::Hkdf::::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."); + .expect("There's always enough data for derivation. qed."); aes_key }