mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 19:01:08 +00:00
Export app-crypto specific keystore functions (#7489)
* Export app-crypto specific keystore functions * Also add back the insert function * Switch KeystoreContainer to an enum * Only export the bare minimal for LocalKeystore and fix service compile * fix: should return Arc * Add docs stating that functions only available in local keystore * Remove insert and generate functions * fix: generate function should be available in test * Add keypair function to trait * Revert "Add keypair function to trait" This reverts commit ad921b09ca73d3c09298e3a51b562ef8e0067781. * Add note for local_keystore function in service
This commit is contained in:
@@ -38,7 +38,7 @@ use sp_keystore::{
|
||||
SyncCryptoStore,
|
||||
vrf::{VRFTranscriptData, VRFSignature, make_transcript},
|
||||
};
|
||||
use sp_application_crypto::{ed25519, sr25519, ecdsa};
|
||||
use sp_application_crypto::{ed25519, sr25519, ecdsa, AppPair, AppKey, IsWrappedBy};
|
||||
|
||||
use crate::{Result, Error};
|
||||
|
||||
@@ -57,6 +57,14 @@ impl LocalKeystore {
|
||||
let inner = KeystoreInner::new_in_memory();
|
||||
Self(RwLock::new(inner))
|
||||
}
|
||||
|
||||
/// Get a key pair for the given public key.
|
||||
///
|
||||
/// This function is only available for a local keystore. If your application plans to work with
|
||||
/// remote keystores, you do not want to depend on it.
|
||||
pub fn key_pair<Pair: AppPair>(&self, public: &<Pair as AppKey>::Public) -> Result<Pair> {
|
||||
self.0.read().key_pair::<Pair>(public)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -470,6 +478,11 @@ impl KeystoreInner {
|
||||
|
||||
Ok(public_keys)
|
||||
}
|
||||
|
||||
/// Get a key pair for the given public key.
|
||||
pub fn key_pair<Pair: AppPair>(&self, public: &<Pair as AppKey>::Public) -> Result<Pair> {
|
||||
self.key_pair_by_type::<Pair::Generic>(IsWrappedBy::from_ref(public), Pair::ID).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -479,47 +492,32 @@ mod tests {
|
||||
use tempfile::TempDir;
|
||||
use sp_core::{
|
||||
Pair,
|
||||
crypto::{IsWrappedBy, Ss58Codec},
|
||||
crypto::Ss58Codec,
|
||||
testing::SR25519,
|
||||
};
|
||||
use sp_application_crypto::{ed25519, sr25519, AppPublic, AppKey, AppPair};
|
||||
use sp_application_crypto::{ed25519, sr25519, AppPublic};
|
||||
use std::{
|
||||
fs,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
/// Generate a new key.
|
||||
///
|
||||
/// Places it into the file system store.
|
||||
fn generate<Pair: AppPair>(store: &KeystoreInner) -> Result<Pair> {
|
||||
store.generate_by_type::<Pair::Generic>(Pair::ID).map(Into::into)
|
||||
}
|
||||
impl KeystoreInner {
|
||||
fn insert_ephemeral_from_seed<Pair: AppPair>(&mut self, seed: &str) -> Result<Pair> {
|
||||
self.insert_ephemeral_from_seed_by_type::<Pair::Generic>(seed, Pair::ID).map(Into::into)
|
||||
}
|
||||
|
||||
/// Create a new key from seed.
|
||||
///
|
||||
/// Does not place it into the file system store.
|
||||
fn insert_ephemeral_from_seed<Pair: AppPair>(store: &mut KeystoreInner, seed: &str) -> Result<Pair> {
|
||||
store.insert_ephemeral_from_seed_by_type::<Pair::Generic>(seed, Pair::ID).map(Into::into)
|
||||
}
|
||||
fn public_keys<Public: AppPublic>(&self) -> Result<Vec<Public>> {
|
||||
self.raw_public_keys(Public::ID)
|
||||
.map(|v| {
|
||||
v.into_iter()
|
||||
.map(|k| Public::from_slice(k.as_slice()))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
/// Get public keys of all stored keys that match the key type.
|
||||
///
|
||||
/// This will just use the type of the public key (a list of which to be returned) in order
|
||||
/// to determine the key type. Unless you use a specialized application-type public key, then
|
||||
/// this only give you keys registered under generic cryptography, and will not return keys
|
||||
/// registered under the application type.
|
||||
fn public_keys<Public: AppPublic>(store: &KeystoreInner) -> Result<Vec<Public>> {
|
||||
store.raw_public_keys(Public::ID)
|
||||
.map(|v| {
|
||||
v.into_iter()
|
||||
.map(|k| Public::from_slice(k.as_slice()))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a key pair for the given public key.
|
||||
fn key_pair<Pair: AppPair>(store: &KeystoreInner, public: &<Pair as AppKey>::Public) -> Result<Pair> {
|
||||
store.key_pair_by_type::<Pair::Generic>(IsWrappedBy::from_ref(public), Pair::ID).map(Into::into)
|
||||
fn generate<Pair: AppPair>(&self) -> Result<Pair> {
|
||||
self.generate_by_type::<Pair::Generic>(Pair::ID).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -527,14 +525,14 @@ mod tests {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let store = KeystoreInner::open(temp_dir.path(), None).unwrap();
|
||||
|
||||
assert!(public_keys::<ed25519::AppPublic>(&store).unwrap().is_empty());
|
||||
assert!(store.public_keys::<ed25519::AppPublic>().unwrap().is_empty());
|
||||
|
||||
let key: ed25519::AppPair = generate(&store).unwrap();
|
||||
let key2: ed25519::AppPair = key_pair(&store, &key.public()).unwrap();
|
||||
let key: ed25519::AppPair = store.generate().unwrap();
|
||||
let key2: ed25519::AppPair = store.key_pair(&key.public()).unwrap();
|
||||
|
||||
assert_eq!(key.public(), key2.public());
|
||||
|
||||
assert_eq!(public_keys::<ed25519::AppPublic>(&store).unwrap()[0], key.public());
|
||||
assert_eq!(store.public_keys::<ed25519::AppPublic>().unwrap()[0], key.public());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -542,8 +540,7 @@ mod tests {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let mut store = KeystoreInner::open(temp_dir.path(), None).unwrap();
|
||||
|
||||
let pair: ed25519::AppPair = insert_ephemeral_from_seed(
|
||||
&mut store,
|
||||
let pair: ed25519::AppPair = store.insert_ephemeral_from_seed(
|
||||
"0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc"
|
||||
).unwrap();
|
||||
assert_eq!(
|
||||
@@ -554,7 +551,7 @@ mod tests {
|
||||
drop(store);
|
||||
let store = KeystoreInner::open(temp_dir.path(), None).unwrap();
|
||||
// Keys generated from seed should not be persisted!
|
||||
assert!(key_pair::<ed25519::AppPair>(&store, &pair.public()).is_err());
|
||||
assert!(store.key_pair::<ed25519::AppPair>(&pair.public()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -566,15 +563,15 @@ mod tests {
|
||||
Some(FromStr::from_str(password.as_str()).unwrap()),
|
||||
).unwrap();
|
||||
|
||||
let pair: ed25519::AppPair = generate(&store).unwrap();
|
||||
let pair: ed25519::AppPair = store.generate().unwrap();
|
||||
assert_eq!(
|
||||
pair.public(),
|
||||
key_pair::<ed25519::AppPair>(&store, &pair.public()).unwrap().public(),
|
||||
store.key_pair::<ed25519::AppPair>(&pair.public()).unwrap().public(),
|
||||
);
|
||||
|
||||
// Without the password the key should not be retrievable
|
||||
let store = KeystoreInner::open(temp_dir.path(), None).unwrap();
|
||||
assert!(key_pair::<ed25519::AppPair>(&store, &pair.public()).is_err());
|
||||
assert!(store.key_pair::<ed25519::AppPair>(&pair.public()).is_err());
|
||||
|
||||
let store = KeystoreInner::open(
|
||||
temp_dir.path(),
|
||||
@@ -582,7 +579,7 @@ mod tests {
|
||||
).unwrap();
|
||||
assert_eq!(
|
||||
pair.public(),
|
||||
key_pair::<ed25519::AppPair>(&store, &pair.public()).unwrap().public(),
|
||||
store.key_pair::<ed25519::AppPair>(&pair.public()).unwrap().public(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -593,18 +590,17 @@ mod tests {
|
||||
|
||||
let mut keys = Vec::new();
|
||||
for i in 0..10 {
|
||||
keys.push(generate::<ed25519::AppPair>(&store).unwrap().public());
|
||||
keys.push(insert_ephemeral_from_seed::<ed25519::AppPair>(
|
||||
&mut store,
|
||||
keys.push(store.generate::<ed25519::AppPair>().unwrap().public());
|
||||
keys.push(store.insert_ephemeral_from_seed::<ed25519::AppPair>(
|
||||
&format!("0x3d97c819d68f9bafa7d6e79cb991eebcd7{}d966c5334c0b94d9e1fa7ad0869dc", i),
|
||||
).unwrap().public());
|
||||
}
|
||||
|
||||
// Generate a key of a different type
|
||||
generate::<sr25519::AppPair>(&store).unwrap();
|
||||
store.generate::<sr25519::AppPair>().unwrap();
|
||||
|
||||
keys.sort();
|
||||
let mut store_pubs = public_keys::<ed25519::AppPublic>(&store).unwrap();
|
||||
let mut store_pubs = store.public_keys::<ed25519::AppPublic>().unwrap();
|
||||
store_pubs.sort();
|
||||
|
||||
assert_eq!(keys, store_pubs);
|
||||
|
||||
@@ -205,12 +205,13 @@ pub type TLightClientWithBackend<TBl, TRtApi, TExecDisp, TBackend> = Client<
|
||||
TRtApi,
|
||||
>;
|
||||
|
||||
/// Construct and hold different layers of Keystore wrappers
|
||||
pub struct KeystoreContainer {
|
||||
keystore: Arc<dyn CryptoStore>,
|
||||
sync_keystore: SyncCryptoStorePtr,
|
||||
enum KeystoreContainerInner {
|
||||
Local(Arc<LocalKeystore>)
|
||||
}
|
||||
|
||||
/// Construct and hold different layers of Keystore wrappers
|
||||
pub struct KeystoreContainer(KeystoreContainerInner);
|
||||
|
||||
impl KeystoreContainer {
|
||||
/// Construct KeystoreContainer
|
||||
pub fn new(config: &KeystoreConfig) -> Result<Self, Error> {
|
||||
@@ -221,22 +222,36 @@ impl KeystoreContainer {
|
||||
)?,
|
||||
KeystoreConfig::InMemory => LocalKeystore::in_memory(),
|
||||
});
|
||||
let sync_keystore = keystore.clone() as SyncCryptoStorePtr;
|
||||
|
||||
Ok(Self {
|
||||
keystore,
|
||||
sync_keystore,
|
||||
})
|
||||
Ok(Self(KeystoreContainerInner::Local(keystore)))
|
||||
}
|
||||
|
||||
/// Returns an adapter to the asynchronous keystore that implements `CryptoStore`
|
||||
pub fn keystore(&self) -> Arc<dyn CryptoStore> {
|
||||
self.keystore.clone()
|
||||
match self.0 {
|
||||
KeystoreContainerInner::Local(ref keystore) => keystore.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the synchrnous keystore wrapper
|
||||
pub fn sync_keystore(&self) -> SyncCryptoStorePtr {
|
||||
self.sync_keystore.clone()
|
||||
match self.0 {
|
||||
KeystoreContainerInner::Local(ref keystore) => keystore.clone() as SyncCryptoStorePtr,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the local keystore if available
|
||||
///
|
||||
/// The function will return None if the available keystore is not a local keystore.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Using the [`LocalKeystore`] will result in loosing the ability to use any other keystore implementation, like
|
||||
/// a remote keystore for example. Only use this if you a certain that you require it!
|
||||
pub fn local_keystore(&self) -> Option<Arc<LocalKeystore>> {
|
||||
match self.0 {
|
||||
KeystoreContainerInner::Local(ref keystore) => Some(keystore.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user