Add hold_htlc param to internal Channel APIs
What changed, and why it matters
This commit is a small, preparatory code change inside the Lightning Dev Kit's internal channel machinery. It adds a new 'hold_htlc' parameter to internal functions that send HTLCs (payment forwarding instructions), but the commit explicitly states that no code actually sets this flag to true yet. It is groundwork for a future feature described in BOLTs PR 989, which lets an often-offline sender ask a hop to hold an HTLC until a release message arrives. There is no immediate security issue visible in the diff itself.
No immediate action required. Treat as normal feature groundwork. When the full 'hold_htlc' feature is implemented, review the validation, release_held_htlc onion-message handling, and edge cases around held HTLC timeouts or channel force-closes carefully.
Security signals we found
New protocol flag (hold_htlc) wired through internal HTLC sending path
Forwarded HTLC path explicitly hardcoded to false with explanatory comment
No validation logic or behavior change for held HTLCs is introduced
Commit message frames change as groundwork, not active feature
Evidence from the diff
The patch threads a boolean ‘hold_htlc’ through internal Channel send_htlc APIs and serializes it as an Option<()> in the pending HTLC state. Two call sites are updated: one in channel.rs now passes through the deserialized hold_htlc flag from a pending update_add_htlc, and another (for forwarded HTLCs) is hardcoded to false with a comment explaining that forwarded HTLCs are never held at the next hop. channelmanager.rs’s call to send_htlc_and_commit is also hardcoded to false. The commit message says the flag is not yet used.
Changed components
lightning/src/ln/channel.rslightning/src/ln/channelmanager.rsInspect captured patch +10 / −5
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 17bd70d..a1982e7 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -8048,7 +8048,7 @@ where
ref onion_routing_packet,
skimmed_fee_msat,
blinding_point,
- hold_htlc: _,
+ hold_htlc,
..
} => {
match self.send_htlc(
@@ -8060,6 +8060,7 @@ where
false,
skimmed_fee_msat,
blinding_point,
+ hold_htlc.is_some(),
fee_estimator,
logger,
) {
@@ -12022,6 +12023,8 @@ where
true,
skimmed_fee_msat,
blinding_point,
+ // This method is only called for forwarded HTLCs, which are never held at the next hop
+ false,
fee_estimator,
logger,
)
@@ -12052,7 +12055,7 @@ where
fn send_htlc<F: Deref, L: Deref>(
&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32,
source: HTLCSource, onion_routing_packet: msgs::OnionPacket, mut force_holding_cell: bool,
- skimmed_fee_msat: Option<u64>, blinding_point: Option<PublicKey>,
+ skimmed_fee_msat: Option<u64>, blinding_point: Option<PublicKey>, hold_htlc: bool,
fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L,
) -> Result<bool, (LocalHTLCFailureReason, String)>
where
@@ -12134,7 +12137,7 @@ where
onion_routing_packet,
skimmed_fee_msat,
blinding_point,
- hold_htlc: None,
+ hold_htlc: hold_htlc.then(|| ()),
});
return Ok(false);
}
@@ -12156,7 +12159,7 @@ where
blinding_point,
skimmed_fee_msat,
send_timestamp,
- hold_htlc: None,
+ hold_htlc: hold_htlc.then(|| ()),
});
self.context.next_holder_htlc_id += 1;
@@ -12391,7 +12394,7 @@ where
pub fn send_htlc_and_commit<F: Deref, L: Deref>(
&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32,
source: HTLCSource, onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option<u64>,
- fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L,
+ hold_htlc: bool, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L,
) -> Result<Option<ChannelMonitorUpdate>, ChannelError>
where
F::Target: FeeEstimator,
@@ -12406,6 +12409,7 @@ where
false,
skimmed_fee_msat,
None,
+ hold_htlc,
fee_estimator,
logger,
);
diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 3f722ae..a93c7c5 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -5098,6 +5098,7 @@ where
htlc_source,
onion_packet,
None,
+ false,
&self.fee_estimator,
&&logger,
);
Why this scored 18/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.