diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index be8553b7b3..ca6830085b 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -592,7 +592,7 @@ mod tests { use sc_service_test::TestNetNode; use sc_transaction_pool_api::{ChainEvent, MaintainedTransactionPool}; use sp_consensus::{BlockOrigin, Environment, Proposer}; - use sp_core::{crypto::Pair as CryptoPair, Public}; + use sp_core::crypto::Pair; use sp_inherents::InherentDataProvider; use sp_keyring::AccountKeyring; use sp_keystore::KeystorePtr; @@ -737,16 +737,10 @@ mod tests { // add it to a digest item. let to_sign = pre_hash.encode(); let signature = keystore - .sign_with( - sp_consensus_babe::AuthorityId::ID, - &alice.to_public_crypto_pair(), - &to_sign, - ) + .sr25519_sign(sp_consensus_babe::AuthorityId::ID, alice.as_ref(), &to_sign) .unwrap() - .unwrap() - .try_into() .unwrap(); - let item = ::babe_seal(signature); + let item = ::babe_seal(signature.into()); slot += 1; let mut params = BlockImportParams::new(BlockOrigin::File, new_header); diff --git a/substrate/bin/node/executor/tests/submit_transaction.rs b/substrate/bin/node/executor/tests/submit_transaction.rs index 9bff415d27..b260f90a87 100644 --- a/substrate/bin/node/executor/tests/submit_transaction.rs +++ b/substrate/bin/node/executor/tests/submit_transaction.rs @@ -18,7 +18,7 @@ use codec::Decode; use frame_system::offchain::{SendSignedTransaction, Signer, SubmitTransaction}; use kitchensink_runtime::{Executive, Indices, Runtime, UncheckedExtrinsic}; -use sp_application_crypto::AppKey; +use sp_application_crypto::AppCrypto; use sp_core::offchain::{testing::TestTransactionPoolExt, TransactionPoolExt}; use sp_keyring::sr25519::Keyring::Alice; use sp_keystore::{testing::MemoryKeystore, Keystore, KeystoreExt}; diff --git a/substrate/client/authority-discovery/src/error.rs b/substrate/client/authority-discovery/src/error.rs index 89c05b71b9..447116b0f6 100644 --- a/substrate/client/authority-discovery/src/error.rs +++ b/substrate/client/authority-discovery/src/error.rs @@ -18,8 +18,6 @@ //! Authority discovery errors. -use sp_core::crypto::CryptoTypePublicPair; - /// AuthorityDiscovery Result. pub type Result = std::result::Result; @@ -59,11 +57,8 @@ pub enum Error { #[error("Failed to parse a libp2p key.")] ParsingLibp2pIdentity(#[from] libp2p::identity::error::DecodingError), - #[error("Failed to sign using a specific public key.")] - MissingSignature(CryptoTypePublicPair), - - #[error("Failed to sign using all public keys.")] - Signing, + #[error("Failed to sign: {0}.")] + CannotSign(String), #[error("Failed to register Prometheus metric.")] Prometheus(#[from] prometheus_endpoint::PrometheusError), diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs index 5d7d21a5b6..43e44cac4d 100644 --- a/substrate/client/authority-discovery/src/worker.rs +++ b/substrate/client/authority-discovery/src/worker.rs @@ -32,7 +32,7 @@ use std::{ use futures::{channel::mpsc, future, stream::Fuse, FutureExt, Stream, StreamExt}; use addr_cache::AddrCache; -use codec::Decode; +use codec::{Decode, Encode}; use ip_network::IpNetwork; use libp2p::{ core::multiaddr, @@ -43,6 +43,7 @@ use log::{debug, error, log_enabled}; use prometheus_endpoint::{register, Counter, CounterVec, Gauge, Opts, U64}; use prost::Message; use rand::{seq::SliceRandom, thread_rng}; + use sc_network::{ event::DhtEvent, KademliaKey, NetworkDHTProvider, NetworkSigner, NetworkStateInfo, Signature, }; @@ -51,8 +52,7 @@ use sp_authority_discovery::{ AuthorityDiscoveryApi, AuthorityId, AuthorityPair, AuthoritySignature, }; use sp_blockchain::HeaderBackend; - -use sp_core::crypto::{key_types, CryptoTypePublicPair, Pair}; +use sp_core::crypto::{key_types, ByteArray, Pair}; use sp_keystore::{Keystore, KeystorePtr}; use sp_runtime::traits::Block as BlockT; @@ -127,7 +127,7 @@ pub struct Worker { publish_if_changed_interval: ExpIncInterval, /// List of keys onto which addresses have been published at the latest publication. /// Used to check whether they have changed. - latest_published_keys: HashSet, + latest_published_keys: HashSet, /// Same value as in the configuration. publish_non_global_ips: bool, /// Same value as in the configuration. @@ -339,7 +339,7 @@ where let keys = Worker::::get_own_public_keys_within_authority_set( key_store.clone(), self.client.as_ref(), - ).await?.into_iter().map(Into::into).collect::>(); + ).await?.into_iter().collect::>(); if only_if_changed && keys == self.latest_published_keys { return Ok(()) @@ -654,7 +654,7 @@ fn sign_record_with_peer_id( ) -> Result { let signature = network .sign_with_local_identity(serialized_record) - .map_err(|_| Error::Signing)?; + .map_err(|e| Error::CannotSign(format!("{} (network packet)", e)))?; let public_key = signature.public_key.to_protobuf_encoding(); let signature = signature.bytes; Ok(schema::PeerSignature { signature, public_key }) @@ -664,15 +664,20 @@ fn sign_record_with_authority_ids( serialized_record: Vec, peer_signature: Option, key_store: &dyn Keystore, - keys: Vec, + keys: Vec, ) -> Result)>> { let mut result = Vec::with_capacity(keys.len()); for key in keys.iter() { let auth_signature = key_store - .sign_with(key_types::AUTHORITY_DISCOVERY, key, &serialized_record) - .map_err(|_| Error::Signing)? - .ok_or_else(|| Error::MissingSignature(key.clone()))?; + .sr25519_sign(key_types::AUTHORITY_DISCOVERY, key.as_ref(), &serialized_record) + .map_err(|e| Error::CannotSign(format!("{}. Key: {:?}", e, key)))? + .ok_or_else(|| { + Error::CannotSign(format!("Could not find key in keystore. Key: {:?}", key)) + })?; + + // Scale encode + let auth_signature = auth_signature.encode(); let signed_record = schema::SignedAuthorityRecord { record: serialized_record.clone(), @@ -681,7 +686,7 @@ fn sign_record_with_authority_ids( } .encode_to_vec(); - result.push((hash_authority_id(&key.1), signed_record)); + result.push((hash_authority_id(key.as_slice()), signed_record)); } Ok(result) diff --git a/substrate/client/consensus/aura/src/lib.rs b/substrate/client/consensus/aura/src/lib.rs index d06a6016a2..a48eeac5ce 100644 --- a/substrate/client/consensus/aura/src/lib.rs +++ b/substrate/client/consensus/aura/src/lib.rs @@ -45,7 +45,7 @@ use sc_consensus_slots::{ }; use sc_telemetry::TelemetryHandle; use sp_api::{Core, ProvideRuntimeApi}; -use sp_application_crypto::{AppKey, AppPublic}; +use sp_application_crypto::{AppCrypto, AppPublic}; use sp_blockchain::{HeaderBackend, Result as CResult}; use sp_consensus::{BlockOrigin, Environment, Error as ConsensusError, Proposer, SelectChain}; use sp_consensus_slots::Slot; @@ -205,7 +205,7 @@ pub fn start_aura( telemetry, compatibility_mode, }: StartAuraParams>, -) -> Result, sp_consensus::Error> +) -> Result, ConsensusError> where P: Pair + Send + Sync, P::Public: AppPublic + Hash + Member + Encode + Decode, @@ -222,7 +222,7 @@ where CIDP: CreateInherentDataProviders + Send + 'static, CIDP::InherentDataProviders: InherentDataProviderExt + Send, BS: BackoffAuthoringBlocksStrategy> + Send + Sync + 'static, - Error: std::error::Error + Send + From + 'static, + Error: std::error::Error + Send + From + 'static, { let worker = build_aura_worker::(BuildAuraWorkerParams { client, @@ -320,7 +320,7 @@ where P::Public: AppPublic + Hash + Member + Encode + Decode, P::Signature: TryFrom> + Hash + Member + Encode + Decode, I: BlockImport> + Send + Sync + 'static, - Error: std::error::Error + Send + From + 'static, + Error: std::error::Error + Send + From + 'static, SO: SyncOracle + Send + Sync + Clone, L: sc_consensus::JustificationSyncLink, BS: BackoffAuthoringBlocksStrategy> + Send + Sync + 'static, @@ -374,13 +374,13 @@ where SO: SyncOracle + Send + Clone + Sync, L: sc_consensus::JustificationSyncLink, BS: BackoffAuthoringBlocksStrategy> + Send + Sync + 'static, - Error: std::error::Error + Send + From + 'static, + Error: std::error::Error + Send + From + 'static, { type BlockImport = I; type SyncOracle = SO; type JustificationSyncLink = L; type CreateProposer = - Pin> + Send + 'static>>; + Pin> + Send + 'static>>; type Proposer = E::Proposer; type Claim = P::Public; type AuxData = Vec>; @@ -393,11 +393,7 @@ where &mut self.block_import } - fn aux_data( - &self, - header: &B::Header, - _slot: Slot, - ) -> Result { + fn aux_data(&self, header: &B::Header, _slot: Slot) -> Result { authorities( self.client.as_ref(), header.hash(), @@ -406,17 +402,17 @@ where ) } - fn authorities_len(&self, epoch_data: &Self::AuxData) -> Option { - Some(epoch_data.len()) + fn authorities_len(&self, authorities: &Self::AuxData) -> Option { + Some(authorities.len()) } async fn claim_slot( &self, _header: &B::Header, slot: Slot, - epoch_data: &Self::AuxData, + authorities: &Self::AuxData, ) -> Option { - let expected_author = slot_author::

(slot, epoch_data); + let expected_author = slot_author::

(slot, authorities); expected_author.and_then(|p| { if self .keystore @@ -440,29 +436,30 @@ where body: Vec, storage_changes: StorageChanges<>::Transaction, B>, public: Self::Claim, - _epoch: Self::AuxData, + _authorities: Self::AuxData, ) -> Result< sc_consensus::BlockImportParams>::Transaction>, - sp_consensus::Error, + ConsensusError, > { - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let public_type_pair = public.to_public_crypto_pair(); - let public = public.to_raw_vec(); let signature = self .keystore - .sign_with( as AppKey>::ID, &public_type_pair, header_hash.as_ref()) - .map_err(|e| sp_consensus::Error::CannotSign(public.clone(), e.to_string()))? + .sign_with( + as AppCrypto>::ID, + as AppCrypto>::CRYPTO_ID, + public.as_slice(), + header_hash.as_ref(), + ) + .map_err(|e| ConsensusError::CannotSign(format!("{}. Key: {:?}", e, public)))? .ok_or_else(|| { - sp_consensus::Error::CannotSign( - public.clone(), - "Could not find key in keystore.".into(), - ) + ConsensusError::CannotSign(format!( + "Could not find key in keystore. Key: {:?}", + public + )) })?; let signature = signature .clone() .try_into() - .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; + .map_err(|_| ConsensusError::InvalidSignature(signature, public.to_raw_vec()))?; let signature_digest_item = >::aura_seal(signature); @@ -507,7 +504,7 @@ where fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer { self.env .init(block) - .map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e))) + .map_err(|e| ConsensusError::ClientImport(format!("{:?}", e))) .boxed() } @@ -620,14 +617,14 @@ where Default::default(), ), ) - .map_err(|_| sp_consensus::Error::InvalidAuthoritiesSet)?; + .map_err(|_| ConsensusError::InvalidAuthoritiesSet)?; }, } runtime_api .authorities(parent_hash) .ok() - .ok_or(sp_consensus::Error::InvalidAuthoritiesSet) + .ok_or(ConsensusError::InvalidAuthoritiesSet) } #[cfg(test)] diff --git a/substrate/client/consensus/babe/rpc/src/lib.rs b/substrate/client/consensus/babe/rpc/src/lib.rs index 005d84938e..cdc8dbfd80 100644 --- a/substrate/client/consensus/babe/rpc/src/lib.rs +++ b/substrate/client/consensus/babe/rpc/src/lib.rs @@ -30,7 +30,7 @@ use sc_consensus_epochs::{descendent_query, Epoch as EpochT, SharedEpochChanges} use sc_rpc_api::DenyUnsafe; use serde::{Deserialize, Serialize}; use sp_api::ProvideRuntimeApi; -use sp_application_crypto::AppKey; +use sp_application_crypto::AppCrypto; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; use sp_consensus::{Error as ConsensusError, SelectChain}; use sp_consensus_babe::{ diff --git a/substrate/client/consensus/babe/src/authorship.rs b/substrate/client/consensus/babe/src/authorship.rs index c4b43b0d07..3ff4c393ff 100644 --- a/substrate/client/consensus/babe/src/authorship.rs +++ b/substrate/client/consensus/babe/src/authorship.rs @@ -22,7 +22,7 @@ use super::Epoch; use codec::Encode; use sc_consensus_epochs::Epoch as EpochT; use schnorrkel::{keys::PublicKey, vrf::VRFInOut}; -use sp_application_crypto::AppKey; +use sp_application_crypto::AppCrypto; use sp_consensus_babe::{ digests::{PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest}, make_transcript, make_transcript_data, AuthorityId, BabeAuthorityWeight, Slot, BABE_VRF_PREFIX, diff --git a/substrate/client/consensus/babe/src/lib.rs b/substrate/client/consensus/babe/src/lib.rs index e2c2793b11..a59870ced0 100644 --- a/substrate/client/consensus/babe/src/lib.rs +++ b/substrate/client/consensus/babe/src/lib.rs @@ -108,7 +108,7 @@ use sc_consensus_slots::{ }; use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_TRACE}; use sp_api::{ApiExt, ProvideRuntimeApi}; -use sp_application_crypto::AppKey; +use sp_application_crypto::AppCrypto; use sp_block_builder::BlockBuilder as BlockBuilderApi; use sp_blockchain::{ Backend as _, BlockStatus, Error as ClientError, ForkBackend, HeaderBackend, HeaderMetadata, @@ -117,7 +117,7 @@ use sp_blockchain::{ use sp_consensus::{BlockOrigin, Environment, Error as ConsensusError, Proposer, SelectChain}; use sp_consensus_babe::inherents::BabeInherentData; use sp_consensus_slots::Slot; -use sp_core::{crypto::ByteArray, ExecutionContext}; +use sp_core::ExecutionContext; use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider}; use sp_keystore::KeystorePtr; use sp_runtime::{ @@ -274,7 +274,7 @@ pub enum Error { MultipleConfigChangeDigests, /// Could not extract timestamp and slot #[error("Could not extract timestamp and slot: {0}")] - Extraction(sp_consensus::Error), + Extraction(ConsensusError), /// Could not fetch epoch #[error("Could not fetch epoch at {0:?}")] FetchEpoch(B::Hash), @@ -471,7 +471,7 @@ pub fn start_babe( max_block_proposal_slot_portion, telemetry, }: BabeParams, -) -> Result, sp_consensus::Error> +) -> Result, ConsensusError> where B: BlockT, C: ProvideRuntimeApi @@ -739,7 +739,7 @@ where type SyncOracle = SO; type JustificationSyncLink = L; type CreateProposer = - Pin> + Send + 'static>>; + Pin> + Send + 'static>>; type Proposer = E::Proposer; type BlockImport = I; type AuxData = ViableEpochDescriptor, Epoch>; @@ -762,7 +762,7 @@ where slot, ) .map_err(|e| ConsensusError::ChainLookup(e.to_string()))? - .ok_or(sp_consensus::Error::InvalidAuthoritiesSet) + .ok_or(ConsensusError::InvalidAuthoritiesSet) } fn authorities_len(&self, epoch_descriptor: &Self::AuxData) -> Option { @@ -827,28 +827,21 @@ where (_, public): Self::Claim, epoch_descriptor: Self::AuxData, ) -> Result< - sc_consensus::BlockImportParams>::Transaction>, - sp_consensus::Error, + BlockImportParams>::Transaction>, + ConsensusError, > { - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let public_type_pair = public.clone().into(); - let public = public.to_raw_vec(); let signature = self .keystore - .sign_with(::ID, &public_type_pair, header_hash.as_ref()) - .map_err(|e| sp_consensus::Error::CannotSign(public.clone(), e.to_string()))? + .sr25519_sign(::ID, public.as_ref(), header_hash.as_ref()) + .map_err(|e| ConsensusError::CannotSign(format!("{}. Key: {:?}", e, public)))? .ok_or_else(|| { - sp_consensus::Error::CannotSign( - public.clone(), - "Could not find key in keystore.".into(), - ) + ConsensusError::CannotSign(format!( + "Could not find key in keystore. Key: {:?}", + public + )) })?; - let signature: AuthoritySignature = signature - .clone() - .try_into() - .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; - let digest_item = ::babe_seal(signature); + + let digest_item = ::babe_seal(signature.into()); let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); import_block.post_digests.push(digest_item); @@ -891,11 +884,7 @@ where } fn proposer(&mut self, block: &B::Header) -> Self::CreateProposer { - Box::pin( - self.env - .init(block) - .map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e))), - ) + Box::pin(self.env.init(block).map_err(|e| ConsensusError::ClientImport(e.to_string()))) } fn telemetry(&self) -> Option { @@ -1182,7 +1171,7 @@ where .create_inherent_data_providers .create_inherent_data_providers(parent_hash, ()) .await - .map_err(|e| Error::::Client(sp_consensus::Error::from(e).into()))?; + .map_err(|e| Error::::Client(ConsensusError::from(e).into()))?; let slot_now = create_inherent_data_providers.slot(); diff --git a/substrate/client/consensus/grandpa/src/lib.rs b/substrate/client/consensus/grandpa/src/lib.rs index cf98e17920..90cb8a51fa 100644 --- a/substrate/client/consensus/grandpa/src/lib.rs +++ b/substrate/client/consensus/grandpa/src/lib.rs @@ -72,7 +72,7 @@ use sc_network::types::ProtocolName; use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use sp_api::ProvideRuntimeApi; -use sp_application_crypto::AppKey; +use sp_application_crypto::AppCrypto; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult}; use sp_consensus::SelectChain; use sp_consensus_grandpa::{ diff --git a/substrate/client/consensus/slots/src/lib.rs b/substrate/client/consensus/slots/src/lib.rs index f1d817ab7d..e414734079 100644 --- a/substrate/client/consensus/slots/src/lib.rs +++ b/substrate/client/consensus/slots/src/lib.rs @@ -150,7 +150,7 @@ pub trait SimpleSlotWorker { body: Vec, storage_changes: StorageChanges<>::Transaction, B>, public: Self::Claim, - epoch: Self::AuxData, + aux_data: Self::AuxData, ) -> Result< sc_consensus::BlockImportParams>::Transaction>, sp_consensus::Error, diff --git a/substrate/client/keystore/src/local.rs b/substrate/client/keystore/src/local.rs index a4af781172..abdf97bb22 100644 --- a/substrate/client/keystore/src/local.rs +++ b/substrate/client/keystore/src/local.rs @@ -18,13 +18,10 @@ //! Local keystore implementation use parking_lot::RwLock; -use sp_application_crypto::{ecdsa, ed25519, sr25519, AppKey, AppPair, IsWrappedBy}; +use sp_application_crypto::{AppCrypto, AppPair, IsWrappedBy}; use sp_core::{ - crypto::{ - ByteArray, CryptoTypePublicPair, ExposeSecret, KeyTypeId, Pair as PairT, SecretString, - }, - sr25519::{Pair as Sr25519Pair, Public as Sr25519Public}, - Encode, + crypto::{ByteArray, ExposeSecret, KeyTypeId, Pair as CorePair, SecretString}, + ecdsa, ed25519, sr25519, }; use sp_keystore::{ vrf::{make_transcript, VRFSignature, VRFTranscriptData}, @@ -62,67 +59,13 @@ impl LocalKeystore { /// `Err(_)` when something failed. pub fn key_pair( &self, - public: &::Public, + public: &::Public, ) -> Result> { self.0.read().key_pair::(public) } } impl Keystore for LocalKeystore { - fn keys(&self, id: KeyTypeId) -> std::result::Result, TraitError> { - let raw_keys = self.0.read().raw_public_keys(id)?; - Ok(raw_keys.into_iter().fold(Vec::new(), |mut v, k| { - v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone())); - v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone())); - v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k)); - v - })) - } - - fn sign_with( - &self, - id: KeyTypeId, - key: &CryptoTypePublicPair, - msg: &[u8], - ) -> std::result::Result>, TraitError> { - match key.0 { - ed25519::CRYPTO_ID => { - let pub_key = ed25519::Public::from_slice(key.1.as_slice()).map_err(|()| { - TraitError::Other("Corrupted public key - Invalid size".into()) - })?; - let key_pair = self - .0 - .read() - .key_pair_by_type::(&pub_key, id) - .map_err(TraitError::from)?; - key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() - }, - sr25519::CRYPTO_ID => { - let pub_key = sr25519::Public::from_slice(key.1.as_slice()).map_err(|()| { - TraitError::Other("Corrupted public key - Invalid size".into()) - })?; - let key_pair = self - .0 - .read() - .key_pair_by_type::(&pub_key, id) - .map_err(TraitError::from)?; - key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() - }, - ecdsa::CRYPTO_ID => { - let pub_key = ecdsa::Public::from_slice(key.1.as_slice()).map_err(|()| { - TraitError::Other("Corrupted public key - Invalid size".into()) - })?; - let key_pair = self - .0 - .read() - .key_pair_by_type::(&pub_key, id) - .map_err(TraitError::from)?; - key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() - }, - _ => Err(TraitError::KeyNotSupported(id)), - } - } - fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { self.0 .read() @@ -140,19 +83,49 @@ impl Keystore for LocalKeystore { /// If the `[seed]` is `Some` then the key will be ephemeral and stored in memory. fn sr25519_generate_new( &self, - id: KeyTypeId, + key_type: KeyTypeId, seed: Option<&str>, ) -> std::result::Result { let pair = match seed { - Some(seed) => - self.0.write().insert_ephemeral_from_seed_by_type::(seed, id), - None => self.0.write().generate_by_type::(id), + Some(seed) => self + .0 + .write() + .insert_ephemeral_from_seed_by_type::(seed, key_type), + None => self.0.write().generate_by_type::(key_type), } .map_err(|e| -> TraitError { e.into() })?; Ok(pair.public()) } + fn sr25519_sign( + &self, + key_type: KeyTypeId, + public: &sr25519::Public, + msg: &[u8], + ) -> std::result::Result, TraitError> { + let res = self + .0 + .read() + .key_pair_by_type::(public, key_type)? + .map(|pair| pair.sign(msg)); + Ok(res) + } + + fn sr25519_vrf_sign( + &self, + key_type: KeyTypeId, + public: &sr25519::Public, + transcript_data: VRFTranscriptData, + ) -> std::result::Result, TraitError> { + let res = self.0.read().key_pair_by_type::(public, key_type)?.map(|pair| { + let transcript = make_transcript(transcript_data); + let (inout, proof, _) = pair.as_ref().vrf_sign(transcript); + VRFSignature { output: inout.to_output(), proof } + }); + Ok(res) + } + fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec { self.0 .read() @@ -170,19 +143,35 @@ impl Keystore for LocalKeystore { /// If the `[seed]` is `Some` then the key will be ephemeral and stored in memory. fn ed25519_generate_new( &self, - id: KeyTypeId, + key_type: KeyTypeId, seed: Option<&str>, ) -> std::result::Result { let pair = match seed { - Some(seed) => - self.0.write().insert_ephemeral_from_seed_by_type::(seed, id), - None => self.0.write().generate_by_type::(id), + Some(seed) => self + .0 + .write() + .insert_ephemeral_from_seed_by_type::(seed, key_type), + None => self.0.write().generate_by_type::(key_type), } .map_err(|e| -> TraitError { e.into() })?; Ok(pair.public()) } + fn ed25519_sign( + &self, + key_type: KeyTypeId, + public: &ed25519::Public, + msg: &[u8], + ) -> std::result::Result, TraitError> { + let res = self + .0 + .read() + .key_pair_by_type::(public, key_type)? + .map(|pair| pair.sign(msg)); + Ok(res) + } + fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec { self.0 .read() @@ -200,19 +189,47 @@ impl Keystore for LocalKeystore { /// If the `[seed]` is `Some` then the key will be ephemeral and stored in memory. fn ecdsa_generate_new( &self, - id: KeyTypeId, + key_type: KeyTypeId, seed: Option<&str>, ) -> std::result::Result { let pair = match seed { Some(seed) => - self.0.write().insert_ephemeral_from_seed_by_type::(seed, id), - None => self.0.write().generate_by_type::(id), + self.0.write().insert_ephemeral_from_seed_by_type::(seed, key_type), + None => self.0.write().generate_by_type::(key_type), } .map_err(|e| -> TraitError { e.into() })?; Ok(pair.public()) } + fn ecdsa_sign( + &self, + key_type: KeyTypeId, + public: &ecdsa::Public, + msg: &[u8], + ) -> std::result::Result, TraitError> { + let res = self + .0 + .read() + .key_pair_by_type::(public, key_type)? + .map(|pair| pair.sign(msg)); + Ok(res) + } + + fn ecdsa_sign_prehashed( + &self, + key_type: KeyTypeId, + public: &ecdsa::Public, + msg: &[u8; 32], + ) -> std::result::Result, TraitError> { + let res = self + .0 + .read() + .key_pair_by_type::(public, key_type)? + .map(|pair| pair.sign_prehashed(msg)); + Ok(res) + } + fn insert( &self, key_type: KeyTypeId, @@ -222,39 +239,15 @@ impl Keystore for LocalKeystore { self.0.write().insert(key_type, suri, public).map_err(|_| ()) } + fn keys(&self, key_type: KeyTypeId) -> std::result::Result>, TraitError> { + self.0.read().raw_public_keys(key_type).map_err(|e| e.into()) + } + fn has_keys(&self, public_keys: &[(Vec, KeyTypeId)]) -> bool { public_keys .iter() .all(|(p, t)| self.0.read().key_phrase_by_type(p, *t).ok().flatten().is_some()) } - - fn sr25519_vrf_sign( - &self, - key_type: KeyTypeId, - public: &Sr25519Public, - transcript_data: VRFTranscriptData, - ) -> std::result::Result, TraitError> { - let transcript = make_transcript(transcript_data); - let pair = self.0.read().key_pair_by_type::(public, key_type)?; - - if let Some(pair) = pair { - let (inout, proof, _) = pair.as_ref().vrf_sign(transcript); - Ok(Some(VRFSignature { output: inout.to_output(), proof })) - } else { - Ok(None) - } - } - - fn ecdsa_sign_prehashed( - &self, - id: KeyTypeId, - public: &ecdsa::Public, - msg: &[u8; 32], - ) -> std::result::Result, TraitError> { - let pair = self.0.read().key_pair_by_type::(public, id)?; - - pair.map(|k| k.sign_prehashed(msg)).map(Ok).transpose() - } } impl Into for LocalKeystore { @@ -305,7 +298,12 @@ impl KeystoreInner { /// Insert the given public/private key pair with the given key type. /// /// Does not place it into the file system store. - fn insert_ephemeral_pair(&mut self, pair: &Pair, seed: &str, key_type: KeyTypeId) { + fn insert_ephemeral_pair( + &mut self, + pair: &Pair, + seed: &str, + key_type: KeyTypeId, + ) { let key = (key_type, pair.public().to_raw_vec()); self.additional.insert(key, seed.into()); } @@ -325,7 +323,7 @@ impl KeystoreInner { /// /// Places it into the file system store, if a path is configured. Otherwise insert /// it into the memory cache only. - fn generate_by_type(&mut self, key_type: KeyTypeId) -> Result { + fn generate_by_type(&mut self, key_type: KeyTypeId) -> Result { let (pair, phrase, _) = Pair::generate_with_phrase(self.password()); if let Some(path) = self.key_file_path(pair.public().as_slice(), key_type) { Self::write_to_file(path, &phrase)?; @@ -354,7 +352,7 @@ impl KeystoreInner { /// Create a new key from seed. /// /// Does not place it into the file system store. - fn insert_ephemeral_from_seed_by_type( + fn insert_ephemeral_from_seed_by_type( &mut self, seed: &str, key_type: KeyTypeId, @@ -386,7 +384,7 @@ impl KeystoreInner { } /// Get a key pair for the given public key and key type. - fn key_pair_by_type( + fn key_pair_by_type( &self, public: &Pair::Public, key_type: KeyTypeId, @@ -418,12 +416,12 @@ impl KeystoreInner { } /// Returns a list of raw public keys filtered by `KeyTypeId` - fn raw_public_keys(&self, id: KeyTypeId) -> Result>> { + fn raw_public_keys(&self, key_type: KeyTypeId) -> Result>> { let mut public_keys: Vec> = self .additional .keys() .into_iter() - .filter_map(|k| if k.0 == id { Some(k.1.clone()) } else { None }) + .filter_map(|k| if k.0 == key_type { Some(k.1.clone()) } else { None }) .collect(); if let Some(path) = &self.path { @@ -435,7 +433,7 @@ impl KeystoreInner { if let Some(name) = path.file_name().and_then(|n| n.to_str()) { match array_bytes::hex2bytes(name) { Ok(ref hex) if hex.len() > 4 => { - if hex[0..4] != id.0 { + if hex[0..4] != key_type.0 { continue } let public = hex[4..].to_vec(); @@ -456,7 +454,7 @@ impl KeystoreInner { /// when something failed. pub fn key_pair( &self, - public: &::Public, + public: &::Public, ) -> Result> { self.key_pair_by_type::(IsWrappedBy::from_ref(public), Pair::ID) .map(|v| v.map(Into::into)) diff --git a/substrate/client/rpc/src/author/tests.rs b/substrate/client/rpc/src/author/tests.rs index 75b6390c83..fbbd1a92fd 100644 --- a/substrate/client/rpc/src/author/tests.rs +++ b/substrate/client/rpc/src/author/tests.rs @@ -31,8 +31,8 @@ use sc_transaction_pool_api::TransactionStatus; use sp_core::{ blake2_256, bytes::to_hex, - crypto::{ByteArray, CryptoTypePublicPair, Pair}, - ed25519, sr25519, + crypto::{ByteArray, Pair}, + ed25519, testing::{ED25519, SR25519}, H256, }; @@ -227,9 +227,7 @@ async fn author_should_insert_key() { api.call::<_, ()>("author_insertKey", params).await.unwrap(); let pubkeys = setup.keystore.keys(ED25519).unwrap(); - assert!( - pubkeys.contains(&CryptoTypePublicPair(ed25519::CRYPTO_ID, keypair.public().to_raw_vec())) - ); + assert!(pubkeys.contains(&keypair.public().to_raw_vec())); } #[tokio::test] @@ -242,10 +240,8 @@ async fn author_should_rotate_keys() { SessionKeys::decode(&mut &new_pubkeys[..]).expect("SessionKeys decode successfully"); let ed25519_pubkeys = setup.keystore.keys(ED25519).unwrap(); let sr25519_pubkeys = setup.keystore.keys(SR25519).unwrap(); - assert!(ed25519_pubkeys - .contains(&CryptoTypePublicPair(ed25519::CRYPTO_ID, session_keys.ed25519.to_raw_vec()))); - assert!(sr25519_pubkeys - .contains(&CryptoTypePublicPair(sr25519::CRYPTO_ID, session_keys.sr25519.to_raw_vec()))); + assert!(ed25519_pubkeys.contains(&session_keys.ed25519.to_raw_vec())); + assert!(sr25519_pubkeys.contains(&session_keys.sr25519.to_raw_vec())); } #[tokio::test] diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs index 0685477ddf..bf73881333 100644 --- a/substrate/primitives/application-crypto/src/lib.rs +++ b/substrate/primitives/application-crypto/src/lib.rs @@ -27,10 +27,7 @@ pub use sp_core::crypto::{DeriveError, DeriveJunction, Pair, SecretStringError, #[doc(hidden)] pub use sp_core::{ self, - crypto::{ - ByteArray, CryptoType, CryptoTypePublicPair, Derive, IsWrappedBy, Public, UncheckedFrom, - Wraps, - }, + crypto::{ByteArray, CryptoType, Derive, IsWrappedBy, Public, UncheckedFrom, Wraps}, RuntimeDebug, }; @@ -170,8 +167,7 @@ macro_rules! app_crypto_pair { } } - impl $crate::AppKey for Pair { - type UntypedGeneric = $pair; + impl $crate::AppCrypto for Pair { type Public = Public; type Pair = Pair; type Signature = Signature; @@ -238,8 +234,7 @@ macro_rules! app_crypto_public_full_crypto { type Pair = Pair; } - impl $crate::AppKey for Public { - type UntypedGeneric = $public; + impl $crate::AppCrypto for Public { type Public = Public; type Pair = Pair; type Signature = Signature; @@ -272,8 +267,7 @@ macro_rules! app_crypto_public_not_full_crypto { impl $crate::CryptoType for Public {} - impl $crate::AppKey for Public { - type UntypedGeneric = $public; + impl $crate::AppCrypto for Public { type Public = Public; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; @@ -306,11 +300,8 @@ macro_rules! app_crypto_public_common { impl $crate::ByteArray for Public { const LEN: usize = <$public>::LEN; } - impl $crate::Public for Public { - fn to_public_crypto_pair(&self) -> $crate::CryptoTypePublicPair { - $crate::CryptoTypePublicPair($crypto_type, $crate::ByteArray::to_raw_vec(self)) - } - } + + impl $crate::Public for Public {} impl $crate::AppPublic for Public { type Generic = $public; @@ -350,18 +341,6 @@ macro_rules! app_crypto_public_common { } } - impl From for $crate::CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } - } - - impl From<&Public> for $crate::CryptoTypePublicPair { - fn from(key: &Public) -> Self { - $crate::CryptoTypePublicPair($crypto_type, $crate::ByteArray::to_raw_vec(key)) - } - } - impl<'a> TryFrom<&'a [u8]> for Public { type Error = (); @@ -450,8 +429,7 @@ macro_rules! app_crypto_signature_full_crypto { type Pair = Pair; } - impl $crate::AppKey for Signature { - type UntypedGeneric = $sig; + impl $crate::AppCrypto for Signature { type Public = Public; type Pair = Pair; type Signature = Signature; @@ -482,8 +460,7 @@ macro_rules! app_crypto_signature_not_full_crypto { impl $crate::CryptoType for Signature {} - impl $crate::AppKey for Signature { - type UntypedGeneric = $sig; + impl $crate::AppCrypto for Signature { type Public = Public; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; diff --git a/substrate/primitives/application-crypto/src/traits.rs b/substrate/primitives/application-crypto/src/traits.rs index e3586ccecd..f672efb8a8 100644 --- a/substrate/primitives/application-crypto/src/traits.rs +++ b/substrate/primitives/application-crypto/src/traits.rs @@ -23,24 +23,22 @@ use sp_core::crypto::{CryptoType, CryptoTypeId, IsWrappedBy, KeyTypeId, Public}; use sp_std::{fmt::Debug, vec::Vec}; /// An application-specific key. -pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { - /// The corresponding type as a generic crypto type. - type UntypedGeneric: IsWrappedBy; +pub trait AppCrypto: 'static + Send + Sync + Sized + CryptoType + Clone { + /// Identifier for application-specific key type. + const ID: KeyTypeId; + + /// Identifier of the crypto type of this application-specific key type. + const CRYPTO_ID: CryptoTypeId; /// The corresponding public key type in this application scheme. type Public: AppPublic; - /// The corresponding key pair type in this application scheme. - #[cfg(feature = "full_crypto")] - type Pair: AppPair; - /// The corresponding signature type in this application scheme. type Signature: AppSignature; - /// An identifier for this application-specific key type. - const ID: KeyTypeId; - /// The identifier of the crypto type of this application-specific key type. - const CRYPTO_ID: CryptoTypeId; + /// The corresponding key pair type in this application scheme. + #[cfg(feature = "full_crypto")] + type Pair: AppPair; } /// Type which implements Hash in std, not when no-std (std variant). @@ -63,7 +61,7 @@ impl MaybeDebugHash for T {} /// A application's public key. pub trait AppPublic: - AppKey + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec + AppCrypto + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec { /// The wrapped type which is just a plain instance of `Public`. type Generic: IsWrappedBy @@ -79,14 +77,15 @@ pub trait AppPublic: /// A application's key pair. #[cfg(feature = "full_crypto")] -pub trait AppPair: AppKey + Pair::Public> { +pub trait AppPair: AppCrypto + Pair::Public> { /// The wrapped type which is just a plain instance of `Pair`. type Generic: IsWrappedBy - + Pair::Public as AppPublic>::Generic>; + + Pair::Public as AppPublic>::Generic> + + Pair::Signature as AppSignature>::Generic>; } /// A application's signature. -pub trait AppSignature: AppKey + Eq + PartialEq + Debug + MaybeHash { +pub trait AppSignature: AppCrypto + Eq + PartialEq + Debug + MaybeHash { /// The wrapped type which is just a plain instance of `Signature`. type Generic: IsWrappedBy + Eq + PartialEq + Debug + MaybeHash; } diff --git a/substrate/primitives/application-crypto/test/src/ecdsa.rs b/substrate/primitives/application-crypto/test/src/ecdsa.rs index fe9e17a65b..99ca6f4c4a 100644 --- a/substrate/primitives/application-crypto/test/src/ecdsa.rs +++ b/substrate/primitives/application-crypto/test/src/ecdsa.rs @@ -17,8 +17,11 @@ //! Integration tests for ecdsa use sp_api::ProvideRuntimeApi; -use sp_application_crypto::ecdsa::{AppPair, AppPublic}; -use sp_core::{crypto::Pair, testing::ECDSA}; +use sp_application_crypto::ecdsa::AppPair; +use sp_core::{ + crypto::{ByteArray, Pair}, + testing::ECDSA, +}; use sp_keystore::{testing::MemoryKeystore, Keystore}; use std::sync::Arc; use substrate_test_runtime_client::{ @@ -35,6 +38,6 @@ fn ecdsa_works_in_runtime() { .expect("Tests `ecdsa` crypto."); let supported_keys = keystore.keys(ECDSA).unwrap(); - assert!(supported_keys.contains(&public.clone().into())); - assert!(AppPair::verify(&signature, "ecdsa", &AppPublic::from(public))); + assert!(supported_keys.contains(&public.to_raw_vec())); + assert!(AppPair::verify(&signature, "ecdsa", &public)); } diff --git a/substrate/primitives/application-crypto/test/src/ed25519.rs b/substrate/primitives/application-crypto/test/src/ed25519.rs index 5687bd0139..f4553f95bf 100644 --- a/substrate/primitives/application-crypto/test/src/ed25519.rs +++ b/substrate/primitives/application-crypto/test/src/ed25519.rs @@ -18,8 +18,11 @@ //! Integration tests for ed25519 use sp_api::ProvideRuntimeApi; -use sp_application_crypto::ed25519::{AppPair, AppPublic}; -use sp_core::{crypto::Pair, testing::ED25519}; +use sp_application_crypto::ed25519::AppPair; +use sp_core::{ + crypto::{ByteArray, Pair}, + testing::ED25519, +}; use sp_keystore::{testing::MemoryKeystore, Keystore}; use std::sync::Arc; use substrate_test_runtime_client::{ @@ -36,6 +39,6 @@ fn ed25519_works_in_runtime() { .expect("Tests `ed25519` crypto."); let supported_keys = keystore.keys(ED25519).unwrap(); - assert!(supported_keys.contains(&public.clone().into())); - assert!(AppPair::verify(&signature, "ed25519", &AppPublic::from(public))); + assert!(supported_keys.contains(&public.to_raw_vec())); + assert!(AppPair::verify(&signature, "ed25519", &public)); } diff --git a/substrate/primitives/application-crypto/test/src/sr25519.rs b/substrate/primitives/application-crypto/test/src/sr25519.rs index 92886b80cb..736521d7d9 100644 --- a/substrate/primitives/application-crypto/test/src/sr25519.rs +++ b/substrate/primitives/application-crypto/test/src/sr25519.rs @@ -18,8 +18,11 @@ //! Integration tests for sr25519 use sp_api::ProvideRuntimeApi; -use sp_application_crypto::sr25519::{AppPair, AppPublic}; -use sp_core::{crypto::Pair, testing::SR25519}; +use sp_application_crypto::sr25519::AppPair; +use sp_core::{ + crypto::{ByteArray, Pair}, + testing::SR25519, +}; use sp_keystore::{testing::MemoryKeystore, Keystore}; use std::sync::Arc; use substrate_test_runtime_client::{ @@ -36,6 +39,6 @@ fn sr25519_works_in_runtime() { .expect("Tests `sr25519` crypto."); let supported_keys = keystore.keys(SR25519).unwrap(); - assert!(supported_keys.contains(&public.clone().into())); - assert!(AppPair::verify(&signature, "sr25519", &AppPublic::from(public))); + assert!(supported_keys.contains(&public.to_raw_vec())); + assert!(AppPair::verify(&signature, "sr25519", &public)); } diff --git a/substrate/primitives/consensus/common/src/error.rs b/substrate/primitives/consensus/common/src/error.rs index e881259da1..fb8d0447fe 100644 --- a/substrate/primitives/consensus/common/src/error.rs +++ b/substrate/primitives/consensus/common/src/error.rs @@ -48,8 +48,8 @@ pub enum Error { #[error("Chain lookup failed: {0}")] ChainLookup(String), /// Signing failed. - #[error("Failed to sign using key: {0:?}. Reason: {1}")] - CannotSign(Vec, String), + #[error("Failed to sign: {0}")] + CannotSign(String), /// Some other error. #[error(transparent)] Other(#[from] Box), diff --git a/substrate/primitives/consensus/grandpa/src/lib.rs b/substrate/primitives/consensus/grandpa/src/lib.rs index 7f5857e4ba..728ce30928 100644 --- a/substrate/primitives/consensus/grandpa/src/lib.rs +++ b/substrate/primitives/consensus/grandpa/src/lib.rs @@ -451,12 +451,11 @@ where H: Encode, N: Encode, { - use sp_application_crypto::AppKey; - use sp_core::crypto::Public; + use sp_application_crypto::AppCrypto; let encoded = localized_payload(round, set_id, &message); let signature = keystore - .sign_with(AuthorityId::ID, &public.to_public_crypto_pair(), &encoded[..]) + .ed25519_sign(AuthorityId::ID, public.as_ref(), &encoded[..]) .ok() .flatten()? .try_into() diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs index 80e65b342c..2e60ac2370 100644 --- a/substrate/primitives/core/src/crypto.rs +++ b/substrate/primitives/core/src/crypto.rs @@ -19,8 +19,6 @@ //! Cryptographic utilities. // end::description[] -#[cfg(feature = "std")] -use crate::hexdisplay::HexDisplay; use crate::{ed25519, sr25519}; #[cfg(feature = "std")] use base58::{FromBase58, ToBase58}; @@ -487,10 +485,7 @@ pub trait ByteArray: AsRef<[u8]> + AsMut<[u8]> + for<'a> TryFrom<&'a [u8], Error } /// Trait suitable for typical cryptographic PKI key public type. -pub trait Public: ByteArray + Derive + CryptoType + PartialEq + Eq + Clone + Send + Sync { - /// Return `CryptoTypePublicPair` from public key. - fn to_public_crypto_pair(&self) -> CryptoTypePublicPair; -} +pub trait Public: ByteArray + Derive + CryptoType + PartialEq + Eq + Clone + Send + Sync {} /// An opaque 32-byte cryptographic identifier. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, TypeInfo)] @@ -689,11 +684,7 @@ mod dummy { b"" } } - impl Public for Dummy { - fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { - CryptoTypePublicPair(CryptoTypeId(*b"dumm"), ::to_raw_vec(self)) - } - } + impl Public for Dummy {} impl Pair for Dummy { type Public = Dummy; @@ -1118,24 +1109,6 @@ impl<'a> TryFrom<&'a str> for KeyTypeId { #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct CryptoTypeId(pub [u8; 4]); -/// A type alias of CryptoTypeId & a public key -#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] -pub struct CryptoTypePublicPair(pub CryptoTypeId, pub Vec); - -#[cfg(feature = "std")] -impl sp_std::fmt::Display for CryptoTypePublicPair { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - let id = match str::from_utf8(&(self.0).0[..]) { - Ok(id) => id.to_string(), - Err(_) => { - format!("{:#?}", self.0) - }, - }; - write!(f, "{}-{}", id, HexDisplay::from(&self.1)) - } -} - /// Known key types; this also functions as a global registry of key types for projects wishing to /// avoid collisions with each other. /// @@ -1223,11 +1196,7 @@ mod tests { vec![] } } - impl Public for TestPublic { - fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { - CryptoTypePublicPair(CryptoTypeId(*b"dumm"), self.to_raw_vec()) - } - } + impl Public for TestPublic {} impl Pair for TestPair { type Public = TestPublic; type Seed = [u8; 8]; diff --git a/substrate/primitives/core/src/ecdsa.rs b/substrate/primitives/core/src/ecdsa.rs index e63b283d26..8dc4a55130 100644 --- a/substrate/primitives/core/src/ecdsa.rs +++ b/substrate/primitives/core/src/ecdsa.rs @@ -24,8 +24,7 @@ use sp_runtime_interface::pass_by::PassByInner; #[cfg(feature = "std")] use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, CryptoTypeId, CryptoTypePublicPair, Derive, Public as TraitPublic, - UncheckedFrom, + ByteArray, CryptoType, CryptoTypeId, Derive, Public as TraitPublic, UncheckedFrom, }; #[cfg(feature = "full_crypto")] use crate::{ @@ -103,23 +102,7 @@ impl ByteArray for Public { const LEN: usize = 33; } -impl TraitPublic for Public { - fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { - CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) - } -} - -impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } -} - -impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } -} +impl TraitPublic for Public {} impl Derive for Public {} diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs index 503c127a9e..884d29dc12 100644 --- a/substrate/primitives/core/src/ed25519.rs +++ b/substrate/primitives/core/src/ed25519.rs @@ -31,9 +31,7 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use crate::crypto::Ss58Codec; -use crate::crypto::{ - CryptoType, CryptoTypeId, CryptoTypePublicPair, Derive, Public as TraitPublic, UncheckedFrom, -}; +use crate::crypto::{CryptoType, CryptoTypeId, Derive, Public as TraitPublic, UncheckedFrom}; #[cfg(feature = "full_crypto")] use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; #[cfg(feature = "full_crypto")] @@ -355,26 +353,10 @@ impl ByteArray for Public { const LEN: usize = 32; } -impl TraitPublic for Public { - fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { - CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) - } -} +impl TraitPublic for Public {} impl Derive for Public {} -impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } -} - -impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } -} - /// Derive a single hard junction. #[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { diff --git a/substrate/primitives/core/src/sr25519.rs b/substrate/primitives/core/src/sr25519.rs index 8dbcca9e26..d7c1c79c3f 100644 --- a/substrate/primitives/core/src/sr25519.rs +++ b/substrate/primitives/core/src/sr25519.rs @@ -34,10 +34,7 @@ use schnorrkel::{ use sp_std::vec::Vec; use crate::{ - crypto::{ - ByteArray, CryptoType, CryptoTypeId, CryptoTypePublicPair, Derive, Public as TraitPublic, - UncheckedFrom, - }, + crypto::{ByteArray, CryptoType, CryptoTypeId, Derive, Public as TraitPublic, UncheckedFrom}, hash::{H256, H512}, }; use codec::{Decode, Encode, MaxEncodedLen}; @@ -386,23 +383,7 @@ impl ByteArray for Public { const LEN: usize = 32; } -impl TraitPublic for Public { - fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { - CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) - } -} - -impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } -} - -impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } -} +impl TraitPublic for Public {} #[cfg(feature = "std")] impl From for Pair { diff --git a/substrate/primitives/io/src/lib.rs b/substrate/primitives/io/src/lib.rs index 709e1fa642..306ac8e60c 100644 --- a/substrate/primitives/io/src/lib.rs +++ b/substrate/primitives/io/src/lib.rs @@ -762,10 +762,9 @@ pub trait Crypto { ) -> Option { self.extension::() .expect("No `keystore` associated for the current context!") - .sign_with(id, &pub_key.into(), msg) + .ed25519_sign(id, pub_key, msg) .ok() .flatten() - .and_then(|sig| ed25519::Signature::from_slice(&sig)) } /// Verify `ed25519` signature. @@ -902,10 +901,9 @@ pub trait Crypto { ) -> Option { self.extension::() .expect("No `keystore` associated for the current context!") - .sign_with(id, &pub_key.into(), msg) + .sr25519_sign(id, pub_key, msg) .ok() .flatten() - .and_then(|sig| sr25519::Signature::from_slice(&sig)) } /// Verify an `sr25519` signature. @@ -949,10 +947,9 @@ pub trait Crypto { ) -> Option { self.extension::() .expect("No `keystore` associated for the current context!") - .sign_with(id, &pub_key.into(), msg) + .ecdsa_sign(id, pub_key, msg) .ok() .flatten() - .and_then(|sig| ecdsa::Signature::from_slice(&sig)) } /// Sign the given a pre-hashed `msg` with the `ecdsa` key that corresponds to the given public diff --git a/substrate/primitives/keystore/src/lib.rs b/substrate/primitives/keystore/src/lib.rs index d1cbe227ed..577969cdfe 100644 --- a/substrate/primitives/keystore/src/lib.rs +++ b/substrate/primitives/keystore/src/lib.rs @@ -21,7 +21,7 @@ pub mod vrf; use crate::vrf::{VRFSignature, VRFTranscriptData}; use sp_core::{ - crypto::{CryptoTypePublicPair, KeyTypeId}, + crypto::{ByteArray, CryptoTypeId, KeyTypeId}, ecdsa, ed25519, sr25519, }; use std::sync::Arc; @@ -45,84 +45,44 @@ pub enum Error { /// Something that generates, stores and provides access to secret keys. pub trait Keystore: Send + Sync { - /// Returns all sr25519 public keys for the given key type. - fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec; + /// Returns all the sr25519 public keys for the given key type. + fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec; /// Generate a new sr25519 key pair for the given key type and an optional seed. /// - /// If the given seed is `Some(_)`, the key pair will only be stored in memory. - /// - /// Returns the public key of the generated key pair. + /// Returns an `sr25519::Public` key of the generated key pair or an `Err` if + /// something failed during key generation. fn sr25519_generate_new( &self, - id: KeyTypeId, + key_type: KeyTypeId, seed: Option<&str>, ) -> Result; - /// Returns all ed25519 public keys for the given key type. - fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec; - - /// Generate a new ed25519 key pair for the given key type and an optional seed. + /// Generate an sr25519 signature for a given message. /// - /// If the given seed is `Some(_)`, the key pair will only be stored in memory. + /// Receives [`KeyTypeId`] and an [`sr25519::Public`] key to be able to map + /// them to a private key that exists in the keystore. /// - /// Returns the public key of the generated key pair. - fn ed25519_generate_new( + /// Returns an [`sr25519::Signature`] or `None` in case the given `key_type` + /// and `public` combination doesn't exist in the keystore. + /// An `Err` will be returned if generating the signature itself failed. + fn sr25519_sign( &self, - id: KeyTypeId, - seed: Option<&str>, - ) -> Result; - - /// Returns all ecdsa public keys for the given key type. - fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec; - - /// Generate a new ecdsa key pair for the given key type and an optional seed. - /// - /// If the given seed is `Some(_)`, the key pair will only be stored in memory. - /// - /// Returns the public key of the generated key pair. - fn ecdsa_generate_new(&self, id: KeyTypeId, seed: Option<&str>) - -> Result; - - /// Insert a new secret key. - fn insert(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()>; - - /// List all supported keys - /// - /// Returns a set of public keys the signer supports. - fn keys(&self, id: KeyTypeId) -> Result, Error>; - - /// Checks if the private keys for the given public key and key type combinations exist. - /// - /// Returns `true` iff all private keys could be found. - fn has_keys(&self, public_keys: &[(Vec, KeyTypeId)]) -> bool; - - /// Sign with key - /// - /// Signs a message with the private key that matches - /// the public key passed. - /// - /// Returns the SCALE encoded signature if key is found and supported, `None` if the key doesn't - /// exist or an error when something failed. - fn sign_with( - &self, - id: KeyTypeId, - key: &CryptoTypePublicPair, + key_type: KeyTypeId, + public: &sr25519::Public, msg: &[u8], - ) -> Result>, Error>; + ) -> Result, Error>; - /// Generate VRF signature for given transcript data. + /// Generate an sr25519 VRF signature for a given transcript data. /// - /// Receives KeyTypeId and Public key to be able to map - /// them to a private key that exists in the keystore which - /// is, in turn, used for signing the provided transcript. + /// Receives [`KeyTypeId`] and an [`sr25519::Public`] key to be able to map + /// them to a private key that exists in the keystore. /// /// Returns a result containing the signature data. - /// Namely, VRFOutput and VRFProof which are returned - /// inside the `VRFSignature` container struct. - /// - /// This function will return `None` if the given `key_type` and `public` combination - /// doesn't exist in the keystore or an `Err` when something failed. + /// Namely, VRFOutput and VRFProof which are returned inside the `VRFSignature` + /// container struct. + /// Returns `None` if the given `key_type` and `public` combination doesn't + /// exist in the keystore or an `Err` when something failed. fn sr25519_vrf_sign( &self, key_type: KeyTypeId, @@ -130,24 +90,129 @@ pub trait Keystore: Send + Sync { transcript_data: VRFTranscriptData, ) -> Result, Error>; - /// Generate an ECDSA signature for a given pre-hashed message. + /// Returns all ed25519 public keys for the given key type. + fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec; + + /// Generate a new ed25519 key pair for the given key type and an optional seed. + /// + /// Returns an `ed25519::Public` key of the generated key pair or an `Err` if + /// something failed during key generation. + fn ed25519_generate_new( + &self, + key_type: KeyTypeId, + seed: Option<&str>, + ) -> Result; + + /// Generate an ed25519 signature for a given message. + /// + /// Receives [`KeyTypeId`] and an [`ed25519::Public`] key to be able to map + /// them to a private key that exists in the keystore. + /// + /// Returns an [`ed25519::Signature`] or `None` in case the given `key_type` + /// and `public` combination doesn't exist in the keystore. + /// An `Err` will be returned if generating the signature itself failed. + fn ed25519_sign( + &self, + key_type: KeyTypeId, + public: &ed25519::Public, + msg: &[u8], + ) -> Result, Error>; + + /// Returns all ecdsa public keys for the given key type. + fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec; + + /// Generate a new ecdsa key pair for the given key type and an optional seed. + /// + /// Returns an `ecdsa::Public` key of the generated key pair or an `Err` if + /// something failed during key generation. + fn ecdsa_generate_new( + &self, + key_type: KeyTypeId, + seed: Option<&str>, + ) -> Result; + + /// Generate an ecdsa signature for a given message. /// /// Receives [`KeyTypeId`] and an [`ecdsa::Public`] key to be able to map - /// them to a private key that exists in the keystore. This private key is, - /// in turn, used for signing the provided pre-hashed message. + /// them to a private key that exists in the keystore. /// - /// The `msg` argument provided should be a hashed message for which an - /// ECDSA signature should be generated. + /// Returns an [`ecdsa::Signature`] or `None` in case the given `key_type` + /// and `public` combination doesn't exist in the keystore. + /// An `Err` will be returned if generating the signature itself failed. + fn ecdsa_sign( + &self, + key_type: KeyTypeId, + public: &ecdsa::Public, + msg: &[u8], + ) -> Result, Error>; + + /// Generate an ecdsa signature for a given pre-hashed message. /// - /// Returns an [`ecdsa::Signature`] or `None` in case the given `id` and - /// `public` combination doesn't exist in the keystore. An `Err` will be - /// returned if generating the signature itself failed. + /// Receives [`KeyTypeId`] and an [`ecdsa::Public`] key to be able to map + /// them to a private key that exists in the keystore. + /// + /// Returns an [`ecdsa::Signature`] or `None` in case the given `key_type` + /// and `public` combination doesn't exist in the keystore. + /// An `Err` will be returned if generating the signature itself failed. fn ecdsa_sign_prehashed( &self, - id: KeyTypeId, + key_type: KeyTypeId, public: &ecdsa::Public, msg: &[u8; 32], ) -> Result, Error>; + + /// Insert a new secret key. + fn insert(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()>; + + /// List all supported keys of a given type. + /// + /// Returns a set of public keys the signer supports in raw format. + fn keys(&self, key_type: KeyTypeId) -> Result>, Error>; + + /// Checks if the private keys for the given public key and key type combinations exist. + /// + /// Returns `true` iff all private keys could be found. + fn has_keys(&self, public_keys: &[(Vec, KeyTypeId)]) -> bool; + + /// Convenience method to sign a message using the given key type and a raw public key + /// for secret lookup. + /// + /// The message is signed using the cryptographic primitive specified by `crypto_id`. + /// + /// Schemes supported by the default trait implementation: sr25519, ed25519 and ecdsa. + /// To support more schemes you can overwrite this method. + /// + /// Returns the SCALE encoded signature if key is found and supported, `None` if the key doesn't + /// exist or an error when something failed. + fn sign_with( + &self, + id: KeyTypeId, + crypto_id: CryptoTypeId, + public: &[u8], + msg: &[u8], + ) -> Result>, Error> { + use codec::Encode; + + let signature = match crypto_id { + sr25519::CRYPTO_ID => { + let public = sr25519::Public::from_slice(public) + .map_err(|_| Error::ValidationError("Invalid public key format".into()))?; + self.sr25519_sign(id, &public, msg)?.map(|s| s.encode()) + }, + ed25519::CRYPTO_ID => { + let public = ed25519::Public::from_slice(public) + .map_err(|_| Error::ValidationError("Invalid public key format".into()))?; + self.ed25519_sign(id, &public, msg)?.map(|s| s.encode()) + }, + ecdsa::CRYPTO_ID => { + let public = ecdsa::Public::from_slice(public) + .map_err(|_| Error::ValidationError("Invalid public key format".into()))?; + self.ecdsa_sign(id, &public, msg)?.map(|s| s.encode()) + }, + _ => return Err(Error::KeyNotSupported(id)), + }; + Ok(signature) + } } /// A shared pointer to a keystore implementation. diff --git a/substrate/primitives/keystore/src/testing.rs b/substrate/primitives/keystore/src/testing.rs index 73b560d563..de034c6588 100644 --- a/substrate/primitives/keystore/src/testing.rs +++ b/substrate/primitives/keystore/src/testing.rs @@ -18,7 +18,7 @@ //! Types that should only be used for testing! use sp_core::{ - crypto::{ByteArray, CryptoTypePublicPair, KeyTypeId, Pair}, + crypto::{ByteArray, KeyTypeId, Pair}, ecdsa, ed25519, sr25519, }; @@ -42,51 +42,44 @@ impl MemoryKeystore { Self::default() } - fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option { - self.keys.read().get(&id).and_then(|inner| { - inner.get(pub_key.as_slice()).map(|s| { + fn sr25519_key_pair( + &self, + key_type: KeyTypeId, + public: &sr25519::Public, + ) -> Option { + self.keys.read().get(&key_type).and_then(|inner| { + inner.get(public.as_slice()).map(|s| { sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid") }) }) } - fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option { - self.keys.read().get(&id).and_then(|inner| { - inner.get(pub_key.as_slice()).map(|s| { + fn ed25519_key_pair( + &self, + key_type: KeyTypeId, + public: &ed25519::Public, + ) -> Option { + self.keys.read().get(&key_type).and_then(|inner| { + inner.get(public.as_slice()).map(|s| { ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid") }) }) } - fn ecdsa_key_pair(&self, id: KeyTypeId, pub_key: &ecdsa::Public) -> Option { - self.keys.read().get(&id).and_then(|inner| { + fn ecdsa_key_pair(&self, key_type: KeyTypeId, public: &ecdsa::Public) -> Option { + self.keys.read().get(&key_type).and_then(|inner| { inner - .get(pub_key.as_slice()) + .get(public.as_slice()) .map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid")) }) } } impl Keystore for MemoryKeystore { - fn keys(&self, id: KeyTypeId) -> Result, Error> { + fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { self.keys .read() - .get(&id) - .map(|map| { - Ok(map.keys().fold(Vec::new(), |mut v, k| { - v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone())); - v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone())); - v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k.clone())); - v - })) - }) - .unwrap_or_else(|| Ok(vec![])) - } - - fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec { - self.keys - .read() - .get(&id) + .get(&key_type) .map(|keys| { keys.values() .map(|s| { @@ -100,7 +93,7 @@ impl Keystore for MemoryKeystore { fn sr25519_generate_new( &self, - id: KeyTypeId, + key_type: KeyTypeId, seed: Option<&str>, ) -> Result { match seed { @@ -110,7 +103,7 @@ impl Keystore for MemoryKeystore { })?; self.keys .write() - .entry(id) + .entry(key_type) .or_default() .insert(pair.public().to_raw_vec(), seed.into()); Ok(pair.public()) @@ -119,7 +112,7 @@ impl Keystore for MemoryKeystore { let (pair, phrase, _) = sr25519::Pair::generate_with_phrase(None); self.keys .write() - .entry(id) + .entry(key_type) .or_default() .insert(pair.public().to_raw_vec(), phrase); Ok(pair.public()) @@ -127,137 +120,13 @@ impl Keystore for MemoryKeystore { } } - fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec { - self.keys - .read() - .get(&id) - .map(|keys| { - keys.values() - .map(|s| { - ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid") - }) - .map(|p| p.public()) - .collect() - }) - .unwrap_or_default() - } - - fn ed25519_generate_new( + fn sr25519_sign( &self, - id: KeyTypeId, - seed: Option<&str>, - ) -> Result { - match seed { - Some(seed) => { - let pair = ed25519::Pair::from_string(seed, None).map_err(|_| { - Error::ValidationError("Generates an `ed25519` pair.".to_owned()) - })?; - self.keys - .write() - .entry(id) - .or_default() - .insert(pair.public().to_raw_vec(), seed.into()); - Ok(pair.public()) - }, - None => { - let (pair, phrase, _) = ed25519::Pair::generate_with_phrase(None); - self.keys - .write() - .entry(id) - .or_default() - .insert(pair.public().to_raw_vec(), phrase); - Ok(pair.public()) - }, - } - } - - fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec { - self.keys - .read() - .get(&id) - .map(|keys| { - keys.values() - .map(|s| { - ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid") - }) - .map(|p| p.public()) - .collect() - }) - .unwrap_or_default() - } - - fn ecdsa_generate_new( - &self, - id: KeyTypeId, - seed: Option<&str>, - ) -> Result { - match seed { - Some(seed) => { - let pair = ecdsa::Pair::from_string(seed, None) - .map_err(|_| Error::ValidationError("Generates an `ecdsa` pair.".to_owned()))?; - self.keys - .write() - .entry(id) - .or_default() - .insert(pair.public().to_raw_vec(), seed.into()); - Ok(pair.public()) - }, - None => { - let (pair, phrase, _) = ecdsa::Pair::generate_with_phrase(None); - self.keys - .write() - .entry(id) - .or_default() - .insert(pair.public().to_raw_vec(), phrase); - Ok(pair.public()) - }, - } - } - - fn insert(&self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> { - self.keys - .write() - .entry(id) - .or_default() - .insert(public.to_owned(), suri.to_string()); - Ok(()) - } - - fn has_keys(&self, public_keys: &[(Vec, KeyTypeId)]) -> bool { - public_keys - .iter() - .all(|(k, t)| self.keys.read().get(t).and_then(|s| s.get(k)).is_some()) - } - - fn sign_with( - &self, - id: KeyTypeId, - key: &CryptoTypePublicPair, + key_type: KeyTypeId, + public: &sr25519::Public, msg: &[u8], - ) -> Result>, Error> { - use codec::Encode; - - match key.0 { - ed25519::CRYPTO_ID => { - let key_pair = self - .ed25519_key_pair(id, &ed25519::Public::from_slice(key.1.as_slice()).unwrap()); - - key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() - }, - sr25519::CRYPTO_ID => { - let key_pair = self - .sr25519_key_pair(id, &sr25519::Public::from_slice(key.1.as_slice()).unwrap()); - - key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() - }, - ecdsa::CRYPTO_ID => { - let key_pair = - self.ecdsa_key_pair(id, &ecdsa::Public::from_slice(key.1.as_slice()).unwrap()); - - key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() - }, - _ => Err(Error::KeyNotSupported(id)), - } + ) -> Result, Error> { + Ok(self.sr25519_key_pair(key_type, public).map(|pair| pair.sign(msg))) } fn sr25519_vrf_sign( @@ -274,14 +143,144 @@ impl Keystore for MemoryKeystore { Ok(Some(VRFSignature { output: inout.to_output(), proof })) } + fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.keys + .read() + .get(&key_type) + .map(|keys| { + keys.values() + .map(|s| { + ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid") + }) + .map(|p| p.public()) + .collect() + }) + .unwrap_or_default() + } + + fn ed25519_generate_new( + &self, + key_type: KeyTypeId, + seed: Option<&str>, + ) -> Result { + match seed { + Some(seed) => { + let pair = ed25519::Pair::from_string(seed, None).map_err(|_| { + Error::ValidationError("Generates an `ed25519` pair.".to_owned()) + })?; + self.keys + .write() + .entry(key_type) + .or_default() + .insert(pair.public().to_raw_vec(), seed.into()); + Ok(pair.public()) + }, + None => { + let (pair, phrase, _) = ed25519::Pair::generate_with_phrase(None); + self.keys + .write() + .entry(key_type) + .or_default() + .insert(pair.public().to_raw_vec(), phrase); + Ok(pair.public()) + }, + } + } + + fn ed25519_sign( + &self, + key_type: KeyTypeId, + public: &ed25519::Public, + msg: &[u8], + ) -> Result, Error> { + Ok(self.ed25519_key_pair(key_type, public).map(|pair| pair.sign(msg))) + } + + fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.keys + .read() + .get(&key_type) + .map(|keys| { + keys.values() + .map(|s| { + ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid") + }) + .map(|p| p.public()) + .collect() + }) + .unwrap_or_default() + } + + fn ecdsa_generate_new( + &self, + key_type: KeyTypeId, + seed: Option<&str>, + ) -> Result { + match seed { + Some(seed) => { + let pair = ecdsa::Pair::from_string(seed, None) + .map_err(|_| Error::ValidationError("Generates an `ecdsa` pair.".to_owned()))?; + self.keys + .write() + .entry(key_type) + .or_default() + .insert(pair.public().to_raw_vec(), seed.into()); + Ok(pair.public()) + }, + None => { + let (pair, phrase, _) = ecdsa::Pair::generate_with_phrase(None); + self.keys + .write() + .entry(key_type) + .or_default() + .insert(pair.public().to_raw_vec(), phrase); + Ok(pair.public()) + }, + } + } + + fn ecdsa_sign( + &self, + key_type: KeyTypeId, + public: &ecdsa::Public, + msg: &[u8], + ) -> Result, Error> { + Ok(self.ecdsa_key_pair(key_type, public).map(|pair| pair.sign(msg))) + } + fn ecdsa_sign_prehashed( &self, - id: KeyTypeId, + key_type: KeyTypeId, public: &ecdsa::Public, msg: &[u8; 32], ) -> Result, Error> { - let pair = self.ecdsa_key_pair(id, public); - pair.map(|k| k.sign_prehashed(msg)).map(Ok).transpose() + let pair = self.ecdsa_key_pair(key_type, public); + pair.map(|pair| pair.sign_prehashed(msg)).map(Ok).transpose() + } + + fn insert(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> { + self.keys + .write() + .entry(key_type) + .or_default() + .insert(public.to_owned(), suri.to_string()); + Ok(()) + } + + fn keys(&self, key_type: KeyTypeId) -> Result>, Error> { + let keys = self + .keys + .read() + .get(&key_type) + .map(|map| map.keys().cloned().collect()) + .unwrap_or_default(); + Ok(keys) + } + + fn has_keys(&self, public_keys: &[(Vec, KeyTypeId)]) -> bool { + public_keys + .iter() + .all(|(k, t)| self.keys.read().get(t).and_then(|s| s.get(k)).is_some()) } } @@ -306,7 +305,7 @@ mod tests { let public = store.ed25519_generate_new(ED25519, None).expect("Generates key"); - let public_keys = store.keys(ED25519).unwrap(); + let public_keys = store.ed25519_public_keys(ED25519); assert!(public_keys.contains(&public.into())); } @@ -322,7 +321,7 @@ mod tests { .insert(SR25519, secret_uri, key_pair.public().as_ref()) .expect("Inserts unknown key"); - let public_keys = store.keys(SR25519).unwrap(); + let public_keys = store.sr25519_public_keys(SR25519); assert!(public_keys.contains(&key_pair.public().into())); } diff --git a/substrate/primitives/runtime/src/traits.rs b/substrate/primitives/runtime/src/traits.rs index 4bba6f6bc1..95f977077e 100644 --- a/substrate/primitives/runtime/src/traits.rs +++ b/substrate/primitives/runtime/src/traits.rs @@ -30,7 +30,7 @@ use crate::{ use impl_trait_for_tuples::impl_for_tuples; #[cfg(feature = "std")] use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use sp_application_crypto::AppKey; +use sp_application_crypto::AppCrypto; pub use sp_arithmetic::traits::{ checked_pow, ensure_pow, AtLeast32Bit, AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedShl, CheckedShr, CheckedSub, Ensure, EnsureAdd, EnsureAddAssign, EnsureDiv, @@ -148,10 +148,10 @@ pub trait AppVerify { } impl< - S: Verify::Public as sp_application_crypto::AppPublic>::Generic> + S: Verify::Public as sp_application_crypto::AppPublic>::Generic> + From, T: sp_application_crypto::Wraps - + sp_application_crypto::AppKey + + sp_application_crypto::AppCrypto + sp_application_crypto::AppSignature + AsRef + AsMut @@ -159,16 +159,18 @@ impl< > AppVerify for T where ::Signer: IdentifyAccount::Signer>, - <::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount< - AccountId = <::Public as sp_application_crypto::AppPublic>::Generic, + <::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount< + AccountId = <::Public as sp_application_crypto::AppPublic>::Generic, >, { - type AccountId = ::Public; - fn verify>(&self, msg: L, signer: &::Public) -> bool { + type AccountId = ::Public; + fn verify>(&self, msg: L, signer: &::Public) -> bool { use sp_application_crypto::IsWrappedBy; let inner: &S = self.as_ref(); let inner_pubkey = - <::Public as sp_application_crypto::AppPublic>::Generic::from_ref(signer); + <::Public as sp_application_crypto::AppPublic>::Generic::from_ref( + signer, + ); Verify::verify(inner, msg, inner_pubkey) } }