mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 17:31:05 +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:
@@ -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()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user