Skip to content

Commit 91edfdb

Browse files
Gather to-decode HTLC fwds from channels on manager read
We have an overarching goal of (mostly) getting rid of ChannelManager persistence and rebuilding the ChannelManager's state from existing ChannelMonitors, due to issues when the two structs are out-of-sync on restart. The main issue that can arise is channel force closure. Here we start this process by rebuilding ChannelManager::decode_update_add_htlcs from the Channels, which will soon be included in the ChannelMonitors as part of a different series of PRs. The newly built map is not yet used but will be in the next commit.
1 parent 2900eea commit 91edfdb

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

lightning/src/ln/channel.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7778,6 +7778,20 @@ where
77787778
Ok(())
77797779
}
77807780

7781+
/// Useful for reconstructing the set of pending HTLCs when deserializing the `ChannelManager`.
7782+
pub(super) fn get_inbound_committed_update_adds(&self) -> Vec<msgs::UpdateAddHTLC> {
7783+
self.context
7784+
.pending_inbound_htlcs
7785+
.iter()
7786+
.filter_map(|htlc| match htlc.state {
7787+
InboundHTLCState::Committed { ref update_add_htlc_opt } => {
7788+
update_add_htlc_opt.clone()
7789+
},
7790+
_ => None,
7791+
})
7792+
.collect()
7793+
}
7794+
77817795
/// Marks an outbound HTLC which we have received update_fail/fulfill/malformed
77827796
#[inline]
77837797
fn mark_outbound_htlc_removed(

lightning/src/ln/channelmanager.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17358,6 +17358,7 @@ where
1735817358
decode_update_add_htlcs_legacy.unwrap_or_else(|| new_hash_map());
1735917359
let mut pending_intercepted_htlcs_legacy =
1736017360
pending_intercepted_htlcs_legacy.unwrap_or_else(|| new_hash_map());
17361+
let mut decode_update_add_htlcs = new_hash_map();
1736117362
let peer_storage_dir: Vec<(PublicKey, Vec<u8>)> = peer_storage_dir.unwrap_or_else(Vec::new);
1736217363
if fake_scid_rand_bytes.is_none() {
1736317364
fake_scid_rand_bytes = Some(args.entropy_source.get_secure_random_bytes());
@@ -17669,6 +17670,21 @@ where
1766917670
let mut peer_state_lock = peer_state_mtx.lock().unwrap();
1767017671
let peer_state = &mut *peer_state_lock;
1767117672
is_channel_closed = !peer_state.channel_by_id.contains_key(channel_id);
17673+
if let Some(chan) = peer_state.channel_by_id.get(channel_id) {
17674+
if let Some(funded_chan) = chan.as_funded() {
17675+
let inbound_committed_update_adds =
17676+
funded_chan.get_inbound_committed_update_adds();
17677+
if !inbound_committed_update_adds.is_empty() {
17678+
// Reconstruct `ChannelManager::decode_update_add_htlcs` from the serialized
17679+
// `Channel`, as part of removing the requirement to regularly persist the
17680+
// `ChannelManager`.
17681+
decode_update_add_htlcs.insert(
17682+
funded_chan.context.outbound_scid_alias(),
17683+
inbound_committed_update_adds,
17684+
);
17685+
}
17686+
}
17687+
}
1767217688
}
1767317689

1767417690
if is_channel_closed {
@@ -17727,9 +17743,15 @@ where
1772717743
};
1772817744
// The ChannelMonitor is now responsible for this HTLC's
1772917745
// failure/success and will let us know what its outcome is. If we
17730-
// still have an entry for this HTLC in `forward_htlcs` or
17731-
// `pending_intercepted_htlcs`, we were apparently not persisted after
17732-
// the monitor was when forwarding the payment.
17746+
// still have an entry for this HTLC in `forward_htlcs`,
17747+
// `pending_intercepted_htlcs`, or `decode_update_add_htlcs`, we were apparently not
17748+
// persisted after the monitor was when forwarding the payment.
17749+
dedup_decode_update_add_htlcs(
17750+
&mut decode_update_add_htlcs,
17751+
&prev_hop_data,
17752+
"HTLC was forwarded to the closed channel",
17753+
&args.logger,
17754+
);
1773317755
dedup_decode_update_add_htlcs(
1773417756
&mut decode_update_add_htlcs_legacy,
1773517757
&prev_hop_data,
@@ -18220,6 +18242,31 @@ where
1822018242
}
1822118243
}
1822218244

18245+
// De-duplicate HTLCs that are present in both `failed_htlcs` and `decode_update_add_htlcs`.
18246+
// Omitting this de-duplication could lead to redundant HTLC processing and/or bugs.
18247+
for (src, _, _, _, _, _) in failed_htlcs.iter() {
18248+
if let HTLCSource::PreviousHopData(prev_hop_data) = src {
18249+
dedup_decode_update_add_htlcs(
18250+
&mut decode_update_add_htlcs,
18251+
prev_hop_data,
18252+
"HTLC was failed backwards during manager read",
18253+
&args.logger,
18254+
);
18255+
}
18256+
}
18257+
18258+
// See above comment on `failed_htlcs`.
18259+
for htlcs in claimable_payments.values().map(|pmt| &pmt.htlcs) {
18260+
for prev_hop_data in htlcs.iter().map(|h| &h.prev_hop) {
18261+
dedup_decode_update_add_htlcs(
18262+
&mut decode_update_add_htlcs,
18263+
prev_hop_data,
18264+
"HTLC was already decoded and marked as a claimable payment",
18265+
&args.logger,
18266+
);
18267+
}
18268+
}
18269+
1822318270
let best_block = BestBlock::new(best_block_hash, best_block_height);
1822418271
let flow = OffersMessageFlow::new(
1822518272
chain_hash,

0 commit comments

Comments
 (0)