Skip to content

Commit b3481be

Browse files
author
Antoine Riard
committed
Fail back dust HTLC of local commitment tx after enough confirmations
Add test_failure_delay_htlc_local_commitment Move some bits of check_spend_remote as we need to fail dust HTLCs which can be spread on both prev/lastest local commitment tx
1 parent bb2d1ca commit b3481be

File tree

2 files changed

+137
-13
lines changed

2 files changed

+137
-13
lines changed

src/ln/channelmonitor.rs

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,42 +1627,77 @@ impl ChannelMonitor {
16271627
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
16281628
/// revoked using data in local_claimable_outpoints.
16291629
/// Should not be used if check_spend_revoked_transaction succeeds.
1630-
fn check_spend_local_transaction(&self, tx: &Transaction, _height: u32) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>, (Sha256dHash, Vec<TxOut>)) {
1630+
fn check_spend_local_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>, (Sha256dHash, Vec<TxOut>)) {
16311631
let commitment_txid = tx.txid();
1632-
// TODO: If we find a match here we need to fail back HTLCs that weren't included in the
1633-
// broadcast commitment transaction, either because they didn't meet dust or because they
1634-
// weren't yet included in our commitment transaction(s).
1632+
let mut local_txn = Vec::new();
1633+
let mut spendable_outputs = Vec::new();
1634+
let mut watch_outputs = Vec::new();
1635+
1636+
macro_rules! wait_threshold_conf {
1637+
($height: expr, $source: expr, $update: expr, $commitment_tx: expr, $payment_hash: expr) => {
1638+
log_trace!(self, "Failing HTLC with payment_hash {} from {} local commitment tx due to broadcast of transaction, waiting confirmation until {} height", log_bytes!($payment_hash.0), $commitment_tx, height + HTLC_FAIL_ANTI_REORG_DELAY - 1);
1639+
match self.htlc_updated_waiting_threshold_conf.entry($height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
1640+
hash_map::Entry::Occupied(mut entry) => {
1641+
let e = entry.get_mut();
1642+
e.retain(|ref update| update.0 != $source);
1643+
e.push(($source, $update, $payment_hash));
1644+
}
1645+
hash_map::Entry::Vacant(entry) => {
1646+
entry.insert(vec![($source, $update, $payment_hash)]);
1647+
}
1648+
}
1649+
}
1650+
}
1651+
1652+
macro_rules! append_onchain_update {
1653+
($updates: expr) => {
1654+
local_txn.append(&mut $updates.0);
1655+
spendable_outputs.append(&mut $updates.1);
1656+
watch_outputs.append(&mut $updates.2);
1657+
}
1658+
}
1659+
16351660
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
1661+
for &(ref htlc, _, ref source) in &local_tx.htlc_outputs {
1662+
if htlc.transaction_output_index.is_none() {
1663+
if let &Some(ref source) = source {
1664+
wait_threshold_conf!(height, source.clone(), None, "lastest", htlc.payment_hash.clone());
1665+
}
1666+
}
1667+
}
16361668
if local_tx.txid == commitment_txid {
16371669
log_trace!(self, "Got latest local commitment tx broadcast, searching for available HTLCs to claim");
16381670
match self.key_storage {
16391671
Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
1640-
let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key));
1641-
return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
1672+
append_onchain_update!(self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key)));
16421673
},
16431674
Storage::Watchtower { .. } => {
1644-
let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, &None, &None);
1645-
return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
1675+
append_onchain_update!(self.broadcast_by_local_state(local_tx, &None, &None));
16461676
}
16471677
}
16481678
}
16491679
}
16501680
if let &Some(ref local_tx) = &self.prev_local_signed_commitment_tx {
1681+
for &(ref htlc, _, ref source) in &local_tx.htlc_outputs {
1682+
if htlc.transaction_output_index.is_none() {
1683+
if let &Some(ref source) = source {
1684+
wait_threshold_conf!(height, source.clone(), None, "previous", htlc.payment_hash.clone());
1685+
}
1686+
}
1687+
}
16511688
if local_tx.txid == commitment_txid {
16521689
log_trace!(self, "Got previous local commitment tx broadcast, searching for available HTLCs to claim");
16531690
match self.key_storage {
16541691
Storage::Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => {
1655-
let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key));
1656-
return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
1692+
append_onchain_update!(self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key)));
16571693
},
16581694
Storage::Watchtower { .. } => {
1659-
let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, &None, &None);
1660-
return (local_txn, spendable_outputs, (commitment_txid, watch_outputs));
1695+
append_onchain_update!(self.broadcast_by_local_state(local_tx, &None, &None));
16611696
}
16621697
}
16631698
}
16641699
}
1665-
(Vec::new(), Vec::new(), (commitment_txid, Vec::new()))
1700+
(local_txn, spendable_outputs, (commitment_txid, watch_outputs))
16661701
}
16671702

