From 78939a7e0374d6343576ba1440b7d708158ac611 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 6 Jan 2019 23:00:56 -0500 Subject: [PATCH] Test for failing channel after local commitment dust HTLC timeout --- src/ln/channelmonitor.rs | 1 - src/ln/functional_tests.rs | 46 +++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index c1c24f5f..546e4a68 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -1797,7 +1797,6 @@ impl ChannelMonitor { // to the source, and if we don't fail the channel we will have to ensure that the next // updates that peer sends us are update_fails, failing the channel if not. It's probably // easier to just fail the channel as this case should be rare enough anyway. - // TODO: Test below dust HTLC channel failing if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx { for &(ref htlc, _, _) in cur_local_tx.htlc_outputs.iter() { // For inbound HTLCs which we know the preimage for, we have to ensure we hit the diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index 6dd09e1e..ca394fcd 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -50,11 +50,12 @@ use std::sync::atomic::Ordering; use std::time::Instant; use std::mem; +const CHAN_CONFIRM_DEPTH: u32 = 100; fn confirm_transaction(chain: &chaininterface::ChainWatchInterfaceUtil, tx: &Transaction, chan_id: u32) { assert!(chain.does_match_tx(tx)); let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; chain.block_connected_checked(&header, 1, &[tx; 1], &[chan_id; 1]); - for i in 2..100 { + for i in 2..CHAN_CONFIRM_DEPTH { header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; chain.block_connected_checked(&header, i, &[tx; 0], &[0; 0]); } @@ -6046,6 +6047,49 @@ fn test_static_output_closing_tx() { check_spends!(spend_txn[0], closing_tx); } +fn do_htlc_claim_local_commitment_only(use_dust: bool) { + let nodes = create_network(2); + let chan = create_announced_chan_between_nodes(&nodes, 0, 1); + + let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1]], if use_dust { 50000 } else { 3000000 }); + + // Claim the payment, but don't deliver A's commitment_signed, resulting in the HTLC only being + // present in B's local commitment transaction, but none of A's commitment transactions. + assert!(nodes[1].node.claim_funds(our_payment_preimage)); + check_added_monitors!(nodes[1], 1); + + let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]).unwrap(); + let events = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + Event::PaymentSent { payment_preimage } => { + assert_eq!(payment_preimage, our_payment_preimage); + }, + _ => panic!("Unexpected event"), + } + + nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_updates.commitment_signed).unwrap(); + check_added_monitors!(nodes[0], 1); + let as_updates = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_updates.0).unwrap(); + check_added_monitors!(nodes[1], 1); + + let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + for i in 1..TEST_FINAL_CLTV - CLTV_CLAIM_BUFFER + CHAN_CONFIRM_DEPTH + 1 { + nodes[1].chain_monitor.block_connected_checked(&header, i, &Vec::new(), &Vec::new()); + header.prev_blockhash = header.bitcoin_hash(); + } + test_txn_broadcast(&nodes[1], &chan, None, if use_dust { HTLCType::NONE } else { HTLCType::SUCCESS }); + check_closed_broadcast!(nodes[1]); +} + +#[test] +fn htlc_claim_local_commitment_only() { + do_htlc_claim_local_commitment_only(true); + do_htlc_claim_local_commitment_only(false); +} + fn run_onion_failure_test(_name: &str, test_case: u8, nodes: &Vec, route: &Route, payment_hash: &PaymentHash, callback_msg: F1, callback_node: F2, expected_retryable: bool, expected_error_code: Option, expected_channel_update: Option) where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC), F2: FnMut(), -- 2.30.2