Skip to content

Commit 74c258f

Browse files
author
Antoine Riard
committed
Add is_resolving_output in ChannelMonitor to be called by ChannelManager
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 and prune them when htlc is updated by other node
1 parent 7ae15d0 commit 74c258f

File tree

4 files changed

+248
-37
lines changed

4 files changed

+248
-37
lines changed

src/ln/channel.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,7 +1576,7 @@ impl Channel {
15761576

15771577
/// Marks an outbound HTLC which we have received update_fail/fulfill/malformed
15781578
#[inline]
1579-
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<&HTLCSource, ChannelError> {
1579+
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
15801580
for htlc in self.pending_outbound_htlcs.iter_mut() {
15811581
if htlc.htlc_id == htlc_id {
15821582
match check_preimage {
@@ -1596,13 +1596,13 @@ impl Channel {
15961596
OutboundHTLCState::AwaitingRemoteRevokeToRemove | OutboundHTLCState::AwaitingRemovedRemoteRevoke | OutboundHTLCState::RemoteRemoved =>
15971597
return Err(ChannelError::Close("Remote tried to fulfill/fail HTLC that they'd already fulfilled/failed")),
15981598
}
1599-
return Ok(&htlc.source);
1599+
return Ok((&htlc.source, htlc.payment_hash));
16001600
}
16011601
}
16021602
Err(ChannelError::Close("Remote tried to fulfill/fail an HTLC we couldn't find"))
16031603
}
16041604

1605-
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<&HTLCSource, ChannelError> {
1605+
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
16061606
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16071607
return Err(ChannelError::Close("Got fulfill HTLC message when channel was not in an operational state"));
16081608
}
@@ -1618,7 +1618,7 @@ impl Channel {
16181618
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None)
16191619
}
16201620

1621-
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<&HTLCSource, ChannelError> {
1621+
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
16221622
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16231623
return Err(ChannelError::Close("Got fail HTLC message when channel was not in an operational state"));
16241624
}
@@ -1629,7 +1629,7 @@ impl Channel {
16291629
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
16301630
}
16311631

1632-
pub fn update_fail_malformed_htlc<'a>(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<&HTLCSource, ChannelError> {
1632+
pub fn update_fail_malformed_htlc<'a>(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<(&HTLCSource, [u8;32]), ChannelError> {
16331633
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16341634
return Err(ChannelError::Close("Got fail malformed HTLC message when channel was not in an operational state"));
16351635
}

src/ln/channelmanager.rs

Lines changed: 171 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -586,13 +586,7 @@ impl ChannelManager {
586586
for tx in local_txn {
587587
self.tx_broadcaster.broadcast_transaction(&tx);
588588
}
589-
//TODO: We need to have a way where outbound HTLC claims can result in us claiming the
590-
//now-on-chain HTLC output for ourselves (and, thereafter, passing the HTLC backwards).
591-
//TODO: We need to handle monitoring of pending offered HTLCs which just hit the chain and
592-
//may be claimed, resulting in us claiming the inbound HTLCs (and back-failing after
593-
//timeouts are hit and our claims confirm).
594-
//TODO: In any case, we need to make sure we remove any pending htlc tracking (via
595-
//fail_backwards or claim_funds) eventually for all HTLCs that were in the channel
589+
596590
}
597591

