mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 23:31:07 +00:00
Introduces author_hasKey and author_hasSessionKeys rpc endpoints (#4720)
* Introduces `author_hasKey` and `author_hasSessionKeys` rpc endpoints Both endpoints can be used to check if a key is present in the keystore. - `hasKey` works on with an individual public key and key type. It checks if a private key for the given combination exists in the keystore. - `hasSessionKeys` works with the full encoded session key blob stored on-chain in `nextKeys`. This requires that the given blob can be decoded by the runtime. It will return `true`, iff all public keys of the session key exist in the storage. Fixes: https://github.com/paritytech/substrate/issues/4696 * Update client/rpc-api/src/author/error.rs Co-Authored-By: Nikolay Volf <nikvolf@gmail.com> * Indentation Co-authored-by: Nikolay Volf <nikvolf@gmail.com>
This commit is contained in:
@@ -72,7 +72,8 @@ impl std::error::Error for Error {
|
||||
/// Every pair that is being generated by a `seed`, will be placed in memory.
|
||||
pub struct Store {
|
||||
path: Option<PathBuf>,
|
||||
additional: HashMap<(KeyTypeId, Vec<u8>), Vec<u8>>,
|
||||
/// Map over `(KeyTypeId, Raw public key)` -> `Key phrase/seed`
|
||||
additional: HashMap<(KeyTypeId, Vec<u8>), String>,
|
||||
password: Option<Protected<String>>,
|
||||
}
|
||||
|
||||
@@ -97,25 +98,22 @@ impl Store {
|
||||
}))
|
||||
}
|
||||
|
||||
/// Get the public/private key pair for the given public key and key type.
|
||||
fn get_additional_pair<Pair: PairT>(
|
||||
/// Get the key phrase for the given public key and key type from the in-memory store.
|
||||
fn get_additional_pair(
|
||||
&self,
|
||||
public: &Pair::Public,
|
||||
public: &[u8],
|
||||
key_type: KeyTypeId,
|
||||
) -> Result<Option<Pair>> {
|
||||
let key = (key_type, public.to_raw_vec());
|
||||
self.additional
|
||||
.get(&key)
|
||||
.map(|bytes| Pair::from_seed_slice(bytes).map_err(|_| Error::InvalidSeed))
|
||||
.transpose()
|
||||
) -> Option<&String> {
|
||||
let key = (key_type, public.to_vec());
|
||||
self.additional.get(&key)
|
||||
}
|
||||
|
||||
/// 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<Pair: PairT>(&mut self, pair: &Pair, key_type: KeyTypeId) {
|
||||
fn insert_ephemeral_pair<Pair: PairT>(&mut self, pair: &Pair, seed: &str, key_type: KeyTypeId) {
|
||||
let key = (key_type, pair.public().to_raw_vec());
|
||||
self.additional.insert(key, pair.to_raw_vec());
|
||||
self.additional.insert(key, seed.into());
|
||||
}
|
||||
|
||||
/// Insert a new key with anonymous crypto.
|
||||
@@ -179,7 +177,7 @@ impl Store {
|
||||
key_type: KeyTypeId,
|
||||
) -> Result<Pair> {
|
||||
let pair = Pair::from_string(seed, None).map_err(|_| Error::InvalidSeed)?;
|
||||
self.insert_ephemeral_pair(&pair, key_type);
|
||||
self.insert_ephemeral_pair(&pair, seed, key_type);
|
||||
Ok(pair)
|
||||
}
|
||||
|
||||
@@ -190,20 +188,24 @@ impl Store {
|
||||
self.insert_ephemeral_from_seed_by_type::<Pair::Generic>(seed, Pair::ID).map(Into::into)
|
||||
}
|
||||
|
||||
/// Get the key phrase for a given public key and key type.
|
||||
fn key_phrase_by_type(&self, public: &[u8], key_type: KeyTypeId) -> Result<String> {
|
||||
if let Some(phrase) = self.get_additional_pair(public, key_type) {
|
||||
return Ok(phrase.clone())
|
||||
}
|
||||
|
||||
let path = self.key_file_path(public, key_type).ok_or_else(|| Error::Unavailable)?;
|
||||
let file = File::open(path)?;
|
||||
|
||||
serde_json::from_reader(&file).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Get a key pair for the given public key and key type.
|
||||
pub fn key_pair_by_type<Pair: PairT>(&self,
|
||||
public: &Pair::Public,
|
||||
key_type: KeyTypeId,
|
||||
) -> Result<Pair> {
|
||||
if let Some(pair) = self.get_additional_pair(public, key_type)? {
|
||||
return Ok(pair)
|
||||
}
|
||||
|
||||
let path = self.key_file_path(public.as_slice(), key_type)
|
||||
.ok_or_else(|| Error::Unavailable)?;
|
||||
let file = File::open(path)?;
|
||||
|
||||
let phrase: String = serde_json::from_reader(&file)?;
|
||||
let phrase = self.key_phrase_by_type(public.as_slice(), key_type)?;
|
||||
let pair = Pair::from_string(
|
||||
&phrase,
|
||||
self.password.as_ref().map(|p| &***p),
|
||||
@@ -328,6 +330,10 @@ impl BareCryptoStore for Store {
|
||||
fn password(&self) -> Option<&str> {
|
||||
self.password.as_ref().map(|x| x.as_str())
|
||||
}
|
||||
|
||||
fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool {
|
||||
public_keys.iter().all(|(p, t)| self.key_phrase_by_type(&p, *t).is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user