Merge pull request #2964 from jbesraa/prune-stale-chanmonitor
[rust-lightning] / lightning / src / util / test_utils.rs
index d77575d90b26dd709e71c3fc931a5d08f35b0338..95bc2a7c661982ea9062497f1647af434111dcd6 100644 (file)
@@ -13,6 +13,7 @@ use crate::chain;
 use crate::chain::WatchedOutput;
 use crate::chain::chaininterface;
 use crate::chain::chaininterface::ConfirmationTarget;
+#[cfg(test)]
 use crate::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW;
 use crate::chain::chainmonitor;
 use crate::chain::chainmonitor::{MonitorUpdateId, UpdateOrigin};
@@ -25,6 +26,7 @@ use crate::events;
 use crate::events::bump_transaction::{WalletSource, Utxo};
 use crate::ln::ChannelId;
 use crate::ln::channelmanager::{ChannelDetails, self};
+#[cfg(test)]
 use crate::ln::chan_utils::CommitmentTransaction;
 use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use crate::ln::{msgs, wire};
@@ -59,9 +61,6 @@ use bitcoin::secp256k1::ecdh::SharedSecret;
 use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
 use bitcoin::secp256k1::schnorr;
 
-#[cfg(any(test, feature = "_test_utils"))]
-use regex;
-
 use crate::io;
 use crate::prelude::*;
 use core::cell::RefCell;
@@ -143,7 +142,9 @@ impl<'a> Router for TestRouter<'a> {
                &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>,
                inflight_htlcs: InFlightHtlcs
        ) -> Result<Route, msgs::LightningError> {
-               if let Some((find_route_query, find_route_res)) = self.next_routes.lock().unwrap().pop_front() {
+               let route_res;
+               let next_route_opt = self.next_routes.lock().unwrap().pop_front();
+               if let Some((find_route_query, find_route_res)) = next_route_opt {
                        assert_eq!(find_route_query, *params);
                        if let Ok(ref route) = find_route_res {
                                assert_eq!(route.route_params, Some(find_route_query));
@@ -201,10 +202,18 @@ impl<'a> Router for TestRouter<'a> {
                                        }
                                }
                        }
-                       return find_route_res;
-               }
+                       route_res = find_route_res;
+               } else {
+                       route_res = self.router.find_route(payer, params, first_hops, inflight_htlcs);
+               };
 
-               self.router.find_route(payer, params, first_hops, inflight_htlcs)
+               if let Ok(route) = &route_res {
+                       // Previously, `Route`s failed to round-trip through serialization due to a write/read
+                       // mismatch. Thus, here we test all test-generated routes round-trip:
+                       let ser = route.encode();
+                       assert_eq!(Route::read(&mut &ser[..]).unwrap(), *route);
+               }
+               route_res
        }
 
        fn create_blinded_payment_paths<
