Skip to content

Commit 10baa3d

Browse files
author
Antoine Riard
committed
Add tracking in ChannelManager of unresolved htlcs give us by channel
close, add preimages extraction in block_connected to claim funds backward Add caching of PreviousHopData even in case of non-terminal peer to be able to route backward from on-chain resolution
1 parent 48825e0 commit 10baa3d

File tree

2 files changed

+202
-20
lines changed

2 files changed

+202
-20
lines changed

src/ln/channel.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,7 +1065,7 @@ impl Channel {
10651065
}
10661066
}
10671067
if pending_idx == std::usize::MAX {
1068-
debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID");
1068+
//TODO: how to go around collisions ? debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID {}", htlc_id_arg);
10691069
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: Some(msgs::ErrorAction::IgnoreError)});
10701070
}
10711071

@@ -1146,7 +1146,7 @@ impl Channel {
11461146
}
11471147
}
11481148
if pending_idx == std::usize::MAX {
1149-
debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID");
1149+
//TODO: how to go around collision ? debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID");
11501150
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: Some(msgs::ErrorAction::IgnoreError)});
11511151
}
11521152

@@ -2799,7 +2799,7 @@ impl Channel {
27992799
/// those explicitly stated to be allowed after shutdown completes, eg some simple getters).
28002800
/// Also returns the list of payment_hashes for channels which we can safely fail backwards
28012801
/// immediately (others we will have to allow to time out).
2802-
pub fn force_shutdown(&mut self) -> (Vec<Transaction>, Vec<(HTLCSource, [u8; 32])>) {
2802+
pub fn force_shutdown(&mut self) -> (Vec<Transaction>, Vec<(HTLCSource, [u8; 32])>, Vec<[u8;32]>) {
28032803
assert!(self.channel_state != ChannelState::ShutdownComplete as u32);
28042804

28052805
// We go ahead and "free" any holding cell HTLCs or HTLCs we haven't yet committed to and
@@ -2814,17 +2814,19 @@ impl Channel {
28142814
}
28152815
}
28162816

2817-
for _htlc in self.pending_outbound_htlcs.drain(..) {
2818-
//TODO: Do something with the remaining HTLCs
2819-
//(we need to have the ChannelManager monitor them so we can claim the inbound HTLCs
2820-
//which correspond)
2817+
let mut unsolved_htlcs = Vec::with_capacity(self.pending_outbound_htlcs.len() + self.pending_inbound_htlcs.len());
2818+
for outbound_htlcs in self.pending_outbound_htlcs.iter() {
2819+
unsolved_htlcs.push(outbound_htlcs.payment_hash);
2820+
}
2821+
for inbound_htlcs in self.pending_inbound_htlcs.iter() {
2822+
unsolved_htlcs.push(inbound_htlcs.payment_hash);
28212823
}
28222824

28232825
self.channel_state = ChannelState::ShutdownComplete as u32;
28242826
self.channel_update_count += 1;
28252827
let mut res = Vec::new();
28262828
mem::swap(&mut res, &mut self.last_local_commitment_txn);
2827-
(res, dropped_outbound_htlcs)
2829+
(res, dropped_outbound_htlcs, unsolved_htlcs)
28282830
}
28292831
}
28302832

src/ln/channelmanager.rs

Lines changed: 192 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use crypto::mac::{Mac,MacResult};
3737
use crypto::hmac::Hmac;
3838
use crypto::digest::Digest;
3939
use crypto::symmetriccipher::SynchronousStreamCipher;
40+
use crypto::ripemd160::Ripemd160;
4041

4142
use std::{ptr, mem};
4243
use std::collections::HashMap;
@@ -240,6 +241,8 @@ pub struct ChannelManager {
240241
channel_state: Mutex<ChannelHolder>,
241242
our_network_key: SecretKey,
242243

244+
unsolved_htlcs: Mutex<Vec<[u8;32]>>,
245+
243246
pending_events: Mutex<Vec<events::Event>>,
244247

245248
logger: Arc<Logger>,
@@ -314,6 +317,8 @@ impl ChannelManager {
314317
}),
315318
our_network_key,
316319

320+
unsolved_htlcs: Mutex::new(Vec::new()),
321+
317322
pending_events: Mutex::new(Vec::new()),
318323

319324
logger,
@@ -450,22 +455,18 @@ impl ChannelManager {
450455
}
451456

452457
#[inline]
453-
fn finish_force_close_channel(&self, shutdown_res: (Vec<Transaction>, Vec<(HTLCSource, [u8; 32])>)) {
454-
let (local_txn, mut failed_htlcs) = shutdown_res;
458+
fn finish_force_close_channel(&self, shutdown_res: (Vec<Transaction>, Vec<(HTLCSource, [u8; 32])>, Vec<[u8;32]>)) {
459+
let (local_txn, mut failed_htlcs, mut unsolved_htlcs) = shutdown_res;
455460
for htlc_source in failed_htlcs.drain(..) {
456461
// unknown_next_peer...I dunno who that is anymore....
457462
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source.0, &htlc_source.1, HTLCFailReason::Reason { failure_code: 0x4000 | 10, data: Vec::new() });
458463
}
459464
for tx in local_txn {
460465
self.tx_broadcaster.broadcast_transaction(&tx);
461466
}
462-
//TODO: We need to have a way where outbound HTLC claims can result in us claiming the
463-
//now-on-chain HTLC output for ourselves (and, thereafter, passing the HTLC backwards).
464-
//TODO: We need to handle monitoring of pending offered HTLCs which just hit the chain and
465-
//may be claimed, resulting in us claiming the inbound HTLCs (and back-failing after
466-
//timeouts are hit and our claims confirm).
467-
//TODO: In any case, we need to make sure we remove any pending htlc tracking (via
468-
//fail_backwards or claim_funds) eventually for all HTLCs that were in the channel
467+
let mut unsolved_htlcs_lock = self.unsolved_htlcs.lock().unwrap();
468+
unsolved_htlcs_lock.append(&mut unsolved_htlcs);
469+
469470
}
470471

471472
/// Force closes a channel, immediately broadcasting the latest local commitment transaction to
@@ -1141,11 +1142,16 @@ impl ChannelManager {
11411142

11421143
let mut add_htlc_msgs = Vec::new();
11431144
for HTLCForwardInfo { prev_short_channel_id, prev_htlc_id, forward_info } in pending_forwards.drain(..) {
1144-
let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData {
1145+
let prev_hop_data = HTLCPreviousHopData {
11451146
short_channel_id: prev_short_channel_id,
11461147
htlc_id: prev_htlc_id,
11471148
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
1148-
});
1149+
};
1150+
match channel_state.claimable_htlcs.entry(forward_info.payment_hash) {
1151+
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(prev_hop_data.clone()),
1152+
hash_map::Entry::Vacant(entry) => { entry.insert(vec![prev_hop_data.clone()]); },
1153+
};
1154+
let htlc_source = HTLCSource::PreviousHopData(prev_hop_data);
11491155
match forward_chan.send_htlc(forward_info.amt_to_forward, forward_info.payment_hash, forward_info.outgoing_cltv_value, htlc_source.clone(), forward_info.onion_packet.unwrap()) {
11501156
Err(_e) => {
11511157
let chan_update = self.get_channel_update(forward_chan).unwrap();
@@ -1988,6 +1994,39 @@ impl ChainListener for ChannelManager {
19881994
for failure in failed_channels.drain(..) {
19891995
self.finish_force_close_channel(failure);
19901996
}
1997+
1998+
{
1999+
let mut unsolved_htlcs = self.unsolved_htlcs.lock().unwrap();
2000+
for tx in txn_matched {
2001+
unsolved_htlcs.retain(|&payment_hash| {
2002+
let payment_hash160 = {
2003+
let mut ripemd = Ripemd160::new();
2004+
ripemd.input(&payment_hash);
2005+
let mut res = [0; 20];
2006+
ripemd.result(&mut res);
2007+
res
2008+
};
2009+
//TODO: size of redeemScript is test-only right now
2010+
if tx.input.len() > 0 && tx.input[0].witness.len() == 5 && tx.input[0].witness[4].len() == 138 && payment_hash160 == tx.input[0].witness[4][69..89] {
2011+
let mut payment_preimage = [0; 32];
2012+
for (arr, vec) in payment_preimage.iter_mut().zip(tx.input[0].witness[3].iter()) {
2013+
*arr = *vec;
2014+
}
2015+
self.claim_funds(payment_preimage);
2016+
return false
2017+
} else if tx.input.len() > 0 && tx.input[0].witness.len() == 3 && tx.input[0].witness[2].len() == 133 && payment_hash160 == tx.input[0].witness[2][109..129] {
2018+
let mut payment_preimage = [0;32];
2019+
for (arr, vec) in payment_preimage.iter_mut().zip(tx.input[0].witness[1].iter()) {
2020+
*arr = *vec;
2021+
}
2022+
self.claim_funds(payment_preimage);
2023+
return false
2024+
} //TODO: check if HTLC Timeout tx (offered HTLC) or timeout tx (received HTLC) and call fail_htlc_backwards ((5, 133, [110..130]), (3, 138, [69..89]))
2025+
true
2026+
});
2027+
}
2028+
}
2029+
19912030
let mut pending_events = self.pending_events.lock().unwrap();
19922031
for funding_locked in new_events.drain(..) {
19932032
pending_events.push(funding_locked);
@@ -3201,7 +3240,7 @@ mod tests {
32013240
}
32023241

32033242
/// Tests that the given node has broadcast a claim transaction against the provided revoked
3204-
/// HTLC transaction.
3243+
/// HTLC transaction issued from a revoked commitment tx
32053244
fn test_revoked_htlc_claim_txn_broadcast(node: &Node, revoked_tx: Transaction) {
32063245
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
32073246
assert_eq!(node_txn.len(), 1);
@@ -3426,6 +3465,147 @@ mod tests {
34263465
assert_eq!(nodes[1].node.list_channels().len(), 0);
34273466
}
34283467

3468+
#[test]
3469+
fn test_htlc_on_chain_success() {
3470+
// Test that in case of an unilateral close onchain, we detect the state of output thanks to
3471+
// ChainWatchInterface and pass the preimage backward accordingly. So here we test that ChannelManager is
3472+
// broadcasting the right event to other nodes in payment path.
3473+
// A --------------------> B ----------------------> C (preimage)
3474+
// A's commitment tx C's commitment tx
3475+
// \ \
3476+
// B's preimage tx C's HTLC Success tx
3477+
3478+
let nodes = create_network(4);
3479+
3480+
// Create some initial channels
3481+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
3482+
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
3483+
3484+
// Rebalance the network a bit by relaying one payment through all the channels...
3485+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
3486+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
3487+
3488+
let (payment_preimage, payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
3489+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
3490+
3491+
// Broadcast legit commitment tx from C on B's chain
3492+
// Broadcast HTLC Success transation by C on received output from C's commitment tx on B's chain
3493+
let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone();
3494+
nodes[2].node.claim_funds(payment_preimage);
3495+
{
3496+
let mut added_monitors = nodes[2].chan_monitor.added_monitors.lock().unwrap();
3497+
assert_eq!(added_monitors.len(), 1);
3498+
added_monitors.clear();
3499+
}
3500+
let events = nodes[2].node.get_and_clear_pending_events();
3501+
assert_eq!(events.len(), 1);
3502+
match events[0] {
3503+
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => {
3504+
assert!(update_add_htlcs.is_empty());
3505+
assert!(update_fail_htlcs.is_empty());
3506+
assert!(!update_fulfill_htlcs.is_empty());
3507+
assert!(update_fail_malformed_htlcs.is_empty());
3508+
assert_eq!(nodes[1].node.get_our_node_id(), *node_id);
3509+
},
3510+
_ => panic!("Unexpected event"),
3511+
};
3512+
nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
3513+
let events = nodes[2].node.get_and_clear_pending_events();
3514+
assert_eq!(events.len(), 1);
3515+
match events[0] {
3516+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
3517+
_ => panic!("Unexpected event"),
3518+
}
3519+
let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
3520+
3521+
// Verify that B's ChannelManager is able to extract preimage from HTLC Success tx and pass it backward
3522+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn}, 1);
3523+
{
3524+
let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap();
3525+
assert_eq!(added_monitors.len(), 1);
3526+
added_monitors.clear();
3527+
}
3528+
let events = nodes[1].node.get_and_clear_pending_events();
3529+
assert_eq!(events.len(), 2);
3530+
match events[0] {
3531+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
3532+
_ => panic!("Unexpected event"),
3533+
}
3534+
match events[1] {
3535+
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => {
3536+
assert!(update_add_htlcs.is_empty());
3537+
assert!(update_fail_htlcs.is_empty());
3538+
assert!(!update_fulfill_htlcs.is_empty());
3539+
assert!(update_fail_malformed_htlcs.is_empty());
3540+
assert_eq!(nodes[0].node.get_our_node_id(), *node_id);
3541+
},
3542+
_ => panic!("Unexpected event"),
3543+
};
3544+
3545+
// Broadcast legit commitment tx from A on B's chain
3546+
// Broadcast preimage tx by B on offered output from A commitment tx on A's chain
3547+
let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
3548+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
3549+
let events = nodes[1].node.get_and_clear_pending_events();
3550+
assert_eq!(events.len(), 1);
3551+
match events[0] {
3552+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
3553+
_ => panic!("Unexpected event"),
3554+
}
3555+
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
3556+
3557+
// Verify that A's ChannelManager is able to extract preimage from preimage tx and pass it backward
3558+
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn }, 1);
3559+
let events = nodes[0].node.get_and_clear_pending_events();
3560+
assert_eq!(events.len(), 1);
3561+
match events[0] {
3562+
Event::BroadcastChannelUpdate { msg: msgs::ChannelUpdate { .. } } => {},
3563+
_ => panic!("Unexpected event"),
3564+
}
3565+
}
3566+
3567+
//#[test]
3568+
fn test_htlc_on_chain_timeout() {
3569+
// Test that in case of an unilateral close onchain, we detect the state of HTLC (timeout) thanks to
3570+
// ChainWtachInterface and pass the timeout backward
3571+
// A -------> B --------> C --------> D (timeout)
3572+
// output input
3573+
3574+
let nodes = create_network(4);
3575+
3576+
// Create some initial channels
3577+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
3578+
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
3579+
let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3);
3580+
3581+
// Rebalance the network a bit by relaying one payment through all the channels...
3582+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
3583+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
3584+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
3585+
3586+
let (payment_preimage, payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3]), 3000000);
3587+
3588+
// broadcast legit commitment tx from D on C's chain
3589+
let commitment_tx = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan_3.2).unwrap().last_local_commitment_txn.clone();
3590+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
3591+
3592+
// broadcast timeout tx on received
3593+
nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
3594+
test_txn_broadcast(&nodes[2], &chan_3, Some(commitment_tx[0].clone()), HTLCType::TIMEOUT);
3595+
let events = nodes[2].node.get_and_clear_pending_events();
3596+
assert_eq!(events.len(), 1); //should be an UpdateFailHTLC event, verify it
3597+
3598+
let commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone();
3599+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
3600+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
3601+
let node_txn = test_txn_broadcast(&nodes[1], &chan_3, Some(commitment_tx[0].clone()), HTLCType::TIMEOUT);
3602+
let events = nodes[1].node.get_and_clear_pending_events();
3603+
assert_eq!(events.len(), 1); //should be an UpdateFailHTLC event, verify it
3604+
3605+
3606+
//assert!(nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &events[0].updates.update_fulfill_htlcs[0]).is_ok());
3607+
}
3608+
34293609
#[test]
34303610
fn test_htlc_ignore_latest_remote_commitment() {
34313611
// Test that HTLC transactions spending the latest remote commitment transaction are simply

0 commit comments

Comments
 (0)