Add additional testing in `montior_tests` for chain idempotency
[rust-lightning] / lightning / src / ln / monitor_tests.rs
index de54e3d12219009da9340f97dfa533190cb2112c..cee75f8c2076b9df36e4bcf824aa887795358387 100644 (file)
@@ -13,7 +13,7 @@ use crate::chain::channelmonitor::{ANTI_REORG_DELAY, Balance};
 use crate::chain::transaction::OutPoint;
 use crate::chain::chaininterface::LowerBoundedFeeEstimator;
 use crate::ln::channel;
-use crate::ln::channelmanager::{self, BREAKDOWN_TIMEOUT};
+use crate::ln::channelmanager::{self, BREAKDOWN_TIMEOUT, PaymentId};
 use crate::ln::msgs::ChannelMessageHandler;
 use crate::util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
 
@@ -52,7 +52,7 @@ fn chanmon_fail_from_stale_commitment() {
        let (update_a, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features());
 
        let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000);
-       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
+       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
        check_added_monitors!(nodes[0], 1);
 
        let bs_txn = get_local_commitment_txn!(nodes[1], chan_id_2);
@@ -567,6 +567,16 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) {
        connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
        assert_eq!(Vec::<Balance>::new(),
                nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
+
+       // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're
+       // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new
+       // monitor events or claimable balances.
+       for node in nodes.iter() {
+               connect_blocks(node, 6);
+               connect_blocks(node, 6);
+               assert!(node.chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
+               assert!(node.chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
+       }
 }
 
 #[test]
@@ -598,7 +608,7 @@ fn test_balances_on_local_commitment_htlcs() {
 
        let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 10_000_000);
        let htlc_cltv_timeout = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 1; // Note ChannelManager adds one to CLTV timeouts for safety
-       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
+       nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
        check_added_monitors!(nodes[0], 1);
 
        let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
@@ -609,7 +619,7 @@ fn test_balances_on_local_commitment_htlcs() {
        expect_payment_received!(nodes[1], payment_hash, payment_secret, 10_000_000);
 
        let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 20_000_000);
-       nodes[0].node.send_payment(&route_2, payment_hash_2, &Some(payment_secret_2)).unwrap();
+       nodes[0].node.send_payment(&route_2, payment_hash_2, &Some(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap();
        check_added_monitors!(nodes[0], 1);
 
        let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
@@ -750,6 +760,14 @@ fn test_balances_on_local_commitment_htlcs() {
        connect_blocks(&nodes[0], node_a_htlc_claimable - nodes[0].best_block_info().1);
        assert!(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
        test_spendable_output(&nodes[0], &as_txn[1]);
+
+       // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're
+       // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new
+       // monitor events or claimable balances.
+       connect_blocks(&nodes[0], 6);
+       connect_blocks(&nodes[0], 6);
+       assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
+       assert!(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
 }
 
 #[test]
@@ -982,6 +1000,14 @@ fn test_no_preimage_inbound_htlc_balances() {
 
        connect_blocks(&nodes[1], 1);
        assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
+
+       // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're
+       // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new
+       // monitor events or claimable balances.
+       connect_blocks(&nodes[1], 6);
+       connect_blocks(&nodes[1], 6);
+       assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
+       assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
 }
 
 fn sorted_vec_with_additions<T: Ord + Clone>(v_orig: &Vec<T>, extra_ts: &[&T]) -> Vec<T> {
@@ -1231,6 +1257,14 @@ fn do_test_revoked_counterparty_commitment_balances(confirm_htlc_spend_first: bo
        test_spendable_output(&nodes[1], &claim_txn[1]);
        expect_payment_failed!(nodes[1], timeout_payment_hash, false);
        assert_eq!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances(), Vec::new());
+
+       // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're
+       // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new
+       // monitor events or claimable balances.
+       connect_blocks(&nodes[1], 6);
+       connect_blocks(&nodes[1], 6);
+       assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
+       assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
 }
 
 #[test]
@@ -1437,6 +1471,14 @@ fn test_revoked_counterparty_htlc_tx_balances() {
        test_spendable_output(&nodes[0], &as_second_htlc_claim_tx[1]);
 
        assert_eq!(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances(), Vec::new());
+
+       // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're
+       // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new
+       // monitor events or claimable balances.
+       connect_blocks(&nodes[0], 6);
+       connect_blocks(&nodes[0], 6);
+       assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
+       assert!(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
 }
 
 #[test]
@@ -1628,4 +1670,12 @@ fn test_revoked_counterparty_aggregated_claims() {
        expect_payment_failed!(nodes[1], revoked_payment_hash, false);
        test_spendable_output(&nodes[1], &claim_txn_2[0]);
        assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
+
+       // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're
+       // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new
+       // monitor events or claimable balances.
+       connect_blocks(&nodes[1], 6);
+       connect_blocks(&nodes[1], 6);
+       assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
+       assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty());
 }