598592
/// Force closes a channel, immediately broadcasting the latest local commitment transaction to
@@ -1340,11 +1334,16 @@ impl ChannelManager {
13401334

13411335
let mut add_htlc_msgs = Vec::new();
13421336
for HTLCForwardInfo { prev_short_channel_id, prev_htlc_id, forward_info } in pending_forwards.drain(..) {
1343-
let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData {
1337+
let prev_hop_data = HTLCPreviousHopData {
13441338
short_channel_id: prev_short_channel_id,
13451339
htlc_id: prev_htlc_id,
13461340
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
1347-
});
1341+
};
1342+
match channel_state.claimable_htlcs.entry(forward_info.payment_hash) {
1343+
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(prev_hop_data.clone()),
1344+
hash_map::Entry::Vacant(entry) => { entry.insert(vec![prev_hop_data.clone()]); },
1345+
};
1346+
let htlc_source = HTLCSource::PreviousHopData(prev_hop_data);
13481347
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()) {
13491348
Err(_e) => {
13501349
let chan_update = self.get_channel_update(forward_chan).unwrap();
@@ -1957,21 +1956,50 @@ impl ChannelManager {
19571956

19581957
fn internal_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> {
19591958
let mut channel_state = self.channel_state.lock().unwrap();
1960-
let htlc_source = match channel_state.by_id.get_mut(&msg.channel_id) {
1959+
let (htlc_source, payment_hash) = match channel_state.by_id.get_mut(&msg.channel_id) {
19611960
Some(chan) => {
19621961
if chan.get_their_node_id() != *their_node_id {
19631962
//TODO: here and below MsgHandleErrInternal, #153 case
19641963
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
19651964
}
1966-
chan.update_fulfill_htlc(&msg)
1967-
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?.clone()
1965+
let (htlc_source, payment_hash) = chan.update_fulfill_htlc(&msg)
1966+
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
1967+
(htlc_source.clone(), payment_hash)
19681968
},
19691969
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
19701970
};
1971+
if let Some(sources) = channel_state.claimable_htlcs.get_mut(&payment_hash) {
1972+
if let HTLCSource::PreviousHopData(previous_hop_data) = htlc_source.clone() {
1973+
sources.retain(|ref source| !(source.short_channel_id == previous_hop_data.short_channel_id && source.htlc_id == previous_hop_data.htlc_id));
1974+
}
1975+
}
19711976
self.claim_funds_internal(channel_state, htlc_source, msg.payment_preimage.clone());
19721977
Ok(())
19731978
}
19741979

1980+
fn internal_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), MsgHandleErrInternal> {
1981+
let mut channel_state_lock = self.channel_state.lock().unwrap();
1982+
let channel_state = channel_state_lock.borrow_parts();
1983+
let (htlc_source, payment_hash) = match channel_state.by_id.get_mut(&msg.channel_id) {
1984+
Some(chan) => {
1985+
if chan.get_their_node_id() != *their_node_id {
1986+
//TODO: here and below MsgHandleErrInternal, #153 case
1987+
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
1988+
}
1989+
let (htlc_source, payment_hash) = chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() })
1990+
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
1991+
(htlc_source, payment_hash)
1992+
},
1993+
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
1994+
};
1995+
if let Some(sources) = channel_state.claimable_htlcs.get_mut(&payment_hash) {
1996+
if let HTLCSource::PreviousHopData(previous_hop_data) = htlc_source.clone() {
1997+
sources.retain(|ref source| !(source.short_channel_id == previous_hop_data.short_channel_id && source.htlc_id == previous_hop_data.htlc_id));
1998+
}
1999+
}
2000+
Ok(())
2001+
}
2002+
19752003
// Process failure we got back from upstream on a payment we sent. Returns update and a boolean
19762004
// indicating that the payment itself failed
19772005
fn process_onion_failure(&self, htlc_source: &HTLCSource, mut packet_decrypted: Vec<u8>) -> (Option<msgs::HTLCFailChannelUpdate>, bool) {
@@ -2169,25 +2197,9 @@ impl ChannelManager {
21692197
} else { ((None, true)) }
21702198
}
21712199

2172-
fn internal_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), MsgHandleErrInternal> {
2173-
let mut channel_state = self.channel_state.lock().unwrap();
2174-
match channel_state.by_id.get_mut(&msg.channel_id) {
2175-
Some(chan) => {
2176-
if chan.get_their_node_id() != *their_node_id {
2177-
//TODO: here and below MsgHandleErrInternal, #153 case
2178-
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
2179-
}
2180-
chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() })
2181-
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))
2182-
},
2183-
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
2184-
}?;
2185-
Ok(())
2186-
}
2187-
21882200
fn internal_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), MsgHandleErrInternal> {
21892201
let mut channel_state = self.channel_state.lock().unwrap();
2190-
match channel_state.by_id.get_mut(&msg.channel_id) {
2202+
let (htlc_source, payment_hash) = match channel_state.by_id.get_mut(&msg.channel_id) {
21912203
Some(chan) => {
21922204
if chan.get_their_node_id() != *their_node_id {
21932205
//TODO: here and below MsgHandleErrInternal, #153 case
@@ -2196,12 +2208,18 @@ impl ChannelManager {
21962208
if (msg.failure_code & 0x8000) == 0 {
21972209
return Err(MsgHandleErrInternal::send_err_msg_close_chan("Got update_fail_malformed_htlc with BADONION not set", msg.channel_id));
21982210
}
2199-
chan.update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() })
2211+
let (htlc_source, payment_hash) = chan.update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() })
22002212
.map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
2201-
Ok(())
2213+
(htlc_source.clone(), payment_hash)
22022214
},
22032215
None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
2216+
};
2217+
if let Some(sources) = channel_state.claimable_htlcs.get_mut(&payment_hash) {
2218+
if let HTLCSource::PreviousHopData(previous_hop_data) = htlc_source {
2219+
sources.retain(|ref source| !(source.short_channel_id == previous_hop_data.short_channel_id && source.htlc_id == previous_hop_data.htlc_id));
2220+
}
22042221
}
2222+
Ok(())
22052223
}
22062224

