From: Matt Corallo Date: Tue, 21 Jan 2020 03:13:44 +0000 (-0500) Subject: Test that we don't forget to track any outputs at monitor-load X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=7728d3b6a86db7a12d591c8947fbe88a94fdffdd;p=rust-lightning Test that we don't forget to track any outputs at monitor-load 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. --- diff --git a/lightning/src/chain/chaininterface.rs b/lightning/src/chain/chaininterface.rs index 3a2e69cd1..4e444b28e 100644 --- a/lightning/src/chain/chaininterface.rs +++ b/lightning/src/chain/chaininterface.rs @@ -121,6 +121,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, @@ -302,6 +303,17 @@ pub struct ChainWatchInterfaceUtil { logger: Arc, } +// 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) { diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index acd3f313c..a1266379c 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -4,6 +4,7 @@ use chain::chaininterface; use chain::transaction::OutPoint; use chain::keysinterface::KeysInterface; +use ln::channelmonitor::{ChannelMonitor, ManyChannelMonitor}; use ln::channelmanager::{ChannelManager,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSendFailure}; use ln::router::{Route, Router}; use ln::features::InitFeatures; @@ -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; @@ -88,6 +90,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 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 new_watch = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&self.logger) as Arc)); + let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }); + let new_monitor = test_utils::TestChannelMonitor::new(new_watch.clone(), self.tx_broadcaster.clone(), self.logger.clone(), feeest); + let old_monitors = self.chan_monitor.simple_monitor.monitors.lock().unwrap(); + for (_, monitor) in old_monitors.iter() { + let mut w = test_utils::TestVecWriter(Vec::new()); + monitor.write_for_disk(&mut w).unwrap(); + let (_, new_mon) = <(Sha256d, ChannelMonitor)>::read( + &mut ::std::io::Cursor::new(&w.0), Arc::clone(&self.logger) as Arc).unwrap(); + if let Err(_) = new_monitor.add_update_monitor(new_mon.get_funding_txo().unwrap(), new_mon) { + panic!(); + } + } + + if *new_watch != *self.chain_monitor { + panic!(); + } } } }