Every captured commit receives deterministic security triage and a separate communication-quality score. Security candidates and broader second-pass signals receive full-patch Ollama analysis.
Message quality measures whether a commit identifies its scope, purpose, rationale, testing, and supporting references. It does not change the security-severity score.
This commit makes on-chain 'MonitorEvent' notifications durable and replay-safe. Previously, if a node crashed after a ChannelMonitor persisted a block update but before the ChannelManager processed the resulting event, the event could be …
Durability/atomicity fix for async persistence: prevents lost MonitorEvents across crashesNew ack-based event lifecycle with random event IDsArchival gating on unacknowledged events to avoid losing preimage/timeout information
This commit refactors how LDK nodes claim incoming Lightning payments. It replaces a separate 'claim with known custom TLVs' method with an options struct passed to the normal claim call, and fixes two edge cases in payment attribution dat…
API change: claim_funds now takes ClaimFundsOptions, consolidating TLV-known behavior into one pathFailure-packet length bound added to prevent oversized onion error messagesIncoming failure packet truncated at 32 KiB before processing
This change fixes a wallet bookkeeping problem in rust-lightning's built-in coin-selection wrappers. Previously, when a splice attempt failed or coin selection errored after picking UTXOs, those UTXOs stayed marked as 'reserved' in memory …
Resource exhaustion / denial-of-service via permanent in-memory UTXO reservationIncorrect state tracking in coin-selection wrapperNew API method required for correct lifecycle management (release_utxos)
This commit fixes a bug in the wallet's coin-selection code. When the wallet picked UTXOs to spend, it locked them immediately so they couldn't be reused. But if a later step—fetching the change address or the previous transaction—failed, …
Resource lock leak on error pathUTXO lock state inconsistency between selection and confirmationDenial-of-service/funds-unavailability risk from persistent UTXO locks
This commit rewrites how a Lightning wallet talks to Esplora block-explorer servers so that many status checks happen in parallel instead of one at a time. It is a performance/refactoring change. There is no direct evidence in the commit t…
Concurrency/timing change in transaction confirmation logicNew inconsistency check preserved when a previously-confirmed tx is reported unconfirmedAdded defensive error path for missing pre-fetched block status
This change stops the Electrum-based transaction sync client from downloading the very transaction that created an output it is watching. Previously, the client could request that transaction from Electrum, even though a transaction can ne…
Avoids unnecessary Electrum transaction.get requests for watched outputsReduces information disclosure to Electrum server about watched outpointsAdds regression test verifying request suppression
This change improves how the Lightning Dev Kit's Electrum and Esplora transaction-sync clients track watched Bitcoin transactions. Previously, the code ignored the script pubkey (the 'address' associated with a transaction) supplied when r…
Previously ignored `script_pubkey` argument in `register_tx` for transaction watchersElectrum script-history queries previously used an arbitrary transaction output, which could be OP_RETURN and therefore unindexed by some Electrum serversNew logic prefers caller-supplied script pubkey and falls back to non-OP_RETURN outputs
This commit changes how LDK stores pending event notifications. It adds serialization support for several event types that previously were not fully saved to disk, and introduces a helper method so the code can decide which events are wort…
Data-loss prevention: previously non-round-trippable event variants are now fully serialized, avoiding accidental event loss when users serialize Event queues themselvesState-consistency hardening: ChannelManager now explicitly skips events that describe non-surviving restart state, preventing replay of stale eventsDefensive assertion: debug builds assert that every persisted event round-trips to Some(event), catching serialization mismatches
This commit only adds documentation comments to two source files. It explains that certain funding-signing events can become stale if the underlying negotiation fails, and that callers may see specific harmless errors as a result. No code …
This commit fixes a design flaw in LDK's built-in wallet helper where coins selected for a splice-in (or other unclaimed funding) were permanently reserved in memory if the transaction was abandoned. Over repeated failed splices, all spend…
Denial-of-service via UTXO exhaustion from repeated failed splice negotiationsRisk of inability to broadcast fee-bumping/claim transactions due to lack of available UTXOsNew API surface (release_utxos) introduced to mitigate resource leak
This commit removes a fixed-version pin for the honggfuzz fuzzing tool in a continuous-integration script. The project now uses the current release of honggfuzz instead of an older pinned version. There is no change to the actual Lightning…
This commit changes the Rust toolchain used in the continuous integration (CI) fuzzing job from a fixed older version (1.75) to the latest stable release. It is purely a build/test infrastructure change to fix a dependency compatibility is…
This commit makes a previously internal helper function public so that outside developers can build dummy-hop tails for blinded payment paths without recreating the logic themselves. It is an API usability change, not a fix for a known sec…
No security-relevant behavior change in the diffAPI visibility broadened from crate-public to publicCLTV expiry overflow check already present and unchanged
This change adds a safety check in a Bitcoin Lightning Network library (LDK). Previously, if the software tried to verify a peer's commitment signature before it had learned the peer's channel parameters, it could crash with a panic. Now i…
Defensive check added on peer-driven code path to prevent panicMissing counterparty_parameters could previously cause panic during commitment transaction constructionChannel closure returned instead of panic
This commit only changes the wording of an error message sent to peers when a commitment transaction fails validation. It replaces the vague phrase 'Failed to validate our commitment' with the clearer 'Received commitment failed validation…
This commit moves the checks that validate a counterparty's signatures on the holder's commitment and HTLC transactions out of the general channel code and into the signer module (InMemorySigner). Previously, these signature checks were do…
Moved signature validation from channel state machine into signer moduleAdded new tests that corrupt signatures and verify rejectionChanged error message from 'Invalid commitment tx signature from peer' / 'Invalid funding_created signature from peer' to 'Failed to validate our commitment'
This change fixes a Lightning channel splicing bug: when two peers temporarily disconnect during a splice, any half-finished signature the other side already sent is now discarded. Before the fix, that stale signature could be reused after…
State-invalidation bug in multi-step protocol (splice negotiation)Stale cryptographic signature not cleared on disconnectPotential reuse of old commitment state after reconnect
This fix prevents a Lightning channel from being accidentally force-closed. During a splice (a way to resize a payment channel), one side's initial signature could be kept in memory after the peers disconnected. If the peers later reconnec…
State inconsistency: in-memory buffered message not cleared on disconnectDuplicate message processing after reconnectionForce-close consequence for active Lightning channel
This commit is a simple rename of a public function from `matches_invoice_signing_pubkey` to `key_can_sign_invoice`, plus matching updates to its documentation, callers, tests, and changelog. No behavior changed. It is not a security fix.
This commit is a simple rename of a function and its documentation from matches_invoice_signing_pubkey to key_can_sign_invoice. No logic, behavior, or security properties changed. It is a follow-up code-review naming cleanup.
Expand any commit for its author, full message, clarity score, changed files, triage signals, analysis, and source link.
Lower-priorityRebuild pending payments list before replaying pending claims/failsby Matt Corallo · 8106dbfd · Aug 26, 2025 · 1 fileMessage 73 · AdequateLow 34Details
Commit message · Matt Corallo
Rebuild pending payments list before replaying pending claims/fails
On `ChannelManager` reload we rebuild the pending outbound payments list by looking for any missing payments in `ChannelMonitor`s. However, in the same loop over `ChannelMonitor`s, we also re-claim any pending payments which we see we have a payment preimage for.
If we send an MPP payment across different chanels, the result may be that we'll iterate the loop, and in each iteration add a pending payment with only one known path, then claim/fail it and remove the pending apyment (at least for the claim case). This may result in spurious extra events, or even both a `PaymentFailed` and `PaymentSent` event on startup for the same payment.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Low 34/100
This patch fixes a startup bug in the Lightning Dev Kit's channel manager. When the software restarts, it scans past payment data to rebuild its list of pending payments and to finalize any that already have a result. Previously, these two steps were mixed together in one loop, which could cause a multi-path payment to be partially rebuilt and then finalized before all paths were seen. This could produce duplicate or contradictory events, such as reporting the same payment as both failed and sent. The fix separates the work into two loops: first rebuild all pending payments, then finalize them. There is no direct security exploit here, but the inconsistent state could confuse downstream software or users.
Lower-priority`rustfmt` and clean up `get_onchain_failed_outbound_htlcs`by Matt Corallo · 9186900a · Aug 26, 2025 · 1 fileMessage 50 · ThinInformational 15Details
Commit message · Matt Corallo
`rustfmt` and clean up `get_onchain_failed_outbound_htlcs`
50/100 · ThinMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component! No meaningful explanatory body
AI analysis · Informational 15/100
This commit is purely a code cleanup: it removes a `#[rustfmt::skip]` annotation and reformats a helper function, converting a macro into an equivalent closure. There is no functional change to how the software processes payments or channel data.
Lower-priorityRe-fail perm-failed HTLCs on startup in case of `MonitorEvent` lossby Matt Corallo · f809e6c8 · Aug 26, 2025 · 3 filesMessage 85 · StrongModerate 53Details
Commit message · Matt Corallo
Re-fail perm-failed HTLCs on startup in case of `MonitorEvent` loss
`MonitorEvent`s aren't delivered to the `ChannelManager` in a durable fashion - if the `ChannelManager` fetches the pending `MonitorEvent`s, then the `ChannelMonitor` gets persisted (i.e. due to a block update) then the node crashes, prior to persisting the `ChannelManager` again, the `MonitorEvent` and its effects on the `ChannelManger` will be lost. This isn't likely in a sync persist environment, but in an async one this could be an issue.
Note that this is only an issue for closed channels - `MonitorEvent`s only inform the `ChannelManager` that a channel is closed (which the `ChannelManager` will learn on startup or when it next tries to advance the channel state), that `ChannelMonitorUpdate` writes completed (which the `ChannelManager` will detect on startup), or that HTLCs resolved on-chain post closure. Of the three, only the last is problematic to lose prior to a reload.
In a previous commit we handled the case of claimed HTLCs by replaying payment preimages on startup to avoid `MonitorEvent` loss causing us to miss an HTLC claim. Here we handle the HTLC-failed case similarly.
Unlike with HTLC claims via preimage, we don't already have replay logic in `ChannelManager` startup, but its easy enough to add one. Luckily, we already track when an HTLC reaches permanently-failed state in `ChannelMonitor` (i.e. it has `ANTI_REORG_DELAY` confirmations on-chain on the failing transaction), so all we need to do is add the ability to query for that and fail them on `ChannelManager` startup.
85/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
AI analysis · Moderate 53/100
This commit fixes a bug in rust-lightning where a Lightning node could permanently lose track of failed payments after a crash. If the node crashed at exactly the wrong moment, it might never report that a payment had failed, leaving funds in limbo and potentially causing the user or downstream nodes to wait forever. The fix makes the node re-check on startup whether any HTLCs (payment contracts) were already resolved as failed on-chain, and if so, properly fail them again in its internal state.
Lower-priorityAdd clarifying comment to signer_maybe_unblockedby Jeffrey Czyz · de65412a · Aug 26, 2025 · 1 fileMessage 45 · ThinInformational 15Details
Commit message · Jeffrey Czyz
Add clarifying comment to signer_maybe_unblocked
45/100 · ThinMessage clarity
✓ Descriptive subject✓ Names a concrete action or component! No meaningful explanatory body
AI analysis · Informational 15/100
This commit only adds a clarifying code comment explaining why a specific transaction number is used when building a commitment transaction. No code behavior was changed, so there is no security impact.
Lower-priorityInclude fees in SpliceContribution docsby Jeffrey Czyz · 8213f65d · Aug 25, 2025 · 1 fileMessage 68 · AdequateInformational 15Details
Commit message · Jeffrey Czyz
Include fees in SpliceContribution docs
How fees are paid for in a SpliceContribution depends on whether it is a SpliceIn or SpliceOut. Include this in its docs for clarification.
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Informational 15/100
This commit only updates documentation comments for the SpliceContribution type. It clarifies that users must account for transaction fees when providing inputs for a splice-in or outputs for a splice-out. No code behavior changed.
Lower-priorityFix debug_assert on our_funding_contributionby Jeffrey Czyz · 9fa6e3c6 · Aug 25, 2025 · 1 fileMessage 58 · ThinInformational 16Details
Commit message · Jeffrey Czyz
Fix debug_assert on our_funding_contribution
When processing a splice_ack, the debug_assert on the range of our_funding_contribution should account for values that are for both positive (splice-in) and negative (splice-out).
This commit fixes a sanity check (debug_assert) used during a new experimental feature called splicing in the Lightning Dev Kit. The check previously only accepted positive funding contributions, but splicing can also involve negative contributions (splice-out). The fix makes the check use the absolute value. This is a debug-only assertion, so it only affects test/debug builds and cannot be exploited in production release builds.
Update SpliceContribution with a variant used to support splice-out (i.e., removing funds from a channel). The TxOut values must not exceed the users channel balance after accounting for fees and the reserve requirement.
51/100 · ThinMessage clarity
✓ Subject identifies a change✓ Provides detailed explanatory context
AI analysis · Low 32/100
This commit adds 'splice-out' support to the Lightning Dev Kit, allowing users to remove funds from an existing channel while keeping the channel open. The change introduces new code paths that handle negative contributions (removing funds) and adds checks to ensure the user cannot remove more than their channel balance after accounting for fees and reserve requirements. It is a feature addition, not a documented security fix, but it touches sensitive financial-validation logic.
When a counterparty sends splice_init with a negative contribution, they are requesting to remove funds from a channel. Remove conditions guarding against this and check that they have enough channel balance to cover the removed funds.
This commit adds support for 'splice-out', a way for a Lightning channel partner to remove funds from an existing channel rather than only adding funds. Previously, the code rejected negative contribution values outright. The change removes that blanket rejection and adds checks to ensure the counterparty actually has enough balance in the channel to cover the requested withdrawal. It also centralizes validation of the counterparty's splice contribution in a new helper function used in both incoming and outgoing splice paths.
Lower-priorityUse a SpliceContribution enum for passing splice-in paramsby Jeffrey Czyz · ae58a4f6 · Aug 25, 2025 · 4 filesMessage 73 · AdequateInformational 15Details
Commit message · Jeffrey Czyz
Use a SpliceContribution enum for passing splice-in params
ChannelManager::splice_channel takes individual parameters to support splice-in. Change these to an enum such that it can be used for splice-out as well.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Informational 15/100
This commit is a straightforward code refactor. It bundles several parameters related to adding funds to a Lightning channel (a 'splice-in') into a single new enum called SpliceContribution. The goal is to make the API cleaner and prepare it for a future 'splice-out' feature. There is no security fix or vulnerability here.
The funding inputs used for splicing and v2 channel establishment are passed as a tuple of txin, prevtx, and witness weight. Add a struct so that the items included can be better documented.
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Informational 15/100
This commit is a straightforward internal code cleanup in the Lightning Dev Kit's rust-lightning project. It replaces a plain tuple (a simple grouping of three related pieces of data) with a named struct called FundingTxInput for funding inputs used in splicing and v2 channel establishment. The change improves code readability and documentation but does not fix a security bug or change user-facing behavior in a security-relevant way.
To align with the "current" and "next" nomenclature used by HolderCommitmentPoint, update the naming of the counterparty commitment point field to use "current" instead of "previous".
This commit is a pure internal rename of a variable from 'previous' to 'current' to make the code easier to understand. No behavior changed, and there is no security issue.
To align with the "current" and "next" nomenclature used by HolderCommitmentPoint, update the naming of the counterparty commitment point field to use "next" instead of "current".
This commit is a simple rename of an internal variable from 'current' to 'next' to make the code's naming more consistent. It does not change any program logic, security behavior, or data format. There is no security issue here.
To align with the "current" and "next" nomenclature used by HolderCommitmentPoint, update the naming of the counterparty commitment transaction number field to use "next" instead of "current".
This commit is a simple rename of an internal variable from 'cur_counterparty_commitment_transaction_number' to 'counterparty_next_commitment_transaction_number' to make the naming more consistent with other parts of the code. There are no functional changes, no bug fixes, and no security implications.
✓ Descriptive subject✓ Names a concrete action or component! No meaningful explanatory body
AI analysis · Low 42/100
This change replaces a hard program crash (an 'expect' call that would terminate the node) with a graceful error return when a specific piece of channel state is missing during a splicing operation. Instead of the entire Lightning node panicking and shutting down, the node now reports a controlled channel-closing error. This is a defensive improvement that reduces denial-of-service risk from malformed or unexpected peer messages, but the commit itself does not claim a security vulnerability was fixed.
Lower-priorityDelete dead `next_{local, remote}_commitment_tx_fee_info_cached`by Leo Nash · f75812ff · Aug 21, 2025 · 1 fileMessage 75 · AdequateInformational 14Details
Commit message · Leo Nash
Delete dead `next_{local, remote}_commitment_tx_fee_info_cached`
The cached fee is never checked in the current test suite.
75/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides an explanatory body✓ Mentions testing or verification
AI analysis · Informational 14/100
This commit removes unused test-only code that cached predicted commitment transaction fees. The removed fields were only compiled under test/fuzzing configurations and were never checked by the current test suite. The commit does not change production behavior or fix any security issue.
Lower-priorityAdd validation of the fees predicted by `next_commitment_stats`by Leo Nash · 8a1c9d94 · Aug 21, 2025 · 1 fileMessage 73 · AdequateLow 27Details
Commit message · Leo Nash
Add validation of the fees predicted by `next_commitment_stats`
Anytime we build a (feerate, nondust-htlc-count, fee) pair, cache it, and check that the fee matches if the feerate and nondust-htlc-count match when building a commitment transaction.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Low 27/100
This commit adds internal bookkeeping and consistency checks to make sure the fee predicted when planning a Lightning channel commitment transaction matches the fee actually used when the transaction is later built. It only runs during tests and fuzzing, so it does not directly change production behavior. It is a defensive hardening/debugging patch rather than a fix for an active exploit.
Lower-priorityAdd `ChannelContext::get_next_{local, remote}_commitment_stats`by Leo Nash · 06ed9cb5 · Aug 21, 2025 · 1 fileMessage 73 · AdequateInformational 11Details
In upcoming commits, these methods will serve as proxies to `SpecTxBuilder::get_next_commitment_stats` in all validation of channel updates in `ChannelContext`.
Eventually, these methods will completely replace `get_pending_htlc_stats`, and `get_next_{local, remote}_commit_tx_fee_msat`.
When predicting the HTLCs on next commitment, we take the conservative approach and only assume that a HTLC will not be in the next commitment when it is guaranteed that it won't be.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Informational 11/100
This commit adds four new private helper methods to the Lightning channel code. The methods are marked `#[allow(dead_code)]`, meaning they are not yet called anywhere. They are intended to replace older balance/fee estimation helpers in future commits. There is no functional change to how channels are validated today, and no security fix or vulnerability is introduced in this patch.
Lower-priorityImprove prediction of commitment stats in `can_send_update_fee`by Leo Nash · 124bd421 · Aug 21, 2025 · 1 fileMessage 73 · AdequateModerate 63Details
Commit message · Leo Nash
Improve prediction of commitment stats in `can_send_update_fee`
`ChannelContext::get_pending_htlc_stats` predicts that the set of HTLCs on the next commitment will be all the HTLCs in `ChannelContext.pending_inbound_htlcs`, and `ChannelContext.pending_outbound_htlcs`, as well as all the outbound HTLC adds in the holding cell.
This is an overestimate:
* Outbound HTLC removals which have been ACK'ed by the counterparty will certainly not be present in any *next* commitment, even though they remain in `pending_outbound_htlcs` (I refer to states `AwaitingRemoteRevokeToRemove` and `AwaitingRemovedRemoteRevoke`).
* Outbound HTLCs in the `RemoteRemoved` state, will not be present in the next *local* commitment.
* Inbound HTLCs in the `LocalRemoved` state will not be present in the next *remote* commitment.
`ChannelContext::build_commitment_stats(funding, true, true, ..)` makes these errors when predicting the HTLC count on the remote commitment:
* Inbound HTLCs in the state `RemoteAnnounced` are not included, but they will be in the next remote commitment transaction if the local ACK's the addition before producing the next remote commitment.
* Inbound HTLCs in the state `AwaitingRemoteRevokeToAnnounce` are not included, even though the local has ACK'ed the addition.
* Outbound HTLCs in the state `AwaitingRemoteRevokeToRemove` are counted, even though the local party has ACK'ed the removal.
This commit replaces these functions in favor of the newly added `ChannelContext::get_next_{local, remote}_commitment_stats` methods, and fixes the issues described above.
We now always calculate dust exposure using a buffer from `msg.feerate_per_kw`, and not from `max(feerate_per_kw, self.feerate_per_kw, self.pending_update_fee)`.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Moderate 63/100
This commit fixes how a Lightning node predicts the contents of its next commitment transactions when deciding whether it can safely propose a fee update. Previously the code over- or under-counted pending HTLCs depending on their state, which could let the node accept a feerate that leaves it unable to pay the resulting commitment transaction fee or reserve, or that exceeds dust-exposure safety limits. The fix replaces the old prediction helpers with new state-aware methods that model the next local and remote commitments more accurately.
Lower-priorityImprove prediction of commitment stats in `can_accept_incoming_htlc`by Leo Nash · 3218db15 · Aug 21, 2025 · 2 filesMessage 73 · AdequateModerate 63Details
Commit message · Leo Nash
Improve prediction of commitment stats in `can_accept_incoming_htlc`
`ChannelContext::get_pending_htlc_stats` predicts that the set of HTLCs on the next commitment will be all the HTLCs in `ChannelContext.pending_inbound_htlcs`, and `ChannelContext.pending_outbound_htlcs`, as well as all the outbound HTLC adds in the holding cell.
This is an overestimate:
* Outbound HTLC removals which have been ACK'ed by the counterparty will certainly not be present in any *next* commitment, even though they remain in `pending_outbound_htlcs`.
* Outbound HTLCs in the `RemoteRemoved` state, will not be present in the next *local* commitment.
* Outbound HTLCs in the `LocalAnnounced` state have no guarantee that they were yet received by the counterparty.
* Outbound `update_add_htlc`'s in the holding cell are certainly not known by the counterparty, and we will reevaluate their addition to the channel when freeing the holding cell.
* Inbound HTLCs in the `LocalRemoved` state will not be present in the next *remote* commitment.
This commit stops using `get_pending_htlc_stats` in favor of the newly added `ChannelContext::get_next_{local, remote}_commitment_stats` methods, and fixes the issues described above.
`ChannelContext::next_remote_commit_tx_fee_msat` counts inbound HTLCs in the `LocalRemoved` state, as well as outbound HTLCs in the `LocalAnnounced` state. We now do not count them for the same reasons described above.
Inbound `LocalRemoved` HTLCs that were **not** successful are now credited to `remote_balance_before_fee_msat` as they will certainly not be on the next remote commitment. We previously debited these from the remote balance to arrive at `remote_balance_before_fee_msat`.
We now always check holder dust exposure, whereas we previously would only do it if the incoming HTLC was dust on our own commitment transaction.
Furthermore, dust exposure calculations now take a buffer from the currently committed feerate, and ignore any fee updates in `ChannelContext.pending_update_fee`.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Moderate 63/100
This commit fixes how a Lightning node predicts the contents of its next commitment transactions when deciding whether to accept an incoming payment (HTLC). Previously, the node overestimated which HTLCs would appear on the next commitment, which could cause it to wrongly reject valid incoming payments (a denial-of-service/availability issue) or apply incorrect fee and dust checks. The patch replaces the overestimate with more precise per-commitment statistics and tightens dust-exposure checks for the node's own commitment transaction.
Lower-priorityImprove prediction of commitment stats in `validate_update_add_htlc`by Leo Nash · 48b412a4 · Aug 21, 2025 · 1 fileMessage 73 · AdequateModerate 63Details
Commit message · Leo Nash
Improve prediction of commitment stats in `validate_update_add_htlc`
`ChannelContext::get_pending_htlc_stats` predicts that the set of HTLCs on the next commitment will be all the HTLCs in `ChannelContext.pending_inbound_htlcs`, and `ChannelContext.pending_outbound_htlcs`, as well as all the outbound HTLC adds in the holding cell.
This is an overestimate:
* Outbound HTLC removals which have been ACK'ed by the counterparty will certainly not be present in any *next* commitment, even though they remain in `pending_outbound_htlcs`.
* Outbound HTLCs in the `RemoteRemoved` state, will not be present in the next *local* commitment.
* Outbound HTLCs in the `LocalAnnounced` state have no guarantee that they were received by the counterparty before she sent the `update_fee`.
* Outbound `update_add_htlc`'s in the holding cell are certainly not known by the counterparty, and we will reevaluate their addition to the channel when freeing the holding cell.
* Inbound HTLCs in the `LocalRemoved` state will not be present in the next *remote* commitment.
`ChannelContext::next_local_commit_tx_fee_msat` over-counts outbound HTLCs in the `LocalAnnounced` and `RemoteRemoved` states, as well as outbound `update_add_htlc`'s in the holding cell.
`ChannelContext::next_remote_commit_tx_fee_msat` over-counts inbound HTLCs in the `LocalRemoved` state, as well as outbound HTLCs in the `LocalAnnounced` state.
This commit stops using these functions in favor of the newly added `ChannelContext::get_next_{local, remote}_commitment_stats` methods, and fixes the issues described above.
If we are the funder, we also check that adding this inbound HTLC doesn't increase the commitment transaction fee to the point of exhausting our balance on the local commitment. Previously, we would only subtract the anchors from `funding.value_to_self_msat`; we now also subtract the outbound HTLCs on the next local commitment from `funding.value_to_self_msat` before checking if we can afford the additional transaction fees.
Inbound `LocalRemoved` HTLCs that were **not** successful are now credited to `remote_balance_before_fee_msat` as they will certainly not be on the next remote commitment. We previously debited these from the remote balance to arrive at `remote_balance_before_fee_msat`.
When calculating dust exposure, we now take a buffer from the currently committed feerate, and ignore any fee updates in `ChannelContext.pending_update_fee`.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
defensive validation
AI analysis · Moderate 63/100
This commit fixes how a Lightning node predicts which pending payments (HTLCs) will actually appear on the next commitment transaction when validating a new incoming HTLC. The old code over-counted HTLCs, which could cause the node to reject valid HTLCs or, more importantly, accept HTLCs while miscalculating whether the remote party can afford the on-chain fees and channel reserve. The patch also improves the funder's check so it subtracts outbound HTLCs from its own balance before checking fee affordability, and fixes a balance-credit bug for inbound HTLCs being removed. In short, it tightens the economic safety checks that prevent a channel from being created with terms one side cannot actually honor on-chain.
Lower-priorityImprove prediction of commitment stats in `validate_update_fee`by Leo Nash · d36fdabe · Aug 21, 2025 · 1 fileMessage 73 · AdequateModerate 61Details
Commit message · Leo Nash
Improve prediction of commitment stats in `validate_update_fee`
`ChannelContext::get_pending_htlc_stats` predicts that the set of HTLCs on the next commitment will be all the HTLCs in `ChannelContext.pending_inbound_htlcs`, and `ChannelContext.pending_outbound_htlcs`, as well as all the outbound HTLC adds in the holding cell.
This is an overestimate:
* Outbound HTLC removals which have been ACK'ed by the counterparty will certainly not be present in any *next* commitment, even though they remain in `pending_outbound_htlcs`.
* Outbound HTLCs in the `RemoteRemoved` state, will not be present in the next *local* commitment.
* Outbound HTLCs in the `LocalAnnounced` state have no guarantee that they were received by the counterparty before she sent the `update_fee`.
* Outbound `update_add_htlc`'s in the holding cell are certainly not known by the counterparty, and we will reevaluate their addition to the channel when freeing the holding cell.
* Inbound HTLCs in the `LocalRemoved` state will not be present in the next *remote* commitment.
This commit stops using `get_pending_htlc_stats` in favor of the newly added `ChannelContext::get_next_{local, remote}_commitment_stats` methods, and fixes the issues described above.
We now always calculate dust exposure using a buffer from `msg.feerate_per_kw`, and not from `max(self.feerate_per_kw, msg.feerate_per_kw)`.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
defensive validation
AI analysis · Moderate 61/100
This patch tightens how a Lightning node estimates which pending payments (HTLCs) will actually appear on the next commitment transaction when checking a peer's proposed fee rate. Previously the node counted HTLCs that might already be removed or not yet known to the peer, which could cause it to reject valid fee updates or, conversely, accept fee updates that expose it to more 'dust' HTLC risk than intended. The change makes the dust-exposure check more accurate by predicting the next local and next remote commitment separately and using only the new fee rate for the dust buffer.
AI review queuedAdd `TxBuilder::get_next_commitment_stats`by Leo Nash · 0a75f927 · Aug 21, 2025 · 2 filesMessage 58 · ThinInformational 11Details
Commit message · Leo Nash
Add `TxBuilder::get_next_commitment_stats`
Given a snapshot of the lightning state machine, `TxBuilder::get_next_commitment_stats` calculates the transaction fees, the dust exposure, and the holder and counterparty balances (the balances themselves do *not* account for the transaction fee).
signing or wallet pathsecond-pass: security-sensitive path
AI analysis · Informational 11/100
This commit adds a new internal helper method that estimates the fees, dust exposure, and balances for a future Lightning channel commitment transaction. It does not change any existing behavior or fix a known bug; it appears to be preparatory/refactoring work to support future channel-fee logic. There is no indication in the commit that it addresses a security vulnerability.
AI review queuedAdjust dust exposure due to excess fees for clarityby Leo Nash · 3a3e7eb8 · Aug 21, 2025 · 1 fileMessage 62 · AdequateInformational 12Details
Commit message · Leo Nash
Adjust dust exposure due to excess fees for clarity
62/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Explains rationale or failure mode! No meaningful explanatory body
Why it was queued
signing or wallet pathsecond-pass: security-sensitive path
AI analysis · Informational 12/100
This commit is a code clarity and variable-naming refactor in a function that calculates how much money a Lightning channel could lose due to tiny ('dust') transactions plus extra fees. It renames variables, removes an unnecessary mutable parameter, and reorders calculations so the math is easier to follow. The actual arithmetic result appears unchanged, so this is not a security fix.
In the initially-merged version of the static invoice server protocol, the static invoice server would sometimes have to find a specific static invoice based on (recipient_id, invoice_slot) and sometimetimes based on (recipient_id, invoice_id). This made the API harder to use in terms of how the server would index into the KVStore.
Over the course of the previous commits we transitioned to the server always finding a specific invoice based on (recipient_id, invoice_slot). We still have a few dangling references to invoice_id in some messages and events though, so remove those here.
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Informational 15/100
This commit is a routine cleanup of an internal messaging protocol. It removes a now-unused field called invoice_id and standardizes on a different identifier (invoice_slot) for looking up stored invoices. There is no security fix here; it is purely a simplification of the code and data structures.
Lower-priorityReplace StaticInvoiceReq::invoice_id with ::inv_slotby Valentine Wallace · f53325bf · Aug 21, 2025 · 5 filesMessage 73 · AdequateInformational 15Details
Commit message · Valentine Wallace
Replace StaticInvoiceReq::invoice_id with ::inv_slot
In the initially-merged version of the static invoice server protocol, the static invoice server would sometimes have to find a specific static invoice based on (recipient_id, invoice_slot) and sometime based on (recipient_id, invoice_id). This made the API harder to use in terms of how the server would index into the KVStore.
We'd like to transition to the server always finding a specific invoice based on (recipient_id, invoice_slot) and get rid of the invoice_id concept.
Previously, when an invoice request would come in for the server on behalf of the often-offline recipient, they would need to find the static invoice based on the recipient_id and invoice_id. However, previous commits have now led to the server being able to use the invoice_slot in the initial offer paths that they create, which we do here, obviating the need for them to create their own randomly-generated invoice_id. The final dangling references to the invoice_id will be removed in the next commit.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Informational 15/100
This commit is a straightforward internal API cleanup in the experimental static-invoice-server protocol. It replaces a randomly-generated 128-bit invoice_id with a simpler 16-bit invoice_slot when looking up stored invoices. There is no security fix here—just making the database lookup key consistent and easier to use.