Skip to content

Commit 98ad5d3

Browse files
committed
Track claimed outbound HTLCs in ChannelMonitors
When we receive an update_fulfill_htlc message, we immediately try to "claim" the HTLC against the HTLCSource. If there is one, this works great, we immediately generate a `ChannelMonitorUpdate` for the corresponding inbound HTLC and persist that before we ever get to processing our counterparty's `commitment_signed` and persisting the corresponding `ChannelMonitorUpdate`. However, if there isn't one (and this is the first successful HTLC for a payment we sent), we immediately generate a `PaymentSent` event and queue it up for the user. Then, a millisecond later, we receive the `commitment_signed` from our peer, removing the HTLC from the latest local commitment transaction as a side-effect of the `ChannelMonitorUpdate` applied. If the user has processed the `PaymentSent` event by that point, great, we're done. However, if they have not, and we crash prior to persisting the `ChannelManager`, on startup we get confused about the state of the payment. We'll force-close the channel for being stale, and see an HTLC which was removed and is no longer present in the latest commitment transaction (which we're broadcasting). Because we claim corresponding inbound HTLCs before updating a `ChannelMonitor`, we assume such HTLCs have failed - attempting to fail after having claimed should be a noop. However, in the sent-payment case we now generate a `PaymentFailed` event for the user, allowing an HTLC to complete without giving the user a preimage. Here we address this issue by storing the payment preimages for claimed outbound HTLCs in the `ChannelMonitor`, in addition to the existing inbound HTLC preimages already stored there. This allows us to fix the specific issue described by checking for a preimage and switching the type of event generated in response. In addition, it reduces the risk of future confusion by ensuring we don't fail HTLCs which were claimed but not fully committed to before a crash. It does not, however, full fix the issue here - because the preimages are removed after the HTLC has been fully removed from available commitment transactions if we are substantially delayed in persisting the `ChannelManager` from the time we receive the `update_fulfill_htlc` until after a full commitment signed dance completes we may still hit this issue. The full fix for this issue is to delay the persistence of the `ChannelMonitorUpdate` until after the `PaymentSent` event has been processed. This avoids the issue entirely, ensuring we process the event before updating the `ChannelMonitor`, the same as we ensure the upstream HTLC has been claimed before updating the `ChannelMonitor` for forwarded payments. The full solution will be implemented in a later work, however this change still makes sense at that point as well - if we were to delay the initial `commitment_signed` `ChannelMonitorUpdate` util after the `PaymentSent` event has been processed (which likely requires a database update on the users' end), we'd hold our `commitment_signed` + `revoke_and_ack` response for two DB writes (i.e. `fsync()` calls), making our commitment transaction processing a full `fsync` slower. By making this change first, we can instead delay the `ChannelMonitorUpdate` from the counterparty's final `revoke_and_ack` message until the event has been processed, giving us a full network roundtrip to do so and avoiding delaying our response as long as an `fsync` is faster than a network roundtrip.
1 parent 46fd703 commit 98ad5d3

File tree

5 files changed

+230
-62
lines changed

5 files changed

+230
-62
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::ln::{PaymentHash, PaymentPreimage};
3737
use crate::ln::msgs::DecodeError;
3838
use crate::ln::chan_utils;
3939
use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction};
40-
use crate::ln::channelmanager::HTLCSource;
40+
use crate::ln::channelmanager::{HTLCSource, SentHTLCId};
4141
use crate::chain;
4242
use crate::chain::{BestBlock, WatchedOutput};
4343
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
@@ -498,6 +498,7 @@ pub(crate) enum ChannelMonitorUpdateStep {
498498
LatestHolderCommitmentTXInfo {
499499
commitment_tx: HolderCommitmentTransaction,
500500
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
501+
claimed_htlcs: Vec<(SentHTLCId, PaymentPreimage)>,
501502
},
502503
LatestCounterpartyCommitmentTXInfo {
503504
commitment_txid: Txid,
@@ -540,6 +541,7 @@ impl ChannelMonitorUpdateStep {
540541
impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
541542
(0, LatestHolderCommitmentTXInfo) => {
542543
(0, commitment_tx, required),
544+
(1, claimed_htlcs, vec_type),
543545
(2, htlc_outputs, vec_type),
544546
},
545547
(1, LatestCounterpartyCommitmentTXInfo) => {
@@ -754,6 +756,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
754756
/// Serialized to disk but should generally not be sent to Watchtowers.
755757
counterparty_hash_commitment_number: HashMap<PaymentHash, u64>,
756758

759+
counterparty_fulfilled_htlcs: HashMap<SentHTLCId, PaymentPreimage>,
760+
757761
// We store two holder commitment transactions to avoid any race conditions where we may update
758762
// some monitors (potentially on watchtowers) but then fail to update others, resulting in the
759763
// various monitors for one channel being out of sync, and us broadcasting a holder
@@ -1033,6 +1037,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signe
10331037
(9, self.counterparty_node_id, option),
10341038
(11, self.confirmed_commitment_tx_counterparty_output, option),
10351039
(13, self.spendable_txids_confirmed, vec_type),
1040+
(15, self.counterparty_fulfilled_htlcs, required),
10361041
});
10371042

10381043
Ok(())
@@ -1120,6 +1125,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
11201125
counterparty_claimable_outpoints: HashMap::new(),
11211126
counterparty_commitment_txn_on_chain: HashMap::new(),
11221127
counterparty_hash_commitment_number: HashMap::new(),
1128+
counterparty_fulfilled_htlcs: HashMap::new(),
11231129

11241130
prev_holder_signed_commitment_tx: None,
11251131
current_holder_commitment_tx: holder_commitment_tx,
@@ -1174,7 +1180,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
11741180
&self, holder_commitment_tx: HolderCommitmentTransaction,
11751181
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
11761182
) -> Result<(), ()> {
1177-
self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs).map_err(|_| ())
1183+
self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs, &Vec::new()).map_err(|_| ())
11781184
}
11791185

