From 5a244dcd62395c81fea06eea7f770236c37ae0a2 Mon Sep 17 00:00:00 2001 From: Andrew Burger Date: Thu, 5 Dec 2024 12:16:15 +0100 Subject: [PATCH] new branch --- substrate/client/keystore/src/local.rs | 10 ++++- .../primitives/application-crypto/src/lib.rs | 1 - .../application-crypto/test/Cargo.toml | 4 ++ .../application-crypto/test/src/bls381.rs | 28 ++++++++++++++ .../application-crypto/test/src/lib.rs | 2 + substrate/primitives/core/src/bls.rs | 1 + substrate/primitives/core/src/crypto.rs | 3 ++ .../primitives/core/src/paired_crypto.rs | 1 + substrate/test-utils/runtime/Cargo.toml | 7 +++- substrate/test-utils/runtime/src/lib.rs | 37 ++++++++++++++++--- 10 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 substrate/primitives/application-crypto/test/src/bls381.rs diff --git a/substrate/client/keystore/src/local.rs b/substrate/client/keystore/src/local.rs index 91c52bfcd50a..4c210cc1fc6b 100644 --- a/substrate/client/keystore/src/local.rs +++ b/substrate/client/keystore/src/local.rs @@ -20,7 +20,7 @@ use parking_lot::RwLock; use sp_application_crypto::{AppCrypto, AppPair, IsWrappedBy}; use sp_core::{ - crypto::{ByteArray, ExposeSecret, KeyTypeId, Pair as CorePair, SecretString, VrfSecret}, + crypto::{ByteArray, ExposeSecret, KeyTypeId, Pair as CorePair, SecretString, VrfSecret, ProofOfPossessionGenerator}, ecdsa, ed25519, sr25519, }; use sp_keystore::{Error as TraitError, Keystore, KeystorePtr}; @@ -357,6 +357,14 @@ impl Keystore for LocalKeystore { self.sign::(key_type, public, msg) } + fn bls381_generate_pop( + &self, + key_type: KeyTypeId, + public: &bls381::Public + ) -> std::result::Result, TraitError> { + self.bls381_generate_pop(key_type, public) + } + fn ecdsa_bls381_public_keys(&self, key_type: KeyTypeId) -> Vec { self.public_keys::(key_type) } diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs index 000d356ae4bc..69af988b5358 100644 --- a/substrate/primitives/application-crypto/src/lib.rs +++ b/substrate/primitives/application-crypto/src/lib.rs @@ -184,7 +184,6 @@ macro_rules! app_crypto_pair_common { proof_of_possession: &Self::Signature, allegedly_possessed_pubkey: &Self::Public, ) -> bool { - use sp_core::crypto::ProofOfPossessionVerifier; <$pair>::verify_proof_of_possession( &proof_of_possession.0, allegedly_possessed_pubkey.as_ref(), diff --git a/substrate/primitives/application-crypto/test/Cargo.toml b/substrate/primitives/application-crypto/test/Cargo.toml index 5c19161bc870..9cc0e7a0663a 100644 --- a/substrate/primitives/application-crypto/test/Cargo.toml +++ b/substrate/primitives/application-crypto/test/Cargo.toml @@ -21,3 +21,7 @@ sp-application-crypto = { workspace = true, default-features = true } sp-core = { workspace = true } sp-keystore = { workspace = true } substrate-test-runtime-client = { workspace = true } + +[features] +full_crypto = [] +bls-experimental = [] diff --git a/substrate/primitives/application-crypto/test/src/bls381.rs b/substrate/primitives/application-crypto/test/src/bls381.rs new file mode 100644 index 000000000000..a8a311537670 --- /dev/null +++ b/substrate/primitives/application-crypto/test/src/bls381.rs @@ -0,0 +1,28 @@ +use sp_api::{ApiExt, ProvideRuntimeApi}; +use sp_application_crypto::ecdsa::AppPair; +use sp_core::{ + crypto::{ByteArray, Pair}, + testing::BLS381, +}; +use sp_keystore::{testing::MemoryKeystore, Keystore, KeystoreExt}; +use std::sync::Arc; +use substrate_test_runtime_client::{ + runtime::TestAPI, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt, +}; + +#[test] +fn bls381_works_in_runtime() { + let keystore = Arc::new(MemoryKeystore::new()); + let test_client = TestClientBuilder::new().build(); + + let mut runtime_api = test_client.runtime_api(); + runtime_api.register_extension(KeystoreExt::new(keystore.clone())); + + let (signature, public) = runtime_api + .test_bls381_crypto(test_client.chain_info().genesis_hash) + .expect("Tests `bls381` crypto."); + + let supported_keys = keystore.keys(BLS381).unwrap(); + assert!(supported_keys.contains(&public.to_raw_vec())); + assert!(AppPair::verify(&signature, "bls381", &public)); +} \ No newline at end of file diff --git a/substrate/primitives/application-crypto/test/src/lib.rs b/substrate/primitives/application-crypto/test/src/lib.rs index 90856ee1e596..42ecf98c93c1 100644 --- a/substrate/primitives/application-crypto/test/src/lib.rs +++ b/substrate/primitives/application-crypto/test/src/lib.rs @@ -23,3 +23,5 @@ mod ecdsa; mod ed25519; #[cfg(test)] mod sr25519; +#[cfg(all(test, feature = "bls-experimental"))] +mod bls381; diff --git a/substrate/primitives/core/src/bls.rs b/substrate/primitives/core/src/bls.rs index f6f2efc47ee2..ba3a9fb244ff 100644 --- a/substrate/primitives/core/src/bls.rs +++ b/substrate/primitives/core/src/bls.rs @@ -237,6 +237,7 @@ impl TraitPair for Pair { } impl ProofOfPossessionGenerator for Pair { + #[cfg(feature = "full_crypto")] fn generate_proof_of_possession(&mut self) -> Self::Signature { let r: [u8; SIGNATURE_SERIALIZED_SIZE] = as BlsProofOfPossessionGenerator< T, diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs index 82d68ad2c9e4..114b23a649cb 100644 --- a/substrate/primitives/core/src/crypto.rs +++ b/substrate/primitives/core/src/crypto.rs @@ -975,6 +975,7 @@ where /// - Ristenpart, T., & Yilek, S. (2007). The power of proofs-of-possession: Securing multiparty /// signatures against rogue-key attacks. In , Annual {{International Conference}} on the /// {{Theory}} and {{Applications}} of {{Cryptographic Techniques} (pp. 228–245). : Springer. + #[cfg(feature = "full_crypto")] fn generate_proof_of_possession(&mut self) -> Self::Signature { let pub_key_as_bytes = self.public().to_raw_vec(); let pop_statement = [POP_CONTEXT_TAG, pub_key_as_bytes.as_slice()].concat(); @@ -1016,6 +1017,7 @@ where T: Pair + NonAggregatable, T::Public: CryptoType, { + } impl ProofOfPossessionGenerator for T @@ -1023,6 +1025,7 @@ where T: Pair + NonAggregatable, T::Public: CryptoType, { + } /// One type is wrapped by another. diff --git a/substrate/primitives/core/src/paired_crypto.rs b/substrate/primitives/core/src/paired_crypto.rs index 3416084ff478..7caca2bed287 100644 --- a/substrate/primitives/core/src/paired_crypto.rs +++ b/substrate/primitives/core/src/paired_crypto.rs @@ -405,6 +405,7 @@ where LeftPair::Seed: From + Into, RightPair::Seed: From + Into, { + #[cfg(feature = "full_crypto")] fn generate_proof_of_possession(&mut self) -> Self::Signature { let mut raw: [u8; SIGNATURE_LEN] = [0u8; SIGNATURE_LEN]; diff --git a/substrate/test-utils/runtime/Cargo.toml b/substrate/test-utils/runtime/Cargo.toml index 1c82c73072bc..93746370e072 100644 --- a/substrate/test-utils/runtime/Cargo.toml +++ b/substrate/test-utils/runtime/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { features = ["serde"], workspace = true } +sp-application-crypto = { features = ["serde", "bls-experimental"], workspace = true } sp-consensus-aura = { features = ["serde"], workspace = true } sp-consensus-babe = { features = ["serde"], workspace = true } sp-genesis-builder = { workspace = true } @@ -118,3 +118,8 @@ std = [ # Special feature to disable logging disable-logging = ["sp-api/disable-logging"] + +# This feature adds BLS crypto primitives. +# It should not be used in production since the implementation and interface may still +# be subject to significant changes. +bls-experimental = [] diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index a08574c45726..681f75ef8671 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -49,7 +49,11 @@ use scale_info::TypeInfo; use sp_application_crypto::Ss58Codec; use sp_keyring::AccountKeyring; -use sp_application_crypto::{ecdsa, ed25519, sr25519, blsRuntimeAppPublic, bls381}; +use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic}; + +#[cfg(feature = "bls-experimental")] +use sp_application_crypto::{bls381, ecdsa_bls381}; + use sp_core::{OpaqueMetadata, RuntimeDebug}; use sp_trie::{ trie_types::{TrieDBBuilder, TrieDBMutBuilderV1}, @@ -181,6 +185,24 @@ pub type Header = sp_runtime::generic::Header; /// Balance of an account. pub type Balance = u64; +#[cfg(not(feature = "bls-experimental"))] +type Bls381Signature = (); + +#[cfg(feature = "bls-experimental")] +type Bls381Signature = bls381::AppSignature; + +#[cfg(not(feature = "bls-experimental"))] +type Bls381Public = (); + +#[cfg(feature = "bls-experimental")] +type Bls381Public = bls381::AppPublic; + +#[cfg(feature = "bls-experimental")] +compile_error!("bls-experimental is active"); + +#[cfg(not(feature = "bls-experimental"))] +compile_error!("bls-experimental is NOT active"); + decl_runtime_apis! { #[api_version(2)] pub trait TestAPI { @@ -206,7 +228,6 @@ decl_runtime_apis! { fn vec_with_capacity(size: u32) -> Vec; /// Returns the initialized block number. fn get_block_number() -> u64; - /// Test that `ed25519` crypto works in the runtime. /// /// Returns the signature generated for the message `ed25519` and the public key. @@ -222,8 +243,7 @@ decl_runtime_apis! { /// Test that 'bls381' crypto works in the runtime /// /// Returns the signature generated for the message `bls381`. - #[cfg(feature = "bls-experimental")] - fn test_bls381_crypto() -> (bls381::AppSignature, bls381::AppPublic); + fn test_bls381_crypto() -> (Bls381Signature, Bls381Public); /// Run various tests against storage. fn test_storage(); /// Check a witness. @@ -586,10 +606,15 @@ impl_runtime_apis! { } #[cfg(feature = "bls-experimental")] - fn test_bls381_crypto() -> (bls381::AppSignature, bls381::AppPublic) { + fn test_bls381_crypto() -> (Bls381Signature, Bls381Public) { test_bls381_crypto() } + #[cfg(not(feature = "bls-experimental"))] + fn test_bls381_crypto() -> (Bls381Signature, Bls381Public) { + ((), ()) + } + fn test_storage() { test_read_storage(); test_read_child_storage(); @@ -826,6 +851,8 @@ fn test_bls381_crypto() -> (bls381::AppSignature, bls381::AppPublic) { assert!(all.contains(&public1)); assert!(all.contains(&public2)); + // let pop = bls381::AppPublic::generate_pop(); + let signature = public0.sign(&"bls381").expect("Generates a valid `bls381` signature."); assert!(public0.verify(&"bls381", &signature));