16681703
/// Generate a spendable output event when closing_transaction get registered onchain.

src/ln/functional_tests.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5365,3 +5365,92 @@ fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_upda
53655365

53665366
check_added_monitors!(nodes[1], 1);
53675367
}
5368+
5369+
fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
5370+
// Dust-HTLC failure updates must be delayed until failure-trigger tx (in this case local commitment) reach HTLC_FAIL_ANTI_REORG_DELAY
5371+
// We can have at most two valid local commitment tx, so both cases must be covered, and both txs must be checked to get them all as
5372+
// HTLC could have been removed from lastest local commitment tx but still valid until we get remote RAA
5373+
5374+
let nodes = create_network(2);
5375+
let chan =create_announced_chan_between_nodes(&nodes, 0, 1);
5376+
5377+
let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis;
5378+
5379+
// We route 2 dust-HTLCs between A and B
5380+
let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
5381+
let (_, payment_hash_2) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
5382+
route_payment(&nodes[0], &[&nodes[1]], 1000000);
5383+
5384+
// Cache one local commitment tx as previous
5385+
let as_prev_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
5386+
5387+
// Fail one HTLC to prune it in the will-be-latest-local commitment tx
5388+
assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2));
5389+
check_added_monitors!(nodes[1], 0);
5390+
expect_pending_htlcs_forwardable!(nodes[1]);
5391+
check_added_monitors!(nodes[1], 1);
5392+
5393+
let remove = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
5394+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &remove.update_fail_htlcs[0]).unwrap();
5395+
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &remove.commitment_signed).unwrap();
5396+
check_added_monitors!(nodes[0], 1);
5397+
5398+
// Cache one local commitment tx as lastest
5399+
let as_last_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
5400+
5401+
let events = nodes[0].node.get_and_clear_pending_msg_events();
5402+
match events[0] {
5403+
MessageSendEvent::SendRevokeAndACK { node_id, .. } => {
5404+
assert_eq!(node_id, nodes[1].node.get_our_node_id());
5405+
},
5406+
_ => panic!("Unexpected event"),
5407+
}
5408+
match events[1] {
5409+
MessageSendEvent::UpdateHTLCs { node_id, .. } => {
5410+
assert_eq!(node_id, nodes[1].node.get_our_node_id());
5411+
},
5412+
_ => panic!("Unexpected event"),
5413+
}
5414+
5415+
assert_ne!(as_prev_commitment_tx, as_last_commitment_tx);
5416+
// Fail the 2 dust-HTLCs, move their failure in maturation buffer (htlc_updated_waiting_threshold_conf)
5417+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
5418+
if announce_latest {
5419+
nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_last_commitment_tx[0]], &[1; 1]);
5420+
} else {
5421+
nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_prev_commitment_tx[0]], &[1; 1]);
5422+
}
5423+
5424+
let events = nodes[0].node.get_and_clear_pending_msg_events();
5425+
assert_eq!(events.len(), 1);
5426+
match events[0] {
5427+
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
5428+
_ => panic!("Unexpected event"),
5429+
}
5430+
5431+
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
5432+
connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash());
5433+
let events = nodes[0].node.get_and_clear_pending_events();
5434+
// Only 2 PaymentFailed events should show up, over-dust HTLC has to be failed by timeout tx
5435+
assert_eq!(events.len(), 2);
5436+
let mut first_failed = false;
5437+
for event in events {
5438+
match event {
5439+
Event::PaymentFailed { payment_hash, .. } => {
5440+
if payment_hash == payment_hash_1 {
5441+
assert!(!first_failed);
5442+
first_failed = true;
5443+
} else {
5444+
assert_eq!(payment_hash, payment_hash_2);
5445+
}
5446+
}
5447+
_ => panic!("Unexpected event"),
5448+
}
5449+
}
5450+
}
5451+
5452+
#[test]
5453+
fn test_failure_delay_dust_htlc_local_commitment() {
5454+
do_test_failure_delay_dust_htlc_local_commitment(true);
5455+
do_test_failure_delay_dust_htlc_local_commitment(false);
5456+
}

0 commit comments

Comments
 (0)