From 6afda60d8898455a003e7e085e0b6f1c1277d8fa Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 12 May 2020 13:20:31 -0400 Subject: [PATCH] Make ManyChannelMonitor Keys an associated type Instead of using a raw generic type, an associted type allows us to have explicit docs on the type, which is nice. More importantly, however, our automated bindings generator knows how to read associated types but not raw generics. Also, our bindings generator expects things which are referenced to have already been defined, so we move ManyChannelMonitor below the ChannelMonitor definition. --- fuzz/src/chanmon_consistency.rs | 4 +- lightning/src/ln/channelmanager.rs | 20 ++--- lightning/src/ln/channelmonitor.rs | 128 +++++++++++++++-------------- lightning/src/util/test_utils.rs | 4 +- 4 files changed, 83 insertions(+), 73 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index e0fa7d3ed..9dea831e0 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -96,7 +96,9 @@ impl TestChannelMonitor { } } } -impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { +impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { + type Keys = EnforcingChannelKeys; + fn add_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { let mut ser = VecWriter(Vec::new()); monitor.write_for_disk(&mut ser).unwrap(); diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 709ddde2e..d1004bcef 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -370,7 +370,7 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L> = ChannelManage /// SimpleArcChannelManager when you require a ChannelManager with a static lifetime, such as when /// you're using lightning-net-tokio. pub struct ChannelManager - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -683,7 +683,7 @@ macro_rules! maybe_break_monitor_err { } impl ChannelManager - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -2889,7 +2889,7 @@ impl } impl events::MessageSendEventsProvider for ChannelManager - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -2920,7 +2920,7 @@ impl } impl events::EventsProvider for ChannelManager - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -2952,7 +2952,7 @@ impl impl ChainListener for ChannelManager - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -3120,7 +3120,7 @@ impl ChannelMessageHandler for ChannelManager - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -3559,7 +3559,7 @@ impl Readable for HTLCForwardInfo { } impl Writeable for ChannelManager - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -3643,7 +3643,7 @@ impl - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -3693,7 +3693,7 @@ pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T: // SipmleArcChannelManager type: impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ReadableArgs> for (BlockHash, Arc>) - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, @@ -3707,7 +3707,7 @@ impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: De impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ReadableArgs> for (BlockHash, ChannelManager) - where M::Target: ManyChannelMonitor, + where M::Target: ManyChannelMonitor, T::Target: BroadcasterInterface, K::Target: KeysInterface, F::Target: FeeEstimator, diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index ff0b6e9eb..b05425831 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -149,66 +149,6 @@ pub struct HTLCUpdate { } impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source }); -/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between -/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing -/// events to it, while also taking any add/update_monitor events and passing them to some remote -/// server(s). -/// -/// In general, you must always have at least one local copy in memory, which must never fail to -/// update (as it is responsible for broadcasting the latest state in case the channel is closed), -/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails -/// to update (eg out-of-memory or some other condition), you must immediately shut down without -/// taking any further action such as writing the current state to disk. This should likely be -/// accomplished via panic!() or abort(). -/// -/// Note that any updates to a channel's monitor *must* be applied to each instance of the -/// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If -/// an update occurs and a remote watchtower is left with old state, it may broadcast transactions -/// which we have revoked, allowing our counterparty to claim all funds in the channel! -/// -/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or -/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather -/// than calling these methods directly, the user should register implementors as listeners to the -/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify -/// all registered listeners in one go. -pub trait ManyChannelMonitor: Send + Sync { - /// Adds a monitor for the given `funding_txo`. - /// - /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with - /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected - /// callbacks with the funding transaction, or any spends of it. - /// - /// Further, the implementer must also ensure that each output returned in - /// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about - /// any spends of any of the outputs. - /// - /// Any spends of outputs which should have been registered which aren't passed to - /// ChannelMonitors via block_connected may result in FUNDS LOSS. - fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; - - /// Updates a monitor for the given `funding_txo`. - /// - /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with - /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected - /// callbacks with the funding transaction, or any spends of it. - /// - /// Further, the implementer must also ensure that each output returned in - /// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about - /// any spends of any of the outputs. - /// - /// Any spends of outputs which should have been registered which aren't passed to - /// ChannelMonitors via block_connected may result in FUNDS LOSS. - fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>; - - /// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated - /// with success or failure. - /// - /// You should probably just call through to - /// ChannelMonitor::get_and_clear_pending_htlcs_updated() for each ChannelMonitor and return - /// the full list. - fn get_and_clear_pending_htlcs_updated(&self) -> Vec; -} - /// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a /// watchtower or watch our own channels. /// @@ -320,12 +260,14 @@ impl ManyChannelMonitor for SimpleManyChannelMonitor +impl ManyChannelMonitor for SimpleManyChannelMonitor where T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, C::Target: ChainWatchInterface, { + type Keys = ChanSigner; + fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { match self.add_monitor_by_key(funding_txo, monitor) { Ok(_) => Ok(()), @@ -803,6 +745,70 @@ pub struct ChannelMonitor { secp_ctx: Secp256k1, //TODO: dedup this a bit... } +/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between +/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing +/// events to it, while also taking any add/update_monitor events and passing them to some remote +/// server(s). +/// +/// In general, you must always have at least one local copy in memory, which must never fail to +/// update (as it is responsible for broadcasting the latest state in case the channel is closed), +/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails +/// to update (eg out-of-memory or some other condition), you must immediately shut down without +/// taking any further action such as writing the current state to disk. This should likely be +/// accomplished via panic!() or abort(). +/// +/// Note that any updates to a channel's monitor *must* be applied to each instance of the +/// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If +/// an update occurs and a remote watchtower is left with old state, it may broadcast transactions +/// which we have revoked, allowing our counterparty to claim all funds in the channel! +/// +/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or +/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather +/// than calling these methods directly, the user should register implementors as listeners to the +/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify +/// all registered listeners in one go. +pub trait ManyChannelMonitor: Send + Sync { + /// The concrete type which signs for transactions and provides access to our channel public + /// keys. + type Keys: ChannelKeys; + + /// Adds a monitor for the given `funding_txo`. + /// + /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with + /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected + /// callbacks with the funding transaction, or any spends of it. + /// + /// Further, the implementer must also ensure that each output returned in + /// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about + /// any spends of any of the outputs. + /// + /// Any spends of outputs which should have been registered which aren't passed to + /// ChannelMonitors via block_connected may result in FUNDS LOSS. + fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; + + /// Updates a monitor for the given `funding_txo`. + /// + /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with + /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected + /// callbacks with the funding transaction, or any spends of it. + /// + /// Further, the implementer must also ensure that each output returned in + /// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about + /// any spends of any of the outputs. + /// + /// Any spends of outputs which should have been registered which aren't passed to + /// ChannelMonitors via block_connected may result in FUNDS LOSS. + fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>; + + /// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated + /// with success or failure. + /// + /// You should probably just call through to + /// ChannelMonitor::get_and_clear_pending_htlcs_updated() for each ChannelMonitor and return + /// the full list. + fn get_and_clear_pending_htlcs_updated(&self) -> Vec; +} + #[cfg(any(test, feature = "fuzztarget"))] /// Used only in testing and fuzztarget to check serialization roundtrips don't change the /// underlying object diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 0dddd4996..b7b6f0422 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -66,7 +66,9 @@ impl<'a> TestChannelMonitor<'a> { } } } -impl<'a> channelmonitor::ManyChannelMonitor for TestChannelMonitor<'a> { +impl<'a> channelmonitor::ManyChannelMonitor for TestChannelMonitor<'a> { + type Keys = EnforcingChannelKeys; + fn add_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { // At every point where we get a monitor update, we should be able to send a useful monitor // to a watchtower and disk... -- 2.39.5