LDK
← All projectsLightning Dev Kit

rust-lightning

Composable Rust libraries for building Lightning wallets, nodes, and services.

BitcoinCryptographic librariesLightning NetworkNormal
Repository coverage

1478 commits in the local evidence base

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.

225security candidates208second-pass queue449AI analyses
63commits · 30 days
191commits · 60 days
647commits · 180 days
1475commits · 365 days
Backfill bands
Aug 5 → Feb 6819 seen18 candidatesComplete
Feb 6 → Jun 6468 seen16 candidatesComplete
Jun 6 → Jul 6128 seen8 candidatesComplete
Jul 6 → Aug 561 seen3 candidatesComplete
Commit communication

Does the history explain itself?

Message quality measures whether a commit identifies its scope, purpose, rationale, testing, and supporting references. It does not change the security-severity score.

69/100 average clarity
352Strong · 80–100
782Adequate · 60–79
285Thin · 40–59
59Opaque · 0–39
3security candidates with opaque commit messaging
Read the scoring rubric →
Developer activity

Who is changing the project?

Public Git author strings; identities are not independently verified.

DeveloperCommitsCandidatesAnalyzedHigh riskMessage avg.
Elias Rohrer1531541567
Matt Corallo3564796273
Jeffrey Czyz1774161168
Leo Nash1161364162
Valentine Wallace1351020169
Wilmer Paulino1493953069
Joost Jager1622443069
elnosh301319056
shaavan2266069
Carla Kirk-Cohen6536069
benthecarman1834071
Duncan Dean836057
Analysis record

Published AI watches

Last scanned 34 minutes ago

