Optimize dedup_decode_update_add_htlcs
What changed, and why it matters
This commit is a straightforward performance optimization in the Lightning Dev Kit's channel manager. It changes how pending payment packets (HTLCs) are looked up and removed from a tracking map, replacing a full scan of all entries with a direct lookup by channel identifier. There is no security-relevant change visible in the diff.
No security action required. Treat as a normal performance refactor. If desired, verify via unit tests that duplicate HTLC removal behavior is unchanged.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The function dedup_decode_update_add_htlcs previously used HashMap::retain to iterate over every (src_outb_alias, update_add_htlcs) entry and then Vec::retain over each inner vector to find and remove a specific HTLC matching both prev_outbound_scid_alias and htlc_id. The patch replaces this with HashMap::entry(prev_hop_data.prev_outbound_scid_alias), retaining only the matching vector and removing the entry if it becomes empty. The logical behavior appears equivalent: it still removes the same HTLC and removes the map entry if no HTLCs remain. No new input validation, state-machine, or authorization logic is introduced.
Changed components
lightning/src/ln/channelmanager.rsdedup_decode_update_add_htlcsInspect captured patch +25 / −21
diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 7d145e0..1728ced 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -17106,28 +17106,32 @@ fn dedup_decode_update_add_htlcs<L: Deref>(
) where
L::Target: Logger,
{
- decode_update_add_htlcs.retain(|src_outb_alias, update_add_htlcs| {
- update_add_htlcs.retain(|update_add| {
- let matches = *src_outb_alias == prev_hop_data.prev_outbound_scid_alias
- && update_add.htlc_id == prev_hop_data.htlc_id;
- if matches {
- let logger = WithContext::from(
- logger,
- prev_hop_data.counterparty_node_id,
- Some(update_add.channel_id),
- Some(update_add.payment_hash),
- );
- log_info!(
- logger,
- "Removing pending to-decode HTLC with id {}: {}",
- update_add.htlc_id,
- removal_reason
- );
+ match decode_update_add_htlcs.entry(prev_hop_data.prev_outbound_scid_alias) {
+ hash_map::Entry::Occupied(mut update_add_htlcs) => {
+ update_add_htlcs.get_mut().retain(|update_add| {
+ let matches = update_add.htlc_id == prev_hop_data.htlc_id;
+ if matches {
+ let logger = WithContext::from(
+ logger,
+ prev_hop_data.counterparty_node_id,
+ Some(update_add.channel_id),
+ Some(update_add.payment_hash),
+ );
+ log_info!(
+ logger,
+ "Removing pending to-decode HTLC with id {}: {}",
+ update_add.htlc_id,
+ removal_reason
+ );
+ }
+ !matches
+ });
+ if update_add_htlcs.get().is_empty() {
+ update_add_htlcs.remove();
}
- !matches
- });
- !update_add_htlcs.is_empty()
- });
+ },
+ _ => {},
+ }
}
// Implement ReadableArgs for an Arc'd ChannelManager to make it a bit easier to work with the
Why this scored 12/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.