mod contract;
mod wallet;
use std::sync::Arc;
use crate::logger::{log_info, WriteLog};
use crate::Storage;
use crate::{error::WalletError, logger::Logger};
use bdk_chain::Merge;
use bdk_wallet::ChangeSet;
use ddk_manager::contract::ser::Serializable;
use ddk_manager::error::Error;
use lightning::io::{Cursor, Read};
use sled::{Db, Tree};
const CONTRACT_TREE: u8 = 1;
const CHANNEL_TREE: u8 = 2;
pub const CHAIN_MONITOR_TREE: u8 = 3;
pub const CHAIN_MONITOR_KEY: u8 = 4;
const SIGNER_TREE: u8 = 6;
const WALLET_TREE: u8 = 7;
const MARKETPLACE_TREE: u8 = 8;
const CHANGESET_KEY: &str = "changeset";
#[derive(Debug, Clone)]
pub struct SledStorage {
db: Db,
logger: Arc<Logger>,
}
impl SledStorage {
pub fn new(path: &str, logger: Arc<Logger>) -> Result<Self, sled::Error> {
Ok(SledStorage {
db: sled::open(path)?,
logger,
})
}
fn get_data_with_prefix<T: Serializable>(
&self,
tree: &Tree,
prefix: &[u8],
consume: Option<u64>,
) -> Result<Vec<T>, Error> {
let iter = tree.iter();
iter.values()
.filter_map(|res| {
let value = res.unwrap();
let mut cursor = Cursor::new(&value);
let mut pref = vec![0u8; prefix.len()];
cursor.read_exact(&mut pref).expect("Error reading prefix");
if pref == prefix {
if let Some(c) = consume {
cursor.set_position(cursor.position() + c);
}
Some(Ok(T::deserialize(&mut cursor).ok()?))
} else {
None
}
})
.collect()
}
fn open_tree(&self, tree_id: &[u8; 1]) -> Result<Tree, Error> {
self.db
.open_tree(tree_id)
.map_err(|e| Error::StorageError(format!("Error opening contract tree: {}", e)))
}
fn contract_tree(&self) -> Result<Tree, Error> {
self.open_tree(&[CONTRACT_TREE])
}
fn channel_tree(&self) -> Result<Tree, Error> {
self.open_tree(&[CHANNEL_TREE])
}
fn signer_tree(&self) -> Result<Tree, sled::Error> {
self.db.open_tree([SIGNER_TREE])
}
pub fn wallet_tree(&self) -> Result<Tree, sled::Error> {
self.db.open_tree([WALLET_TREE])
}
pub fn marketplace_tree(&self) -> Result<Tree, sled::Error> {
self.db.open_tree([MARKETPLACE_TREE])
}
}
#[async_trait::async_trait]
impl Storage for SledStorage {
async fn persist_bdk(&self, changeset: &ChangeSet) -> Result<(), WalletError> {
let wallet_tree = self.wallet_tree().map_err(sled_to_wallet_error)?;
let new_changeset = match wallet_tree
.get(CHANGESET_KEY)
.map_err(sled_to_wallet_error)?
{
Some(stored_changeset) => {
let mut stored_changeset = serde_json::from_slice::<ChangeSet>(&stored_changeset)?;
stored_changeset.merge(changeset.clone());
stored_changeset
}
None => changeset.to_owned(),
};
wallet_tree
.insert(CHANGESET_KEY, serde_json::to_vec(&new_changeset)?)
.map_err(sled_to_wallet_error)?;
Ok(())
}
async fn initialize_bdk(&self) -> Result<ChangeSet, WalletError> {
log_info!(self.logger, "Initializing sled wallet persistance.");
let changeset = match self
.wallet_tree()
.map_err(sled_to_wallet_error)?
.get(CHANGESET_KEY)
.map_err(sled_to_wallet_error)?
{
Some(changeset) => serde_json::from_slice(&changeset)?,
None => ChangeSet::default(),
};
Ok(changeset)
}
}
fn sled_to_wallet_error(error: sled::Error) -> WalletError {
WalletError::StorageError(error.to_string())
}