Skip to content

Commit bb8ebd4

Browse files
committed
Deduplicate HTLC preimage events from channelmonitor.
This avoids calling get_update_fulfill_htlc_and_commit twice for the same HTLC if we have to rescan a block.
1 parent df283a6 commit bb8ebd4

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

lightning/src/ln/channel.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
11401140
/// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made.
11411141
/// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return
11421142
/// Ok(_) if debug assertions are turned on and preconditions are met.
1143+
///
1144+
/// Note that it is still possible to hit these assertions in case we find a preimage on-chain
1145+
/// but then have a reorg which settles on an HTLC-failure on chain.
11431146
fn get_update_fulfill_htlc(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage) -> Result<(Option<msgs::UpdateFulfillHTLC>, Option<ChannelMonitorUpdate>), ChannelError> {
11441147
// Either ChannelFunded got set (which means it won't be unset) or there is no way any
11451148
// caller thought we could have something claimed (cause we wouldn't have accepted in an
@@ -1167,6 +1170,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
11671170
} else {
11681171
log_warn!(self, "Have preimage and want to fulfill HTLC with payment hash {} we already failed against channel {}", log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id()));
11691172
}
1173+
debug_assert!(false, "Tried to fulfill an HTLC that was already fail/fulfilled");
11701174
return Ok((None, None));
11711175
},
11721176
_ => {
@@ -1202,6 +1206,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12021206
if htlc_id_arg == htlc_id {
12031207
// Make sure we don't leave latest_monitor_update_id incremented here:
12041208
self.latest_monitor_update_id -= 1;
1209+
debug_assert!(false, "Tried to fulfill an HTLC that was already fulfilled");
12051210
return Ok((None, None));
12061211
}
12071212
},
@@ -1210,6 +1215,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12101215
log_warn!(self, "Have preimage and want to fulfill HTLC with pending failure against channel {}", log_bytes!(self.channel_id()));
12111216
// TODO: We may actually be able to switch to a fulfill here, though its
12121217
// rare enough it may not be worth the complexity burden.
1218+
debug_assert!(false, "Tried to fulfill an HTLC that was already failed");
12131219
return Ok((None, Some(monitor_update)));
12141220
}
12151221
},
@@ -1263,6 +1269,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12631269
/// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made.
12641270
/// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return
12651271
/// Ok(_) if debug assertions are turned on and preconditions are met.
1272+
///
1273+
/// Note that it is still possible to hit these assertions in case we find a preimage on-chain
1274+
/// but then have a reorg which settles on an HTLC-failure on chain.
12661275
pub fn get_update_fail_htlc(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket) -> Result<Option<msgs::UpdateFailHTLC>, ChannelError> {
12671276
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
12681277
panic!("Was asked to fail an HTLC when channel was not in an operational state");
@@ -1279,6 +1288,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12791288
match htlc.state {
12801289
InboundHTLCState::Committed => {},
12811290
InboundHTLCState::LocalRemoved(_) => {
1291+
debug_assert!(false, "Tried to fail an HTLC that was already fail/fulfilled");
12821292
return Ok(None);
12831293
},
12841294
_ => {
@@ -1299,11 +1309,13 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12991309
match pending_update {
13001310
&HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => {
13011311
if htlc_id_arg == htlc_id {
1312+
debug_assert!(false, "Tried to fail an HTLC that was already fulfilled");
13021313
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID"));
13031314
}
13041315
},
13051316
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => {
13061317
if htlc_id_arg == htlc_id {
1318+
debug_assert!(false, "Tried to fail an HTLC that was already failed");
13071319
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID"));
13081320
}
13091321
},

lightning/src/ln/channelmonitor.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -2278,19 +2278,23 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
22782278
if let Some((source, payment_hash)) = payment_data {
22792279
let mut payment_preimage = PaymentPreimage([0; 32]);
22802280
if accepted_preimage_claim {
2281-
payment_preimage.0.copy_from_slice(&input.witness[3]);
2282-
self.pending_htlcs_updated.push(HTLCUpdate {
2283-
source,
2284-
payment_preimage: Some(payment_preimage),
2285-
payment_hash
2286-
});
2281+
if !self.pending_htlcs_updated.iter().any(|update| update.source == source) {
2282+
payment_preimage.0.copy_from_slice(&input.witness[3]);
2283+
self.pending_htlcs_updated.push(HTLCUpdate {
2284+
source,
2285+
payment_preimage: Some(payment_preimage),
2286+
payment_hash
2287+
});
2288+
}
22872289
} else if offered_preimage_claim {
2288-
payment_preimage.0.copy_from_slice(&input.witness[1]);
2289-
self.pending_htlcs_updated.push(HTLCUpdate {
2290-
source,
2291-
payment_preimage: Some(payment_preimage),
2292-
payment_hash
2293-
});
2290+
if !self.pending_htlcs_updated.iter().any(|update| update.source == source) {
2291+
payment_preimage.0.copy_from_slice(&input.witness[1]);
2292+
self.pending_htlcs_updated.push(HTLCUpdate {
2293+
source,
2294+
payment_preimage: Some(payment_preimage),
2295+
payment_hash
2296+
});
2297+
}
22942298
} else {
22952299
log_info!(self, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height{})", log_bytes!(payment_hash.0), height + ANTI_REORG_DELAY - 1);
22962300
match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {

0 commit comments

Comments
 (0)