X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fmonitor_tests.rs;h=1cb32bed08dc42e2cbb7371856343d14d8d21e35;hb=e38ab09c3a9514768a9833b2636b2b969f62b3e1;hp=67ea07f2abdb0507fd6dfd0704e45504a1c8f29c;hpb=65d71cdc6be11b5f46b55f8507b414255c07249e;p=rust-lightning diff --git a/lightning/src/ln/monitor_tests.rs b/lightning/src/ln/monitor_tests.rs index 67ea07f2..1cb32bed 100644 --- a/lightning/src/ln/monitor_tests.rs +++ b/lightning/src/ln/monitor_tests.rs @@ -9,23 +9,22 @@ //! Further functional tests which test blockchain reorganizations. -use chain::channelmonitor::{ANTI_REORG_DELAY, Balance}; -use chain::transaction::OutPoint; -use chain::chaininterface::LowerBoundedFeeEstimator; -use ln::channel; -use ln::channelmanager::BREAKDOWN_TIMEOUT; -use ln::features::InitFeatures; -use ln::msgs::ChannelMessageHandler; -use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination}; +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, PaymentId}; +use crate::ln::msgs::ChannelMessageHandler; +use crate::util::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination}; use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; use bitcoin::secp256k1::Secp256k1; use bitcoin::Transaction; -use prelude::*; +use crate::prelude::*; -use ln::functional_test_utils::*; +use crate::ln::functional_test_utils::*; #[test] fn chanmon_fail_from_stale_commitment() { @@ -49,11 +48,11 @@ fn chanmon_fail_from_stale_commitment() { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); - let (update_a, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known()); + create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()); + 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); @@ -106,7 +105,7 @@ fn revoked_output_htlc_resolution_timing() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()); + let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()); let payment_hash_1 = route_payment(&nodes[1], &[&nodes[0]], 1_000_000).1; @@ -125,9 +124,8 @@ fn revoked_output_htlc_resolution_timing() { check_closed_broadcast!(nodes[1], true); let bs_spend_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(bs_spend_txn.len(), 2); + assert_eq!(bs_spend_txn.len(), 1); check_spends!(bs_spend_txn[0], revoked_local_txn[0]); - check_spends!(bs_spend_txn[1], chan.3); // After the commitment transaction confirms, we should still wait on the HTLC spend // transaction to confirm before resolving the HTLC. @@ -141,7 +139,7 @@ fn revoked_output_htlc_resolution_timing() { assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); - expect_payment_failed!(nodes[1], payment_hash_1, true); + expect_payment_failed!(nodes[1], payment_hash_1, false); } #[test] @@ -156,7 +154,7 @@ fn chanmon_claim_value_coop_close() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = - create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, InitFeatures::known(), InitFeatures::known()); + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()); let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; assert_eq!(funding_outpoint.to_channel_id(), chan_id); @@ -172,9 +170,9 @@ fn chanmon_claim_value_coop_close() { nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown); + nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_0_shutdown); let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown); + nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &channelmanager::provided_init_features(), &node_1_shutdown); let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_closing_signed); @@ -257,7 +255,7 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = - create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, InitFeatures::known(), InitFeatures::known()); + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 1_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()); let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; assert_eq!(funding_outpoint.to_channel_id(), chan_id); @@ -280,18 +278,24 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { claimable_amount_satoshis: 1_000_000 - 3_000 - 4_000 - 1_000 - 3 - chan_feerate * (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 3_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, }]), sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); - assert_eq!(vec![Balance::ClaimableOnChannelClose { + assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { claimable_amount_satoshis: 1_000, - }], - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 3_000, + expiry_height: htlc_cltv_timeout, + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 4_000, + expiry_height: htlc_cltv_timeout, + }]), + sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); nodes[1].node.claim_funds(payment_preimage); check_added_monitors!(nodes[1], 1); @@ -335,12 +339,12 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { chan_feerate * (channel::commitment_tx_base_weight(opt_anchors) + if prev_commitment_tx { 1 } else { 2 } * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, }]; if !prev_commitment_tx { - a_expected_balances.push(Balance::MaybeClaimableHTLCAwaitingTimeout { + a_expected_balances.push(Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 3_000, claimable_height: htlc_cltv_timeout, }); @@ -359,21 +363,14 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { mine_transaction(&nodes[1], &remote_txn[0]); let b_broadcast_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(b_broadcast_txn.len(), if prev_commitment_tx { 4 } else { 5 }); - if prev_commitment_tx { - check_spends!(b_broadcast_txn[3], b_broadcast_txn[2]); - } else { - assert_eq!(b_broadcast_txn[0], b_broadcast_txn[3]); - assert_eq!(b_broadcast_txn[1], b_broadcast_txn[4]); - } - // b_broadcast_txn[0] should spend the HTLC output of the commitment tx for 3_000 sats + assert_eq!(b_broadcast_txn.len(), 2); + // b_broadcast_txn should spend the HTLCs output of the commitment tx for 3_000 and 4_000 sats check_spends!(b_broadcast_txn[0], remote_txn[0]); check_spends!(b_broadcast_txn[1], remote_txn[0]); assert_eq!(b_broadcast_txn[0].input.len(), 1); assert_eq!(b_broadcast_txn[1].input.len(), 1); assert_eq!(remote_txn[0].output[b_broadcast_txn[0].input[0].previous_output.vout as usize].value, 3_000); assert_eq!(remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize].value, 4_000); - check_spends!(b_broadcast_txn[2], funding_tx); assert!(nodes[0].node.list_channels().is_empty()); check_closed_broadcast!(nodes[0], true); @@ -397,10 +394,10 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { claimable_amount_satoshis: 1_000_000 - 3_000 - 4_000 - 1_000 - 3 - chan_feerate * (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 3_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, }]), @@ -423,15 +420,15 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); - expect_payment_failed!(nodes[0], dust_payment_hash, true); + expect_payment_failed!(nodes[0], dust_payment_hash, false); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); // After ANTI_REORG_DELAY, A will consider its balance fully spendable and generate a // `SpendableOutputs` event. However, B still has to wait for the CSV delay. - assert_eq!(sorted_vec(vec![Balance::MaybeClaimableHTLCAwaitingTimeout { + assert_eq!(sorted_vec(vec![Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 3_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, }]), @@ -459,16 +456,16 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { } else { expect_payment_sent!(nodes[0], payment_preimage); } - assert_eq!(sorted_vec(vec![Balance::MaybeClaimableHTLCAwaitingTimeout { + assert_eq!(sorted_vec(vec![Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 3_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, }]), sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); - assert_eq!(vec![Balance::MaybeClaimableHTLCAwaitingTimeout { + assert_eq!(vec![Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, }], @@ -477,21 +474,20 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { // When the HTLC timeout output is spendable in the next block, A should broadcast it connect_blocks(&nodes[0], htlc_cltv_timeout - nodes[0].best_block_info().1 - 1); let a_broadcast_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(a_broadcast_txn.len(), 3); - check_spends!(a_broadcast_txn[0], funding_tx); + assert_eq!(a_broadcast_txn.len(), 2); + assert_eq!(a_broadcast_txn[0].input.len(), 1); + check_spends!(a_broadcast_txn[0], remote_txn[0]); assert_eq!(a_broadcast_txn[1].input.len(), 1); check_spends!(a_broadcast_txn[1], remote_txn[0]); - assert_eq!(a_broadcast_txn[2].input.len(), 1); - check_spends!(a_broadcast_txn[2], remote_txn[0]); - assert_ne!(a_broadcast_txn[1].input[0].previous_output.vout, - a_broadcast_txn[2].input[0].previous_output.vout); - // a_broadcast_txn [1] and [2] should spend the HTLC outputs of the commitment tx - assert_eq!(remote_txn[0].output[a_broadcast_txn[1].input[0].previous_output.vout as usize].value, 3_000); - assert_eq!(remote_txn[0].output[a_broadcast_txn[2].input[0].previous_output.vout as usize].value, 4_000); + assert_ne!(a_broadcast_txn[0].input[0].previous_output.vout, + a_broadcast_txn[1].input[0].previous_output.vout); + // a_broadcast_txn [0] and [1] should spend the HTLC outputs of the commitment tx + assert_eq!(remote_txn[0].output[a_broadcast_txn[0].input[0].previous_output.vout as usize].value, 3_000); + assert_eq!(remote_txn[0].output[a_broadcast_txn[1].input[0].previous_output.vout as usize].value, 4_000); // Once the HTLC-Timeout transaction confirms, A will no longer consider the HTLC // "MaybeClaimable", but instead move it to "AwaitingConfirmations". - mine_transaction(&nodes[0], &a_broadcast_txn[2]); + mine_transaction(&nodes[0], &a_broadcast_txn[1]); assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { claimable_amount_satoshis: 4_000, @@ -503,9 +499,9 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); assert_eq!(Vec::::new(), nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); - expect_payment_failed!(nodes[0], timeout_payment_hash, true); + expect_payment_failed!(nodes[0], timeout_payment_hash, false); - test_spendable_output(&nodes[0], &a_broadcast_txn[2]); + test_spendable_output(&nodes[0], &a_broadcast_txn[1]); // Node B will no longer consider the HTLC "contentious" after the HTLC claim transaction // confirms, and consider it simply "awaiting confirmations". Note that it has to wait for the @@ -553,7 +549,7 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { // Finally, mine the HTLC timeout transaction that A broadcasted (even though B should be able // to claim this HTLC with the preimage it knows!). It will remain listed as a claimable HTLC // until ANTI_REORG_DELAY confirmations on the spend. - mine_transaction(&nodes[1], &a_broadcast_txn[2]); + mine_transaction(&nodes[1], &a_broadcast_txn[1]); assert_eq!(vec![Balance::ContentiousClaimable { claimable_amount_satoshis: 4_000, timeout_height: htlc_cltv_timeout, @@ -562,6 +558,16 @@ fn do_test_claim_value_force_close(prev_commitment_tx: bool) { connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); assert_eq!(Vec::::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] @@ -588,12 +594,12 @@ fn test_balances_on_local_commitment_htlcs() { // Create a single channel with two pending HTLCs from nodes[0] to nodes[1], one which nodes[1] // knows the preimage for, one which it does not. - let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known()); + let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features()); let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; 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()); @@ -601,10 +607,10 @@ fn test_balances_on_local_commitment_htlcs() { commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_payment_received!(nodes[1], payment_hash, payment_secret, 10_000_000); + expect_payment_claimable!(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()); @@ -612,7 +618,7 @@ fn test_balances_on_local_commitment_htlcs() { commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_payment_received!(nodes[1], payment_hash_2, payment_secret_2, 20_000_000); + expect_payment_claimable!(nodes[1], payment_hash_2, payment_secret_2, 20_000_000); nodes[1].node.claim_funds(payment_preimage_2); get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); @@ -640,10 +646,10 @@ fn test_balances_on_local_commitment_htlcs() { claimable_amount_satoshis: 1_000_000 - 10_000 - 20_000 - chan_feerate * (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, confirmation_height: node_a_commitment_claimable, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 10_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 20_000, claimable_height: htlc_cltv_timeout, }]), @@ -655,10 +661,8 @@ fn test_balances_on_local_commitment_htlcs() { check_closed_broadcast!(nodes[1], true); check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed); let bs_htlc_claim_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(bs_htlc_claim_txn.len(), 3); + assert_eq!(bs_htlc_claim_txn.len(), 1); check_spends!(bs_htlc_claim_txn[0], as_txn[0]); - check_spends!(bs_htlc_claim_txn[1], funding_tx); - check_spends!(bs_htlc_claim_txn[2], bs_htlc_claim_txn[1]); // Connect blocks until the HTLCs expire, allowing us to (validly) broadcast the HTLC-Timeout // transaction. @@ -667,10 +671,10 @@ fn test_balances_on_local_commitment_htlcs() { claimable_amount_satoshis: 1_000_000 - 10_000 - 20_000 - chan_feerate * (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, confirmation_height: node_a_commitment_claimable, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 10_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 20_000, claimable_height: htlc_cltv_timeout, }]), @@ -691,7 +695,7 @@ fn test_balances_on_local_commitment_htlcs() { }, Balance::ClaimableAwaitingConfirmations { claimable_amount_satoshis: 10_000, confirmation_height: node_a_htlc_claimable, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 20_000, claimable_height: htlc_cltv_timeout, }]), @@ -708,7 +712,7 @@ fn test_balances_on_local_commitment_htlcs() { }, Balance::ClaimableAwaitingConfirmations { claimable_amount_satoshis: 10_000, confirmation_height: node_a_htlc_claimable, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 20_000, claimable_height: htlc_cltv_timeout, }]), @@ -718,7 +722,7 @@ fn test_balances_on_local_commitment_htlcs() { // panicked as described in the test introduction. This will remove the "maybe claimable" // spendable output as nodes[1] has fully claimed the second HTLC. connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); - expect_payment_failed!(nodes[0], payment_hash, true); + expect_payment_failed!(nodes[0], payment_hash, false); assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { claimable_amount_satoshis: 1_000_000 - 10_000 - 20_000 - chan_feerate * @@ -745,6 +749,254 @@ 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] +fn test_no_preimage_inbound_htlc_balances() { + // Tests that MaybePreimageClaimableHTLC are generated for inbound HTLCs for which we do not + // have a preimage. + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()); + let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; + + // Send two HTLCs, one from A to B, and one from B to A. + let to_b_failed_payment_hash = route_payment(&nodes[0], &[&nodes[1]], 10_000_000).1; + let to_a_failed_payment_hash = route_payment(&nodes[1], &[&nodes[0]], 20_000_000).1; + let htlc_cltv_timeout = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 1; // Note ChannelManager adds one to CLTV timeouts for safety + + let chan_feerate = get_feerate!(nodes[0], chan_id) as u64; + let opt_anchors = get_opt_anchors!(nodes[0], chan_id); + + // Both A and B will have an HTLC that's claimable on timeout and one that's claimable if they + // receive the preimage. These will remain the same through the channel closure and until the + // HTLC output is spent. + + assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { + claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * + (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 20_000, + expiry_height: htlc_cltv_timeout, + }, Balance::MaybeTimeoutClaimableHTLC { + claimable_amount_satoshis: 10_000, + claimable_height: htlc_cltv_timeout, + }]), + sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { + claimable_amount_satoshis: 500_000 - 20_000, + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 10_000, + expiry_height: htlc_cltv_timeout, + }, Balance::MaybeTimeoutClaimableHTLC { + claimable_amount_satoshis: 20_000, + claimable_height: htlc_cltv_timeout, + }]), + sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + // Get nodes[0]'s commitment transaction and HTLC-Timeout transaction + let as_txn = get_local_commitment_txn!(nodes[0], chan_id); + assert_eq!(as_txn.len(), 2); + check_spends!(as_txn[1], as_txn[0]); + check_spends!(as_txn[0], funding_tx); + + // Now close the channel by confirming A's commitment transaction on both nodes, checking the + // claimable balances remain the same except for the non-HTLC balance changing variant. + let node_a_commitment_claimable = nodes[0].best_block_info().1 + BREAKDOWN_TIMEOUT as u32; + let as_pre_spend_claims = sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * + (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, + confirmation_height: node_a_commitment_claimable, + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 20_000, + expiry_height: htlc_cltv_timeout, + }, Balance::MaybeTimeoutClaimableHTLC { + claimable_amount_satoshis: 10_000, + claimable_height: htlc_cltv_timeout, + }]); + + mine_transaction(&nodes[0], &as_txn[0]); + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); + check_added_monitors!(nodes[0], 1); + check_closed_broadcast!(nodes[0], true); + check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed); + + assert_eq!(as_pre_spend_claims, + sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + mine_transaction(&nodes[1], &as_txn[0]); + check_added_monitors!(nodes[1], 1); + check_closed_broadcast!(nodes[1], true); + check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed); + + let node_b_commitment_claimable = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; + let mut bs_pre_spend_claims = sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 500_000 - 20_000, + confirmation_height: node_b_commitment_claimable, + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 10_000, + expiry_height: htlc_cltv_timeout, + }, Balance::MaybeTimeoutClaimableHTLC { + claimable_amount_satoshis: 20_000, + claimable_height: htlc_cltv_timeout, + }]); + assert_eq!(bs_pre_spend_claims, + sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + // We'll broadcast the HTLC-Timeout transaction one block prior to the htlc's expiration (as it + // is confirmable in the next block), but will still include the same claimable balances as no + // HTLC has been spent, even after the HTLC expires. We'll also fail the inbound HTLC, but it + // won't do anything as the channel is already closed. + + connect_blocks(&nodes[0], TEST_FINAL_CLTV - 1); + let as_htlc_timeout_claim = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); + assert_eq!(as_htlc_timeout_claim.len(), 1); + check_spends!(as_htlc_timeout_claim[0], as_txn[0]); + expect_pending_htlcs_forwardable_conditions!(nodes[0], + [HTLCDestination::FailedPayment { payment_hash: to_a_failed_payment_hash }]); + + assert_eq!(as_pre_spend_claims, + sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + connect_blocks(&nodes[0], 1); + assert_eq!(as_pre_spend_claims, + sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + // For node B, we'll get the non-HTLC funds claimable after ANTI_REORG_DELAY confirmations + connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); + test_spendable_output(&nodes[1], &as_txn[0]); + bs_pre_spend_claims.retain(|e| if let Balance::ClaimableAwaitingConfirmations { .. } = e { false } else { true }); + + // The next few blocks for B look the same as for A, though for the opposite HTLC + nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); + connect_blocks(&nodes[1], TEST_FINAL_CLTV - (ANTI_REORG_DELAY - 1) - 1); + expect_pending_htlcs_forwardable_conditions!(nodes[1], + [HTLCDestination::FailedPayment { payment_hash: to_b_failed_payment_hash }]); + let bs_htlc_timeout_claim = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); + assert_eq!(bs_htlc_timeout_claim.len(), 1); + check_spends!(bs_htlc_timeout_claim[0], as_txn[0]); + + assert_eq!(bs_pre_spend_claims, + sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + connect_blocks(&nodes[1], 1); + assert_eq!(bs_pre_spend_claims, + sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + // Now confirm the two HTLC timeout transactions for A, checking that the inbound HTLC resolves + // after ANTI_REORG_DELAY confirmations and the other takes BREAKDOWN_TIMEOUT confirmations. + mine_transaction(&nodes[0], &as_htlc_timeout_claim[0]); + let as_timeout_claimable_height = nodes[0].best_block_info().1 + (BREAKDOWN_TIMEOUT as u32) - 1; + assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * + (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, + confirmation_height: node_a_commitment_claimable, + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 20_000, + expiry_height: htlc_cltv_timeout, + }, Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 10_000, + confirmation_height: as_timeout_claimable_height, + }]), + sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + mine_transaction(&nodes[0], &bs_htlc_timeout_claim[0]); + assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * + (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, + confirmation_height: node_a_commitment_claimable, + }, Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 20_000, + expiry_height: htlc_cltv_timeout, + }, Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 10_000, + confirmation_height: as_timeout_claimable_height, + }]), + sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + // Once as_htlc_timeout_claim[0] reaches ANTI_REORG_DELAY confirmations, we should get a + // payment failure event. + connect_blocks(&nodes[0], ANTI_REORG_DELAY - 2); + expect_payment_failed!(nodes[0], to_b_failed_payment_hash, false); + + connect_blocks(&nodes[0], 1); + assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * + (channel::commitment_tx_base_weight(opt_anchors) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, + confirmation_height: node_a_commitment_claimable, + }, Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 10_000, + confirmation_height: core::cmp::max(as_timeout_claimable_height, htlc_cltv_timeout), + }]), + sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + connect_blocks(&nodes[0], node_a_commitment_claimable - nodes[0].best_block_info().1); + assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 10_000, + confirmation_height: core::cmp::max(as_timeout_claimable_height, htlc_cltv_timeout), + }], + nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + test_spendable_output(&nodes[0], &as_txn[0]); + + connect_blocks(&nodes[0], as_timeout_claimable_height - 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_htlc_timeout_claim[0]); + + // The process for B should be completely identical as well, noting that the non-HTLC-balance + // was already claimed. + mine_transaction(&nodes[1], &bs_htlc_timeout_claim[0]); + let bs_timeout_claimable_height = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; + assert_eq!(sorted_vec(vec![Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 10_000, + expiry_height: htlc_cltv_timeout, + }, Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 20_000, + confirmation_height: bs_timeout_claimable_height, + }]), + sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + mine_transaction(&nodes[1], &as_htlc_timeout_claim[0]); + assert_eq!(sorted_vec(vec![Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 10_000, + expiry_height: htlc_cltv_timeout, + }, Balance::ClaimableAwaitingConfirmations { + claimable_amount_satoshis: 20_000, + confirmation_height: bs_timeout_claimable_height, + }]), + sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + + connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2); + expect_payment_failed!(nodes[1], to_a_failed_payment_hash, false); + + assert_eq!(vec![Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: 10_000, + expiry_height: htlc_cltv_timeout, + }], + nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + test_spendable_output(&nodes[1], &bs_htlc_timeout_claim[0]); + + 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(v_orig: &Vec, extra_ts: &[&T]) -> Vec { @@ -769,7 +1021,7 @@ fn do_test_revoked_counterparty_commitment_balances(confirm_htlc_spend_first: bo let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = - create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, InitFeatures::known(), InitFeatures::known()); + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()); let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; assert_eq!(funding_outpoint.to_channel_id(), chan_id); @@ -851,13 +1103,13 @@ fn do_test_revoked_counterparty_commitment_balances(confirm_htlc_spend_first: bo // lists the two on-chain timeout-able HTLCs as claimable balances. assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { claimable_amount_satoshis: 100_000 - 5_000 - 4_000 - 3 - 2_000 + 3_000, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 2_000, claimable_height: missing_htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 5_000, claimable_height: live_htlc_cltv_timeout, }]), @@ -978,22 +1230,30 @@ fn do_test_revoked_counterparty_commitment_balances(confirm_htlc_spend_first: bo let mut payment_failed_events = nodes[1].node.get_and_clear_pending_events(); expect_payment_failed_conditions_event(&nodes[1], payment_failed_events.pop().unwrap(), - dust_payment_hash, true, PaymentFailedConditions::new()); + dust_payment_hash, false, PaymentFailedConditions::new()); expect_payment_failed_conditions_event(&nodes[1], payment_failed_events.pop().unwrap(), - missing_htlc_payment_hash, true, PaymentFailedConditions::new()); + missing_htlc_payment_hash, false, PaymentFailedConditions::new()); assert!(payment_failed_events.is_empty()); connect_blocks(&nodes[1], 1); test_spendable_output(&nodes[1], &claim_txn[if confirm_htlc_spend_first { 2 } else { 3 }]); connect_blocks(&nodes[1], 1); test_spendable_output(&nodes[1], &claim_txn[if confirm_htlc_spend_first { 3 } else { 2 }]); - expect_payment_failed!(nodes[1], live_payment_hash, true); + expect_payment_failed!(nodes[1], live_payment_hash, false); connect_blocks(&nodes[1], 1); test_spendable_output(&nodes[1], &claim_txn[0]); connect_blocks(&nodes[1], 1); test_spendable_output(&nodes[1], &claim_txn[1]); - expect_payment_failed!(nodes[1], timeout_payment_hash, true); + 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] @@ -1013,7 +1273,7 @@ fn test_revoked_counterparty_htlc_tx_balances() { // Create some initial channels let (_, _, chan_id, funding_tx) = - create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 11_000_000, InitFeatures::known(), InitFeatures::known()); + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 11_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()); let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; assert_eq!(funding_outpoint.to_channel_id(), chan_id); @@ -1038,11 +1298,10 @@ fn test_revoked_counterparty_htlc_tx_balances() { check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed); let revoked_htlc_success_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(revoked_htlc_success_txn.len(), 2); + assert_eq!(revoked_htlc_success_txn.len(), 1); assert_eq!(revoked_htlc_success_txn[0].input.len(), 1); assert_eq!(revoked_htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); check_spends!(revoked_htlc_success_txn[0], revoked_local_txn[0]); - check_spends!(revoked_htlc_success_txn[1], funding_tx); connect_blocks(&nodes[1], TEST_FINAL_CLTV); let revoked_htlc_timeout_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); @@ -1060,9 +1319,8 @@ fn test_revoked_counterparty_htlc_tx_balances() { let to_remote_conf_height = nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1; let as_commitment_claim_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(as_commitment_claim_txn.len(), 2); + assert_eq!(as_commitment_claim_txn.len(), 1); check_spends!(as_commitment_claim_txn[0], revoked_local_txn[0]); - check_spends!(as_commitment_claim_txn[1], funding_tx); // The next two checks have the same balance set for A - even though we confirm a revoked HTLC // transaction our balance tracking doesn't use the on-chain value so the @@ -1200,6 +1458,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] @@ -1217,7 +1483,7 @@ fn test_revoked_counterparty_aggregated_claims() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = - create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, InitFeatures::known(), InitFeatures::known()); + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000, channelmanager::provided_init_features(), channelmanager::provided_init_features()); let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; assert_eq!(funding_outpoint.to_channel_id(), chan_id); @@ -1263,10 +1529,10 @@ fn test_revoked_counterparty_aggregated_claims() { assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { claimable_amount_satoshis: 100_000 - 4_000 - 3_000, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, - }, Balance::MaybeClaimableHTLCAwaitingTimeout { + }, Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: 3_000, claimable_height: htlc_cltv_timeout, }]), @@ -1388,7 +1654,15 @@ fn test_revoked_counterparty_aggregated_claims() { assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); // We shouldn't fail the payment until we spend the output connect_blocks(&nodes[1], 5); - expect_payment_failed!(nodes[1], revoked_payment_hash, true); + 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()); }