Skip to content

Commit 29d649f

Browse files
Antoine RiardTheBlueMatt
authored andcommitted
Add is_resolving_output in ChannelMonitor
Called in ChannelMonitor block_connected, returning HTLCUpdate upstream via ManyChannelMonitor to link htlcs between monitors. Used by ChannelManager to fulfill/fail htlcs backwards accordingly If spurrious HTLCUpdate are generated due to block re-scan and htlc are already LocalRemoved, discard them in channel get_update_*_htlc
1 parent 84a5072 commit 29d649f

File tree

4 files changed

+188
-30
lines changed

4 files changed

+188
-30
lines changed

src/ln/channel.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,10 +1140,22 @@ impl Channel {
11401140
for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() {
11411141
if htlc.htlc_id == htlc_id_arg {
11421142
assert_eq!(htlc.payment_hash, payment_hash_calc);
1143-
if let InboundHTLCState::Committed = htlc.state {
1144-
} else {
1145-
debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to");
1146-
// Don't return in release mode here so that we can update channel_monitor
1143+
match htlc.state {
1144+
InboundHTLCState::Committed => {},
1145+
InboundHTLCState::LocalRemoved(ref reason) => {
1146+
// ChannelManager may generate duplicate claims due to HTLC update events from on-chain
1147+
// ChannelsMonitors during block rescan
1148+
// TODO: Ideally we'd just drop these
1149+
if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
1150+
return Ok((None, None));
1151+
} else {
1152+
assert!(false, "Got an update_fulfill for previously-failed HTLC!");
1153+
}
1154+
},
1155+
_ => {
1156+
debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to");
1157+
// Don't return in release mode here so that we can update channel_monitor
1158+
}
11471159
}
11481160
pending_idx = idx;
11491161
break;
@@ -1226,10 +1238,22 @@ impl Channel {
12261238
let mut pending_idx = std::usize::MAX;
12271239
for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() {
12281240
if htlc.htlc_id == htlc_id_arg {
1229-
if let InboundHTLCState::Committed = htlc.state {
1230-
} else {
1231-
debug_assert!(false, "Have an inbound HTLC we tried to fail before it was fully committed to");
1232-
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID"));
1241+
match htlc.state {
1242+
InboundHTLCState::Committed => {},
1243+
InboundHTLCState::LocalRemoved(ref reason) => {
1244+
// ChannelManager may generate duplicate claims due to HTLC update events from on-chain
1245+
// ChannelsMonitors during block rescan
1246+
// TODO: Ideally we'd just drop these
1247+
if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
1248+
assert!(false, "Got an update_fail for previously-fulfilled HTLC!");
1249+
} else {
1250+
return Ok(None);
1251+
}
1252+
},
1253+
_ => {
1254+
debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to");
1255+
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matchd the given HTLC ID"));
1256+
}
12331257
}
12341258
pending_idx = idx;
12351259
}
@@ -1251,7 +1275,9 @@ impl Channel {
12511275
},
12521276
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => {
12531277
if htlc_id_arg == htlc_id {
1254-
debug_assert!(false, "Tried to fail an HTLC that we already had a pending failure for");
1278+
// ChannelManager may generate duplicate claims due to HTLC update events from on-chain
1279+
// ChannelsMonitors during block rescan
1280+
// TODO: Ideally we'd just drop these
12551281
return Ok(None);
12561282
}
12571283
},

src/ln/channelmanager.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -679,13 +679,6 @@ impl ChannelManager {
679679
for tx in local_txn {
680680
self.tx_broadcaster.broadcast_transaction(&tx);
681681
}
682-
//TODO: We need to have a way where outbound HTLC claims can result in us claiming the
683-
//now-on-chain HTLC output for ourselves (and, thereafter, passing the HTLC backwards).
684-
//TODO: We need to handle monitoring of pending offered HTLCs which just hit the chain and
685-
//may be claimed, resulting in us claiming the inbound HTLCs (and back-failing after
686-
//timeouts are hit and our claims confirm).
687-
//TODO: In any case, we need to make sure we remove any pending htlc tracking (via
688-
//fail_backwards or claim_funds) eventually for all HTLCs that were in the channel
689682
}
690683

691684
/// Force closes a channel, immediately broadcasting the latest local commitment transaction to
@@ -2718,6 +2711,13 @@ impl ChainListener for ChannelManager {
27182711
for failure in failed_channels.drain(..) {
27192712
self.finish_force_close_channel(failure);
27202713
}
2714+
{
2715+
for htlc_update in self.monitor.fetch_pending_htlc_updated() {
2716+
if let Some(preimage) = htlc_update.payment_preimage {
2717+
self.claim_funds_internal(self.channel_state.lock().unwrap(), htlc_update.source, preimage);
2718+
}
2719+
}
2720+
}
27212721
self.latest_block_height.store(height as usize, Ordering::Release);
27222722
*self.last_block_hash.try_lock().expect("block_(dis)connected must not be called in parallel") = header.bitcoin_hash();
27232723
}

0 commit comments

Comments
 (0)