Test that we don't forget to track any outputs at monitor-load
authorMatt Corallo <git@bluematt.me>
Tue, 21 Jan 2020 03:13:44 +0000 (22:13 -0500)
committerMatt Corallo <git@bluematt.me>
Tue, 18 Feb 2020 23:20:33 +0000 (18:20 -0500)
This tests, after each functional test, that if we serialize and
reload all of our ChannelMonitors we end up tracking the same set
of outputs as before.

lightning/src/chain/chaininterface.rs
lightning/src/ln/functional_test_utils.rs

index 0845eb5fc6965392cf6340a5a682bffe70ebe7db..7a077e895a615fce737c4aa4db1cd13c0667e092 100644 (file)
@@ -126,6 +126,7 @@ pub trait FeeEstimator: Sync + Send {
 pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
 
 /// Utility for tracking registered txn/outpoints and checking for matches
+#[cfg_attr(test, derive(PartialEq))]
 pub struct ChainWatchedUtil {
        watch_all: bool,
 
@@ -305,6 +306,17 @@ pub struct ChainWatchInterfaceUtil {
        logger: Arc<Logger>,
 }
 
+// We only expose PartialEq in test since its somewhat unclear exactly what it should do and we're
+// only comparing a subset of fields (essentially just checking that the set of things we're
+// watching is the same).
+#[cfg(test)]
+impl PartialEq for ChainWatchInterfaceUtil {
+       fn eq(&self, o: &Self) -> bool {
+               self.network == o.network &&
+               *self.watched.lock().unwrap() == *o.watched.lock().unwrap()
+       }
+}
+
 /// Register listener
 impl ChainWatchInterface for ChainWatchInterfaceUtil {
        fn install_watch_tx(&self, txid: &Sha256dHash, script_pub_key: &Script) {
index 1ae8ca1e0058cbb59a006017fc30f9aa4bb75849..674e7d0ff322df1b17f7db5926601789c4ddbe50 100644 (file)
@@ -5,6 +5,7 @@ use chain::chaininterface;
 use chain::transaction::OutPoint;
 use chain::keysinterface::KeysInterface;
 use ln::channelmanager::{ChannelManager,RAACommitmentOrder, PaymentPreimage, PaymentHash};
+use ln::channelmonitor::{ChannelMonitor, ManyChannelMonitor};
 use ln::router::{Route, Router};
 use ln::features::InitFeatures;
 use ln::msgs;
@@ -16,6 +17,7 @@ use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsPro
 use util::errors::APIError;
 use util::logger::Logger;
 use util::config::UserConfig;
+use util::ser::ReadableArgs;
 
 use bitcoin::util::hash::BitcoinHash;
 use bitcoin::blockdata::block::BlockHeader;
@@ -89,6 +91,27 @@ impl<'a, 'b> Drop for Node<'a, 'b> {
                        assert!(self.node.get_and_clear_pending_msg_events().is_empty());
                        assert!(self.node.get_and_clear_pending_events().is_empty());
                        assert!(self.chan_monitor.added_monitors.lock().unwrap().is_empty());
+
+                       // Check that if we serialize and then deserialize all our channel monitors we get the
+                       // same set of outputs to watch for on chain as we have now. Note that if we write
+                       // tests that fully close channels and remove the monitors at some point this may break.
+                       let chain_watch = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&self.logger) as Arc<Logger>));
+                       let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 });
+                       let channel_monitor = test_utils::TestChannelMonitor::new(chain_watch.clone(), self.tx_broadcaster.clone(), self.logger.clone(), feeest);
+                       let old_monitors = self.chan_monitor.simple_monitor.monitors.lock().unwrap();
+                       for (_, old_monitor) in old_monitors.iter() {
+                               let mut w = test_utils::TestVecWriter(Vec::new());
+                               old_monitor.write_for_disk(&mut w).unwrap();
+                               let (_, deserialized_monitor) = <(Sha256d, ChannelMonitor<EnforcingChannelKeys>)>::read(
+                                       &mut ::std::io::Cursor::new(&w.0), Arc::clone(&self.logger) as Arc<Logger>).unwrap();
+                               if let Err(_) = channel_monitor.add_update_monitor(deserialized_monitor.get_funding_txo().unwrap(), deserialized_monitor) {
+                                       panic!();
+                               }
+                       }
+
+                       if *chain_watch != *self.chain_monitor {
+                               panic!();
+                       }
                }
        }
 }