Replace use of ChainWatchInterface with WatchEvent
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index 91f81fa573664d6d0ceb64380181ee2d4d5adc86..fd724c1cacb952a9b38f5b68c37d3ddf945e0077 100644 (file)
@@ -40,7 +40,8 @@ use ln::chan_utils;
 use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HolderCommitmentTransaction, HTLCType};
 use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
 use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
-use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface, FeeEstimator};
+use chain;
+use chain::chaininterface::{ChainListener, ChainWatchInterface, ChainWatchedUtil, BroadcasterInterface, FeeEstimator};
 use chain::transaction::OutPoint;
 use chain::keysinterface::{SpendableOutputDescriptor, ChannelKeys};
 use util::logger::Logger;
@@ -48,7 +49,7 @@ use util::ser::{Readable, MaybeReadable, Writer, Writeable, U48};
 use util::{byte_utils, events};
 use util::events::Event;
 
-use std::collections::{HashMap, hash_map};
+use std::collections::{HashMap, HashSet, hash_map};
 use std::sync::Mutex;
 use std::{hash,cmp, mem};
 use std::ops::Deref;
@@ -198,12 +199,74 @@ pub struct SimpleManyChannelMonitor<Key, ChanSigner: ChannelKeys, T: Deref, F: D
 {
        /// The monitors
        pub monitors: Mutex<HashMap<Key, ChannelMonitor<ChanSigner>>>,
+       watch_events: Mutex<WatchEventQueue>,
        chain_monitor: C,
        broadcaster: T,
        logger: L,
        fee_estimator: F
 }
 
+struct WatchEventQueue {
+       watched: ChainWatchedUtil,
+       events: Vec<chain::WatchEvent>,
+}
+
+impl WatchEventQueue {
+       fn new() -> Self {
+               Self {
+                       watched: ChainWatchedUtil::new(),
+                       events: Vec::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 {
+                               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 {
+                               outpoint: OutPoint {
+                                       txid: *txid,
+                                       index: index as u16,
+                               },
+                               script_pubkey: script_pubkey.clone(),
+                       });
+               }
+       }
+
+       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 filter_block<'a>(&self, txdata: &[(usize, &'a Transaction)]) -> Vec<(usize, &'a Transaction)> {
+               let mut matched_txids = HashSet::new();
+               txdata.iter().filter(|&&(_, tx)| {
+                       // A tx matches the filter if it either matches the filter directly (via does_match_tx)
+                       // or if it is a descendant of another matched transaction within the same block.
+                       let mut matched = self.watched.does_match_tx(tx);
+                       for input in tx.input.iter() {
+                               if matched || matched_txids.contains(&input.previous_output.txid) {
+                                       matched = true;
+                                       break;
+                               }
+                       }
+                       if matched {
+                               matched_txids.insert(tx.txid());
+                       }
+                       matched
+               }).map(|e| *e).collect()
+       }
+}
+
 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,
@@ -211,16 +274,17 @@ impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync
              L::Target: Logger,
         C::Target: ChainWatchInterface,
 {
-       fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[usize]) {
-               let block_hash = header.block_hash();
+       fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32) {
+               let mut watch_events = self.watch_events.lock().unwrap();
+               let matched_txn = watch_events.filter_block(txdata);
                {
                        let mut monitors = self.monitors.lock().unwrap();
                        for monitor in monitors.values_mut() {
-                               let txn_outputs = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
+                               let txn_outputs = monitor.block_connected(header, &matched_txn, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
 
                                for (ref txid, ref outputs) in txn_outputs {
                                        for (idx, output) in outputs.iter().enumerate() {
-                                               self.chain_monitor.install_watch_outpoint((txid.clone(), idx as u32), &output.script_pubkey);
+                                               watch_events.watch_output((txid, idx), &output.script_pubkey);
                                        }
                                }
                        }
@@ -228,10 +292,9 @@ impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync
        }
 
        fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
-               let block_hash = header.block_hash();
                let mut monitors = self.monitors.lock().unwrap();
                for monitor in monitors.values_mut() {
-                       monitor.block_disconnected(disconnected_height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
+                       monitor.block_disconnected(header, disconnected_height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
                }
        }
 }
@@ -247,6 +310,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
        pub fn new(chain_monitor: C, broadcaster: T, logger: L, feeest: F) -> SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C> {
                let res = SimpleManyChannelMonitor {
                        monitors: Mutex::new(HashMap::new()),
+                       watch_events: Mutex::new(WatchEventQueue::new()),
                        chain_monitor,
                        broadcaster,
                        logger,
@@ -258,6 +322,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
 
        /// 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> {
+               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")),
@@ -266,11 +331,11 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
                {
                        let funding_txo = monitor.get_funding_txo();
                        log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(funding_txo.0.to_channel_id()[..]));
-                       self.chain_monitor.install_watch_tx(&funding_txo.0.txid, &funding_txo.1);
-                       self.chain_monitor.install_watch_outpoint((funding_txo.0.txid, funding_txo.0.index as u32), &funding_txo.1);
+                       watch_events.watch_tx(&funding_txo.0.txid, &funding_txo.1);
+                       watch_events.watch_output((&funding_txo.0.txid, funding_txo.0.index as usize), &funding_txo.1);
                        for (txid, outputs) in monitor.get_outputs_to_watch().iter() {
                                for (idx, script) in outputs.iter().enumerate() {
-                                       self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
+                                       watch_events.watch_output((txid, idx), script);
                                }
                        }
                }
@@ -337,6 +402,17 @@ impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref, F: De
        }
 }
 
+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;
@@ -876,30 +952,14 @@ 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.
+       /// 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`.
        ///
-       /// 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.
+       /// 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
@@ -1885,12 +1945,12 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        /// 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, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
+       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,
        {
-               for tx in txn_matched {
+               for &(_, tx) in txn_matched {
                        let mut output_val = 0;
                        for out in tx.output.iter() {
                                if out.value > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); }
@@ -1899,10 +1959,12 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        }
                }
 
+               let block_hash = header.block_hash();
                log_trace!(logger, "Block {} at height {} connected with {} txn matched", block_hash, height, txn_matched.len());
+
                let mut watch_outputs = Vec::new();
                let mut claimable_outpoints = Vec::new();
-               for tx in txn_matched {
+               for &(_, tx) in txn_matched {
                        if tx.input.len() == 1 {
                                // Assuming our keys were not leaked (in which case we're screwed no matter what),
                                // commitment transactions and HTLC transactions will all only ever have one input,
@@ -1979,7 +2041,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
 
                self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator, &*logger);
 
-               self.last_block_hash = block_hash.clone();
+               self.last_block_hash = block_hash;
                for &(ref txid, ref output_scripts) in watch_outputs.iter() {
                        self.outputs_to_watch.insert(txid.clone(), output_scripts.iter().map(|o| o.script_pubkey.clone()).collect());
                }
@@ -1987,12 +2049,14 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                watch_outputs
        }
 
-       fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)
+       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,
        {
+               let block_hash = header.block_hash();
                log_trace!(logger, "Block {} at height {} disconnected", block_hash, height);
+
                if let Some(_) = self.onchain_events_waiting_threshold_conf.remove(&(height + ANTI_REORG_DELAY - 1)) {
                        //We may discard:
                        //- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
@@ -2001,7 +2065,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
 
                self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger);
 
-               self.last_block_hash = block_hash.clone();
+               self.last_block_hash = block_hash;
        }
 
        fn would_broadcast_at_height<L: Deref>(&self, height: u32, logger: &L) -> bool where L::Target: Logger {