Skip to content

Commit 56d72cf

Browse files
author
Antoine Riard
committed
Time out AwatingRemoteRAA outgoing HTLCs when we reach cltv_expiry
In case of committing out-of-time outgoing HTLCs, we force ourselves to close the channel to avoid remote peer claims on a non-backed HTLC
1 parent 0a4821b commit 56d72cf

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

src/ln/channel.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2756,12 +2756,24 @@ impl Channel {
27562756
}
27572757

27582758
/// Called by channelmanager based on chain blocks being connected.
2759-
/// Note that we only need to use this to detect funding_signed, anything else is handled by
2760-
/// the channel_monitor.
2759+
/// We need to use this to detect funding_signed and outgoing HTLC timed out before we were able
2760+
/// to commit them on remote commitment tx, anything else is handled by the channel_monitor.
27612761
/// In case of Err, the channel may have been closed, at which point the standard requirements
27622762
/// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
27632763
/// Only returns an ErrorAction of DisconnectPeer, if Err.
2764-
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, HandleError> {
2764+
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, [u8; 32])>), HandleError> {
2765+
let mut timed_out_htlcs = Vec::new();
2766+
self.holding_cell_htlc_updates.retain(|htlc_update| {
2767+
match htlc_update {
2768+
&HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, .. } => {
2769+
if cltv_expiry <= &height { // XXX follow 0a4821b
2770+
timed_out_htlcs.push((source.clone(), payment_hash.clone()));
2771+
false
2772+
} else { true }
2773+
},
2774+
_ => true
2775+
}
2776+
});
27652777
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
27662778
if header.bitcoin_hash() != self.last_block_connected {
27672779
self.last_block_connected = header.bitcoin_hash();
@@ -2796,10 +2808,10 @@ impl Channel {
27962808
if need_commitment_update {
27972809
let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
27982810
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret);
2799-
return Ok(Some(msgs::FundingLocked {
2811+
return Ok((Some(msgs::FundingLocked {
28002812
channel_id: self.channel_id,
28012813
next_per_commitment_point: next_per_commitment_point,
2802-
}));
2814+
}), timed_out_htlcs));
28032815
}
28042816
}
28052817
}
@@ -2831,7 +2843,7 @@ impl Channel {
28312843
}
28322844
}
28332845
}
2834-
Ok(None)
2846+
Ok((None, timed_out_htlcs))
28352847
}
28362848

28372849
/// Called by channelmanager based on chain blocks being disconnected.

src/ln/channelmanager.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,20 +2513,23 @@ impl ChainListener for ChannelManager {
25132513
let short_to_id = channel_state.short_to_id;
25142514
let pending_msg_events = channel_state.pending_msg_events;
25152515
channel_state.by_id.retain(|_, channel| {
2516-
let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2517-
if let Ok(Some(funding_locked)) = chan_res {
2518-
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
2519-
node_id: channel.get_their_node_id(),
2520-
msg: funding_locked,
2521-
});
2522-
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2523-
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2516+
let res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2517+
if let Ok((chan_res, mut timed_out_pending_htlcs)) = res {
2518+
timed_out_htlcs.append(&mut timed_out_pending_htlcs);
2519+
if let Some(funding_locked) = chan_res {
2520+
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
25242521
node_id: channel.get_their_node_id(),
2525-
msg: announcement_sigs,
2522+
msg: funding_locked,
25262523
});
2524+
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2525+
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2526+
node_id: channel.get_their_node_id(),
2527+
msg: announcement_sigs,
2528+
});
2529+
}
2530+
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
25272531
}
2528-
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
2529-
} else if let Err(e) = chan_res {
2532+
} else if let Err(e) = res {
25302533
pending_msg_events.push(events::MessageSendEvent::HandleError {
25312534
node_id: channel.get_their_node_id(),
25322535
action: e.action,

0 commit comments

Comments
 (0)