use core::ops::Deref;
use bitcoin::hashes::hex::{FromHex, ToHex};
use bitcoin::{BlockHash, Txid};
use crate::io;
use crate::prelude::{Vec, String};
use crate::routing::scoring::WriteableScore;
use crate::chain;
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use crate::chain::chainmonitor::{Persist, MonitorUpdateId};
use crate::sign::{EntropySource, NodeSigner, WriteableEcdsaChannelSigner, SignerProvider};
use crate::chain::transaction::OutPoint;
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate};
use crate::ln::channelmanager::ChannelManager;
use crate::routing::router::Router;
use crate::routing::gossip::NetworkGraph;
use crate::util::logger::Logger;
use crate::util::ser::{ReadableArgs, Writeable};
pub const KVSTORE_NAMESPACE_KEY_ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
pub const KVSTORE_NAMESPACE_KEY_MAX_LEN: usize = 120;
pub const CHANNEL_MANAGER_PERSISTENCE_NAMESPACE: &str = "";
pub const CHANNEL_MANAGER_PERSISTENCE_SUB_NAMESPACE: &str = "";
pub const CHANNEL_MANAGER_PERSISTENCE_KEY: &str = "manager";
pub const CHANNEL_MONITOR_PERSISTENCE_NAMESPACE: &str = "monitors";
pub const CHANNEL_MONITOR_PERSISTENCE_SUB_NAMESPACE: &str = "";
pub const NETWORK_GRAPH_PERSISTENCE_NAMESPACE: &str = "";
pub const NETWORK_GRAPH_PERSISTENCE_SUB_NAMESPACE: &str = "";
pub const NETWORK_GRAPH_PERSISTENCE_KEY: &str = "network_graph";
pub const SCORER_PERSISTENCE_NAMESPACE: &str = "";
pub const SCORER_PERSISTENCE_SUB_NAMESPACE: &str = "";
pub const SCORER_PERSISTENCE_KEY: &str = "scorer";
pub trait KVStore {
fn read(&self, namespace: &str, sub_namespace: &str, key: &str) -> io::Result<Vec<u8>>;
fn write(&self, namespace: &str, sub_namespace: &str, key: &str, buf: &[u8]) -> io::Result<()>;
fn remove(&self, namespace: &str, sub_namespace: &str, key: &str, lazy: bool) -> io::Result<()>;
fn list(&self, namespace: &str, sub_namespace: &str) -> io::Result<Vec<String>>;
}
pub trait Persister<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref, S: WriteableScore<'a>>
where M::Target: 'static + chain::Watch<<SP::Target as SignerProvider>::Signer>,
T::Target: 'static + BroadcasterInterface,
ES::Target: 'static + EntropySource,
NS::Target: 'static + NodeSigner,
SP::Target: 'static + SignerProvider,
F::Target: 'static + FeeEstimator,
R::Target: 'static + Router,
L::Target: 'static + Logger,
{
fn persist_manager(&self, channel_manager: &ChannelManager<M, T, ES, NS, SP, F, R, L>) -> Result<(), io::Error>;
fn persist_graph(&self, network_graph: &NetworkGraph<L>) -> Result<(), io::Error>;
fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error>;
}
impl<'a, A: KVStore, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, M, T, ES, NS, SP, F, R, L, S> for A
where M::Target: 'static + chain::Watch<<SP::Target as SignerProvider>::Signer>,
T::Target: 'static + BroadcasterInterface,
ES::Target: 'static + EntropySource,
NS::Target: 'static + NodeSigner,
SP::Target: 'static + SignerProvider,
F::Target: 'static + FeeEstimator,
R::Target: 'static + Router,
L::Target: 'static + Logger,
{
fn persist_manager(&self, channel_manager: &ChannelManager<M, T, ES, NS, SP, F, R, L>) -> Result<(), io::Error> {
self.write(CHANNEL_MANAGER_PERSISTENCE_NAMESPACE,
CHANNEL_MANAGER_PERSISTENCE_SUB_NAMESPACE,
CHANNEL_MANAGER_PERSISTENCE_KEY,
&channel_manager.encode())
}
fn persist_graph(&self, network_graph: &NetworkGraph<L>) -> Result<(), io::Error> {
self.write(NETWORK_GRAPH_PERSISTENCE_NAMESPACE,
NETWORK_GRAPH_PERSISTENCE_SUB_NAMESPACE,
NETWORK_GRAPH_PERSISTENCE_KEY,
&network_graph.encode())
}
fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error> {
self.write(SCORER_PERSISTENCE_NAMESPACE,
SCORER_PERSISTENCE_SUB_NAMESPACE,
SCORER_PERSISTENCE_KEY,
&scorer.encode())
}
}
impl<ChannelSigner: WriteableEcdsaChannelSigner, K: KVStore> Persist<ChannelSigner> for K {
fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus {
let key = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
match self.write(
CHANNEL_MONITOR_PERSISTENCE_NAMESPACE,
CHANNEL_MONITOR_PERSISTENCE_SUB_NAMESPACE,
&key, &monitor.encode())
{
Ok(()) => chain::ChannelMonitorUpdateStatus::Completed,
Err(_) => chain::ChannelMonitorUpdateStatus::UnrecoverableError
}
}
fn update_persisted_channel(&self, funding_txo: OutPoint, _update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus {
let key = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
match self.write(
CHANNEL_MONITOR_PERSISTENCE_NAMESPACE,
CHANNEL_MONITOR_PERSISTENCE_SUB_NAMESPACE,
&key, &monitor.encode())
{
Ok(()) => chain::ChannelMonitorUpdateStatus::Completed,
Err(_) => chain::ChannelMonitorUpdateStatus::UnrecoverableError
}
}
}
pub fn read_channel_monitors<K: Deref, ES: Deref, SP: Deref>(
kv_store: K, entropy_source: ES, signer_provider: SP,
) -> io::Result<Vec<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::Signer>)>>
where
K::Target: KVStore,
ES::Target: EntropySource + Sized,
SP::Target: SignerProvider + Sized,
{
let mut res = Vec::new();
for stored_key in kv_store.list(
CHANNEL_MONITOR_PERSISTENCE_NAMESPACE, CHANNEL_MONITOR_PERSISTENCE_SUB_NAMESPACE)?
{
if stored_key.len() < 66 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Stored key has invalid length"));
}
let txid = Txid::from_hex(stored_key.split_at(64).0).map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "Invalid tx ID in stored key")
})?;
let index: u16 = stored_key.split_at(65).1.parse().map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "Invalid tx index in stored key")
})?;
match <(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::Signer>)>::read(
&mut io::Cursor::new(
kv_store.read(CHANNEL_MONITOR_PERSISTENCE_NAMESPACE, CHANNEL_MONITOR_PERSISTENCE_SUB_NAMESPACE, &stored_key)?),
(&*entropy_source, &*signer_provider),
) {
Ok((block_hash, channel_monitor)) => {
if channel_monitor.get_funding_txo().0.txid != txid
|| channel_monitor.get_funding_txo().0.index != index
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"ChannelMonitor was stored under the wrong key",
));
}
res.push((block_hash, channel_monitor));
}
Err(_) => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Failed to deserialize ChannelMonitor"
))
}
}
}
Ok(res)
}