11801186
/// This is used to provide payment preimage(s) out-of-band during startup without updating the
@@ -1812,7 +1818,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
18121818
///
18131819
/// This is similar to [`Self::get_pending_outbound_htlcs`] except it includes HTLCs which were
18141820
/// resolved by this `ChannelMonitor`.
1815-
pub(crate) fn get_all_current_outbound_htlcs(&self) -> HashMap<HTLCSource, HTLCOutputInCommitment> {
1821+
pub(crate) fn get_all_current_outbound_htlcs(&self) -> HashMap<HTLCSource, (HTLCOutputInCommitment, Option<PaymentPreimage>)> {
18161822
let mut res = HashMap::new();
18171823
// Just examine the available counterparty commitment transactions. See docs on
18181824
// `fail_unbroadcast_htlcs`, below, for justification.
@@ -1822,7 +1828,8 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
18221828
if let Some(ref latest_outpoints) = us.counterparty_claimable_outpoints.get($txid) {
18231829
for &(ref htlc, ref source_option) in latest_outpoints.iter() {
18241830
if let &Some(ref source) = source_option {
1825-
res.insert((**source).clone(), htlc.clone());
1831+
res.insert((**source).clone(), (htlc.clone(),
1832+
us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).cloned()));
18261833
}
18271834
}
18281835
}
@@ -1839,7 +1846,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
18391846

18401847
/// Gets the set of outbound HTLCs which are pending resolution in this channel.
18411848
/// This is used to reconstruct pending outbound payments on restart in the ChannelManager.
1842-
pub(crate) fn get_pending_outbound_htlcs(&self) -> HashMap<HTLCSource, HTLCOutputInCommitment> {
1849+
pub(crate) fn get_pending_outbound_htlcs(&self) -> HashMap<HTLCSource, (HTLCOutputInCommitment, Option<PaymentPreimage>)> {
18431850
let us = self.inner.lock().unwrap();
18441851
// We're only concerned with the confirmation count of HTLC transactions, and don't
18451852
// actually care how many confirmations a commitment transaction may or may not have. Thus,
@@ -1888,7 +1895,10 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
18881895
} else { false }
18891896
});
18901897
if !htlc_update_confd {
1891-
res.insert(source.clone(), htlc.clone());
1898+
if us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).is_none() {
1899+
res.insert(source.clone(), (htlc.clone(),
1900+
us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).cloned()));
1901+
}
18921902
}
18931903
}
18941904
}
@@ -1970,6 +1980,9 @@ macro_rules! fail_unbroadcast_htlcs {
19701980
}
19711981
}
19721982
if matched_htlc { continue; }
1983+
if $self.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).is_some() {
1984+
continue;
1985+
}
19731986
$self.onchain_events_awaiting_threshold_conf.retain(|ref entry| {
19741987
if entry.height != $commitment_tx_conf_height { return true; }
19751988
match entry.event {
@@ -2041,8 +2054,23 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
20412054
// Prune HTLCs from the previous counterparty commitment tx so we don't generate failure/fulfill
20422055
// events for now-revoked/fulfilled HTLCs.
20432056
if let Some(txid) = self.prev_counterparty_commitment_txid.take() {
2044-
for &mut (_, ref mut source) in self.counterparty_claimable_outpoints.get_mut(&txid).unwrap() {
2045-
*source = None;
2057+
let cur_claimables = self.counterparty_claimable_outpoints.get(
2058+
&self.current_counterparty_commitment_txid.unwrap()).unwrap();
2059+
for (_, ref source_opt) in self.counterparty_claimable_outpoints.get(&txid).unwrap() {
2060+
if let Some(source) = source_opt {
2061+
let mut also_in_cur_commitment = false;
2062+
for (_, ref cur_source_opt) in cur_claimables {
2063+
if cur_source_opt == source_opt {
2064+
also_in_cur_commitment = true;
2065+
}
2066+
}
2067+
if !also_in_cur_commitment {
2068+
self.counterparty_fulfilled_htlcs.remove(&SentHTLCId::from_source(source));
2069+
}
2070+
}
2071+
}
2072+
for &mut (_, ref mut source_opt) in self.counterparty_claimable_outpoints.get_mut(&txid).unwrap() {
2073+
*source_opt = None;
20462074
}
20472075
}
20482076

@@ -2127,8 +2155,8 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
21272155
/// is important that any clones of this channel monitor (including remote clones) by kept
21282156
/// up-to-date as our holder commitment transaction is updated.
21292157
/// Panics if set_on_holder_tx_csv has never been called.
2130-
fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), &'static str> {
2131-
// block for Rust 1.34 compat
2158+
fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>, claimed_htlcs: &[(SentHTLCId, PaymentPreimage)]) -> Result<(), &'static str> {
2159+
// block for Rust 1.34 compa
21322160
let mut new_holder_commitment_tx = {
21332161
let trusted_tx = holder_commitment_tx.trust();
21342162
let txid = trusted_tx.txid();
@@ -2149,6 +2177,22 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
21492177
self.onchain_tx_handler.provide_latest_holder_tx(holder_commitment_tx);
21502178
mem::swap(&mut new_holder_commitment_tx, &mut self.current_holder_commitment_tx);
21512179
self.prev_holder_signed_commitment_tx = Some(new_holder_commitment_tx);
2180+
for (claimed_htlc_id, claimed_preimage) in claimed_htlcs {
2181+
#[cfg(debug_assertions)] {
2182+
let mut found_matching_pending_htlc = false;
2183+
for (_, source_opt) in self.counterparty_claimable_outpoints.get(
2184+
&self.current_counterparty_commitment_txid.unwrap()
2185+
).unwrap().iter() {
2186+
if let Some(source) = source_opt {
2187+
if SentHTLCId::from_source(source) == *claimed_htlc_id {
2188+
found_matching_pending_htlc = true;
2189+
}
2190+
}
2191+
}
2192+
assert!(found_matching_pending_htlc);
2193+
}
2194+
self.counterparty_fulfilled_htlcs.insert(*claimed_htlc_id, *claimed_preimage);
2195+
}
21522196
if self.holder_tx_signed {
21532197
return Err("Latest holder commitment signed has already been signed, update is rejected");
21542198
}
@@ -2243,10 +2287,10 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
22432287
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator);
22442288
for update in updates.updates.iter() {
22452289
match update {
2246-
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs } => {
2290+
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs } => {
22472291
log_trace!(logger, "Updating ChannelMonitor with latest holder commitment transaction info");
22482292
if self.lockdown_from_offchain { panic!(); }
2249-
if let Err(e) = self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone()) {
2293+
if let Err(e) = self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs) {
22502294
log_error!(logger, "Providing latest holder commitment transaction failed/was refused:");
22512295
log_error!(logger, " {}", e);
22522296
ret = Err(());
@@ -3868,6 +3912,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
38683912
let mut counterparty_node_id = None;
38693913
let mut confirmed_commitment_tx_counterparty_output = None;
38703914
let mut spendable_txids_confirmed = Some(Vec::new());
3915+
let mut counterparty_fulfilled_htlcs = Some(HashMap::new());
38713916
read_tlv_fields!(reader, {
38723917
(1, funding_spend_confirmed, option),
38733918
(3, htlcs_resolved_on_chain, vec_type),
@@ -3876,6 +3921,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
38763921
(9, counterparty_node_id, option),
38773922
(11, confirmed_commitment_tx_counterparty_output, option),
38783923
(13, spendable_txids_confirmed, vec_type),
3924+
(15, counterparty_fulfilled_htlcs, option),
38793925
});
38803926

38813927
Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl {
@@ -3904,6 +3950,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
39043950
counterparty_claimable_outpoints,
39053951
counterparty_commitment_txn_on_chain,
39063952
counterparty_hash_commitment_number,
3953+
counterparty_fulfilled_htlcs: counterparty_fulfilled_htlcs.unwrap(),
39073954

39083955
prev_holder_signed_commitment_tx,
39093956
current_holder_commitment_tx,

lightning/src/ln/channel.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::ln::features::{ChannelTypeFeatures, InitFeatures};
2727
use crate::ln::msgs;
2828
use crate::ln::msgs::{DecodeError, OptionalField, DataLossProtect};
2929
use crate::ln::script::{self, ShutdownScript};
30-
use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
30+
use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
3131
use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
3232
use crate::ln::chan_utils;
3333
use crate::ln::onion_utils::HTLCFailReason;
@@ -192,6 +192,7 @@ enum OutboundHTLCState {
192192

193193
#[derive(Clone)]
194194
enum OutboundHTLCOutcome {
195+
/// LDK version 0.0.105+ will always fill in the preimage here.
195196
Success(Option<PaymentPreimage>),
196197
Failure(HTLCFailReason),
197198
}
@@ -3159,15 +3160,6 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
31593160
}
31603161
}
31613162

3162-
self.latest_monitor_update_id += 1;
3163-
let mut monitor_update = ChannelMonitorUpdate {
3164-
update_id: self.latest_monitor_update_id,
3165-
updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
3166-
commitment_tx: holder_commitment_tx,
3167-
htlc_outputs: htlcs_and_sigs
3168-
}]
3169-
};
3170-
31713163
for htlc in self.pending_inbound_htlcs.iter_mut() {
31723164
let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
31733165
Some(forward_info.clone())
@@ -3179,18 +3171,36 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
31793171
need_commitment = true;
31803172
}
31813173
}
3174+
let mut claimed_htlcs = Vec::new();
31823175
for htlc in self.pending_outbound_htlcs.iter_mut() {
31833176
if let &mut OutboundHTLCState::RemoteRemoved(ref mut outcome) = &mut htlc.state {
31843177
log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToRemove due to commitment_signed in channel {}.",
31853178
log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id));
31863179
// Grab the preimage, if it exists, instead of cloning
31873180
let mut reason = OutboundHTLCOutcome::Success(None);
31883181
mem::swap(outcome, &mut reason);
3182+
if let OutboundHTLCOutcome::Success(Some(preimage)) = reason {
3183+
// While failing to handle the `Success(None)` case here could result in
3184+
// forgetting some HTLC claims, it is only reachable if the HTLC was claimed on
3185+
// LDK 0.0.104 and prior versions, then upgrading to a modern LDK before the
3186+
// HTLC fully resolves.
3187+
claimed_htlcs.push((SentHTLCId::from_source(&htlc.source), preimage));
3188+
}
31893189
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(reason);
31903190
need_commitment = true;
31913191
}
31923192
}
31933193

3194+
self.latest_monitor_update_id += 1;
3195+
let mut monitor_update = ChannelMonitorUpdate {
3196+
update_id: self.latest_monitor_update_id,
3197+
updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
3198+
commitment_tx: holder_commitment_tx,
3199+
htlc_outputs: htlcs_and_sigs,
3200+
claimed_htlcs,
3201+
}]
3202+
};
3203+
31943204
self.cur_holder_commitment_transaction_number -= 1;
31953205
// Note that if we need_commitment & !AwaitingRemoteRevoke we'll call
31963206
// build_commitment_no_status_check() next which will reset this to RAAFirst.

0 commit comments

Comments
 (0)