From 9c92e4987160a17daa72f79186d981b6fbe5879e Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Thu, 30 Mar 2023 01:22:34 +0200 Subject: [PATCH] Generic keystore internals (#13749) * Generic testing keystore internals * Generic local keystore internals * Restore deleted comment --- client/keystore/src/local.rs | 121 +++++++++------------ primitives/keystore/src/testing.rs | 164 +++++++++-------------------- 2 files changed, 95 insertions(+), 190 deletions(-) diff --git a/client/keystore/src/local.rs b/client/keystore/src/local.rs index abdf97bb22aad..2486b2fd045d5 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -63,21 +63,50 @@ impl LocalKeystore { ) -> Result> { self.0.read().key_pair::(public) } -} -impl Keystore for LocalKeystore { - fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { + fn public_keys(&self, key_type: KeyTypeId) -> Vec { self.0 .read() .raw_public_keys(key_type) .map(|v| { - v.into_iter() - .filter_map(|k| sr25519::Public::from_slice(k.as_slice()).ok()) - .collect() + v.into_iter().filter_map(|k| T::Public::from_slice(k.as_slice()).ok()).collect() }) .unwrap_or_default() } + fn generate_new( + &self, + 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, key_type), + None => self.0.write().generate_by_type::(key_type), + } + .map_err(|e| -> TraitError { e.into() })?; + Ok(pair.public()) + } + + fn sign( + &self, + key_type: KeyTypeId, + public: &T::Public, + msg: &[u8], + ) -> std::result::Result, TraitError> { + let signature = self + .0 + .read() + .key_pair_by_type::(public, key_type)? + .map(|pair| pair.sign(msg)); + Ok(signature) + } +} + +impl Keystore for LocalKeystore { + fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.public_keys::(key_type) + } + /// Generate a new pair compatible with the 'ed25519' signature scheme. /// /// If the `[seed]` is `Some` then the key will be ephemeral and stored in memory. @@ -86,16 +115,7 @@ impl Keystore for LocalKeystore { 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, key_type), - None => self.0.write().generate_by_type::(key_type), - } - .map_err(|e| -> TraitError { e.into() })?; - - Ok(pair.public()) + self.generate_new::(key_type, seed) } fn sr25519_sign( @@ -104,12 +124,7 @@ impl Keystore for LocalKeystore { 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) + self.sign::(key_type, public, msg) } fn sr25519_vrf_sign( @@ -118,24 +133,16 @@ impl Keystore for LocalKeystore { 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 sig = 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) + Ok(sig) } fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec { - self.0 - .read() - .raw_public_keys(key_type) - .map(|v| { - v.into_iter() - .filter_map(|k| ed25519::Public::from_slice(k.as_slice()).ok()) - .collect() - }) - .unwrap_or_default() + self.public_keys::(key_type) } /// Generate a new pair compatible with the 'sr25519' signature scheme. @@ -146,16 +153,7 @@ impl Keystore for LocalKeystore { 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, key_type), - None => self.0.write().generate_by_type::(key_type), - } - .map_err(|e| -> TraitError { e.into() })?; - - Ok(pair.public()) + self.generate_new::(key_type, seed) } fn ed25519_sign( @@ -164,24 +162,11 @@ impl Keystore for LocalKeystore { 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) + self.sign::(key_type, public, msg) } fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec { - self.0 - .read() - .raw_public_keys(key_type) - .map(|v| { - v.into_iter() - .filter_map(|k| ecdsa::Public::from_slice(k.as_slice()).ok()) - .collect() - }) - .unwrap_or_default() + self.public_keys::(key_type) } /// Generate a new pair compatible with the 'ecdsa' signature scheme. @@ -192,14 +177,7 @@ impl Keystore for LocalKeystore { 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, key_type), - None => self.0.write().generate_by_type::(key_type), - } - .map_err(|e| -> TraitError { e.into() })?; - - Ok(pair.public()) + self.generate_new::(key_type, seed) } fn ecdsa_sign( @@ -208,12 +186,7 @@ impl Keystore for LocalKeystore { 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) + self.sign::(key_type, public, msg) } fn ecdsa_sign_prehashed( @@ -222,12 +195,12 @@ impl Keystore for LocalKeystore { public: &ecdsa::Public, msg: &[u8; 32], ) -> std::result::Result, TraitError> { - let res = self + let sig = self .0 .read() .key_pair_by_type::(public, key_type)? .map(|pair| pair.sign_prehashed(msg)); - Ok(res) + Ok(sig) } fn insert( diff --git a/primitives/keystore/src/testing.rs b/primitives/keystore/src/testing.rs index de034c65889ff..e5107cba746f2 100644 --- a/primitives/keystore/src/testing.rs +++ b/primitives/keystore/src/testing.rs @@ -42,65 +42,36 @@ impl MemoryKeystore { Self::default() } - 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, - 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, key_type: KeyTypeId, public: &ecdsa::Public) -> Option { + fn pair(&self, key_type: KeyTypeId, public: &T::Public) -> Option { self.keys.read().get(&key_type).and_then(|inner| { inner .get(public.as_slice()) - .map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid")) + .map(|s| T::from_string(s, None).expect("seed slice is valid")) }) } -} -impl Keystore for MemoryKeystore { - fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { + fn public_keys(&self, key_type: KeyTypeId) -> Vec { self.keys .read() .get(&key_type) .map(|keys| { keys.values() - .map(|s| { - sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid") - }) + .map(|s| T::from_string(s, None).expect("seed slice is valid")) .map(|p| p.public()) .collect() }) .unwrap_or_default() } - fn sr25519_generate_new( + fn generate_new( &self, key_type: KeyTypeId, seed: Option<&str>, - ) -> Result { + ) -> Result { match seed { Some(seed) => { - let pair = sr25519::Pair::from_string(seed, None).map_err(|_| { - Error::ValidationError("Generates an `sr25519` pair.".to_owned()) - })?; + let pair = T::from_string(seed, None) + .map_err(|_| Error::ValidationError("Generates a pair.".to_owned()))?; self.keys .write() .entry(key_type) @@ -109,7 +80,7 @@ impl Keystore for MemoryKeystore { Ok(pair.public()) }, None => { - let (pair, phrase, _) = sr25519::Pair::generate_with_phrase(None); + let (pair, phrase, _) = T::generate_with_phrase(None); self.keys .write() .entry(key_type) @@ -120,13 +91,37 @@ impl Keystore for MemoryKeystore { } } + fn sign( + &self, + key_type: KeyTypeId, + public: &T::Public, + msg: &[u8], + ) -> Result, Error> { + let sig = self.pair::(key_type, public).map(|pair| pair.sign(msg)); + Ok(sig) + } +} + +impl Keystore for MemoryKeystore { + fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.public_keys::(key_type) + } + + fn sr25519_generate_new( + &self, + key_type: KeyTypeId, + seed: Option<&str>, + ) -> Result { + self.generate_new::(key_type, seed) + } + fn sr25519_sign( &self, key_type: KeyTypeId, public: &sr25519::Public, msg: &[u8], ) -> Result, Error> { - Ok(self.sr25519_key_pair(key_type, public).map(|pair| pair.sign(msg))) + self.sign::(key_type, public, msg) } fn sr25519_vrf_sign( @@ -135,27 +130,16 @@ impl Keystore for MemoryKeystore { public: &sr25519::Public, transcript_data: VRFTranscriptData, ) -> Result, Error> { - let transcript = make_transcript(transcript_data); - let pair = - if let Some(k) = self.sr25519_key_pair(key_type, public) { k } else { return Ok(None) }; - - let (inout, proof, _) = pair.as_ref().vrf_sign(transcript); - Ok(Some(VRFSignature { output: inout.to_output(), proof })) + let sig = self.pair::(key_type, public).map(|pair| { + let transcript = make_transcript(transcript_data); + let (inout, proof, _) = pair.as_ref().vrf_sign(transcript); + VRFSignature { output: inout.to_output(), proof } + }); + Ok(sig) } 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() + self.public_keys::(key_type) } fn ed25519_generate_new( @@ -163,28 +147,7 @@ impl Keystore for MemoryKeystore { 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()) - }, - } + self.generate_new::(key_type, seed) } fn ed25519_sign( @@ -193,22 +156,11 @@ impl Keystore for MemoryKeystore { public: &ed25519::Public, msg: &[u8], ) -> Result, Error> { - Ok(self.ed25519_key_pair(key_type, public).map(|pair| pair.sign(msg))) + self.sign::(key_type, public, 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() + self.public_keys::(key_type) } fn ecdsa_generate_new( @@ -216,27 +168,7 @@ impl Keystore for MemoryKeystore { 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()) - }, - } + self.generate_new::(key_type, seed) } fn ecdsa_sign( @@ -245,7 +177,7 @@ impl Keystore for MemoryKeystore { public: &ecdsa::Public, msg: &[u8], ) -> Result, Error> { - Ok(self.ecdsa_key_pair(key_type, public).map(|pair| pair.sign(msg))) + self.sign::(key_type, public, msg) } fn ecdsa_sign_prehashed( @@ -254,8 +186,8 @@ impl Keystore for MemoryKeystore { public: &ecdsa::Public, msg: &[u8; 32], ) -> Result, Error> { - let pair = self.ecdsa_key_pair(key_type, public); - pair.map(|pair| pair.sign_prehashed(msg)).map(Ok).transpose() + let sig = self.pair::(key_type, public).map(|pair| pair.sign_prehashed(msg)); + Ok(sig) } fn insert(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> {