Skip to content

Commit d3a418c

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 27aced9 commit d3a418c

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
@@ -3134,12 +3134,24 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
31343134
}
31353135

31363136
/// Called by channelmanager based on chain blocks being connected.
3137-
/// Note that we only need to use this to detect funding_signed, anything else is handled by
3138-
/// the channel_monitor.
3137+
/// We need to use this to detect funding_signed and outgoing HTLC timed out before we were able
3138+
/// to commit them on remote commitment tx, anything else is handled by the channel_monitor.
31393139
/// In case of Err, the channel may have been closed, at which point the standard requirements
31403140
/// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
31413141
/// Only returns an ErrorAction of DisconnectPeer, if Err.
3142-
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, msgs::ErrorMessage> {
3142+
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> {
3143+
let mut timed_out_htlcs = Vec::new();
3144+
self.holding_cell_htlc_updates.retain(|htlc_update| {
3145+
match htlc_update {
3146+
&HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, ref amount_msat, .. } => {
3147+
if cltv_expiry <= &height {
3148+
timed_out_htlcs.push((source.clone(), payment_hash.clone(), *amount_msat));
3149+
false
3150+
} else { true }
3151+
},
3152+
_ => true
3153+
}
3154+
});
31433155
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
31443156
if header.bitcoin_hash() != self.last_block_connected {
31453157
if self.funding_tx_confirmations > 0 {
@@ -3222,19 +3234,19 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
32223234
if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 {
32233235
let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
32243236
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret);
3225-
return Ok(Some(msgs::FundingLocked {
3237+
return Ok((Some(msgs::FundingLocked {
32263238
channel_id: self.channel_id,
32273239
next_per_commitment_point: next_per_commitment_point,
3228-
}));
3240+
}), timed_out_htlcs));
32293241
} else {
32303242
self.monitor_pending_funding_locked = true;
3231-
return Ok(None);
3243+
return Ok((None, timed_out_htlcs));
32323244
}
32333245
}
32343246
}
32353247
}
32363248
}
3237-
Ok(None)
3249+
Ok((None, timed_out_htlcs))
32383250
}
32393251

32403252
/// 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
@@ -2971,23 +2971,29 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
29712971
let short_to_id = &mut channel_state.short_to_id;
29722972
let pending_msg_events = &mut channel_state.pending_msg_events;
29732973
channel_state.by_id.retain(|_, channel| {
2974-
let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2975-
if let Ok(Some(funding_locked)) = chan_res {
2976-
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
2977-
node_id: channel.get_their_node_id(),
2978-
msg: funding_locked,
2979-
});
2980-
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2981-
log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
2982-
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2974+
let res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2975+
if let Ok((chan_res, mut timed_out_pending_htlcs)) = res {
2976+
timed_out_htlcs.reserve(timed_out_pending_htlcs.len());
2977+
for (htlc_src, payment_hash, value) in timed_out_pending_htlcs.drain(..) {
2978+
timed_out_htlcs.push((htlc_src, payment_hash, value));
2979+
}
2980+
if let Some(funding_locked) = chan_res {
2981+
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
29832982
node_id: channel.get_their_node_id(),
2984-
msg: announcement_sigs,
2983+
msg: funding_locked,
29852984
});
2986-
} else {
2987-
log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
2985+
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2986+
log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
2987+
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2988+
node_id: channel.get_their_node_id(),
2989+
msg: announcement_sigs,
2990+
});
2991+
} else {
2992+
log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
2993+
}
2994+
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
29882995
}
2989-
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
2990-
} else if let Err(e) = chan_res {
2996+
} else if let Err(e) = res {
29912997
pending_msg_events.push(events::MessageSendEvent::HandleError {
29922998
node_id: channel.get_their_node_id(),
29932999
action: msgs::ErrorAction::SendErrorMessage { msg: e },

0 commit comments

Comments
 (0)