Skip to content

Commit 7c23847

Browse files
Antoine RiardTheBlueMatt
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 9fd8107 commit 7c23847

File tree

2 files changed

+54
-27
lines changed

2 files changed

+54
-27
lines changed

lightning/src/ln/channel.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use secp256k1;
1818
use ln::features::{ChannelFeatures, InitFeatures};
1919
use ln::msgs;
2020
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
21-
use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep};
21+
use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER};
2222
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
2323
use ln::chan_utils::{CounterpartyCommitmentSecrets, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys};
2424
use ln::chan_utils;
@@ -3154,13 +3154,33 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
31543154
self.network_sync == UpdateStatus::DisabledMarked
31553155
}
31563156

3157-
/// Called by channelmanager based on chain blocks being connected.
3158-
/// Note that we only need to use this to detect funding_signed, anything else is handled by
3159-
/// the channel_monitor.
3160-
/// In case of Err, the channel may have been closed, at which point the standard requirements
3161-
/// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
3157+
/// When we receive a new block, we (a) check whether the block contains the funding
3158+
/// transaction (which would start us counting blocks until we send the funding_signed), and
3159+
/// (b) check the height of the block against outbound holding cell HTLCs in case we need to
3160+
/// give up on them prematurely and time them out. Everything else (e.g. commitment
3161+
/// transaction broadcasts, channel closure detection, HTLC transaction broadcasting, etc) is
3162+
/// handled by the ChannelMonitor.
3163+
///
3164+
/// If we return Err, the channel may have been closed, at which point the standard
3165+
/// requirements apply - no calls may be made except those explicitly stated to be allowed
3166+
/// post-shutdown.
31623167
/// Only returns an ErrorAction of DisconnectPeer, if Err.
3163-
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, msgs::ErrorMessage> {
3168+
///
3169+
/// May return some HTLCs (and their payment_hash) which have timed out and should be failed
3170+
/// back.
3171+
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)>), msgs::ErrorMessage> {
3172+
let mut timed_out_htlcs = Vec::new();
3173+
self.holding_cell_htlc_updates.retain(|htlc_update| {
3174+
match htlc_update {
3175+
&HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, .. } => {
3176+
if *cltv_expiry <= height + HTLC_FAIL_BACK_BUFFER {
3177+
timed_out_htlcs.push((source.clone(), payment_hash.clone()));
3178+
false
3179+
} else { true }
3180+
},
3181+
_ => true
3182+
}
3183+
});
31643184
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
31653185
if header.bitcoin_hash() != self.last_block_connected {
31663186
if self.funding_tx_confirmations > 0 {
@@ -3243,19 +3263,19 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
32433263
if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 {
32443264
let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
32453265
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret);
3246-
return Ok(Some(msgs::FundingLocked {
3266+
return Ok((Some(msgs::FundingLocked {
32473267
channel_id: self.channel_id,
32483268
next_per_commitment_point: next_per_commitment_point,
3249-
}));
3269+
}), timed_out_htlcs));
32503270
} else {
32513271
self.monitor_pending_funding_locked = true;
3252-
return Ok(None);
3272+
return Ok((None, timed_out_htlcs));
32533273
}
32543274
}
32553275
}
32563276
}
32573277
}
3258-
Ok(None)
3278+
Ok((None, timed_out_htlcs))
32593279
}
32603280

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

lightning/src/ln/channelmanager.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,23 +2962,32 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
29622962
let short_to_id = &mut channel_state.short_to_id;
29632963
let pending_msg_events = &mut channel_state.pending_msg_events;
29642964
channel_state.by_id.retain(|_, channel| {
2965-
let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2966-
if let Ok(Some(funding_locked)) = chan_res {
2967-
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
2968-
node_id: channel.get_their_node_id(),
2969-
msg: funding_locked,
2970-
});
2971-
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2972-
log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
2973-
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2965+
let res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
2966+
if let Ok((chan_res, mut timed_out_pending_htlcs)) = res {
2967+
for (source, payment_hash) in timed_out_pending_htlcs.drain(..) {
2968+
let chan_update = self.get_channel_update(&channel).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
2969+
timed_out_htlcs.push((source, payment_hash, HTLCFailReason::Reason {
2970+
failure_code: 0x1000 | 14, // expiry_too_soon, or at least it is now
2971+
data: chan_update,
2972+
}));
2973+
}
2974+
if let Some(funding_locked) = chan_res {
2975+
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
29742976
node_id: channel.get_their_node_id(),
2975-
msg: announcement_sigs,
2977+
msg: funding_locked,
29762978
});
2977-
} else {
2978-
log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
2979+
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2980+
log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
2981+
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2982+
node_id: channel.get_their_node_id(),
2983+
msg: announcement_sigs,
2984+
});
2985+
} else {
2986+
log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
2987+
}
2988+
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
29792989
}
2980-
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
2981-
} else if let Err(e) = chan_res {
2990+
} else if let Err(e) = res {
29822991
pending_msg_events.push(events::MessageSendEvent::HandleError {
29832992
node_id: channel.get_their_node_id(),
29842993
action: msgs::ErrorAction::SendErrorMessage { msg: e },
@@ -3049,8 +3058,6 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
30493058
}
30503059

30513060
for (source, payment_hash, reason) in timed_out_htlcs.drain(..) {
3052-
// Call it incorrect_or_unknown_payment_details as the issue, ultimately, is that the
3053-
// user failed to provide us a preimage within the cltv_expiry time window.
30543061
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), source, &payment_hash, reason);
30553062
}
30563063
self.latest_block_height.store(height as usize, Ordering::Release);

0 commit comments

Comments
 (0)