mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-21 00:25:41 +00:00
Keystore overhaul (final) (#13683)
* Introduce keystore specialized sign methods * Get rid of 'AppKey::UntypedGeneric' associated type. Untyped generics are accessible using associated types 'Generic' associated type. I.e. <T as AppKey>::Public::Generic * Get rid of 'CryptoTypePublicPair' * Trivial fix * Small refactory of local keystore implementations * Remove 'crypto_id' method from 'Public' * Trivial rename of 'AppKey' to 'AppCrypto' * Remove unused import * Improve docs * Better signature related errors for authority-discovery * Apply review suggestion * Apply review suggestions Co-authored-by: Koute <koute@users.noreply.github.com> * Authority discoverty signing error revisited * Signing error revisited for babe and aura as well * Further cleanup --------- Co-authored-by: Koute <koute@users.noreply.github.com>
This commit is contained in:
@@ -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<Public> 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;
|
||||
|
||||
@@ -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<Self>;
|
||||
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<T: sp_std::hash::Hash> 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<Self>
|
||||
@@ -79,14 +77,15 @@ pub trait AppPublic:
|
||||
|
||||
/// A application's key pair.
|
||||
#[cfg(feature = "full_crypto")]
|
||||
pub trait AppPair: AppKey + Pair<Public = <Self as AppKey>::Public> {
|
||||
pub trait AppPair: AppCrypto + Pair<Public = <Self as AppCrypto>::Public> {
|
||||
/// The wrapped type which is just a plain instance of `Pair`.
|
||||
type Generic: IsWrappedBy<Self>
|
||||
+ Pair<Public = <<Self as AppKey>::Public as AppPublic>::Generic>;
|
||||
+ Pair<Public = <<Self as AppCrypto>::Public as AppPublic>::Generic>
|
||||
+ Pair<Signature = <<Self as AppCrypto>::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<Self> + Eq + PartialEq + Debug + MaybeHash;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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<u8>, String),
|
||||
#[error("Failed to sign: {0}")]
|
||||
CannotSign(String),
|
||||
/// Some other error.
|
||||
#[error(transparent)]
|
||||
Other(#[from] Box<dyn std::error::Error + Sync + Send + 'static>),
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"), <Self as ByteArray>::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<u8>);
|
||||
|
||||
#[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];
|
||||
|
||||
@@ -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<Public> 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 {}
|
||||
|
||||
|
||||
@@ -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<Public> 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 {
|
||||
|
||||
@@ -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<Public> 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<MiniSecretKey> for Pair {
|
||||
|
||||
@@ -762,10 +762,9 @@ pub trait Crypto {
|
||||
) -> Option<ed25519::Signature> {
|
||||
self.extension::<KeystoreExt>()
|
||||
.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<sr25519::Signature> {
|
||||
self.extension::<KeystoreExt>()
|
||||
.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<ecdsa::Signature> {
|
||||
self.extension::<KeystoreExt>()
|
||||
.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
|
||||
|
||||
@@ -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<sr25519::Public>;
|
||||
/// Returns all the sr25519 public keys for the given key type.
|
||||
fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec<sr25519::Public>;
|
||||
|
||||
/// 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<sr25519::Public, Error>;
|
||||
|
||||
/// Returns all ed25519 public keys for the given key type.
|
||||
fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public>;
|
||||
|
||||
/// 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<ed25519::Public, Error>;
|
||||
|
||||
/// Returns all ecdsa public keys for the given key type.
|
||||
fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;
|
||||
|
||||
/// 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<ecdsa::Public, Error>;
|
||||
|
||||
/// 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<Vec<CryptoTypePublicPair>, 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<u8>, 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<Option<Vec<u8>>, Error>;
|
||||
) -> Result<Option<sr25519::Signature>, 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<Option<VRFSignature>, 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<ed25519::Public>;
|
||||
|
||||
/// 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<ed25519::Public, Error>;
|
||||
|
||||
/// 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<Option<ed25519::Signature>, Error>;
|
||||
|
||||
/// Returns all ecdsa public keys for the given key type.
|
||||
fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec<ecdsa::Public>;
|
||||
|
||||
/// 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<ecdsa::Public, Error>;
|
||||
|
||||
/// 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<Option<ecdsa::Signature>, 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<Option<ecdsa::Signature>, 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<Vec<Vec<u8>>, 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<u8>, 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<Option<Vec<u8>>, 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.
|
||||
|
||||
@@ -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<sr25519::Pair> {
|
||||
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<sr25519::Pair> {
|
||||
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<ed25519::Pair> {
|
||||
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<ed25519::Pair> {
|
||||
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<ecdsa::Pair> {
|
||||
self.keys.read().get(&id).and_then(|inner| {
|
||||
fn ecdsa_key_pair(&self, key_type: KeyTypeId, public: &ecdsa::Public) -> Option<ecdsa::Pair> {
|
||||
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<Vec<CryptoTypePublicPair>, Error> {
|
||||
fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec<sr25519::Public> {
|
||||
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<sr25519::Public> {
|
||||
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<sr25519::Public, Error> {
|
||||
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<ed25519::Public> {
|
||||
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<ed25519::Public, Error> {
|
||||
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<ecdsa::Public> {
|
||||
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<ecdsa::Public, Error> {
|
||||
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<u8>, 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<Option<Vec<u8>>, 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<Option<sr25519::Signature>, 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<ed25519::Public> {
|
||||
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<ed25519::Public, Error> {
|
||||
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<Option<ed25519::Signature>, Error> {
|
||||
Ok(self.ed25519_key_pair(key_type, public).map(|pair| pair.sign(msg)))
|
||||
}
|
||||
|
||||
fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec<ecdsa::Public> {
|
||||
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<ecdsa::Public, Error> {
|
||||
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<Option<ecdsa::Signature>, 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<Option<ecdsa::Signature>, 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<Vec<Vec<u8>>, 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<u8>, 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()));
|
||||
}
|
||||
|
||||
@@ -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<Signer = <<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic>
|
||||
S: Verify<Signer = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic>
|
||||
+ From<T>,
|
||||
T: sp_application_crypto::Wraps<Inner = S>
|
||||
+ sp_application_crypto::AppKey
|
||||
+ sp_application_crypto::AppCrypto
|
||||
+ sp_application_crypto::AppSignature
|
||||
+ AsRef<S>
|
||||
+ AsMut<S>
|
||||
@@ -159,16 +159,18 @@ impl<
|
||||
> AppVerify for T
|
||||
where
|
||||
<S as Verify>::Signer: IdentifyAccount<AccountId = <S as Verify>::Signer>,
|
||||
<<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount<
|
||||
AccountId = <<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic,
|
||||
<<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount<
|
||||
AccountId = <<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic,
|
||||
>,
|
||||
{
|
||||
type AccountId = <T as AppKey>::Public;
|
||||
fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &<T as AppKey>::Public) -> bool {
|
||||
type AccountId = <T as AppCrypto>::Public;
|
||||
fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &<T as AppCrypto>::Public) -> bool {
|
||||
use sp_application_crypto::IsWrappedBy;
|
||||
let inner: &S = self.as_ref();
|
||||
let inner_pubkey =
|
||||
<<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic::from_ref(signer);
|
||||
<<T as AppCrypto>::Public as sp_application_crypto::AppPublic>::Generic::from_ref(
|
||||
signer,
|
||||
);
|
||||
Verify::verify(inner, msg, inner_pubkey)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user