@@ -317,8 +326,8 @@ impl<'a> TestChainMonitor<'a> {
        pub fn new(chain_source: Option<&'a TestChainSource>, broadcaster: &'a dyn chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator, persister: &'a dyn chainmonitor::Persist<TestChannelSigner>, keys_manager: &'a TestKeysInterface) -> Self {
                Self {
                        added_monitors: Mutex::new(Vec::new()),
-                       monitor_updates: Mutex::new(HashMap::new()),
-                       latest_monitor_update_id: Mutex::new(HashMap::new()),
+                       monitor_updates: Mutex::new(new_hash_map()),
+                       latest_monitor_update_id: Mutex::new(new_hash_map()),
                        chain_monitor: chainmonitor::ChainMonitor::new(chain_source, broadcaster, logger, fee_estimator, persister),
                        keys_manager,
                        expect_channel_force_closed: Mutex::new(None),
@@ -389,12 +398,14 @@ impl<'a> chain::Watch<TestChannelSigner> for TestChainMonitor<'a> {
        }
 }
 
+#[cfg(test)]
 struct JusticeTxData {
        justice_tx: Transaction,
        value: u64,
        commitment_number: u64,
 }
 
+#[cfg(test)]
 pub(crate) struct WatchtowerPersister {
        persister: TestPersister,
        /// Upon a new commitment_signed, we'll get a
@@ -408,13 +419,14 @@ pub(crate) struct WatchtowerPersister {
        destination_script: ScriptBuf,
 }
 
+#[cfg(test)]
 impl WatchtowerPersister {
        #[cfg(test)]
        pub(crate) fn new(destination_script: ScriptBuf) -> Self {
                WatchtowerPersister {
                        persister: TestPersister::new(),
-                       unsigned_justice_tx_data: Mutex::new(HashMap::new()),
-                       watchtower_state: Mutex::new(HashMap::new()),
+                       unsigned_justice_tx_data: Mutex::new(new_hash_map()),
+                       watchtower_state: Mutex::new(new_hash_map()),
                        destination_script,
                }
        }
@@ -438,6 +450,7 @@ impl WatchtowerPersister {
        }
 }
 
+#[cfg(test)]
 impl<Signer: sign::ecdsa::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> for WatchtowerPersister {
        fn persist_new_channel(&self, funding_txo: OutPoint,
                data: &channelmonitor::ChannelMonitor<Signer>, id: MonitorUpdateId
@@ -447,7 +460,7 @@ impl<Signer: sign::ecdsa::WriteableEcdsaChannelSigner> chainmonitor::Persist<Sig
                assert!(self.unsigned_justice_tx_data.lock().unwrap()
                        .insert(funding_txo, VecDeque::new()).is_none());
                assert!(self.watchtower_state.lock().unwrap()
-                       .insert(funding_txo, HashMap::new()).is_none());
+                       .insert(funding_txo, new_hash_map()).is_none());
 
                let initial_counterparty_commitment_tx = data.initial_counterparty_commitment_tx()
                        .expect("First and only call expects Some");
@@ -491,6 +504,10 @@ impl<Signer: sign::ecdsa::WriteableEcdsaChannelSigner> chainmonitor::Persist<Sig
                }
                res
        }
+
+       fn archive_persisted_channel(&self, funding_txo: OutPoint) {
+               <TestPersister as chainmonitor::Persist<TestChannelSigner>>::archive_persisted_channel(&self.persister, funding_txo);
+       }
 }
 
 pub struct TestPersister {
@@ -508,8 +525,8 @@ impl TestPersister {
        pub fn new() -> Self {
                Self {
                        update_rets: Mutex::new(VecDeque::new()),
-                       chain_sync_monitor_persistences: Mutex::new(HashMap::new()),
-                       offchain_monitor_updates: Mutex::new(HashMap::new()),
+                       chain_sync_monitor_persistences: Mutex::new(new_hash_map()),
+                       offchain_monitor_updates: Mutex::new(new_hash_map()),
                }
        }
 
@@ -533,12 +550,24 @@ impl<Signer: sign::ecdsa::WriteableEcdsaChannelSigner> chainmonitor::Persist<Sig
                }
                let is_chain_sync = if let UpdateOrigin::ChainSync(_) = update_id.contents { true } else { false };
                if is_chain_sync {
-                       self.chain_sync_monitor_persistences.lock().unwrap().entry(funding_txo).or_insert(HashSet::new()).insert(update_id);
+                       self.chain_sync_monitor_persistences.lock().unwrap().entry(funding_txo).or_insert(new_hash_set()).insert(update_id);
                } else {
-                       self.offchain_monitor_updates.lock().unwrap().entry(funding_txo).or_insert(HashSet::new()).insert(update_id);
+                       self.offchain_monitor_updates.lock().unwrap().entry(funding_txo).or_insert(new_hash_set()).insert(update_id);
                }
                ret
        }
+
+       fn archive_persisted_channel(&self, funding_txo: OutPoint) { 
+               // remove the channel from the offchain_monitor_updates map
+               match self.offchain_monitor_updates.lock().unwrap().remove(&funding_txo) {
+                       Some(_) => {},
+                       None => {
+                               // If the channel was not in the offchain_monitor_updates map, it should be in the
+                               // chain_sync_monitor_persistences map.
+                               assert!(self.chain_sync_monitor_persistences.lock().unwrap().remove(&funding_txo).is_some());
+                       }
+               };
+       }
 }
 
 pub struct TestStore {
@@ -548,7 +577,7 @@ pub struct TestStore {
 
 impl TestStore {
        pub fn new(read_only: bool) -> Self {
-               let persisted_bytes = Mutex::new(HashMap::new());
+               let persisted_bytes = Mutex::new(new_hash_map());
                Self { persisted_bytes, read_only }
        }
 }
@@ -588,7 +617,7 @@ impl KVStore for TestStore {
                } else {
                        format!("{}/{}", primary_namespace, secondary_namespace)
                };
-               let outer_e = persisted_lock.entry(prefixed).or_insert(HashMap::new());
+               let outer_e = persisted_lock.entry(prefixed).or_insert(new_hash_map());
                let mut bytes = Vec::new();
                bytes.write_all(buf)?;
                outer_e.insert(key.to_string(), bytes);
@@ -632,6 +661,9 @@ impl KVStore for TestStore {
        }
 }
 
+unsafe impl Sync for TestStore {}
+unsafe impl Send for TestStore {}
+
 pub struct TestBroadcaster {
        pub txn_broadcasted: Mutex<Vec<Transaction>>,
        pub blocks: Arc<Mutex<Vec<(Block, u32)>>>,
@@ -655,7 +687,7 @@ impl TestBroadcaster {
 
        pub fn unique_txn_broadcast(&self) -> Vec<Transaction> {
                let mut txn = self.txn_broadcasted.lock().unwrap().split_off(0);
-               let mut seen = HashSet::new();
+               let mut seen = new_hash_set();
                txn.retain(|tx| seen.insert(tx.txid()));
                txn
        }
@@ -692,7 +724,7 @@ impl TestChannelMessageHandler {
                TestChannelMessageHandler {
                        pending_events: Mutex::new(Vec::new()),
                        expected_recv_msgs: Mutex::new(None),
-                       connected_peers: Mutex::new(HashSet::new()),
+                       connected_peers: Mutex::new(new_hash_set()),
                        message_fetch_counter: AtomicUsize::new(0),
                        chain_hash,
                }
@@ -752,12 +784,15 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler {
        fn handle_stfu(&self, _their_node_id: &PublicKey, msg: &msgs::Stfu) {
                self.received_msg(wire::Message::Stfu(msg.clone()));
        }
+       #[cfg(splicing)]
        fn handle_splice(&self, _their_node_id: &PublicKey, msg: &msgs::Splice) {
                self.received_msg(wire::Message::Splice(msg.clone()));
        }
+       #[cfg(splicing)]
        fn handle_splice_ack(&self, _their_node_id: &PublicKey, msg: &msgs::SpliceAck) {
                self.received_msg(wire::Message::SpliceAck(msg.clone()));
        }
+       #[cfg(splicing)]
        fn handle_splice_locked(&self, _their_node_id: &PublicKey, msg: &msgs::SpliceLocked) {
                self.received_msg(wire::Message::SpliceLocked(msg.clone()));
        }
@@ -1044,8 +1079,8 @@ impl TestLogger {
                TestLogger {
                        level: Level::Trace,
                        id,
-                       lines: Mutex::new(HashMap::new()),
-                       context: Mutex::new(HashMap::new()),
+                       lines: Mutex::new(new_hash_map()),
+                       context: Mutex::new(new_hash_map()),
                }
        }
        pub fn enable(&mut self, level: Level) {
@@ -1164,6 +1199,7 @@ pub struct TestKeysInterface {
        pub disable_revocation_policy_check: bool,
        enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
        expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
+       pub unavailable_signers: Mutex<HashSet<[u8; 32]>>,
 }
 
 impl EntropySource for TestKeysInterface {
@@ -1222,7 +1258,11 @@ impl SignerProvider for TestKeysInterface {
        fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> TestChannelSigner {
                let keys = self.backing.derive_channel_signer(channel_value_satoshis, channel_keys_id);
                let state = self.make_enforcement_state_cell(keys.commitment_seed);
-               TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check)
+               let signer = TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check);
+               if self.unavailable_signers.lock().unwrap().contains(&channel_keys_id) {
+                       signer.set_available(false);
+               }
+               signer
        }
 
        fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::EcdsaSigner, msgs::DecodeError> {
@@ -1258,8 +1298,9 @@ impl TestKeysInterface {
                        backing: sign::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed),
                        override_random_bytes: Mutex::new(None),
                        disable_revocation_policy_check: false,
-                       enforcement_states: Mutex::new(HashMap::new()),
+                       enforcement_states: Mutex::new(new_hash_map()),
                        expectations: Mutex::new(None),
+                       unavailable_signers: Mutex::new(new_hash_set()),
                }
        }
 
@@ -1273,9 +1314,7 @@ impl TestKeysInterface {
        }
 
        pub fn derive_channel_keys(&self, channel_value_satoshis: u64, id: &[u8; 32]) -> TestChannelSigner {
-               let keys = self.backing.derive_channel_keys(channel_value_satoshis, id);
-               let state = self.make_enforcement_state_cell(keys.commitment_seed);
-               TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check)
+               self.derive_channel_signer(channel_value_satoshis, *id)
        }
 
        fn make_enforcement_state_cell(&self, commitment_seed: [u8; 32]) -> Arc<Mutex<EnforcementState>> {
@@ -1339,10 +1378,14 @@ impl TestChainSource {
                        chain_hash: ChainHash::using_genesis_block(network),
                        utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { value: u64::max_value(), script_pubkey }))),
                        get_utxo_call_count: AtomicUsize::new(0),
-                       watched_txn: Mutex::new(HashSet::new()),
-                       watched_outputs: Mutex::new(HashSet::new()),
+                       watched_txn: Mutex::new(new_hash_set()),
+                       watched_outputs: Mutex::new(new_hash_set()),
                }
        }
+       pub fn remove_watched_txn_and_outputs(&self, outpoint: OutPoint, script_pubkey: ScriptBuf) {
+               self.watched_outputs.lock().unwrap().remove(&(outpoint, script_pubkey.clone())); 
+               self.watched_txn.lock().unwrap().remove(&(outpoint.txid, script_pubkey));
+       }
 }
 
 impl UtxoLookup for TestChainSource {