22072225
fn internal_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(), MsgHandleErrInternal> {
@@ -2499,6 +2517,7 @@ impl ChainListener for ChannelManager {
24992517
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) {
25002518
let _ = self.total_consistency_lock.read().unwrap();
25012519
let mut failed_channels = Vec::new();
2520+
let mut hash_to_remove = Vec::new();
25022521
{
25032522
let mut channel_lock = self.channel_state.lock().unwrap();
25042523
let channel_state = channel_lock.borrow_parts();
@@ -2566,10 +2585,31 @@ impl ChainListener for ChannelManager {
25662585
}
25672586
true
25682587
});
2588+
2589+
for tx in txn_matched {
2590+
if let Some(payments_data) = self.monitor.is_resolving_output(&tx) {
2591+
for payment_data in payments_data {
2592+
hash_to_remove.push((payment_data.0, payment_data.1));
2593+
}
2594+
}
2595+
}
25692596
}
25702597
for failure in failed_channels.drain(..) {
25712598
self.finish_force_close_channel(failure);
25722599
}
2600+
{
2601+
let mut channel_state = Some(self.channel_state.lock().unwrap());
2602+
for (preimage, hash) in hash_to_remove {
2603+
if let Some(preimage) = preimage {
2604+
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap());}
2605+
if let Some(mut sources) = channel_state.as_mut().unwrap().claimable_htlcs.remove(&hash) {
2606+
for source in sources.drain(..) {
2607+
self.claim_funds_internal(channel_state.take().unwrap(), HTLCSource::PreviousHopData(source), preimage);
2608+
}
2609+
}
2610+
}
2611+
}
2612+
}
25732613
self.latest_block_height.store(height as usize, Ordering::Release);
25742614
*self.last_block_hash.try_lock().expect("block_(dis)connected must not be called in parallel") = header.bitcoin_hash();
25752615
}
@@ -5237,7 +5277,7 @@ mod tests {
52375277
}
52385278

