Align ChannelMonitor interface with ChainListener
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index 0b8f8c07862eeb8514bbea78e254059fc1b73a72..33cc869efe8aeed5168acec5aaf56d6f5ddee8d5 100644 (file)
@@ -183,27 +183,32 @@ 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: &[u32]) {
-               let block_hash = header.bitcoin_hash();
-               {
-                       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);
-
-                               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);
+       fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32) {
+               let mut reentered = true;
+               while reentered {
+                       let matched_indexes = self.chain_monitor.filter_block(header, txdata);
+                       let matched_txn: Vec<_> = matched_indexes.iter().map(|index| txdata[*index]).collect();
+                       let last_seen = self.chain_monitor.reentered();
+                       {
+                               let mut monitors = self.monitors.lock().unwrap();
+                               for monitor in monitors.values_mut() {
+                                       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);
+                                               }
                                        }
                                }
                        }
+                       reentered = last_seen != self.chain_monitor.reentered();
                }
        }
 
        fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
-               let block_hash = header.bitcoin_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);
                }
        }
 }
@@ -235,12 +240,15 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
                        hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
                        hash_map::Entry::Vacant(e) => e,
                };
-               log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(monitor.funding_info.0.to_channel_id()[..]));
-               self.chain_monitor.install_watch_tx(&monitor.funding_info.0.txid, &monitor.funding_info.1);
-               self.chain_monitor.install_watch_outpoint((monitor.funding_info.0.txid, monitor.funding_info.0.index as u32), &monitor.funding_info.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);
+               {
+                       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);
+                       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);
+                               }
                        }
                }
                entry.insert(monitor);
@@ -1408,8 +1416,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        }
 
        /// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
-       pub fn get_funding_txo(&self) -> OutPoint {
-               self.funding_info.0
+       pub fn get_funding_txo(&self) -> &(OutPoint, Script) {
+               &self.funding_info
        }
 
        /// Gets a list of txids, with their output scripts (in the order they appear in the
@@ -1867,12 +1875,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"); }
@@ -1881,10 +1889,12 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        }
                }
 
+               let block_hash = header.bitcoin_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,
@@ -1958,7 +1968,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());
                }
@@ -1966,12 +1976,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.bitcoin_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
@@ -1980,7 +1992,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;
        }
 
        pub(super) fn would_broadcast_at_height<L: Deref>(&self, height: u32, logger: &L) -> bool where L::Target: Logger {
@@ -2544,7 +2556,6 @@ mod tests {
        use util::test_utils::TestLogger;
        use bitcoin::secp256k1::key::{SecretKey,PublicKey};
        use bitcoin::secp256k1::Secp256k1;
-       use rand::{thread_rng,Rng};
        use std::sync::Arc;
        use chain::keysinterface::InMemoryChannelKeys;
 
@@ -2558,10 +2569,8 @@ mod tests {
 
                let mut preimages = Vec::new();
                {
-                       let mut rng  = thread_rng();
-                       for _ in 0..20 {
-                               let mut preimage = PaymentPreimage([0; 32]);
-                               rng.fill_bytes(&mut preimage.0[..]);
+                       for i in 0..20 {
+                               let preimage = PaymentPreimage([i; 32]);
                                let hash = PaymentHash(Sha256::hash(&preimage.0[..]).into_inner());
                                preimages.push((preimage, hash));
                        }