//! This module contains a simple key-value store trait [`KVStore`] that
//! allows one to implement the persistence for [`ChannelManager`], [`NetworkGraph`],
//! and [`ChannelMonitor`] all in one place.
+//!
+//! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
use core::cmp;
use core::convert::{TryFrom, TryInto};
use crate::chain;
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use crate::chain::chainmonitor::{Persist, MonitorUpdateId};
-use crate::sign::{EntropySource, NodeSigner, ecdsa::WriteableEcdsaChannelSigner, SignerProvider};
+use crate::sign::{EntropySource, ecdsa::WriteableEcdsaChannelSigner, SignerProvider};
use crate::chain::transaction::OutPoint;
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, CLOSED_CHANNEL_UPDATE_ID};
-use crate::ln::channelmanager::ChannelManager;
-use crate::routing::router::Router;
+use crate::ln::channelmanager::AChannelManager;
use crate::routing::gossip::NetworkGraph;
use crate::routing::scoring::WriteableScore;
use crate::util::logger::Logger;
pub const KVSTORE_NAMESPACE_KEY_MAX_LEN: usize = 120;
/// The primary namespace under which the [`ChannelManager`] will be persisted.
+///
+/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
pub const CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE: &str = "";
/// The secondary namespace under which the [`ChannelManager`] will be persisted.
+///
+/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
pub const CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE: &str = "";
/// The key under which the [`ChannelManager`] will be persisted.
+///
+/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
pub const CHANNEL_MANAGER_PERSISTENCE_KEY: &str = "manager";
/// The primary namespace under which [`ChannelMonitor`]s will be persisted.
}
/// Trait that handles persisting a [`ChannelManager`], [`NetworkGraph`], and [`WriteableScore`] to disk.
-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>::EcdsaSigner>,
- 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,
+///
+/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+pub trait Persister<'a, CM: Deref, L: Deref, S: WriteableScore<'a>>
+where
+ CM::Target: 'static + AChannelManager,
+ L::Target: 'static + Logger,
{
/// Persist the given ['ChannelManager'] to disk, returning an error if persistence failed.
- fn persist_manager(&self, channel_manager: &ChannelManager<M, T, ES, NS, SP, F, R, L>) -> Result<(), io::Error>;
+ ///
+ /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+ fn persist_manager(&self, channel_manager: &CM) -> Result<(), io::Error>;
/// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed.
fn persist_graph(&self, network_graph: &NetworkGraph<L>) -> 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>::EcdsaSigner>,
- 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,
+impl<'a, A: KVStore, CM: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, CM, L, S> for A
+where
+ CM::Target: 'static + AChannelManager,
+ L::Target: 'static + Logger,
{
- /// Persist the given [`ChannelManager`] to disk, returning an error if persistence failed.
- fn persist_manager(&self, channel_manager: &ChannelManager<M, T, ES, NS, SP, F, R, L>) -> Result<(), io::Error> {
+ fn persist_manager(&self, channel_manager: &CM) -> Result<(), io::Error> {
self.write(CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE,
CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE,
CHANNEL_MANAGER_PERSISTENCE_KEY,
- &channel_manager.encode())
+ &channel_manager.get_cm().encode())
+ }
+
+ fn persist_graph(&self, network_graph: &NetworkGraph<L>) -> Result<(), io::Error> {
+ self.write(NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE,
+ NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE,
+ NETWORK_GRAPH_PERSISTENCE_KEY,
+ &network_graph.encode())
+ }
+
+ fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error> {
+ self.write(SCORER_PERSISTENCE_PRIMARY_NAMESPACE,
+ SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
+ SCORER_PERSISTENCE_KEY,
+ &scorer.encode())
+ }
+}
+
+impl<'a, CM: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, CM, L, S> for dyn KVStore + Send + Sync
+where
+ CM::Target: 'static + AChannelManager,
+ L::Target: 'static + Logger,
+{
+ fn persist_manager(&self, channel_manager: &CM) -> Result<(), io::Error> {
+ self.write(CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE,
+ CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE,
+ CHANNEL_MANAGER_PERSISTENCE_KEY,
+ &channel_manager.get_cm().encode())
}
- /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed.
fn persist_graph(&self, network_graph: &NetworkGraph<L>) -> Result<(), io::Error> {
self.write(NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE,
NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE,
&network_graph.encode())
}
- /// Persist the given [`WriteableScore`] to disk, returning an error if persistence failed.
fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error> {
self.write(SCORER_PERSISTENCE_PRIMARY_NAMESPACE,
SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
}
}
+impl<ChannelSigner: WriteableEcdsaChannelSigner> Persist<ChannelSigner> for dyn KVStore + Send + Sync {
+ // TODO: We really need a way for the persister to inform the user that its time to crash/shut
+ // down once these start returning failure.
+ // Then we should return InProgress rather than UnrecoverableError, implying we should probably
+ // just shut down the node since we're not retrying persistence!
+
+ fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus {
+ let key = format!("{}_{}", funding_txo.txid.to_string(), funding_txo.index);
+ match self.write(
+ CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
+ CHANNEL_MONITOR_PERSISTENCE_SECONDARY_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_string(), funding_txo.index);
+ match self.write(
+ CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
+ CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
+ &key, &monitor.encode())
+ {
+ Ok(()) => chain::ChannelMonitorUpdateStatus::Completed,
+ Err(_) => chain::ChannelMonitorUpdateStatus::UnrecoverableError
+ }
+ }
+}
+
/// Read previously persisted [`ChannelMonitor`]s from the store.
pub fn read_channel_monitors<K: Deref, ES: Deref, SP: Deref>(
kv_store: K, entropy_source: ES, signer_provider: SP,
{
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap();
- let update_id = update_map.get(&added_monitors[0].0.to_channel_id()).unwrap();
+ let update_id = update_map.get(&added_monitors[0].1.channel_id()).unwrap();
let cmu_map = nodes[1].chain_monitor.monitor_updates.lock().unwrap();
- let cmu = &cmu_map.get(&added_monitors[0].0.to_channel_id()).unwrap()[0];
+ let cmu = &cmu_map.get(&added_monitors[0].1.channel_id()).unwrap()[0];
let test_txo = OutPoint { txid: Txid::from_str("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), index: 0 };
let ro_persister = MonitorUpdatingPersister {