LDK
← All projectsLightning Dev Kit

rust-lightning

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

BitcoinCryptographic librariesLightning NetworkNormal
Repository coverage

1655 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.

249security candidates223second-pass queue1517AI analyses
84commits · 30 days
194commits · 60 days
565commits · 180 days
1253commits · 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.

70/100 average clarity
470Strong · 80–100
830Adequate · 60–79
293Thin · 40–59
62Opaque · 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 Rohrer15315153667
Matt Corallo43452370574
Jeffrey Czyz19545182169
Wilmer Paulino15945155169
Leo Nash11613116162
Valentine Wallace14010135169
Vincenzo Palazzo11311183
Joost Jager16224162069
elnosh371331057
auto-pr-bot2478087
shaavan22622069
Carla Kirk-Cohen78366068
Analysis record

Published AI watches

Last scanned 50 minutes ago

Informational 19 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'tx-sync: Parallelize esplora status queries' (#4913)

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
c303f515by Matt Corallo+140−371 file
No security note in commit
Low 30 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'Skip Electrum creator transaction downloads' (#4992)

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
c36e50cbby Matt Corallo+142−02 files
No security note in commit
Low 44 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'Use preferred sPK of watched txn in electrum, not rand ones' (#4867)

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
bfe5ca89by tnull+52−243 files
No security note in commit
Low 33 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'Serialize transient Event variants; move persist decision into ChannelManager' (#4791)

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
a0d4632eby Matt Corallo+694−818 files
No security note in commit
Informational 15 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'Document that funding signing events can go stale' (#4960)

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 …

26eecf2dby Matt Corallo+15−02 files
No security note in commit
Informational 15 AI analysisMessage 100 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Drop the honggfuzz version pin from the CI fuzz job

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…

4a1635efby auto-pr-bot+1−51 file
No security note in commit
Informational 15 AI analysisMessage 86 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Run the CI fuzz job on the stable toolchain

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…

21c4ed2bby auto-pr-bot+3−32 files
No security note in commit
Informational 19 AI analysisMessage 91 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Expose the dummy-hop tail constructor publicly

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
c5443353by auto-pr-bot+14−71 file
No security note in commit
Moderate 54 AI analysisMessage 100 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Fail commitment sig verification without counterparty params

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
de7ecc2fby auto-pr-bot+24−01 file
Vendor flagged security relevance
Informational 15 AI analysisMessage 100 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Clarify the commitment validation failure message

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…

3284a006by auto-pr-bot+11−114 files
No security note in commit
Moderate 61 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'Move holder commit sig checks to `InMemorySigner`' (#4885)

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'
83f5ba55by Matt Corallo+626−31024 files
No security note in commit
Low 42 AI analysisMessage 86 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'Drop stale splice signature on disconnect' (#4954)

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
c9a77251by Matt Corallo+22−12 files
No security note in commit
Moderate 58 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Drop stale splice signature on disconnect

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
71405b4bby Wilmer Paulino+22−12 files
Vendor flagged security relevance
Informational 20 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'offers: rename matches_invoice_signing_pubkey to key_can_sign_invoice' (#4942)

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.

a476cf92by Matt Corallo+13−133 files
No security note in commit
Informational 15 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

offers: rename matches_invoice_signing_pubkey to key_can_sign_invoice

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.

388187caby Vincenzo Palazzo+13−133 files
No security note in commit
Informational 18 AI analysisMessage 81 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Merge PR 'offers: add Offer::permits_invoice_signed_by' (#4884)

This commit adds a new public helper method, Offer::matches_invoice_signed_by (later renamed matches_invoice_signing_pubkey), that lets callers check whether an invoice signing key belongs to the recipient named by a BOLT 12 offer. It also…

Refactors existing BOLT 12 invoice-signing-pubkey validation into a reusable helperAdds public API to bind an invoice signing key to an offer recipientAdds unit tests for issuer-id vs. path-last-hop matching behavior
016af8f9by Matt Corallo+81−135 files
No security note in commit
Low 29 AI analysisMessage 85 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Support retired TLV fields in object-constructing macros

This commit is a feature enhancement for LDK's internal serialization macros. It allows developers to mark old protocol fields as 'retired' (reserved but no longer used) in more places, so those type numbers cannot be accidentally reused. …

TLV type-number reservation mechanism extended to more macro-generated code pathsPrevents accidental reuse of retired protocol field type numbersAvoids UnknownRequiredFeature decode failures for obsolete even-type fields
6d7c2bdaby Jeffrey Czyz+120−222 files
No security note in commit
Informational 17 AI analysisMessage 91 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Replace splice failure wire tests with a 0.2 downgrade test

This commit is a test-only cleanup in the Lightning Dev Kit (LDK) Rust codebase. It removes low-level byte-level tests for splice failure events and replaces them with a single cross-version test that actually loads a 0.2 node with seriali…

Cross-version serialization compatibility test addedRemoval of byte-level tests that could not detect real 0.2 mismatchesNo production code changes
80f2b44fby auto-pr-bot+95−2663 files
No security note in commit
Low 28 AI analysisMessage 98 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Document duplicate HTLC handling on revoked commitments

This commit only adds a code comment explaining an existing quirk: if a revoked old channel transaction contains two identical-looking payment forwards and the other side claims both, the software may only claim one upstream while letting …

Behavioral quirk in revoked-commitment HTLC resolution documentedDuplicate (payment_hash, amount) HTLCs can map to the same upstream sourcePotential missed upstream preimage claim on second identical HTLC
c5bd8b11by auto-pr-bot+19−01 file
Vendor flagged security relevance
Moderate 60 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Abort active splice RBF when prior candidate confirms

This commit fixes a state-handling bug in Lightning Dev Kit's splicing feature. When a user tries to speed up or replace a pending splice (an 'RBF' attempt) and the older splice transaction unexpectedly gets confirmed on-chain, the softwar…

State-conflict handling between confirmed splice candidate and active RBF negotiationStructured abort propagation through chain-event pathConditional abort based on holder signature progress to avoid unsafe cancellation
7587d2cdby Wilmer Paulino+623−424 files
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.

Security candidateSimplify contribution pop in reset_pending_splice_stateby Jeffrey Czyz · 2eb939b1 · May 7, 2026 · 1 fileMessage 85 · StrongInformational 24Details
Commit message · Jeffrey Czyz

Simplify contribution pop in reset_pending_splice_state

The was_negotiated check is unnecessary because reset_pending_splice_state
only runs when funding_negotiation is present, meaning
on_tx_signatures_exchange hasn't been called yet. Since the feerate is
only recorded in last_funding_feerate_sat_per_1000_weight during
on_tx_signatures_exchange, the current round's feerate can never match
it. So the contribution can always be unconditionally popped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

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 boundary
AI analysis · Informational 24/100

This is a small code cleanup in the Lightning payment channel code that handles failed or aborted splice-in transactions. The change removes an unnecessary check when undoing a splice contribution, replacing it with an unconditional pop plus a debug-only sanity check. The commit message argues the old check could never trigger, so behavior should be unchanged. There is no direct evidence of a security bug, but any change to state-rollback logic in financial software warrants careful review because mistakes can leave funds in an inconsistent state.

AI review queuedRename SplicePending and SpliceFailed eventsby Jeffrey Czyz · cc7fb0f5 · May 7, 2026 · 10 filesMessage 68 · AdequateInformational 15Details
Commit message · Jeffrey Czyz

Rename SplicePending and SpliceFailed events

Rename Event::SplicePending to Event::SpliceNegotiated and
Event::SpliceFailed to Event::SpliceNegotiationFailed. These names
better reflect the per-round semantics: each negotiation attempt
resolves to one of these two outcomes, independent of the overall
splice lifecycle.

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 or wallet pathsecond-pass: security-sensitive path
AI analysis · Informational 15/100

This commit is a simple rename of two public event types in the Lightning Dev Kit Rust library. `Event::SplicePending` is renamed to `Event::SpliceNegotiated`, and `Event::SpliceFailed` is renamed to `Event::SpliceNegotiationFailed`. The change is purely cosmetic and intended to make the event names better match their meaning (a single negotiation round outcome, not the overall splice lifecycle). No logic, serialization format, or security behavior is changed.

Lower-priorityEmit DiscardFunding before SpliceFailedby Jeffrey Czyz · 14c68199 · May 7, 2026 · 3 filesMessage 70 · AdequateLow 45Details
Commit message · Jeffrey Czyz

Emit DiscardFunding before SpliceFailed

Reverse the event ordering at all emission sites so that
Event::DiscardFunding is emitted before Event::SpliceFailed. If the
user retries the splice when handling SpliceFailed, the contributed
inputs would still be locked. A subsequent DiscardFunding would then
incorrectly unlock inputs that are now committed to the new attempt.
Emitting DiscardFunding first avoids this by ensuring inputs are
unlocked before any retry occurs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

70/100 · AdequateMessage clarity
✓ Descriptive subject✓ Provides detailed explanatory context✓ Explains rationale or failure mode
AI analysis · Low 45/100

This commit fixes an ordering bug in how LDK tells the user about a failed splice. Previously, the 'splice failed' notice was sent before the 'you may now unlock your funds' notice. If a user automatically retried the splice upon seeing the failure, their old inputs could still be locked, and the later unlock message would accidentally free inputs that were now being used by the retry. The commit simply reverses the order so funds are unlocked before the failure notice is delivered, and updates tests to match.

Lower-priorityAdd FundingContribution to SpliceFailed eventby Jeffrey Czyz · 450eb645 · May 7, 2026 · 5 filesMessage 68 · AdequateInformational 24Details
Commit message · Jeffrey Czyz

Add FundingContribution to SpliceFailed event

Replace the abandoned_funding_txo and channel_type fields on
Event::SpliceFailed with an Option<FundingContribution> from the failed
round. Users can feed this back to funding_contributed to retry or use
it to inform a fresh attempt via splice_channel.

Also makes FundingContribution::feerate() public so users can inspect
the feerate when deciding whether to retry or bump.

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
AI analysis · Informational 24/100

This commit changes the information returned to users when a Lightning channel splice attempt fails. Instead of reporting an abandoned funding transaction outpoint and channel type, the library now returns the full funding contribution object from the failed round. This lets users retry the splice more easily or decide whether to bump the fee. It also suppresses empty 'discard your inputs' events when nothing actually needs discarding. There is no direct security vulnerability here; it is a usability and API-correctness improvement.

AI review queuedAdd NegotiationFailureReason to SpliceFailed eventby Jeffrey Czyz · f0a8cebb · May 7, 2026 · 5 filesMessage 85 · StrongInformational 21Details
Commit message · Jeffrey Czyz

Add NegotiationFailureReason to SpliceFailed event

Each splice negotiation round can fail for different reasons, but
Event::SpliceFailed previously gave no indication of what went wrong.
Add a NegotiationFailureReason enum so users can distinguish failures
and take appropriate action (e.g., retry with a higher feerate vs.
wait for the channel to become usable).

The reason is determined at each channelmanager emission site based on
context rather than threaded through channel.rs internals, since the
channelmanager knows the triggering context (disconnect, tx_abort,
shutdown, etc.) while channel.rs functions like abandon_quiescent_action
handle both splice and non-splice quiescent actions.

The one exception is QuiescentError::FailSplice, which carries a reason
alongside the SpliceFundingFailed. This is appropriate because FailSplice
is already splice-specific, and the channel.rs code that constructs it
(e.g., contribution validation, feerate checks) knows the specific
failure cause. A with_negotiation_failure_reason method on QuiescentError
allows callers to override the default when needed.

Older serializations that lack the reason field default to Unknown via
default_value in deserialization. The persistence reload path uses
PeerDisconnected since a reload implies the peer connection was lost.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

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
second-pass: broader security terminology
AI analysis · Informational 21/100

This commit is a user-facing diagnostic improvement, not a security fix. It adds a 'reason' field to the SpliceFailed event so Lightning node operators can tell why a splice negotiation failed (for example, peer disconnected, feerate too low, or counterparty aborted). It changes no cryptographic checks, access controls, or network behavior. The only code-level risk is a minor serialization compatibility change: old stored events without the new field default to 'Unknown', and the persistence reload path defaults to 'PeerDisconnected'.

Lower-priorityAttempt to unblock blocked monitor updates on startupby Matt Corallo · b0c312db · May 6, 2026 · 1 fileMessage 93 · StrongModerate 55Details
Commit message · Matt Corallo

Attempt to unblock blocked monitor updates on startup

When we make an MPP claim we push RAA blockers for each chanel to
ensure we don't allow any single channel to make too much progress
until all channels have the preimage durably on disk. We don't have
to store those RAA blockers on disk in the ChannelManager as
there's no point - if the ChannelManager gets to disk with the RAA
blockers it also brought with it the pending ChannelMonitorUpdates
that contain the preimages and will now be replayed, ensuring the
preimage makes it to all ChannelMonitors.

However, just because those RAA blockers dissapear on reload
doesn't mean the implications of them does too - if a later
ChannelMonitorUpdate was blocked in the channel we don't have logic
to unblock it on startup.

Here we add such logic, simply attempting to unblock all blocked
`ChannelMonitorUpdate`s that existed on startup.

Code written by Claude.

Fixes #4518

93/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Links an issue, advisory, or supporting reference
AI analysis · Moderate 55/100

This patch fixes a Lightning node startup issue. When a multi-part payment is claimed, the node temporarily blocks certain channel updates until all parts of the payment are safely recorded. Those temporary blockers are intentionally not saved to disk. But if the node restarts, a later blocked update could stay stuck forever, potentially preventing a channel from making progress or resolving funds. The fix adds a startup step that tries to release any blocked channel monitor updates.

Lower-priorityExpose additional FundingContribution accessorsby Jeffrey Czyz · 1d36f7bc · May 6, 2026 · 1 fileMessage 58 · ThinInformational 15Details
Commit message · Jeffrey Czyz

Expose additional FundingContribution accessors

Add public getters for `estimated_fee`, `inputs`, and `max_feerate`, and
elevate `feerate` from `pub(super)` to `pub`. Together with the existing
`value_added`, `outputs`, and `change_output`, this gives downstream
consumers of `TransactionType::Splice` (notably LDK Node, which updates
`PaymentDetails` from the broadcast callback) the data they need
without reaching into the raw transaction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

58/100 · ThinMessage clarity
✓ Descriptive subject✓ Provides detailed explanatory context
AI analysis · Informational 15/100

This commit adds public getter methods to expose more details of a FundingContribution object in the Lightning Dev Kit library. It is a straightforward API visibility change that lets downstream users read fee, input, and feerate information without inspecting raw transaction data. There is no security-relevant change in behavior.

AI review queuedExpose interactive funding candidates on broadcastby Jeffrey Czyz · 0d2ac33e · May 6, 2026 · 6 filesMessage 73 · AdequateInformational 18Details
Commit message · Jeffrey Czyz

Expose interactive funding candidates on broadcast

Replace TransactionType::Splice with TransactionType::InteractiveFunding
so downstream consumers can update their own state tracking from the
broadcast callback. The local contribution data isn't recoverable from
the on-chain transaction, so the broadcast must surface it directly.
Each candidate carries the participating channels and their local
contributions; the broadcast lists every negotiated candidate — original
first, then each RBF replacement — letting downstream reconcile any
historical txid, not just the immediate predecessor.

The new variant is structured to be forward-compatible with batches and
V2 (dual-funded) channel establishment, neither of which is implemented
today. The new types are Writeable/Readable so downstream can persist
them directly.

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
Why it was queued
signing or wallet pathsecond-pass: security-sensitive path
AI analysis · Informational 18/100

This commit is a routine API improvement for the Lightning Dev Kit. It changes the information reported when a splice (or future dual-funded) transaction is broadcast so that downstream wallet software can see all negotiated versions of the transaction and each party's contribution. There is no indication of a security bug being fixed; it is a feature/refactoring change to expose richer data to consumers of the library.

Lower-priorityRoll back composite sub-handlers when one rejects `peer_connected`by Elias Rohrer · 5455058e · May 6, 2026 · 1 fileMessage 73 · AdequateModerate 60Details
Commit message · Elias Rohrer

Roll back composite sub-handlers when one rejects `peer_connected`

`composite_custom_message_handler!` expanded `peer_connected` to call
every sub-handler and remember the last error, but never undo the
already-succeeded ones. The `CustomMessageHandler::peer_connected`
contract is that `PeerManager` will *not* invoke `peer_disconnected`
when `peer_connected` returns `Err` — so any per-peer state allocated
by an earlier sub-handler that returned `Ok` was leaked permanently
once a later sub-handler returned `Err`.

A peer who can elicit `Err` from any sub-handler in the composite
(feature-bit gate, banlist, etc.) could repeatedly reconnect to grow
that leaked state without bound (slow resource DoS), and "currently
connected" predicates in the leaking sub-handler would lie about
peers that were actually rejected.

Mirror the rollback pattern `PeerManager` already uses for the four
built-in handlers (`peer_handler.rs:2149-2188`): record each
sub-handler's `peer_connected` result, and if any returned `Err`,
call `peer_disconnected` on the ones that succeeded before
propagating the failure.

Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>

73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Moderate 60/100

This commit fixes a bug in a Rust macro that combines multiple custom Lightning message handlers. Previously, if one sub-handler rejected a new peer connection, the handlers that had already accepted it were not told the connection failed. That left behind stale per-peer state that could accumulate over reconnects, causing a slow resource drain and making internal 'is this peer connected?' checks lie. The patch now rolls back the successful sub-handlers by calling their disconnect routine before returning the error, and adds a test proving no state leaks.

Security candidateDrop local chacha20poly1305 implementationby Abeeujah · 964a84fc · May 5, 2026 · 4 filesMessage 50 · ThinInformational 12Details
Commit message · Abeeujah

Drop local chacha20poly1305 implementation

Complete the migration process from the local chacha20poly1305 to the
rust-bitcoin chacha20-poly1305 crate.

50/100 · ThinMessage clarity
✓ Descriptive subject✓ Provides an explanatory body
Why it was queued
cryptography-sensitive path
AI analysis · Informational 12/100

This commit removes the project's own implementations of the ChaCha20 stream cipher, Poly1305 message-authentication code, and the ChaCha20-Poly1305 combined encryption mode. It is described as the final step of migrating to the external 'rust-bitcoin chacha20-poly1305' crate. The change itself is a pure deletion of local code and module declarations; it does not add the replacement crate or change any call sites in this diff. There is no direct evidence in the commit that this fixes a security vulnerability.

Security candidateReplace local ChaCha20-Poly1305 with external crateby Abeeujah · a2cc67e7 · May 5, 2026 · 13 filesMessage 83 · StrongLow 36Details
Commit message · Abeeujah

Replace local ChaCha20-Poly1305 with external crate

Migrates ChaCha20-Poly1305 encryption from the local crypto
module to rust-bitcoin's `chacha20-poly1305` crate.

Integrated the crate across all modules (Router,
PeerStorage, Onion Utils, etc.).

Add the chacha20_poly1305_fuzz flag to fuzz config to after
implementing the fuzz logic upstream.

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 evidencecryptography-sensitive pathsigning or wallet path
AI analysis · Low 36/100

This commit swaps out a home-grown ChaCha20-Poly1305 implementation for a widely reviewed external crate from the rust-bitcoin project. It is a routine refactoring/cryptographic-hardening change, not an obvious security fix. The diff shows careful translation of the old code to the new API, including fuzzing support and nonce handling. There is no direct evidence of a vulnerability being patched, but any crypto migration carries risk of subtle behavioral differences.

Lower-priorityRelease `OutputSweeper::pending_sweep` flag on future dropby Elias Rohrer · 6394d18b · May 5, 2026 · 1 fileMessage 85 · StrongModerate 69Details
Commit message · Elias Rohrer

Release `OutputSweeper::pending_sweep` flag on future drop

`regenerate_and_broadcast_spend_if_necessary` used `pending_sweep:
AtomicBool` as a single-runner gate but only cleared the flag with an
unconditional `store(false)` *after* the inner future resolved. If the
caller's future was dropped while the inner await was `Pending` —
which `tokio::time::timeout`, `futures::select!`, manual
`JoinHandle::abort`, etc. all do — the reset never ran, leaving the
flag stuck `true` and every subsequent call to the function
short-circuiting with `Ok(())`.

Because `OutputSweeper` is what claims `SpendableOutputDescriptor`s
back to the user's wallet after channel closure (including HTLC
outputs with time-bounded recovery deadlines), a stuck flag turns
into fund-loss exposure: time-sensitive HTLC sweeps simply stop
happening, while every other code path keeps queueing new outputs to
sweep, until the process is restarted.

Replace the trailing `store(false)` with an RAII `PendingSweepGuard`
whose `Drop` impl always releases the flag — covering normal return,
error, and cancellation alike.

Co-Authored-By: HAL 9000

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 69/100

This commit fixes a bug in rust-lightning's OutputSweeper where a cancellation-safe flag was not actually cancellation-safe. If the future performing sweep operations was dropped mid-await (for example, due to a timeout or abort), a 'sweep in progress' flag would stay stuck on, permanently disabling the sweeper. Because the sweeper is responsible for recovering funds from closed Lightning channels, including time-sensitive HTLC outputs, a stuck flag could lead to real fund loss until the process restarted. The fix replaces a manual flag-clear that ran only on normal completion with an RAII guard whose Drop implementation always releases the flag, even when the future is cancelled. A regression test is included.

Security candidateValidate Esplora merkle proof against the block header's merkle rootby Elias Rohrer · b64efcda · May 5, 2026 · 1 fileMessage 78 · AdequateCritical 88Details
Commit message · Elias Rohrer

Validate Esplora merkle proof against the block header's merkle root

`EsploraSyncClient::get_confirmed_tx` parsed the SPV proof returned by
the Esplora server but threw away the security check: the merkle root
computed by `PartialMerkleTree::extract_matches` was discarded
(`let _ = …`), and only the leaf-equality check (`matches[0] == txid`)
remained. Anyone can construct a single-leaf partial tree advertising
an arbitrary txid via `PartialMerkleTree::from_txids(&[txid], &[true])`,
so this gate was vacuous.

A malicious or compromised Esplora server could therefore convince
`EsploraSyncClient` that any transaction was confirmed in any block by
returning `MerkleBlock { header: real_header, txn: forged_partial_tree }`,
causing LDK to feed a synthesized `ConfirmedTx` into `Confirm`
implementations such as `ChannelManager` / `ChainMonitor`. From there,
the channel-funding / closing / HTLC flows would treat the transaction
as confirmed at an attacker-chosen height, with consequences ranging
from premature state transitions to force-close races.

Capture the merkle root returned by `extract_matches` and require it
to equal `block_header.merkle_root`, matching the validation the
Electrum sibling already performs via `validate_merkle_proof`.

Co-Authored-By: HAL 9000

78/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Names security-relevant behavior explicitly
Why it was queued
explicit security languagedefensive validationsigning or wallet path
AI analysis · Critical 88/100

This commit fixes a security bug in LDK's Esplora client. The client was supposed to verify that a transaction was really included in a Bitcoin block by checking a cryptographic proof (a merkle proof) from the Esplora server. But it only checked that the proof contained the right transaction ID, not that the proof actually connected to the real block header. Because a single-leaf proof can be forged for any transaction ID, a malicious or compromised Esplora server could trick LDK into believing any transaction was confirmed in any block. That could trigger wrong channel state changes, premature force-closes, or other fund-risking behavior. The fix makes the client compare the computed merkle root from the proof against the block header's merkle root, which is the same check the Electrum client already did.

Lower-priorityFix `StaticInvoice::is_offer_expired` to check the offer's expiryby Elias Rohrer · c005b11d · May 5, 2026 · 1 fileMessage 73 · AdequateModerate 62Details
Commit message · Elias Rohrer

Fix `StaticInvoice::is_offer_expired` to check the offer's expiry

The std-only `StaticInvoice::is_offer_expired` accessor delegated to
`InvoiceContents::is_expired`, which compares `created_at +
relative_expiry` against the current time — that is the *invoice*'s
expiry, not the offer's. The `_no_std` sibling and `flow.rs::
enqueue_static_invoice` already treat the two as distinct checks.

A payer or forwarder using the std API to decide whether to honor a
static invoice would therefore get the wrong answer in either
direction: forwarding offers the issuer has already retired (when the
invoice is still fresh), or refusing offers that are still valid (when
the invoice has aged past its `relative_expiry` but the offer itself
has no `absolute_expiry`).

Route the std accessor through `InvoiceContents::is_offer_expired` so
both the std and no-std paths consult the offer's expiry.

Co-Authored-By: HAL 9000

73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI analysis · Moderate 62/100

A bug in a Lightning payment library caused one of its functions to check the wrong expiration date. A function named `is_offer_expired` was accidentally checking when the invoice itself expires, rather than when the underlying offer expires. This could make a payer or forwarder reject valid offers or accept offers the issuer had already retired. The fix routes the standard-library version of the function to the correct offer-expiry check, matching the already-correct no-standard-library version.

Lower-priorityCount zero-fee-commitments channels in anchor reserve checkby Elias Rohrer · 33987e86 · May 5, 2026 · 1 fileMessage 83 · StrongModerate 60Details
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
AI analysis · Moderate 60/100

This commit fixes an accounting bug in the Lightning Dev Kit. When a node uses a newer type of anchor-backed channel (called TRUC or zero-fee-commitments), the software was not counting that channel when checking whether the wallet still has enough on-chain money set aside for emergency fee bumps. That could let the node open more anchor channels than it can actually afford to close safely, raising the risk of being unable to pay fees to claim funds during a force close. The fix counts both old and new anchor channel types the same way and adds a regression test.

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 · AdequateInformational 14Details
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
AI analysis · Informational 14/100

This change only moves the project's fuzzing test data from a GitHub Actions cache into a separate public repository. It updates CI scripts to clone that repository, copy files into place, and open pull requests with any newly discovered fuzz inputs. There is no change to the actual Lightning Dev Kit code that users run, and nothing in the diff suggests a security vulnerability or fix.

Lower-priorityFix typo in `_encode_tlv` leading to confused encodingby Matt Corallo · 05135aec · May 1, 2026 · 1 fileMessage 50 · ThinModerate 61Details
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
AI analysis · Moderate 61/100

This commit fixes a small but meaningful typo in a Rust macro used to encode Lightning protocol data. The misplaced parenthesis could cause the macro to match the wrong pattern when encoding optional fields that use a custom encoding. That could lead to messages being serialized incorrectly, which in a Lightning node might cause peers to reject messages, fail to parse state, or potentially behave in unexpected ways during channel operations. The fix is one character moving a closing parenthesis.