Moderate 66 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Correct HTLC confusion on unrevoked counterparty commitment txs

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
f06a08a6by Matt Corallo+26−192 files
Vendor flagged security relevance
Low 47 AI analysisMessage 85 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Return `Err`s` instead of panicking on oversized messages

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
08f12bc7by Matt Corallo+68−313 files
Vendor flagged security relevance
High 74 AI analysisMessage 78 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Avoid oversized relayed failure messages

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
6b1dfb1aby Matt Corallo+64−191 file
Vendor flagged security relevance
Moderate 64 AI analysisMessage 83 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Reject attempts to advance one-hop blinded forward paths

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
969a40cfby Matt Corallo+49−14 files
Vendor flagged security relevance
Moderate 60 AI analysisMessage 88 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Allow filtered block rescans at the current tip

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
686f9860by Elias Rohrer+118−123 files
Vendor flagged security relevance
Moderate 57 AI analysisMessage 78 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Avoid panic when reorged claims cannot merge

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
f1dc8487by Matt Corallo+219−52 files
Vendor flagged security relevance
Informational 15 AI analysisMessage 45 · Thin
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Update crate repository links to forgejo

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…

eb77676dby benthecarman+15−1515 files
No security note in commit
Moderate 54 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Retransmit splice_locked for 0-conf channels missing tx_signatures

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
5434015bby Wilmer Paulino+266−12 files
No security note in commit
Low 37 AI analysisMessage 83 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

bolt12: add pay_for_bolt12_invoice for externally-sourced invoices

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
5b80fe9cby Alkamal01+550−156 files
No security note in commit
Low 26 AI analysisMessage 90 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Include to_self_delay size in DelayedPaymentOutput weight calculation

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
e6652237by Matt Morehouse+97−83 files
No security note in commit
Informational 18 AI analysisMessage 65 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Correct docs on `ChannelSigner::get_per_commitment_point`

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
5057809bby Matt Corallo+6−31 file
No security note in commit
Informational 15 AI analysisMessage 63 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Require manual reviewer assignment

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…

9c1e5787by Joost Jager+21−232 files
No security note in commit
Informational 15 AI analysisMessage 28 · Opaque
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Format changed functions

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.

05ce4204by Matt Corallo+44−251 file
No security note in commit
Moderate 60 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Handle missing splice tx_signatures on reestablish

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
f93a7f0cby Wilmer Paulino+600−975 files
No security note in commit
Informational 19 AI analysisMessage 68 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

offers: Allow disabling invoice response MPP

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
00aabf81by Elias Rohrer+9−01 file
No security note in commit
Informational 15 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Change assign-reviewer authorized integration token to a bot acct

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…

f734d1ebby Matt Corallo+1−11 file
No security note in commit
Informational 15 AI analysisMessage 35 · Opaque
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Remove taproot build check

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.

81a7b82dby elnosh+0−81 file
No security note in commit
Informational 15 AI analysisMessage 45 · Thin
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Pin jobserver to 0.1.34 on pre-1.85 rustc

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…

a4641403by Matt Corallo+3−01 file
No security note in commit
Informational 17 AI analysisMessage 50 · Thin
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Bump esplora-client to 0.13 to switch from `reqwest` to `bitreq`

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
5cd499e0by Matt Corallo+1−72 files
No security note in commit
Informational 15 AI analysisMessage 83 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Test cross-version serialization of pending splices

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…

0beadb3bby Jeffrey Czyz+208−01 file
No security note in commit
Repository ledger

Explore captured commits

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
Commit message · Leo Nash

Add `AvailableBalances::next_splice_out_maximum_sat`

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.

63/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Provides detailed explanatory context
Why it was queued
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
Lower-priorityCheck fuzz workspace formatting in CIby Joost Jager · 2294480e · Apr 30, 2026 · 2 filesMessage 78 · AdequateTriage 5Details
Commit message · Joost Jager

Check fuzz workspace formatting in CI

Extend the rustfmt CI job to check the fuzz workspace.

This covers fuzz alongside the root workspace and lightning-tests.

78/100 · AdequateMessage clarity
✓ 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 candidateSkip pre-splice announcement_signatures on reestablishby Jeffrey Czyz · 21fed17c · Apr 28, 2026 · 2 filesMessage 88 · StrongModerate 57Details
Commit message · Jeffrey Czyz

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.

Security candidateIgnore stale announcement_signatures instead of force-closingby Jeffrey Czyz · 80528b15 · Apr 28, 2026 · 2 filesMessage 86 · StrongModerate 62Details
Commit message · Jeffrey Czyz

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.

Lower-priorityModel RBF splice tx replacement in chanmon_consistencyby Jeffrey Czyz · e82d36e4 · Apr 24, 2026 · 1 fileMessage 73 · AdequateTriage 0Details
Commit message · Jeffrey Czyz

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>

58/100 · ThinMessage clarity
✓ Descriptive subject✓ Provides detailed explanatory context
Why it was queued
boot or update path
AI analysis · Informational 20/100

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.

Lower-priorityUse `bitreq::Url` for LSPS5 webhook URLsby Elias Rohrer · 5237c9a9 · Apr 24, 2026 · 4 filesMessage 68 · AdequateTriage 0Details
Commit message · Elias Rohrer

Use `bitreq::Url` for LSPS5 webhook URLs

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
Lower-priorityHandle DiscardFunding with FundingInfo::Tx variant in chanmon_consistencyby Jeffrey Czyz · 64c5182b · Apr 23, 2026 · 1 fileMessage 73 · AdequateTriage 0Details
Commit message · Jeffrey Czyz

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
Security candidateClear disconnect timer when exiting quiescenceby Jeffrey Czyz · d2f422bf · Apr 23, 2026 · 2 filesMessage 68 · AdequateLow 44Details
Commit message · Jeffrey Czyz

Clear disconnect timer when exiting quiescence

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.

Lower-priorityReturn InteractiveTxMsgError from splice_init and tx_init_rbfby Jeffrey Czyz · 98ec3e48 · Apr 23, 2026 · 3 filesMessage 73 · AdequateTriage 0Details
Commit message · Jeffrey Czyz

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
Lower-priorityRemove exited_quiescence from error handlingby Jeffrey Czyz · c9292488 · Apr 23, 2026 · 2 filesMessage 68 · AdequateTriage 0Details
Commit message · Jeffrey Czyz

Remove exited_quiescence from error handling

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