Skip to content

Commit fe8de93

Browse files
Antoine RiardTheBlueMatt
Antoine Riard
authored andcommitted
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 e112a94 commit fe8de93

File tree

2 files changed

+39
-21
lines changed

2 files changed

+39
-21
lines changed

lightning/src/ln/channel.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3121,12 +3121,24 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
31213121
}
31223122

31233123
/// Called by channelmanager based on chain blocks being connected.
3124-
/// Note that we only need to use this to detect funding_signed, anything else is handled by
3125-
/// the channel_monitor.
3124+
/// We need to use this to detect funding_signed and outgoing HTLC timed out before we were able
3125+
/// to commit them on remote commitment tx, anything else is handled by the channel_monitor.
31263126
/// In case of Err, the channel may have been closed, at which point the standard requirements
31273127
/// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
31283128
/// Only returns an ErrorAction of DisconnectPeer, if Err.
3129-
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, msgs::ErrorMessage> {
3129+
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash, u64)>), msgs::ErrorMessage> {
3130+
let mut timed_out_htlcs = Vec::new();
3131+
self.holding_cell_htlc_updates.retain(|htlc_update| {
3132+
match htlc_update {
3133+
&HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, ref amount_msat, .. } => {
3134+
if cltv_expiry <= &height {
3135+
timed_out_htlcs.push((source.clone(), payment_hash.clone(), *amount_msat));
3136+
false
3137+
} else { true }
3138+
},
3139+
_ => true
3140+
}
3141+
});
31303142
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
31313143
if header.bitcoin_hash() != self.last_block_connected {
31323144
if self.funding_tx_confirmations > 0 {
@@ -3209,19 +3221,19 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
32093221
if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 {
32103222
let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
32113223
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret);
3212-
return Ok(Some(msgs::FundingLocked {
3224+
return Ok((Some(msgs::FundingLocked {
32133225
channel_id: self.channel_id,
32143226
next_per_commitment_point: next_per_commitment_point,
3215-
}));
3227+
}), timed_out_htlcs));
32163228
} else {
32173229
self.monitor_pending_funding_locked = true;
3218-
return Ok(None);
3230+
return Ok((None, timed_out_htlcs));
32193231
}
32203232
}
32213233
}
32223234
}
32233235
}
3224-
Ok(None)
3236+
Ok((None, timed_out_htlcs))
32253237
}
32263238

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

lightning/src/ln/channelmanager.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,23 +2874,29 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
28742874
let short_to_id = &mut channel_state.short_to_id;
28752875
let pending_msg_events = &mut channel_state.pending_msg_events;
28762876
channel_state.by_id.retain(|_, channel| {
2877-
let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2878-
if let Ok(Some(funding_locked)) = chan_res {
2879-
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
2880-
node_id: channel.get_their_node_id(),
2881-
msg: funding_locked,
2882-
});
2883-
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2884-
log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
2885-
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2877+
let res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2878+
if let Ok((chan_res, mut timed_out_pending_htlcs)) = res {
2879+
timed_out_htlcs.reserve(timed_out_pending_htlcs.len());
2880+
for (htlc_src, payment_hash, value) in timed_out_pending_htlcs.drain(..) {
2881+
timed_out_htlcs.push((htlc_src, payment_hash, value));
2882+
}
2883+
if let Some(funding_locked) = chan_res {
2884+
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
28862885
node_id: channel.get_their_node_id(),
2887-
msg: announcement_sigs,
2886+
msg: funding_locked,
28882887
});
2889-
} else {
2890-
log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
2888+
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2889+
log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
2890+
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2891+
node_id: channel.get_their_node_id(),
2892+
msg: announcement_sigs,
2893+
});
2894+
} else {
2895+
log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
2896+
}
2897+
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
28912898
}
2892-
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
2893-
} else if let Err(e) = chan_res {
2899+
} else if let Err(e) = res {
28942900
pending_msg_events.push(events::MessageSendEvent::HandleError {
28952901
node_id: channel.get_their_node_id(),
28962902
action: msgs::ErrorAction::SendErrorMessage { msg: e },

0 commit comments

Comments
 (0)