Test for failing channel after local commitment dust HTLC timeout
authorMatt Corallo <git@bluematt.me>
Mon, 7 Jan 2019 04:00:56 +0000 (23:00 -0500)
committerMatt Corallo <git@bluematt.me>
Sun, 13 Jan 2019 17:59:19 +0000 (12:59 -0500)
src/ln/channelmonitor.rs
src/ln/functional_tests.rs

index c1c24f5faf6bb0d3425e24965ff67064dcd018fa..546e4a68451cc076c440ca9b2ac0902233d2e8ef 100644 (file)
@@ -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
index 6dd09e1ee4c073a6a8394b0dd56163785ac4681f..ca394fcdf98fda96379630cb2d6c9024e4739f05 100644 (file)
@@ -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<F1,F2>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, callback_msg: F1, callback_node: F2, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<HTLCFailChannelUpdate>)
        where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC),
                                F2: FnMut(),