use crate::{
error::WalletStorageError,
storage::database::{DbKey, DbKeyValuePair, DbValue, WalletBackend, WriteOperation},
};
use aes_gcm::Aes256Gcm;
use std::{
collections::HashMap,
sync::{Arc, RwLock},
};
use tari_comms::{
multiaddr::Multiaddr,
tor::TorIdentity,
types::{CommsPublicKey, CommsSecretKey},
NodeIdentity,
};
use tari_crypto::keys::PublicKey;
#[derive(Default)]
pub struct InnerDatabase {
comms_private_key: Option<CommsSecretKey>,
client_key_values: HashMap<String, String>,
comms_address: Option<Multiaddr>,
features: u64,
identity: Option<NodeIdentity>,
tor_id: Option<TorIdentity>,
}
impl InnerDatabase {
pub fn new() -> Self {
Self {
comms_private_key: None,
client_key_values: HashMap::new(),
comms_address: None,
features: 0,
identity: None,
tor_id: None,
}
}
}
#[derive(Clone)]
pub struct WalletMemoryDatabase {
db: Arc<RwLock<InnerDatabase>>,
}
impl WalletMemoryDatabase {
pub fn new() -> Self {
Self {
db: Arc::new(RwLock::new(InnerDatabase::new())),
}
}
}
impl Default for WalletMemoryDatabase {
fn default() -> Self {
Self::new()
}
}
impl WalletBackend for WalletMemoryDatabase {
fn fetch(&self, key: &DbKey) -> Result<Option<DbValue>, WalletStorageError> {
let db = acquire_read_lock!(self.db);
let result = match key {
DbKey::CommsSecretKey => db.comms_private_key.clone().map(DbValue::CommsSecretKey),
DbKey::CommsPublicKey => db
.comms_private_key
.clone()
.map(|sk| DbValue::CommsPublicKey(CommsPublicKey::from_secret_key(&sk))),
DbKey::ClientKey(k) => db.client_key_values.get(k).map(|v| DbValue::ClientValue(v.clone())),
DbKey::CommsAddress => db.comms_address.clone().map(DbValue::CommsAddress),
DbKey::CommsFeatures => Some(DbValue::CommsFeatures(db.features)),
DbKey::Identity => db.identity.clone().map(DbValue::Identity),
DbKey::TorId => db.tor_id.clone().map(DbValue::TorId),
};
Ok(result)
}
fn write(&self, op: WriteOperation) -> Result<Option<DbValue>, WalletStorageError> {
let mut db = acquire_write_lock!(self.db);
match op {
WriteOperation::Insert(kvp) => match kvp {
DbKeyValuePair::CommsSecretKey(secret) => {
db.comms_private_key = Some(secret);
},
DbKeyValuePair::ClientKeyValue(k, v) => {
db.client_key_values.insert(k, v);
},
DbKeyValuePair::Identity(v) => {
db.identity = Some(*v);
},
DbKeyValuePair::TorId(v) => {
db.tor_id = Some(v);
},
},
WriteOperation::Remove(k) => match k {
DbKey::CommsSecretKey => {
db.comms_private_key = None;
},
DbKey::CommsPublicKey => {
return Err(WalletStorageError::OperationNotSupported);
},
DbKey::ClientKey(k) => {
if db.client_key_values.remove(&k).is_some() {
return Ok(Some(DbValue::ValueCleared));
} else {
return Ok(None);
}
},
DbKey::CommsAddress => {
return Err(WalletStorageError::OperationNotSupported);
},
DbKey::CommsFeatures => {
return Err(WalletStorageError::OperationNotSupported);
},
DbKey::Identity => {
return Err(WalletStorageError::OperationNotSupported);
},
DbKey::TorId => {
db.tor_id = None;
},
},
}
Ok(None)
}
fn apply_encryption(&self, _: Aes256Gcm) -> Result<(), WalletStorageError> {
Ok(())
}
fn remove_encryption(&self) -> Result<(), WalletStorageError> {
Ok(())
}
}