//!
//! ChannelMonitor objects are generated by ChannelManager in response to relevant
//! messages/actions, and MUST be persisted to disk (and, preferably, remotely) before progress can
-//! be made in responding to certain messages, see ManyChannelMonitor for more.
+//! be made in responding to certain messages, see [`chain::Watch`] for more.
//!
//! Note that ChannelMonitors are an important part of the lightning trust model and a copy of the
//! latest ChannelMonitor must always be actively monitoring for chain updates (and no out-of-date
//! ChannelMonitors should do so). Thus, if you're building rust-lightning into an HSM or other
//! security-domain-separated system design, you should consider having multiple paths for
//! ChannelMonitors to get out of the HSM and onto monitoring devices.
+//!
+//! [`chain::Watch`]: ../../chain/trait.Watch.html
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::transaction::{TxOut,Transaction};
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
use chain;
-use chain::chaininterface::{ChainListener, ChainWatchInterface, ChainWatchedUtil, BroadcasterInterface, FeeEstimator};
+use chain::Filter;
+use chain::chaininterface::{ChainWatchedUtil, BroadcasterInterface, FeeEstimator};
use chain::transaction::OutPoint;
use chain::keysinterface::{SpendableOutputDescriptor, ChannelKeys};
use util::logger::Logger;
use std::collections::{HashMap, HashSet, hash_map};
use std::sync::Mutex;
-use std::{hash,cmp, mem};
+use std::{cmp, mem};
use std::ops::Deref;
use std::io::Error;
/// Note that even when you fail a holder commitment transaction update, you must store the
/// update to ensure you can claim from it in case of a duplicate copy of this ChannelMonitor
/// broadcasts it (e.g distributed channel-monitor deployment)
+ ///
+ /// In case of distributed watchtowers deployment, the new version must be written to disk, as
+ /// state may have been stored but rejected due to a block forcing a commitment broadcast. This
+ /// storage is used to claim outputs of rejected state confirmed onchain by another watchtower,
+ /// lagging behind on block processing.
PermanentFailure,
}
CommitmentTxBroadcasted(OutPoint),
}
-/// Simple structure send back by ManyChannelMonitor in case of HTLC detected onchain from a
-/// forward channel and from which info are needed to update HTLC in a backward channel.
+/// Simple structure sent back by `chain::Watch` when an HTLC from a forward channel is detected on
+/// chain. Used to update the corresponding HTLC in the backward channel. Failing to pass the
+/// preimage claim backward will lead to loss of funds.
+///
+/// [`chain::Watch`]: ../../chain/trait.Watch.html
#[derive(Clone, PartialEq)]
pub struct HTLCUpdate {
pub(super) payment_hash: PaymentHash,
}
impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
-/// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a
-/// watchtower or watch our own channels.
+/// An implementation of [`chain::Watch`] for monitoring channels.
///
-/// Note that you must provide your own key by which to refer to channels.
+/// Connected and disconnected blocks must be provided to `ChainMonitor` as documented by
+/// [`chain::Watch`]. May be used in conjunction with [`ChannelManager`] to monitor channels locally
+/// or used independently to monitor channels remotely.
///
-/// If you're accepting remote monitors (ie are implementing a watchtower), you must verify that
-/// users cannot overwrite a given channel by providing a duplicate key. ie you should probably
-/// index by a PublicKey which is required to sign any updates.
-///
-/// If you're using this for local monitoring of your own channels, you probably want to use
-/// `OutPoint` as the key, which will give you a ManyChannelMonitor implementation.
-///
-/// (C-not exported) due to an unconstrained generic in `Key`
-pub struct SimpleManyChannelMonitor<Key, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref>
- where T::Target: BroadcasterInterface,
+/// [`chain::Watch`]: ../../chain/trait.Watch.html
+/// [`ChannelManager`]: ../channelmanager/struct.ChannelManager.html
+pub struct ChainMonitor<ChanSigner: ChannelKeys, C: Deref, T: Deref, F: Deref, L: Deref>
+ where C::Target: chain::Filter,
+ T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
- C::Target: ChainWatchInterface,
{
/// The monitors
- pub monitors: Mutex<HashMap<Key, ChannelMonitor<ChanSigner>>>,
- watch_events: Mutex<WatchEventQueue>,
- chain_monitor: C,
+ pub monitors: Mutex<HashMap<OutPoint, ChannelMonitor<ChanSigner>>>,
+ watch_events: Mutex<WatchEventCache>,
+ chain_source: Option<C>,
broadcaster: T,
logger: L,
fee_estimator: F
}
-struct WatchEventQueue {
+struct WatchEventCache {
watched: ChainWatchedUtil,
- events: Vec<chain::WatchEvent>,
+ events: Vec<WatchEvent>,
+}
+
+/// An event indicating on-chain activity to watch for pertaining to a channel.
+enum WatchEvent {
+ /// Watch for a transaction with `txid` and having an output with `script_pubkey` as a spending
+ /// condition.
+ WatchTransaction {
+ /// Identifier of the transaction.
+ txid: Txid,
+
+ /// Spending condition for an output of the transaction.
+ script_pubkey: Script,
+ },
+ /// Watch for spends of a transaction output identified by `outpoint` having `script_pubkey` as
+ /// the spending condition.
+ WatchOutput {
+ /// Identifier for the output.
+ outpoint: OutPoint,
+
+ /// Spending condition for the output.
+ script_pubkey: Script,
+ }
}
-impl WatchEventQueue {
+impl WatchEventCache {
fn new() -> Self {
Self {
watched: ChainWatchedUtil::new(),
fn watch_tx(&mut self, txid: &Txid, script_pubkey: &Script) {
if self.watched.register_tx(txid, script_pubkey) {
- self.events.push(chain::WatchEvent::WatchTransaction {
+ self.events.push(WatchEvent::WatchTransaction {
txid: *txid,
script_pubkey: script_pubkey.clone()
});
fn watch_output(&mut self, outpoint: (&Txid, usize), script_pubkey: &Script) {
let (txid, index) = outpoint;
if self.watched.register_outpoint((*txid, index as u32), script_pubkey) {
- self.events.push(chain::WatchEvent::WatchOutput {
+ self.events.push(WatchEvent::WatchOutput {
outpoint: OutPoint {
txid: *txid,
index: index as u16,
}
}
- fn dequeue_events(&mut self) -> Vec<chain::WatchEvent> {
- let mut pending_events = Vec::with_capacity(self.events.len());
- pending_events.append(&mut self.events);
- pending_events
+ fn flush_events<C: Deref>(&mut self, chain_source: &Option<C>) -> bool where C::Target: chain::Filter {
+ let num_events = self.events.len();
+ match chain_source {
+ &None => self.events.clear(),
+ &Some(ref chain_source) => {
+ for event in self.events.drain(..) {
+ match event {
+ WatchEvent::WatchTransaction { txid, script_pubkey } => {
+ chain_source.register_tx(txid, script_pubkey)
+ },
+ WatchEvent::WatchOutput { outpoint, script_pubkey } => {
+ chain_source.register_output(outpoint, script_pubkey)
+ },
+ }
+ }
+ }
+ }
+ num_events > 0
}
fn filter_block<'a>(&self, txdata: &[(usize, &'a Transaction)]) -> Vec<(usize, &'a Transaction)> {
}
}
-impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send>
- ChainListener for SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
- where T::Target: BroadcasterInterface,
+impl<ChanSigner: ChannelKeys, C: Deref, T: Deref, F: Deref, L: Deref> ChainMonitor<ChanSigner, C, T, F, L>
+ where C::Target: chain::Filter,
+ T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
- C::Target: ChainWatchInterface,
{
- fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32) {
+ /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view
+ /// of a channel and reacting accordingly based on transactions in the connected block. See
+ /// [`ChannelMonitor::block_connected`] for details. Any HTLCs that were resolved on chain will
+ /// be returned by [`chain::Watch::release_pending_monitor_events`].
+ ///
+ /// Calls back to [`chain::Filter`] if any monitor indicated new outputs to watch, returning
+ /// `true` if so. Subsequent calls must not exclude any transactions matching the new outputs
+ /// nor any in-block descendants of such transactions. It is not necessary to re-fetch the block
+ /// to obtain updated `txdata`.
+ ///
+ /// [`ChannelMonitor::block_connected`]: struct.ChannelMonitor.html#method.block_connected
+ /// [`chain::Watch::release_pending_monitor_events`]: ../../chain/trait.Watch.html#tymethod.release_pending_monitor_events
+ /// [`chain::Filter`]: ../../chain/trait.Filter.html
+ pub fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32) -> bool {
let mut watch_events = self.watch_events.lock().unwrap();
let matched_txn = watch_events.filter_block(txdata);
{
}
}
}
+ watch_events.flush_events(&self.chain_source)
}
- fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
+ /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view
+ /// of a channel based on the disconnected block. See [`ChannelMonitor::block_disconnected`] for
+ /// details.
+ ///
+ /// [`ChannelMonitor::block_disconnected`]: struct.ChannelMonitor.html#method.block_disconnected
+ pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
monitor.block_disconnected(header, disconnected_height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
}
}
-impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref> SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
- where T::Target: BroadcasterInterface,
+impl<ChanSigner: ChannelKeys, C: Deref, T: Deref, F: Deref, L: Deref> ChainMonitor<ChanSigner, C, T, F, L>
+ where C::Target: chain::Filter,
+ T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
- C::Target: ChainWatchInterface,
{
- /// Creates a new object which can be used to monitor several channels given the chain
- /// interface with which to register to receive notifications.
- pub fn new(chain_monitor: C, broadcaster: T, logger: L, feeest: F) -> SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C> {
- let res = SimpleManyChannelMonitor {
+ /// Creates a new `ChainMonitor` used to watch on-chain activity pertaining to channels.
+ ///
+ /// When an optional chain source implementing [`chain::Filter`] is provided, the chain monitor
+ /// will call back to it indicating transactions and outputs of interest. This allows clients to
+ /// pre-filter blocks or only fetch blocks matching a compact filter. Otherwise, clients may
+ /// always need to fetch full blocks absent another means for determining which blocks contain
+ /// transactions relevant to the watched channels.
+ ///
+ /// [`chain::Filter`]: ../../chain/trait.Filter.html
+ pub fn new(chain_source: Option<C>, broadcaster: T, logger: L, feeest: F) -> Self {
+ Self {
monitors: Mutex::new(HashMap::new()),
- watch_events: Mutex::new(WatchEventQueue::new()),
- chain_monitor,
+ watch_events: Mutex::new(WatchEventCache::new()),
+ chain_source,
broadcaster,
logger,
fee_estimator: feeest,
- };
-
- res
+ }
}
- /// Adds or updates the monitor which monitors the channel referred to by the given key.
- pub fn add_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
+ /// Adds the monitor that watches the channel referred to by the given outpoint.
+ ///
+ /// Calls back to [`chain::Filter`] with the funding transaction and outputs to watch.
+ ///
+ /// [`chain::Filter`]: ../../chain/trait.Filter.html
+ fn add_monitor(&self, outpoint: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
let mut watch_events = self.watch_events.lock().unwrap();
let mut monitors = self.monitors.lock().unwrap();
- let entry = match monitors.entry(key) {
- hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
+ let entry = match monitors.entry(outpoint) {
+ hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given outpoint is already present")),
hash_map::Entry::Vacant(e) => e,
};
{
}
}
entry.insert(monitor);
+ watch_events.flush_events(&self.chain_source);
Ok(())
}
- /// Updates the monitor which monitors the channel referred to by the given key.
- pub fn update_monitor_by_key(&self, key: Key, update: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
+ /// Updates the monitor that watches the channel referred to by the given outpoint.
+ fn update_monitor(&self, outpoint: OutPoint, update: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
let mut monitors = self.monitors.lock().unwrap();
- match monitors.get_mut(&key) {
+ match monitors.get_mut(&outpoint) {
Some(orig_monitor) => {
log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor));
orig_monitor.update_monitor(update, &self.broadcaster, &self.logger)
}
}
-impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send> ManyChannelMonitor for SimpleManyChannelMonitor<OutPoint, ChanSigner, T, F, L, C>
- where T::Target: BroadcasterInterface,
+impl<ChanSigner: ChannelKeys, C: Deref + Sync + Send, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send> chain::Watch for ChainMonitor<ChanSigner, C, T, F, L>
+ where C::Target: chain::Filter,
+ T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
- C::Target: ChainWatchInterface,
{
type Keys = ChanSigner;
- fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
- match self.add_monitor_by_key(funding_txo, monitor) {
+ fn watch_channel(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
+ match self.add_monitor(funding_txo, monitor) {
Ok(_) => Ok(()),
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
}
}
- fn update_monitor(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr> {
- match self.update_monitor_by_key(funding_txo, update) {
+ fn update_channel(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr> {
+ match self.update_monitor(funding_txo, update) {
Ok(_) => Ok(()),
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
}
}
- fn get_and_clear_pending_monitor_events(&self) -> Vec<MonitorEvent> {
+ fn release_pending_monitor_events(&self) -> Vec<MonitorEvent> {
let mut pending_monitor_events = Vec::new();
for chan in self.monitors.lock().unwrap().values_mut() {
pending_monitor_events.append(&mut chan.get_and_clear_pending_monitor_events());
}
}
-impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref> events::EventsProvider for SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
- where T::Target: BroadcasterInterface,
+impl<ChanSigner: ChannelKeys, C: Deref, T: Deref, F: Deref, L: Deref> events::EventsProvider for ChainMonitor<ChanSigner, C, T, F, L>
+ where C::Target: chain::Filter,
+ T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
- C::Target: ChainWatchInterface,
{
fn get_and_clear_pending_events(&self) -> Vec<Event> {
let mut pending_events = Vec::new();
}
}
-impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref> chain::WatchEventProvider for SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
- where T::Target: BroadcasterInterface,
- F::Target: FeeEstimator,
- L::Target: Logger,
- C::Target: ChainWatchInterface,
-{
- fn release_pending_watch_events(&self) -> Vec<chain::WatchEvent> {
- self.watch_events.lock().unwrap().dequeue_events()
- }
-}
-
/// If an HTLC expires within this many blocks, don't try to claim it in a shared transaction,
/// instead claiming it in its own individual transaction.
pub(crate) const CLTV_SHARED_CLAIM_BUFFER: u32 = 12;
secp_ctx: Secp256k1<secp256k1::All>, //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`.
- ///
- /// Implementations must ensure that `monitor` receives block_connected calls for blocks with
- /// the funding transaction or any spends of it, as well as any spends of outputs returned by
- /// get_outputs_to_watch. Not doing so may result in LOST FUNDS.
- fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<Self::Keys>) -> Result<(), ChannelMonitorUpdateErr>;
-
- /// Updates a monitor for the given `funding_txo`.
- ///
- /// TODO(jkczyz): Determine where this should go from e73036c6845fd3cc16479a1b497db82a5ebb3897.
- ///
- /// In case of distributed watchtowers deployment, even if an Err is return, the new version
- /// must be written to disk, as state may have been stored but rejected due to a block forcing
- /// a commitment broadcast. This storage is used to claim outputs of rejected state confirmed
- /// onchain by another watchtower, lagging behind on block processing.
- 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_monitor_events() for each ChannelMonitor and return
- /// the full list.
- fn get_and_clear_pending_monitor_events(&self) -> Vec<MonitorEvent>;
-}
-
#[cfg(any(test, feature = "fuzztarget"))]
/// Used only in testing and fuzztarget to check serialization roundtrips don't change the
/// underlying object
}
/// Get the list of HTLCs who's status has been updated on chain. This should be called by
- /// ChannelManager via ManyChannelMonitor::get_and_clear_pending_monitor_events().
+ /// ChannelManager via [`chain::Watch::release_pending_monitor_events`].
+ ///
+ /// [`chain::Watch::release_pending_monitor_events`]: ../../chain/trait.Watch.html#tymethod.release_pending_monitor_events
pub fn get_and_clear_pending_monitor_events(&mut self) -> Vec<MonitorEvent> {
let mut ret = Vec::new();
mem::swap(&mut ret, &mut self.pending_monitor_events);
/// Gets the list of pending events which were generated by previous actions, clearing the list
/// in the process.
///
- /// This is called by ManyChannelMonitor::get_and_clear_pending_events() and is equivalent to
+ /// This is called by ChainMonitor::get_and_clear_pending_events() and is equivalent to
/// EventsProvider::get_and_clear_pending_events() except that it requires &mut self as we do
/// no internal locking in ChannelMonitors.
pub fn get_and_clear_pending_events(&mut self) -> Vec<Event> {
Vec::new()
}
- /// Called by SimpleManyChannelMonitor::block_connected, which implements
- /// ChainListener::block_connected.
- /// Eventually this should be pub and, roughly, implement ChainListener, however this requires
- /// &mut self, as well as returns new spendable outputs and outpoints to watch for spending of
- /// on-chain.
- fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, header: &BlockHeader, txn_matched: &[(usize, &Transaction)], height: u32, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
+ /// Processes transactions in a newly connected block, which may result in any of the following:
+ /// - update the monitor's state against resolved HTLCs
+ /// - punish the counterparty in the case of seeing a revoked commitment transaction
+ /// - force close the channel and claim/timeout incoming/outgoing HTLCs if near expiration
+ /// - detect settled outputs for later spending
+ /// - schedule and bump any in-flight claims
+ ///
+ /// Returns any transaction outputs from `txn_matched` that spends of should be watched for.
+ /// After called these are also available via [`get_outputs_to_watch`].
+ ///
+ /// [`get_outputs_to_watch`]: #method.get_outputs_to_watch
+ pub fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, header: &BlockHeader, txn_matched: &[(usize, &Transaction)], height: u32, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
watch_outputs
}
- fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, header: &BlockHeader, height: u32, broadcaster: B, fee_estimator: F, logger: L)
+ /// Determines if the disconnected block contained any transactions of interest and updates
+ /// appropriately.
+ pub fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, header: &BlockHeader, height: u32, broadcaster: B, fee_estimator: F, logger: L)
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,