pub mod testing;
pub mod vrf;
use std::sync::Arc;
use async_trait::async_trait;
use futures::{executor::block_on, future::join_all};
use tet_core::{
crypto::{KeyTypeId, CryptoTypePublicPair},
ed25519, sr25519, ecdsa,
};
use crate::vrf::{VRFTranscriptData, VRFSignature};
#[derive(Debug, derive_more::Display)]
pub enum Error {
#[display(fmt="Key not supported: {:?}", _0)]
KeyNotSupported(KeyTypeId),
#[display(fmt="Pair was not found: {}", _0)]
PairNotFound(String),
#[display(fmt="Validation error: {}", _0)]
ValidationError(String),
#[display(fmt="Keystore unavailable")]
Unavailable,
#[display(fmt="An unknown keystore error occurred: {}", _0)]
Other(String)
}
#[async_trait]
pub trait CryptoStore: Send + Sync {
async fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;
async fn sr25519_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<sr25519::Public, Error>;
async fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public>;
async fn ed25519_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<ed25519::Public, Error>;
async fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;
async fn ecdsa_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<ecdsa::Public, Error>;
async fn insert_unknown(
&self,
id: KeyTypeId,
suri: &str,
public: &[u8]
) -> Result<(), ()>;
async fn supported_keys(
&self,
id: KeyTypeId,
keys: Vec<CryptoTypePublicPair>
) -> Result<Vec<CryptoTypePublicPair>, Error>;
async fn keys(&self, id: KeyTypeId) -> Result<Vec<CryptoTypePublicPair>, Error>;
async fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool;
async fn sign_with(
&self,
id: KeyTypeId,
key: &CryptoTypePublicPair,
msg: &[u8],
) -> Result<Vec<u8>, Error>;
async fn sign_with_any(
&self,
id: KeyTypeId,
keys: Vec<CryptoTypePublicPair>,
msg: &[u8]
) -> Result<(CryptoTypePublicPair, Vec<u8>), Error> {
if keys.len() == 1 {
return self.sign_with(id, &keys[0], msg).await.map(|s| (keys[0].clone(), s));
} else {
for k in self.supported_keys(id, keys).await? {
if let Ok(sign) = self.sign_with(id, &k, msg).await {
return Ok((k, sign));
}
}
}
Err(Error::KeyNotSupported(id))
}
async fn sign_with_all(
&self,
id: KeyTypeId,
keys: Vec<CryptoTypePublicPair>,
msg: &[u8],
) -> Result<Vec<Result<Vec<u8>, Error>>, ()> {
let futs = keys.iter()
.map(|k| self.sign_with(id, k, msg));
Ok(join_all(futs).await)
}
async fn sr25519_vrf_sign(
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
transcript_data: VRFTranscriptData,
) -> Result<VRFSignature, Error>;
}
pub trait SyncCryptoStore: CryptoStore + Send + Sync {
fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;
fn sr25519_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<sr25519::Public, Error>;
fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public>;
fn ed25519_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<ed25519::Public, Error>;
fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;
fn ecdsa_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<ecdsa::Public, Error>;
fn insert_unknown(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()>;
fn supported_keys(
&self,
id: KeyTypeId,
keys: Vec<CryptoTypePublicPair>
) -> Result<Vec<CryptoTypePublicPair>, Error>;
fn keys(&self, id: KeyTypeId) -> Result<Vec<CryptoTypePublicPair>, Error> {
block_on(CryptoStore::keys(self, id))
}
fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool;
fn sign_with(
&self,
id: KeyTypeId,
key: &CryptoTypePublicPair,
msg: &[u8],
) -> Result<Vec<u8>, Error>;
fn sign_with_any(
&self,
id: KeyTypeId,
keys: Vec<CryptoTypePublicPair>,
msg: &[u8]
) -> Result<(CryptoTypePublicPair, Vec<u8>), Error> {
if keys.len() == 1 {
return SyncCryptoStore::sign_with(self, id, &keys[0], msg).map(|s| (keys[0].clone(), s));
} else {
for k in SyncCryptoStore::supported_keys(self, id, keys)? {
if let Ok(sign) = SyncCryptoStore::sign_with(self, id, &k, msg) {
return Ok((k, sign));
}
}
}
Err(Error::KeyNotSupported(id))
}
fn sign_with_all(
&self,
id: KeyTypeId,
keys: Vec<CryptoTypePublicPair>,
msg: &[u8],
) -> Result<Vec<Result<Vec<u8>, Error>>, ()>{
Ok(keys.iter().map(|k| SyncCryptoStore::sign_with(self, id, k, msg)).collect())
}
fn sr25519_vrf_sign(
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
transcript_data: VRFTranscriptData,
) -> Result<VRFSignature, Error>;
}
pub type SyncCryptoStorePtr = Arc<dyn SyncCryptoStore>;
externalities::decl_extension! {
pub struct KeystoreExt(SyncCryptoStorePtr);
}