use crate::{
json::{OpaqueKeyFile, Uuid},
Error, OpaqueSecret,
};
use cfx_types::H256;
use cfxkey::{Address, Message, Password, Public, Secret, Signature};
use std::{
cmp::Ordering,
hash::{Hash, Hasher},
path::PathBuf,
};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum SecretVaultRef {
Root,
Vault(String),
}
#[derive(Debug, Clone)]
pub struct StoreAccountRef {
pub address: Address,
pub vault: SecretVaultRef,
}
impl PartialOrd for StoreAccountRef {
fn partial_cmp(&self, other: &StoreAccountRef) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for StoreAccountRef {
fn eq(&self, other: &Self) -> bool { self.address == other.address }
}
impl Eq for StoreAccountRef {}
impl Ord for StoreAccountRef {
fn cmp(&self, other: &Self) -> Ordering {
self.address
.cmp(&other.address)
.then_with(|| self.vault.cmp(&other.vault))
}
}
impl Hash for StoreAccountRef {
fn hash<H: Hasher>(&self, state: &mut H) { self.address.hash(state); }
}
impl ::std::borrow::Borrow<Address> for StoreAccountRef {
fn borrow(&self) -> &Address { &self.address }
}
pub trait SimpleSecretStore: Send + Sync {
fn insert_account(
&self, vault: SecretVaultRef, secret: Secret, password: &Password,
) -> Result<StoreAccountRef, Error>;
fn insert_derived(
&self, vault: SecretVaultRef, account_ref: &StoreAccountRef,
password: &Password, derivation: Derivation,
) -> Result<StoreAccountRef, Error>;
fn change_password(
&self, account: &StoreAccountRef, old_password: &Password,
new_password: &Password,
) -> Result<(), Error>;
fn export_account(
&self, account: &StoreAccountRef, password: &Password,
) -> Result<OpaqueKeyFile, Error>;
fn remove_account(
&self, account: &StoreAccountRef, password: &Password,
) -> Result<(), Error>;
fn generate_derived(
&self, account_ref: &StoreAccountRef, password: &Password,
derivation: Derivation,
) -> Result<Address, Error>;
fn sign(
&self, account: &StoreAccountRef, password: &Password,
message: &Message,
) -> Result<Signature, Error>;
fn sign_derived(
&self, account_ref: &StoreAccountRef, password: &Password,
derivation: Derivation, message: &Message,
) -> Result<Signature, Error>;
fn decrypt(
&self, account: &StoreAccountRef, password: &Password,
shared_mac: &[u8], message: &[u8],
) -> Result<Vec<u8>, Error>;
fn agree(
&self, account: &StoreAccountRef, password: &Password, other: &Public,
) -> Result<Secret, Error>;
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error>;
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error>;
fn create_vault(
&self, name: &str, password: &Password,
) -> Result<(), Error>;
fn open_vault(&self, name: &str, password: &Password) -> Result<(), Error>;
fn close_vault(&self, name: &str) -> Result<(), Error>;
fn list_vaults(&self) -> Result<Vec<String>, Error>;
fn list_opened_vaults(&self) -> Result<Vec<String>, Error>;
fn change_vault_password(
&self, name: &str, new_password: &Password,
) -> Result<(), Error>;
fn change_account_vault(
&self, vault: SecretVaultRef, account: StoreAccountRef,
) -> Result<StoreAccountRef, Error>;
fn get_vault_meta(&self, name: &str) -> Result<String, Error>;
fn set_vault_meta(&self, name: &str, meta: &str) -> Result<(), Error>;
}
pub trait SecretStore: SimpleSecretStore {
fn raw_secret(
&self, account: &StoreAccountRef, password: &Password,
) -> Result<OpaqueSecret, Error>;
fn sign_with_secret(
&self, secret: &OpaqueSecret, message: &Message,
) -> Result<Signature, Error> {
Ok(::cfxkey::sign(&secret.0, message)?)
}
fn import_wallet(
&self, vault: SecretVaultRef, json: &[u8], password: &Password,
gen_id: bool,
) -> Result<StoreAccountRef, Error>;
fn copy_account(
&self, new_store: &dyn SimpleSecretStore, new_vault: SecretVaultRef,
account: &StoreAccountRef, password: &Password,
new_password: &Password,
) -> Result<(), Error>;
fn test_password(
&self, account: &StoreAccountRef, password: &Password,
) -> Result<bool, Error>;
fn public(
&self, account: &StoreAccountRef, password: &Password,
) -> Result<Public, Error>;
fn uuid(&self, account: &StoreAccountRef) -> Result<Uuid, Error>;
fn name(&self, account: &StoreAccountRef) -> Result<String, Error>;
fn meta(&self, account: &StoreAccountRef) -> Result<String, Error>;
fn set_name(
&self, account: &StoreAccountRef, name: String,
) -> Result<(), Error>;
fn set_meta(
&self, account: &StoreAccountRef, meta: String,
) -> Result<(), Error>;
fn local_path(&self) -> PathBuf;
fn list_geth_accounts(&self, testnet: bool) -> Vec<Address>;
fn import_geth_accounts(
&self, vault: SecretVaultRef, desired: Vec<Address>, testnet: bool,
) -> Result<Vec<StoreAccountRef>, Error>;
}
impl StoreAccountRef {
pub fn root(address: Address) -> Self {
StoreAccountRef::new(SecretVaultRef::Root, address)
}
pub fn vault(vault_name: &str, address: Address) -> Self {
StoreAccountRef::new(
SecretVaultRef::Vault(vault_name.to_owned()),
address,
)
}
pub fn new(vault_ref: SecretVaultRef, address: Address) -> Self {
StoreAccountRef {
vault: vault_ref,
address,
}
}
}
pub struct IndexDerivation {
pub soft: bool,
pub index: u32,
}
pub enum Derivation {
Hierarchical(Vec<IndexDerivation>),
SoftHash(H256),
HardHash(H256),
}