52395279
/// Tests that the given node has broadcast a claim transaction against the provided revoked
5240-
/// HTLC transaction.
5280+
/// HTLC transaction issued from a revoked commitment tx
52415281
fn test_revoked_htlc_claim_txn_broadcast(node: &Node, revoked_tx: Transaction) {
52425282
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
52435283
assert_eq!(node_txn.len(), 1);
@@ -5960,6 +6000,105 @@ mod tests {
59606000
assert_eq!(nodes[1].node.list_channels().len(), 0);
59616001
}
59626002

6003+
#[test]
6004+
fn test_htlc_on_chain_success() {
6005+
// Test that in case of an unilateral close onchain, we detect the state of output thanks to
6006+
// ChainWatchInterface and pass the preimage backward accordingly. So here we test that ChannelManager is
6007+
// broadcasting the right event to other nodes in payment path.
6008+
// A --------------------> B ----------------------> C (preimage)
6009+
// A's commitment tx C's commitment tx
6010+
// \ \
6011+
// B's preimage tx C's HTLC Success tx
6012+
6013+
let nodes = create_network(3);
6014+
6015+
// Create some initial channels
6016+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
6017+
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
6018+
6019+
// Rebalance the network a bit by relaying one payment through all the channels...
6020+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
6021+
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
6022+
6023+
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
6024+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
6025+
6026+
// Broadcast legit commitment tx from C on B's chain
6027+
// Broadcast HTLC Success transation by C on received output from C's commitment tx on B's chain
6028+
let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone();
6029+
nodes[2].node.claim_funds(payment_preimage);
6030+
{
6031+
let mut added_monitors = nodes[2].chan_monitor.added_monitors.lock().unwrap();
6032+
assert_eq!(added_monitors.len(), 1);
6033+
added_monitors.clear();
6034+
}
6035+
let events = nodes[2].node.get_and_clear_pending_msg_events();
6036+
assert_eq!(events.len(), 1);
6037+
match events[0] {
6038+
MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => {
6039+
assert!(update_add_htlcs.is_empty());
6040+
assert!(update_fail_htlcs.is_empty());
6041+
assert!(!update_fulfill_htlcs.is_empty());
6042+
assert!(update_fail_malformed_htlcs.is_empty());
6043+
assert_eq!(nodes[1].node.get_our_node_id(), *node_id);
6044+
},
6045+
_ => panic!("Unexpected event"),
6046+
};
6047+
nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
6048+
let events = nodes[2].node.get_and_clear_pending_msg_events();
6049+
assert_eq!(events.len(), 1);
6050+
match events[0] {
6051+
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
6052+
_ => panic!("Unexpected event"),
6053+
}
6054+
let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
6055+
6056+
// Verify that B's ChannelManager is able to extract preimage from HTLC Success tx and pass it backward
6057+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn}, 1);
6058+
{
6059+
let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap();
6060+
assert_eq!(added_monitors.len(), 1);
6061+
added_monitors.clear();
6062+
}
6063+
let events = nodes[1].node.get_and_clear_pending_msg_events();
6064+
assert_eq!(events.len(), 2);
6065+
match events[0] {
6066+
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
6067+
_ => panic!("Unexpected event"),
6068+
}
6069+
match events[1] {
6070+
MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => {
6071+
assert!(update_add_htlcs.is_empty());
6072+
assert!(update_fail_htlcs.is_empty());
6073+
assert!(!update_fulfill_htlcs.is_empty());
6074+
assert!(update_fail_malformed_htlcs.is_empty());
6075+
assert_eq!(nodes[0].node.get_our_node_id(), *node_id);
6076+
},
6077+
_ => panic!("Unexpected event"),
6078+
};
6079+
6080+
// Broadcast legit commitment tx from A on B's chain
6081+
// Broadcast preimage tx by B on offered output from A commitment tx on A's chain
6082+
let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
6083+
nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
6084+
let events = nodes[1].node.get_and_clear_pending_msg_events();
6085+
assert_eq!(events.len(), 1);
6086+
match events[0] {
6087+
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
6088+
_ => panic!("Unexpected event"),
6089+
}
6090+
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
6091+
6092+
// Verify that A's ChannelManager is able to extract preimage from preimage tx and pass it backward
6093+
nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn }, 1);
6094+
let events = nodes[0].node.get_and_clear_pending_msg_events();
6095+
assert_eq!(events.len(), 1);
6096+
match events[0] {
6097+
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
6098+
_ => panic!("Unexpected event"),
6099+
}
6100+
}
6101+
59636102
#[test]
59646103
fn test_htlc_ignore_latest_remote_commitment() {
59656104
// Test that HTLC transactions spending the latest remote commitment transaction are simply

0 commit comments

Comments
 (0)