Skip to content

Commit 432d95e

Browse files
author
Antoine Riard
committed
Add block_disconnecting tests to cancel HTLC failure updates
1 parent b1d931b commit 432d95e

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

src/ln/functional_test_utils.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use util::logger::Logger;
1515
use util::config::UserConfig;
1616

1717
use bitcoin::util::hash::{BitcoinHash, Sha256dHash};
18-
use bitcoin::blockdata::block::BlockHeader;
18+
use bitcoin::blockdata::block::{BlockHeader, Block};
1919
use bitcoin::blockdata::transaction::{Transaction, TxOut};
2020
use bitcoin::network::constants::Network;
2121

@@ -55,6 +55,20 @@ pub fn connect_blocks(chain: &chaininterface::ChainWatchInterfaceUtil, depth: u3
5555
}
5656
}
5757

58+
pub fn disconnect_blocks(chain: &chaininterface::ChainWatchInterfaceUtil, depth: u32, height: u32, parent: bool, prev_blockhash: Sha256dHash) {
59+
let mut header = BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
60+
let mut blocks = Vec::new();
61+
for _ in 0..depth {
62+
blocks.push(Block { header, txdata: Vec::new() });
63+
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
64+
}
65+
let mut height = height;
66+
for block in blocks.pop() {
67+
chain.block_disconnected(&block, height);
68+
height -= 1;
69+
}
70+
}
71+
5872
pub struct Node {
5973
pub chain_monitor: Arc<chaininterface::ChainWatchInterfaceUtil>,
6074
pub tx_broadcaster: Arc<test_utils::TestBroadcaster>,

src/ln/functional_tests.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5483,3 +5483,71 @@ fn test_failure_delay_dust_htlc_local_commitment() {
54835483
do_test_failure_delay_dust_htlc_local_commitment(true);
54845484
do_test_failure_delay_dust_htlc_local_commitment(false);
54855485
}
5486+
5487+
fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
5488+
// Outbound HTLC-failure updates must be cancelled if we get a reorg before we reach HTLC_FAIL_ANTI_REORG_DELAY.
5489+
// Broadcast of revoked remote commitment tx, trigger failure-update of dust/non-dust HTLCs
5490+
// Broadcast of remote commitment tx, trigger failure-update of dust-HTLCs
5491+
// Broadcast of timeout tx on remote commitment tx, trigger failure-udate of non-dust HTLCs
5492+
// Broadcast of local commitment tx, trigger failure-update of dust-HTLCs
5493+
// Broadcast of HTLC-timeout tx on local commitment tx, trigger failure-update of non-dust HTLCs
5494+
5495+
let nodes = create_network(2);
5496+
let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
5497+
5498+
let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis;
5499+
5500+
let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
5501+
let (payment_preimage_2, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
5502+
5503+
let as_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
5504+
let bs_commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
5505+
5506+
// We revoked bs_commitment_tx
5507+
if revoked {
5508+
let (payment_preimage_3, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
5509+
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
5510+
}
5511+
5512+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
5513+
let header_2 = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
5514+
let mut timeout_tx = Vec::new();
5515+
if local {
5516+
// We fail dust-HTLC 1 by broadcast of local commitment tx
5517+
nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_commitment_tx[0]], &[1; 1]);
5518+
timeout_tx.push(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].clone());
5519+
assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
5520+
// We fail dust-HTLC 2 by broadcast of local HTLC-timeout tx on local commitment tx
5521+
nodes[0].chain_monitor.block_connected_checked(&header_2, 1, &[&timeout_tx[0]], &[1; 1]);
5522+
} else {
5523+
// We fail dust-HTLC 1 by broadcast of remote commitment tx. If revoked, fail also non-dust HTLC
5524+
nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&bs_commitment_tx[0]], &[1; 1]);
5525+
if !revoked {
5526+
timeout_tx.push(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].clone());
5527+
assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
5528+
// We fail non-dust-HTLC 2 by broadcast of local timeout tx on remote commitment tx
5529+
nodes[0].chain_monitor.block_connected_checked(&header_2, 1, &[&timeout_tx[0]], &[1; 1]);
5530+
}
5531+
}
5532+
5533+
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
5534+
// We connect 3 blocks, not enough to reach HTLC_FAIL_ANTI_REORG_DELAY
5535+
connect_blocks(&nodes[0].chain_monitor, 3, 2, true, header.bitcoin_hash());
5536+
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
5537+
5538+
// We disconnect 5 blocks, updates should have been cancelled and HTLC still claimable
5539+
disconnect_blocks(&nodes[0].chain_monitor, 3, 5, true, header.bitcoin_hash());
5540+
nodes[0].chain_monitor.block_disconnected(&Block { header: header_2, txdata: if !revoked { timeout_tx } else { vec![] } }, 2);
5541+
nodes[0].chain_monitor.block_disconnected(&Block { header, txdata: vec![if local { as_commitment_tx[0].clone() } else { bs_commitment_tx[0].clone() }] }, 1);
5542+
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
5543+
5544+
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1);
5545+
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_2);
5546+
}
5547+
5548+
#[test]
5549+
fn test_sweep_outbound_htlc_failure_update() {
5550+
do_test_sweep_outbound_htlc_failure_update(false, true);
5551+
do_test_sweep_outbound_htlc_failure_update(false, false);
5552+
do_test_sweep_outbound_htlc_failure_update(true, false);
5553+
}

0 commit comments

Comments
 (0)