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 patch fixes a bug in the Lightning Dev Kit where the software could confuse HTLCs (payment contracts) on live, unrevoked counterparty commitment transactions with ones from old, revoked transactions. Previously, it relied only on whet…
Incorrect revocation state detection for counterparty commitment transactionsHTLC direction not previously checked when matching against pending HTLCsPromotion of debug assertions to full assertions for HTLC claim path consistency
This commit changes how the Lightning networking code handles oversized encrypted messages. Previously, certain conditions would cause the program to crash with a panic. Now the code returns errors instead, which is a defensive improvement…
panic-to-error conversion for oversized message encryption/decryptiondenial-of-service hardening against oversized peer messagesdebug_assert retained to preserve test coverage of invariant violations
This patch fixes a crash bug in the Lightning Dev Kit's handling of HTLC failure messages. A downstream peer could send a maximally-sized failure message without attribution data. When the node added its own attribution data while relaying…
Denial-of-service via remote-triggered panic in message encryptionOversized message exceeding Noise/Lightning wire framing limitMissing length validation before adding attribution data during relay
This commit fixes a denial-of-service bug in rust-lightning where a maliciously crafted one-hop blinded reply path could cause the node to panic when it tried to respond. The fix rejects paths with too few hops before advancing them, and a…
Denial-of-service vector via malformed blinded pathPanic in onion construction due to zero-hop pathUntrusted reply path input validation gap
This commit fixes a bug where replaying the current blockchain block through a normal listener callback could crash two core Lightning components (ChannelManager and OutputSweeper) with a panic. The fix recognizes a same-block replay as a …
panic in chain listener callbacksame-block replay/rescan mishandlingassertion failure on valid chain input
This commit fixes a crash bug in the Lightning Dev Kit's on-chain transaction handler. During a deep blockchain reorganization, a previously settled HTLC claim could be 'resurrected' at a block height where it could no longer be combined w…
Assertion/panic in reorg handling pathDeep blockchain reorg as trigger conditionHTLC claim resurrection after reorg
This commit simply updates the 'repository' web links in 15 package metadata files from GitHub to a self-hosted Forgejo instance. It does not change any program code, build logic, dependencies, or security behavior. There is no security is…
This commit fixes a bug in the Lightning Dev Kit where, after a disconnection, a node could fail to retransmit a 'splice_locked' message to a peer that was still waiting for transaction signatures. Without this retransmission, the two peer…
Protocol state desynchronization between channel peers after reconnectionMissing retransmission of splice_locked for 0-conf splice channelsPotential channel unusability or stuck splice negotiation
This commit adds a new API, pay_for_bolt12_invoice, that lets users pay a BOLT 12 invoice even if LDK did not originally request it. It is intended for advanced use cases like multi-sender payments and replaces an older, more restrictive A…
New API removes internal invoice-origin verification, shifting trust boundary to callerDocumentation explicitly warns caller to verify invoice via Bolt12Invoice::verify_using_metadata and to ensure unique payment_id to avoid duplicate paymentsInput validation added for zero amount, overpay, and partial-amount-without-MPP
This commit fixes a small accounting bug in how the Lightning wallet estimates the size (and therefore transaction fee) of a special Bitcoin transaction that sweeps funds back to the user after a channel closes. The old code always assumed…
debug assertion failure possible in development/testing buildstransaction weight/fee estimate overestimation up to 3 WUconstant replaced with per-descriptor length computation
This commit only updates documentation comments for a Rust function called get_per_commitment_point. It removes an outdated warning that the method was non-asynchronous and that returning an error could cause a crash, and replaces it with …
Documentation-only changeRemoves outdated panic warningAdds retry/unblock guidance for signer errors
This commit changes the project's internal code-review workflow. It stops automatically assigning a human reviewer when a pull request is opened; instead, contributors must manually click a button to request a reviewer after first addressi…
This commit is purely a code-formatting cleanup. It removes `#[rustfmt::skip]` annotations and lets rustfmt reformat several functions in the routing/scoring module. No logic, behavior, or security properties of the code are changed.
This commit fixes a bug in LDK's Lightning channel reconnection logic after a splice (a way to resize a channel's on-chain funds). If one peer had already received the splice signatures but the other had not, and then they disconnected and…
Protocol-state inconsistency on reconnection after splice signature exchangePotential channel stall/force-close due to quiescence not being exited before commitment updateFuzzer-discovered edge case in Lightning splicing retransmission
This commit adds a new option for Lightning invoice creators to explicitly tell payers not to use multi-path payments (MPP) when paying an invoice. It does not change any enforcement rules; it only changes what feature bits are advertised …
New API surface for feature advertisement controlExplicit documentation that the method does not enforce single-HTLC receipt, shifting enforcement responsibility to callersNo removal or weakening of existing validation logic
This commit swaps the ID number used by an automated workflow that randomly assigns code reviewers. The old number pointed to a real person's account, so the workflow's assignments appeared to come from that person. The new number points t…
This commit removes a separate CI build step that tested the project with a special 'taproot' compiler flag. It is a workflow cleanup change, not a code change. There is no indication of a security vulnerability.
This commit adjusts the project's continuous integration (CI) test script to pin an older version of a build-time helper crate called `jobserver` when using older Rust compilers. It is a build compatibility fix, not a security patch, and d…
This commit updates a dependency used to talk to Esplora blockchain servers from version 0.12 to 0.13, switching the underlying HTTP library from reqwest to bitreq. It also removes two CI workarounds that pinned older versions of idna_adap…
Dependency version bump (esplora-client 0.12 -> 0.13)HTTP backend switch (reqwest -> bitreq) in a transitive dependencyRemoval of MSRV pins for idna_adapter and hyper-rustls
This commit only adds new test code. It exercises how a newer version of LDK exchanges saved channel data with the older LDK 0.2 release when a channel has a pending splice. There is no change to production logic, no bug fix, and no securi…
Expand any commit for its author, full message, clarity score, changed files, triage signals, analysis, and source link.
Lower-priorityCount zero-fee-commitments channels in anchor reserve checkby Elias Rohrer · 33987e86 · May 5, 2026 · 1 fileMessage 83 · StrongTriage 5Details
Commit message · Elias Rohrer
Count zero-fee-commitments channels in anchor reserve check
`can_support_additional_anchor_channel` decides whether the wallet has enough on-chain reserve to back another anchor channel by counting the node's existing anchor channels. The classification only checked the `anchors_zero_fee_htlc_tx` feature, so channels negotiated with the `anchor_zero_fee_commitments` (TRUC / 0FC, option 41) variant — which require the same on-chain reserve to fund commitment / HTLC fee bumps on force-close — were silently dropped from the count.
A node enabling `negotiate_anchor_zero_fee_commitments` would therefore be green-lit to open more anchor channels than its wallet can actually back, risking unfunded fee bumps and HTLC loss on simultaneous force-closes.
Treat both feature flags as marking a channel as an anchor channel for reserve-accounting purposes (factored into a small `is_anchor_channel_type` helper, used in both the chain-monitor and channel-manager loops), and add a regression test that opens a single 0FC channel with reserves sized for exactly one channel and asserts the function refuses to authorize a second.
Co-Authored-By: HAL 9000
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Why it was queued
fuzzing or regression evidence
Security candidateFree pending_query_count slot when DNS proof build failsby Elias Rohrer · fb4103d7 · May 5, 2026 · 1 fileMessage 95 · StrongHigh 76Details
Commit message · Elias Rohrer
Free pending_query_count slot when DNS proof build fails
`OMDomainResolver` rate-limits in-flight DNSSEC proof builds via a `pending_query_count` counter capped at `MAX_PENDING_RESPONSES` (1024). The counter was only released when the proof build succeeded, so any failure mode -- NXDOMAIN, insecure zones, unreachable resolvers, I/O timeouts, malformed names -- permanently consumed a slot.
Because the queried name is attacker-controlled (it travels in over a `DNSSECQuery` onion message from any LN peer, given DNS resolution is an opt-in network-advertised feature), an adversary could exhaust the counter with ~1025 failing queries and persistently DoS the resolver for any subsequent legitimate BIP-353 lookups, until the process is restarted.
Always release the slot once the proof build completes, regardless of outcome, and add a regression test which points the resolver at a TCP-refusing local port and asserts the counter returns to zero.
Co-Authored-By: HAL 9000
95/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification
Why it was queued
explicit security languagefuzzing or regression evidence
AI analysis · High 76/100
This commit fixes a denial-of-service bug in rust-lightning's optional DNS resolver feature. A counter that limits how many DNS lookups can run at once was only being reset when a lookup succeeded; any failed lookup (bad name, unreachable server, timeout, etc.) permanently consumed one slot. Because any Lightning peer can ask for a DNS lookup, an attacker could send about 1,025 failing requests and permanently block the resolver until the node is restarted. The fix moves the counter reset so it always runs when the lookup finishes, success or failure, and adds a test that triggers a failure and checks the counter returns to zero.
AI review queuedFix signed comparison in `ElectrumClient`by Elias Rohrer · 8b383bb8 · May 5, 2026 · 1 fileMessage 68 · AdequateLow 44Details
Commit message · Elias Rohrer
Fix signed comparison in `ElectrumClient`
`GetHistoryRes::height` from electrum-client is a *signed* integer. Here we first check for `<= 0` *before* casting to `u32`.
Signed-off-by: Elias Rohrer <dev@tnull.de>
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
signing or wallet pathsecond-pass: security-sensitive path
AI analysis · Low 44/100
This commit fixes a bug in how Electrum server transaction history is checked. The code was casting a signed (possibly negative) confirmation height into an unsigned number before checking whether it was valid. That meant unconfirmed or invalid entries could be misread as very large heights instead of being skipped, potentially leading to incorrect transaction confirmation data being used by the Lightning wallet.
AI review queuedAlways enforce the 1000sat min channel value in zero-reserve channelsby Leo Nash · be6cf5b8 · May 5, 2026 · 5 filesMessage 85 · StrongModerate 60Details
Commit message · Leo Nash
Always enforce the 1000sat min channel value in zero-reserve channels
We did not enforce this minimum when accepting 0-reserve channels. This is because we depended on the `MIN_THEIR_CHAN_RESERVE_SATOSHIS` constant to guarantee this minimum channel value, but this value is no longer read in 0-reserve channels.
Note that the user's `min_funding_satoshis` value would still be respected in this case.
When splicing 0-reserve channels, we only enforced that the commitment transaction retained at least one output after the splice, which could produce a channel value lower than 1000sats.
Along the way, we also now enforce this 1000sat minimum when splicing reserve-enabled channels. We previously correctly enforced the reserves after the splice, but this could still result in a channel value smaller than 1000sats. This case is now rejected during splice validation.
Note that the user's `min_funding_satoshis` is not respected when validating splice contributions, we leave this for follow-up work.
85/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
Why it was queued
signing or wallet pathsecond-pass: security-sensitive path
AI analysis · Moderate 60/100
This commit fixes a bug in the Lightning Dev Kit where very small channels could be created or spliced down to below 1000 satoshis when zero-reserve channels were used. Normally, a reserve requirement prevents channels from being too tiny, but that safeguard was skipped for zero-reserve channels. The patch adds a direct 1000-satoshi minimum channel value check for opening and splicing channels, including during splicing of normal reserve-enabled channels. This prevents the creation or modification of channels so small that they could be economically unviable or cause protocol edge cases.
AI review queuedAdd `ChannelDetails::next_splice_out_maximum_sat`by Leo Nash · 9bc7b194 · May 5, 2026 · 3 filesMessage 35 · OpaqueInformational 15Details
Commit message · Leo Nash
Add `ChannelDetails::next_splice_out_maximum_sat`
35/100 · OpaqueMessage clarity
✓ Descriptive subject! No meaningful explanatory body
Why it was queued
second-pass: opaque commit message
AI analysis · Informational 15/100
This commit adds a new read-only field called next_splice_out_maximum_sat to the public ChannelDetails struct. It exposes how much bitcoin can be spliced out of a channel in the next splice operation. There is no change to logic, permissions, or cryptographic checks; it is purely an API/data exposure addition. No security issue is evident from the diff.
AI review queuedAdd `test_0reserve_splice`by Leo Nash · b96c2dbe · May 5, 2026 · 2 filesMessage 25 · OpaqueInformational 12Details
Commit message · Leo Nash
Add `test_0reserve_splice`
25/100 · OpaqueMessage clarity
✓ Descriptive subject! Too few words to establish purpose! No meaningful explanatory body
Why it was queued
second-pass: opaque commit message
AI analysis · Informational 12/100
This commit adds a new test case for the Lightning Dev Kit library. It does not change any production code; it only adds test code that checks how splicing (a way to resize a Lightning channel) behaves when one side has a zero reserve balance. The change makes an existing internal test helper function visible to the new test file. There is no indication this commit fixes or introduces a security issue.
Lower-priorityUse `next_splice_out_maximum_sat` to validate `funding_contributed`by Leo Nash · f86b2eb1 · May 5, 2026 · 2 filesMessage 73 · AdequateLow 41Details
Commit message · Leo Nash
Use `next_splice_out_maximum_sat` to validate `funding_contributed`
This is equivalent to the previous commit, see the debug assertions added in the previous commit. We now also get to communicate the exact maximum back to the user, instead of some "balance is lower than our reserve" message, which is hard to react to.
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 · Low 41/100
This commit changes how a Lightning channel validates splice-out funding contributions. Instead of a more general reserve check, it now uses a dedicated 'next splice-out maximum' calculation to decide whether a proposed splice-out is too large, and reports a clearer error message to the user. The change appears to be a refinement of validation logic rather than a fix for a known exploit, but the commit message references a previous commit with added debug assertions, suggesting it hardens an earlier correction.
AI review queuedAdd `AvailableBalances::next_splice_out_maximum_sat`by Leo Nash · 1d28afca · May 5, 2026 · 5 filesMessage 63 · AdequateLow 46Details
We previously determined this value by subtracting the htlcs, the anchors, and the commitment transaction fee. This ignored the reserve, as well as the at-least-one-output requirement in zero-reserve channels.
This new field now accounts for both of these constraints. It can be seen as the total spliceable balance from the channel.
signing or wallet pathsecond-pass: security-sensitive path
AI analysis · Low 46/100
This commit fixes how rust-lightning calculates the maximum amount a user can splice out of a Lightning channel. Previously the calculation ignored channel reserve rules and a requirement to keep at least one output, which could have allowed a user to request an invalid splice-out that the protocol or counterparty would reject. The new field properly accounts for both constraints, making splice-out operations safer and more likely to succeed.
Lower-priorityRun existing validation code against the candidate funding scopeby Leo Nash · 33b5166c · May 5, 2026 · 1 fileMessage 73 · AdequateModerate 59Details
Commit message · Leo Nash
Run existing validation code against the candidate funding scope
As a result, we now validate that both commitments retain at least one output under the new funding scope, which is crucial for zero-reserve channels.
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 59/100
This commit tightens validation when Lightning channels are re-funded or 'spliced.' Previously, some checks used rough estimates and debug-only assertions; now the code builds a realistic candidate funding state and runs the same balance/reserve checks against it. The key fix is ensuring that after a splice, both sides' commitment transactions still have at least one output, which matters for zero-reserve channels. Without this, a malicious or malformed splice proposal could potentially reduce a party's balance so low that their commitment transaction becomes empty or invalid, risking loss of funds or channel failure.
Lower-prioritySwitch to ldk-fuzzing-corpus repo rather than CI cacheby Matt Corallo · efa95b49 · May 4, 2026 · 2 filesMessage 73 · AdequateTriage 0Details
Commit message · Matt Corallo
Switch to ldk-fuzzing-corpus repo rather than CI cache
Rather than storing our fuzzing corpus in the CI cache, move it to a new repo which anyone can use for their own local fuzzing and can be updated outside of CI with additional seeds.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
fuzzing or regression evidencedocumentation-only discount
Lower-priorityFix typo in `_encode_tlv` leading to confused encodingby Matt Corallo · 05135aec · May 1, 2026 · 1 fileMessage 50 · ThinTriage 0Details
Commit message · Matt Corallo
Fix typo in `_encode_tlv` leading to confused encoding
50/100 · ThinMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component! No meaningful explanatory body
Lower-priority`as_ref()` before wrapping encoded types in writing `option` TLVsby Matt Corallo · 8b1c7710 · Apr 30, 2026 · 4 filesMessage 73 · AdequateTriage 0Details
Commit message · Matt Corallo
`as_ref()` before wrapping encoded types in writing `option` TLVs
We almost certainly don't want to be moving `option` TLVs during serialization, and while we had logic elsewhere to work around this previously its nice not to have to in the future.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Skip pre-splice announcement_signatures on reestablish
When a splice transaction confirms on both sides while peers are disconnected, each peer's `channel_reestablish` carries `my_current_funding_locked` with the splice txid. In the reestablish handler, `get_announcement_sigs` was called before the inferred `splice_locked` was processed and the splice was promoted, so `self.funding` still pointed to the pre-splice scope. If `announcement_sigs_state` was `NotSent`, the generated `announcement_signatures` carried the pre-splice `short_channel_id` and bitcoin key — which the peer (having already promoted via its own inferred `splice_locked`) would verify against the post-splice `UnsignedChannelAnnouncement`, failing the signature check and force-closing.
Skip the pre-promotion call when `my_current_funding_locked` matches the splice we've already confirmed — i.e. `pending_splice.sent_funding_txid` is set and equals the peer's locked txid. `maybe_promote_splice_funding` emits correct post-splice signatures after the inferred `splice_locked` is processed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
88/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Names security-relevant behavior explicitly
Why it was queued
signing boundary
AI analysis · Moderate 57/100
This commit fixes a bug in the Lightning Dev Kit where reconnecting after a channel 'splice' (a funding update) could cause one peer to send outdated channel announcement signatures. The peer receiving those stale signatures would reject them and force-close the channel. The fix skips generating announcement signatures until the splice has been promoted to the new funding, so both sides agree on the current channel state.
Ignore stale announcement_signatures instead of force-closing
A peer may transmit `announcement_signatures` signed over a stale `short_channel_id` — most plausibly a retransmission or a peer implementation whose view hasn't caught up to our post-splice promotion. Verifying such sigs against the current `UnsignedChannelAnnouncement` (built from `self.funding`) always fails the hash check, which previously produced a force-close.
BOLT #7 does not require closing in this situation; the mismatch is expected across splice handoffs. Short-circuit with `ChannelError::Ignore` when `msg.short_channel_id` doesn't match the current funding's scid, leaving the genuine invalid-signature paths in place for sigs that actually target our current scid.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
86/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
Why it was queued
signing boundary
AI analysis · Moderate 62/100
This change fixes a bug where a Lightning node would unnecessarily force-close a payment channel if its peer sent an outdated 'announcement_signatures' message referencing the old channel identifier after a splice (a channel funding update). The node now simply ignores these stale messages, keeping the channel open. The bug was not a direct theft of funds, but it could cause unwanted channel closures and disruption.
Model RBF splice tx replacement in chanmon_consistency
The SplicePending event handler was immediately confirming splice transactions, which caused force-closes when RBF splice replacements were also confirmed for the same channel. Since both transactions spend the same funding UTXO, only one can exist on a real chain.
Model this properly by adding a mempool-like pending pool to ChainState. Splice transactions are added to the pool instead of being confirmed immediately. At chain-sync time, pending transactions are sorted by txid and confirmed together in one block; candidates that double-spend an already-confirmed outpoint or another candidate earlier in the sort are dropped.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Security candidateRename `BestBlock` to `BlockLocator`by Matt Corallo · dcba68d2 · Apr 24, 2026 · 22 filesMessage 58 · ThinInformational 20Details
Commit message · Matt Corallo
Rename `BestBlock` to `BlockLocator`
`BestBlock` is now really a pointer to a block rather than just a block itself, so its weird to still call it `BestBlock`. Here we rename it to `BlockLocator`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is a straightforward rename of the Rust type `BestBlock` to `BlockLocator` across the rust-lightning codebase. The struct's fields, serialization format, and behavior are unchanged; only identifiers, comments, and documentation are updated to reflect that the value now also carries recent ancestor block hashes (a 'block locator') rather than just a single best block. There is no security-relevant code change.
Replace the custom LSPS5 URL parser with `bitreq::Url` while keeping the LSPS5-specific HTTPS and length checks. This reduces bespoke parsing logic and aligns accepted webhook URLs with the HTTP client's URL handling.
Co-Authored-By: HAL 9000 Signed-off-by: Elias Rohrer <dev@tnull.de>
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Handle DiscardFunding with FundingInfo::Tx variant in chanmon_consistency
The process_events! macro only handled DiscardFunding events with FundingInfo::Contribution, but splice RBF replacements can produce DiscardFunding with FundingInfo::Tx when the original splice transaction is discarded.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Several code paths exit quiescence by calling `clear_quiescent()` directly without also clearing the disconnect timer via `mark_response_received()`. This causes the timer to fire after the splice completes or is aborted, spuriously disconnecting the peer.
Replace `clear_quiescent()` with `exit_quiescence()` in `on_tx_signatures_exchange`, `reset_pending_splice_state`, and `peer_connected_get_handshake`, which clears both the quiescent state and the disconnect timer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
signing boundary
AI analysis · Low 44/100
This commit fixes a bug in the Lightning Dev Kit where a timer meant to disconnect unresponsive peers could fire by mistake after a splice operation completed, was aborted, or after reconnecting. The fix makes sure the timer is cleared whenever the protocol leaves its 'quiet' (quiescent) state, preventing unnecessary peer disconnections.
Return InteractiveTxMsgError from splice_init and tx_init_rbf
The prior two commits manually intercepted ChannelError::Abort in the channelmanager handlers for splice_init and tx_init_rbf to exit quiescence before returning, since the channel methods didn't signal this themselves. The interactive TX message handlers already solved this by returning InteractiveTxMsgError which bundles exited_quiescence into the error type.
Apply the same pattern: change splice_init and tx_init_rbf to return InteractiveTxMsgError, adding a quiescent_negotiation_err helper on FundedChannel that exits quiescence for Abort errors and passes through other variants unchanged. Extract handle_interactive_tx_msg_err in channelmanager to deduplicate the error handling across internal_tx_msg, internal_splice_init, internal_tx_init_rbf, and internal_tx_complete.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
The `exited_quiescence` field on `MsgHandleErrInternal` and `InteractiveTxMsgError` is a leaky abstraction -- the channelmanager error handling shouldn't know about quiescence, only whether the holding cell needs to be released.
Infer this from the presence of a `tx_abort` instead, since exiting quiescence via an error always produces one. Remove `exited_quiescence` from `InteractiveTxMsgError`, `MsgHandleErrInternal`, and the return type of `Channel::tx_abort`, along with the `with_exited_quiescence` builder.
For unfunded v2 channels, `tx_abort` may be present without quiescence having been exited, but the holding cell release is a no-op since an unfunded channel won't have any HTLCs. Similarly, the unreachable `debug_assert!(false)` branch in `fail_interactive_tx_negotiation` for funded channels produces a `tx_abort` without exiting quiescence, but the holding cell release is a no-op since the channel is still quiescent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Lower-priorityExit quiescence when tx_init_rbf is rejected with Abortby Jeffrey Czyz · adf87326 · Apr 23, 2026 · 3 filesMessage 95 · StrongTriage 0Details
Commit message · Jeffrey Czyz
Exit quiescence when tx_init_rbf is rejected with Abort
When tx_init_rbf is rejected with ChannelError::Abort (e.g., insufficient RBF feerate, negotiation in progress, feerate too high), the error is converted to a tx_abort message but quiescence is never exited and holding cells are never freed. This leaves the channel stuck in a quiescent state.
Fix this by intercepting ChannelError::Abort before try_channel_entry! in internal_tx_init_rbf, calling exit_quiescence on the channel, and returning the error with exited_quiescence set so that handle_error frees holding cells. Also make exit_quiescence available in non-test builds by removing its cfg gate.
Update tests to use the proper RBF initiation flow (with tampered feerates) so that handle_tx_abort correctly echoes the abort and exits quiescence, rather than manually crafting tx_init_rbf messages that leave node 0 without proper negotiation state.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
95/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification
Lower-priorityExit quiescence when splice_init is rejected with Abortby Jeffrey Czyz · bd5b04dc · Apr 23, 2026 · 2 filesMessage 73 · AdequateTriage 0Details
Commit message · Jeffrey Czyz
Exit quiescence when splice_init is rejected with Abort
The same bug fixed in the prior commit for tx_init_rbf also exists in internal_splice_init: when splice_init triggers FeeRateTooHigh in resolve_queued_contribution, the ChannelError::Abort goes through try_channel_entry! without exiting quiescence.
Apply the same fix: intercept ChannelError::Abort before try_channel_entry!, call exit_quiescence, and return the error with exited_quiescence set.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Lower-priorityAdd FilesystemStoreV2Error for v1 data detectionby benthecarman · 61125214 · Apr 21, 2026 · 1 fileMessage 68 · AdequateTriage 0Details
Commit message · benthecarman
Add FilesystemStoreV2Error for v1 data detection
FilesystemStoreV2::new previously returned io::Error with ErrorKind::InvalidData when the data directory contained top-level files left behind by FilesystemStore (v1). That forced us to match on an error that could potentially be given by our normal io calls. This adds a dedicated FilesystemStoreV2Error enum with a V1DataDetected(PathBuf) so we can distinguish between normal io errors and an old V1 fs store.
68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context