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 queue184AI 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 Rohrer1531512467
Matt Corallo3564733173
Leo Nash116139162
Jeffrey Czyz1774140068
Wilmer Paulino1493937069
Joost Jager1622420069
elnosh30135056
Valentine Wallace135107069
shaavan2266069
Carla Kirk-Cohen6532069
benthecarman1833071
Duncan Dean833057
Analysis record

Published AI watches

Last scanned 1 minute ago

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
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 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 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
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 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 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
Low 25 AI analysisMessage 85 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Require `htlc_value_satoshis` in [pending] `HTLCUpdate`s

This commit removes the 'Option' wrapper from several HTLC amount fields, making them required instead of optional. It is a cleanup/refactoring change that simplifies the code by assuming the amount is always known. The commit message fram…

Removal of Option wrapper for financial amount fieldsSerialization format change from optional to required TLV fieldsLoss of backward compatibility with older serialized monitor/channel state
40957aadby Matt Corallo+24−284 files
No security note in commit
Informational 15 AI analysisMessage 78 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Use a builder for sign_interactive_funding_tx arguments

This commit is a code cleanup inside the project's test suite. It replaces a helper function with several hard-to-read positional arguments (like bare `false` and `None`) with a 'builder' pattern that names each option. This makes the test…

ed250c02by Jeffrey Czyz+116−861 file
No security note in commit
Low 25 AI analysisMessage 83 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

ln: persist the paid BOLT 12 invoice and build payer proofs

This commit is a feature addition, not a vulnerability fix. It extends rust-lightning's BOLT 12 payment support so that when a wallet pays a BOLT 12 invoice, the paid invoice is saved through retries and restarts and is later exposed in th…

New BOLT 12 payer proof feature: persists paid invoice across retries/restarts and exposes it in Event::PaymentSentPayer signing key re-derived from invoice payer metadata rather than storing extra key materialAdds end-to-end test for proof creation, verification, and bech32 round-trip
580c9bc8by Vincenzo Palazzo+226−284 files
No security note in commit
Informational 17 AI analysisMessage 85 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

refactor(offers): extract payer key derivation helpers

This commit is a code cleanup (refactor) in the Lightning Dev Kit library. It moves existing payer key-derivation logic into shared helper functions so that future 'payer proof' features can reuse the same code. The change does not appear …

Refactor only: moves existing key derivation/verification logic into helpers without changing algorithmsAdds new public API `Bolt12Invoice::derive_payer_signing_keys` for payer proof key recoveryNo mention of vulnerability, bug, CVE, security fix, or exploit in commit title/message
2bd9266aby Vincenzo Palazzo+120−212 files
No security note in commit
Informational 15 AI analysisMessage 83 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Upload new fuzz corpus entries as a short-lived CI artifact

This commit changes a CI workflow for the rust-lightning project. It stops trying to push new fuzz test inputs directly to a corpus repository from automated test runs, and instead uploads them as a temporary artifact that a separate sched…

b9f55b6cby Matt Corallo+52−451 file
No security note in commit
Low 25 AI analysisMessage 100 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

ln: add trampoline mpp accumulation with rejection on completion

This commit adds partial support in the Lightning Dev Kit node software for receiving and temporarily holding multi-part trampoline payments, then deliberately rejects them once all parts arrive because full outbound forwarding is not yet …

New trampoline forward handling path accumulates MPP parts before rejectingDebug assertion guards first-HTLC failure in MPP mergeTODO comment flags possible MPP inconsistency in next_node_id across trampoline parts
1afd35e6by Carla Kirk-Cohen+240−112 files
No security note in commit
Informational 23 AI analysisMessage 85 · Strong
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

ln: remove incoming trampoline secret from HTLCSource

This commit removes a redundant 32-byte shared secret field from an internal data structure used when forwarding trampoline payments in the Lightning Dev Kit. The developers realized the secret was already stored inside each previous hop's…

Removes redundant secret field from in-memory/persisted stateChanges TLV serialization layout for HTLCSource::TrampolineForwardBreaking persistence change acknowledged by commit author
816b866dby Carla Kirk-Cohen+10−221 file
No security note in commit
Informational 19 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Use Forgejo OIDC for review requests

This commit changes the project's automated reviewer-assignment workflow to stop using a long-lived secret token and instead request a short-lived authentication token from the Forgejo CI service. This is a security-hardening improvement: …

Removal of long-lived repository secret from CI workflowAdoption of OIDC-based short-lived token for API authorizationWorkflow runs in pull_request_target context with no code checkout
57c84bcaby Elias Rohrer+17−81 file
Vendor flagged security relevance
Informational 15 AI analysisMessage 78 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

fuzz: add chanmon holder signer fuzz ops

This commit only adds new fuzz-testing commands to an existing test harness. It lets the fuzzer temporarily block and then re-enable the local node's own signing operations during simulated channel failures. There is no change to productio…

6ae2634eby Joost Jager+26−31 file
No security note in commit
Informational 18 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Pin actions/checkout + actions/cache to a full URL and commit hash

This commit hardens the project's automated build and test scripts by replacing loose version tags like 'actions/checkout@v4' with exact commit hashes served from a specific domain. This prevents a compromised or renamed third-party action…

CI/CD supply-chain hardeningAction reference pinning to immutable commit hashUse of explicit action mirror URL
3a56fcc2by Matt Corallo+19−196 files
Vendor flagged security relevance
Moderate 57 AI analysisMessage 73 · Adequate
LDK Lightning Dev Kitrust-lightning BitcoinCryptographic librariesLightning Network

Lower strictness of pending monitor update while awaiting tx_signatures

This commit fixes a logic bug in the Lightning Dev Kit's channel splicing code. Previously, the code wrongly assumed that no unrelated monitor update could be pending when a splice `tx_signatures` message arrived while the channel was quie…

Assertion relaxation in state-machine handling of splice `tx_signatures`Race condition between unrelated HTLC preimage monitor update and splice signature exchangePotential panic or protocol stall due to overly strict debug assertion
b8a76c17by Wilmer Paulino+174−42 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 candidateDrop local chacha20poly1305 implementationby Abeeujah · 964a84fc · May 5, 2026 · 4 filesMessage 50 · ThinTriage 15Details
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
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.

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.

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.

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.

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 candidateRename `BestBlock` to `BlockLocator`by Matt Corallo · dcba68d2 · Apr 24, 2026 · 22 filesMessage 58 · ThinTriage 12Details
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
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.

Security candidateSplit fuzz runners by hash modeby Joost Jager · bfc7c7bb · Apr 15, 2026 · 88 filesMessage 78 · AdequateInformational 15Details
Commit message · Joost Jager

Split fuzz runners by hash mode

Move shared fuzz logic into the root fuzz crate and generate
fake-hashes and real-hashes runner crates.

Keep `chanmon_consistency_target` on the real-hashes side, remove
the fuzz-local Cargo config, and update scripts, CI, coverage,
and docs to use explicit flags for each runner.

Generate the hash-mode compile checks in the wrapper bins
without a synthetic Cargo feature, while keeping the wrapper
template close to its original shape.

AI tools were used in preparing this commit.

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 evidenceseed or entropy pathsigning or wallet pathboot or update pathauthentication pathparser or protocol path
AI analysis · Informational 15/100

This commit is a build-system and test-infrastructure refactor for the project's fuzzing (automated randomized testing) harness. It splits fuzz test runners into two groups based on whether they use fake or real cryptographic hashes, moves shared code into a common crate, and updates CI scripts, coverage tooling, and documentation accordingly. There is no change to the actual Lightning protocol library or to how production nodes behave, and no security vulnerability is introduced or fixed.

Security candidateci: pin hyper-rustls for Rust 1.75 sync buildsby Joost Jager · aac136e1 · Apr 14, 2026 · 1 fileMessage 90 · StrongInformational 15Details
Commit message · Joost Jager

ci: pin hyper-rustls for Rust 1.75 sync builds

The build-sync job started resolving hyper-rustls v0.27.8 for the esplora-async-https configuration. That release requires rustc 1.85, but the sync CI job still runs on Rust 1.75.0.

Pin hyper-rustls to 0.27.7 when building with rustc older than 1.85, alongside the existing MSRV dependency pins in ci-tests-common.sh.

AI tools were used in preparing this commit.

90/100 · StrongMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Uses a recognizable type or scope✓ Provides detailed explanatory context✓ Mentions testing or verification
Why it was queued
access control
AI analysis · Informational 15/100

This is a routine CI maintenance commit. It pins an older version of a dependency (hyper-rustls) so that automated builds using an older Rust compiler (1.75) continue to work. It does not change application code, fix a vulnerability, or alter how the software behaves in production.

Security candidateUse `saturating_mul` when multiplying feerates by the fee spike bufby Matt Corallo · b98d7b8a · Apr 13, 2026 · 2 filesMessage 90 · StrongModerate 53Details
Commit message · Matt Corallo

Use `saturating_mul` when multiplying feerates by the fee spike buf

In theory a channel's feerate could be set to some absurd value
(millions of satoshis per vB) and we'd overflow the fee spike
buffer, accepting the absurd fee and ignoring our fee spike buffer
check. This is harmless - the counterparty has much easier ways of
bricking the channel if they want, and paying several BTC in fees
is probably not the best way. Our commitment transaction and dust
fee exposure logic all correctly map the `u32` to a `u64` before
multiplying, making them overflow-safe.

Still, its good to fix overflows because it is a remotely-reachable
crash in debug builds.

Reported by Jordan Mecom of Block's Security Team

90/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Names security-relevant behavior explicitly
Why it was queued
memory safetysigning or wallet path
AI analysis · Moderate 53/100

This patch fixes a potential integer overflow when calculating Lightning channel fees. If a malicious or misconfigured peer set an extremely high transaction fee rate, the software could overflow a 32-bit integer while applying a safety buffer multiplier. In release builds this would silently wrap around and ignore the safety buffer; in debug builds it would crash. The fix uses saturating multiplication so the result stays at the maximum safe value instead of overflowing. The commit notes this is not practically exploitable for theft because a peer already has easier ways to disrupt a channel, but it removes a remotely reachable debug crash.

Security candidateCorrect blinded path forwarding CLTV expiry checkby Matt Corallo · 8d8313de · Apr 13, 2026 · 2 filesMessage 95 · StrongLow 43Details
Commit message · Matt Corallo

Correct blinded path forwarding CLTV expiry check

The `PaymentConstraints::max_cltv_expiry` field exists to ensure
a blinded path expires across the entire path at once - once the
path is expired it will be rejected by the introduction node rather
than traversing the entire path and failing at the destination.

This was broken by the fact that we were checking the outgoing CLTV
value rather than the incoming one, which admittedly isn't clear in
the spec but is somewhat implied. Here we fix this, updating a test
which was actually (kinda) exploiting this privacy loss rather than
allowing the HTLC to fail at the introduction node.

This, of course, does not risk funds loss as our own CLTV policy is
still enforced on top. The only impact it could have is a recipient
which was relying on blinded path expiry to avoid some cost (e.g.
LSPS5 node wakeup cost) involved in receiving an HTLC they
ultimately fail, though I'm not aware of any practical deployment
where that is a concern.

Reported by Jordan Mecom of Block's Security Team

95/100 · StrongMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification✓ Names security-relevant behavior explicitly
Why it was queued
explicit security language
AI analysis · Low 43/100

This commit fixes a bug in how Lightning Dev Kit checks expiry times for payments sent through 'blinded paths' (a privacy feature that hides the final recipient). The code was accidentally checking the outgoing expiry time instead of the incoming one. Because of this, a payment could travel deeper into the blinded path than intended before being rejected, slightly weakening the privacy/cost protection that blinded-path expiry is meant to provide. The commit explicitly states this does not risk loss of funds.

Security candidateAdd `unannounced_channel_max_inbound_htlc_value_in_flight_percentage`by Leo Nash · 2867d5c1 · Apr 2, 2026 · 13 filesMessage 53 · ThinTriage 12Details
Commit message · Leo Nash

Add `unannounced_channel_max_inbound_htlc_value_in_flight_percentage`

Users can now configure two different max percentages for the channel
value that can be allocated to inbound HTLCs, one for announced
channels, and another for unannounced channels.

We also bump the default maximums to 25% for announced channels, and
100% for unannounced channels, to bring them closer to what people would
expect.

53/100 · ThinMessage clarity
✓ Specific, descriptive subject✓ Provides detailed explanatory context! Too few words to establish purpose
Why it was queued
boot or update path
Security candidateReturn `BestBlock` when deserializing chain-synced structsby Matt Corallo · 413c937d · Mar 30, 2026 · 11 filesMessage 85 · StrongTriage 12Details
Commit message · Matt Corallo

Return `BestBlock` when deserializing chain-synced structs

The deserialization of `ChannelMonitor`, `ChannelManager`, and
`OutputSweeper` is implemented for a `(BlockHash, ...)` pair rather
than on the object itself. This ensures developers are pushed to
think about initial chain sync after deserialization and provides
the latest chain sync state conviniently at deserialization-time.

In the previous commit we started storing additional recent block
hashes in `BestBlock` for use during initial sync to ensure we can
handle reorgs while offline if the chain source loses the
reorged-out blocks. Here, we move the deserialization routines to
be on a `(BestBlock, ...)` pair instead of `(BlockHash, ...)`,
providing access to those recent block hashes at
deserialization-time.

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
boot or update path
Security candidateRemove dead string search in fuzz SearchingOutputby Joost Jager · b9181c36 · Mar 30, 2026 · 1 fileMessage 83 · StrongInformational 15Details
Commit message · Joost Jager

Remove dead string search in fuzz SearchingOutput

The searched-for log message ("Outbound update_fee HTLC buffer
overflow") no longer exists in the lightning crate, so the
from_utf8 + contains check on every log line was pure waste.

AI tools were used in preparing this commit.

83/100 · StrongMessage clarity
✓ 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
memory safetyfuzzing or regression evidence
AI analysis · Informational 15/100

This commit is a cleanup of a fuzz-testing helper. It removes a wrapper that scanned every log line for a specific error message that no longer exists in the codebase. Because the searched message was already gone, the wrapper served no purpose and only wasted CPU. There is no change to production Lightning code, no user-facing behavior change, and no security fix.

Security candidateAdd 0-reserve to `accept_inbound_channel_from_trusted_peer`by Leo Nash · 954bf2df · Mar 26, 2026 · 11 filesMessage 65 · AdequateLow 34Details
Commit message · Leo Nash

Add 0-reserve to `accept_inbound_channel_from_trusted_peer`

This new flag sets 0-reserve for the channel opener.

65/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides an explanatory body
Why it was queued
signing or wallet pathboot or update path
AI analysis · Low 34/100

This commit renames and expands a special Lightning channel-acceptance API. Previously, users could manually accept an inbound channel from a trusted peer and treat it as confirmed immediately (zero-conf). Now the same API also allows setting the counterparty's required channel reserve to zero. A zero reserve means the peer can spend their entire balance and force-close the channel at no cost to themselves, which removes a key financial deterrent against cheating. The change is explicitly documented as dangerous and only appropriate for trusted peers, but it introduces a new risky option that did not exist before.

Security candidatePrevent downgrades in case holder-selected reserve is zero satoshisby Leo Nash · 63e4538e · Mar 26, 2026 · 1 fileMessage 73 · AdequateInformational 22Details
Commit message · Leo Nash

Prevent downgrades in case holder-selected reserve is zero satoshis

We prevent downgrades from 0.3 only in the case where the
holder-selected reserve is 0, as we've had support for counterparty
selected 0-reserves in prior releases.

There is no need for this sentinel in `FundingScope` serialization code
as this would only apply to pending `FundingScope`'s.

Also, if the current scope has some zero-reserve, that reserve is
carried over to all pending scopes automatically. Therefore it is not
possible for a pending scope to have some 0-reserve without the current
one also having it.

73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
update trust
AI analysis · Informational 22/100

This commit adds a marker to saved channel data so that older versions of the software will refuse to load it if the channel uses a zero-satoshi reserve chosen by the local user. That prevents accidental downgrades that could mishandle such channels, because older releases only understood zero-reserve channels when the remote side chose the zero reserve. It is a forward-compatibility guard, not a fix for an active attack.

Security candidateAdd inbound and outbound checks for zero reserve channelsby Leo Nash · 98b71c88 · Mar 25, 2026 · 7 filesMessage 77 · AdequateHigh 70Details
Commit message · Leo Nash

Add inbound and outbound checks for zero reserve channels

The goal is to prevent any commitments with no outputs, since these are
not broadcastable.

77/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides an explanatory body✓ Explains rationale or failure mode
Why it was queued
signing or wallet pathboot or update path
AI analysis · High 70/100

This commit fixes a bug in the Lightning Dev Kit where a payment channel could end up with a commitment transaction that has zero spendable outputs. In Bitcoin, a transaction with no outputs is invalid and cannot be broadcast, which would make it impossible to enforce or recover funds from the channel if something goes wrong. The patch adds checks during channel opening, fee updates, and HTLC handling to ensure that zero-reserve channels always keep at least one valid output.

Security candidateDefer monitor update completions after funding spendby Joost Jager · f8a955c5 · Mar 20, 2026 · 2 filesMessage 73 · AdequateTriage 12Details
Commit message · Joost Jager

Defer monitor update completions after funding spend

When no_further_updates_allowed() is true and the persister returns
Completed, ChainMonitor now overrides the return to InProgress and
pushes a MonitorEvent::Completed directly into pending_monitor_events.
In release_pending_monitor_events, these deferred completions are
appended after per-monitor events, so ChannelManager sees the
force-close MonitorEvents before the completion.

This eliminates phantom InProgress entries that would never complete:
previously, a rejected pre-close update (e.g. commitment_signed
arriving after funding spend) returned InProgress with no completion
path, blocking MonitorUpdateCompletionActions (PaymentClaimed,
PaymentForwarded) indefinitely. A subsequent post-close update
returning Completed would then violate the in-order completion
invariant.

AI tools were used in preparing this commit.

73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
boot or update path
Security candidatefuzz: use process::exit panic hook in stdin_fuzz on macOSby Joost Jager · 39c8b0c8 · Mar 20, 2026 · 72 filesMessage 95 · StrongInformational 15Details
Commit message · Joost Jager

fuzz: use process::exit panic hook in stdin_fuzz on macOS

On macOS, panic=abort causes the process to call abort() which sends
SIGABRT. The ReportCrash daemon then tries to generate a crash report,
leaving the process stuck in an uninterruptible wait state that cannot
be killed even with SIGKILL. This makes stdin_fuzz unusable for crash
reproduction on macOS.

Install a custom panic hook (gated behind #[cfg(target_os = "macos")])
that flushes stdout (preserving log output), prints the panic info with
a full backtrace to stderr, then calls process::exit(1) to terminate
cleanly before the abort machinery runs. The hook is only installed on
macOS to avoid interfering with debuggers like GDB on Linux.

AI tools were used in preparing this commit.

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
fuzzing or regression evidencesigning or wallet pathboot or update pathauthentication pathparser or protocol path
AI analysis · Informational 15/100

This commit only changes internal fuzz-testing helper programs so they exit cleanly on macOS instead of getting stuck when a crash occurs. It does not affect the actual Lightning Dev Kit library, real Lightning nodes, or any user-facing code. There is no security vulnerability being fixed or introduced.

Security candidateRelease tx_signatures after async monitor update completesby Wilmer Paulino · ea204f60 · Mar 19, 2026 · 5 filesMessage 100 · StrongModerate 66Details
Commit message · Wilmer Paulino

Release tx_signatures after async monitor update completes

In 83b2d3e, we reworked `ChannelManager::funding_transaction_signed`
such that it would also for a user to cancel a splice up until they send
`commitment_signed`. Previously, we would would only emit
`Event::FundingTransactionReadyForSigning` when both nodes exchanged
`commitment_signed` and the corresponding monitor update completed. With
the event now being generated immediately after the nodes exchange
`tx_complete`, we now need to handle the monitor update not having
completed by the time we are ready to send `tx_signatures`.
Unfortunately, we also did not have test coverage, allowing this to go
unnoticed until being caught by the fuzzer due to a debug assertion.
Doing so avoids a potential funds-loss scenario if the funding
transaction confirms without the counterparty's signature for our
commitment being durably persisted.

100/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✓ Names security-relevant behavior explicitly
Why it was queued
signing boundaryfuzzing or regression evidencesigning or wallet path
AI analysis · Moderate 66/100

This commit fixes a bug in the Lightning Dev Kit where, during a special channel operation called splicing, the node could release its signatures for the new funding transaction before the local channel monitor had durably saved the counterparty's signature for the new commitment. If the funding transaction confirmed on-chain while the counterparty's signature was not yet persisted, the node could be left unable to enforce its funds, creating a potential loss of funds scenario. The fix delays sending `tx_signatures` until the asynchronous monitor update completes, and adds tests to cover this case.

Security candidateAdd test for monitor update after funding spendby Joost Jager · 1d3704d5 · Mar 19, 2026 · 1 fileMessage 78 · AdequateModerate 56Details
Commit message · Joost Jager

Add test for monitor update after funding spend

Add a regression test that reproduces the panic when a commitment_signed
is processed after the counterparty commitment transaction has confirmed.
The ChannelMonitor's no_further_updates_allowed() returns true, causing
update_monitor to fail, which ChainMonitor overrides to InProgress. A
subsequent preimage claim returning Completed then triggers the
per-channel assertion that Completed must not follow InProgress.

AI tools were used in preparing this commit.

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 evidenceboot or update path
AI analysis · Moderate 56/100

This commit adds a regression test that reproduces a crash (panic) in the Lightning Dev Kit's channel monitoring logic. The crash happens when a blockchain event and a peer message arrive in an unlucky order: after the counterparty's commitment transaction confirms on-chain, the local node still processes a new commitment_signed message from that peer. The code marks the channel monitor as frozen, but a later legitimate payment preimage claim returns a success status, conflicting with the earlier frozen status and triggering an internal assertion that crashes the node.

Security candidateReplace dual-sync-async persistence panic with Watch contractby Joost Jager · 970d4d94 · Mar 19, 2026 · 7 filesMessage 95 · StrongLow 44Details
Commit message · Joost Jager

Replace dual-sync-async persistence panic with Watch contract

Commit 0760f99 ("Disallow dual-sync-async persistence without
restarting") added a panic in non-test builds when a Persist
implementation returns both Completed and InProgress from the same
ChannelManager instance. However, this check runs against the status
that ChainMonitor returns to ChannelManager, not the raw Persist
result. When ChannelMonitor::update_monitor fails (e.g. a
counterparty commitment_signed arrives after a funding spend
confirms), ChainMonitor persists the full monitor successfully but
overrides the return value to InProgress. If the user's Persist impl
only ever returns Completed, this override triggers a false
mode-mismatch panic.

This replaces the panic with a per-channel contract at the Watch
trait level: a Watch implementation must not return Completed for a
channel update while prior InProgress updates are still pending.
Switching from Completed to InProgress is always allowed, but
switching back is impractical because the Watch implementation cannot
observe when ChannelManager has finished processing a
MonitorEvent::Completed. The documentation on
ChannelMonitorUpdateStatus is updated to describe these rules.

The mode tracking and panic checks from 0760f99 are removed and
replaced with a panic that validates the new contract directly on
the in-flight update state. Legacy tests that switch the persister
between modes mid-flight can opt out via
Node::disable_monitor_completeness_assertion().

Co-Authored-By: Claude Opus 4.6 <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
Why it was queued
defensive validationboot or update path
AI analysis · Low 44/100

This commit fixes a bug where the Lightning Dev Kit (LDK) node software could crash with a false alarm panic. The panic was meant to catch incorrect use of two persistence modes, but it could also fire in legitimate situations because it checked an overridden status value rather than the raw result from the user's persistence code. The fix replaces the broad panic with a more precise rule at the Watch trait level and adds a test-only opt-out for legacy tests that intentionally switch modes mid-flight.

Security candidateFail HTLCs from late counterparty commitment updates after funding spendby Joost Jager · 3e1a18c8 · Mar 18, 2026 · 4 filesMessage 73 · AdequateTriage 12Details
Commit message · Joost Jager

Fail HTLCs from late counterparty commitment updates after funding spend

When a ChannelMonitorUpdate containing a new counterparty commitment is
dispatched (e.g. via deferred writes) before a channel force-closes but
only applied to the in-memory monitor after the commitment transaction
has already confirmed on-chain, the outbound HTLCs in that update must
be failed back.

Add fail_htlcs_from_update_after_funding_spend to ChannelMonitorImpl
which detects this race condition during update_monitor. When a
LatestCounterpartyCommitmentTXInfo or LatestCounterpartyCommitment
update is applied and the funding output has already been spent, the
function iterates all outbound HTLCs from the update and creates
OnchainEvent::HTLCUpdate entries for those that need to be failed back.
These entries mature after ANTI_REORG_DELAY blocks, giving time for the
peer to potentially broadcast the newer commitment.

HTLCs that appear as non-dust outputs in the confirmed commitment
(whether counterparty or holder) are skipped, as they will be resolved
on-chain via the normal HTLC timeout/success path. HTLCs already
fulfilled by the counterparty (tracked in counterparty_fulfilled_htlcs)
are also skipped. Duplicate failures from previously-known counterparty
commitments are handled gracefully by the ChannelManager.

AI tools were used in preparing this commit.

73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
boot or update path
Security candidateAdd deferred bool to ChainMonitorby Joost Jager · 9b015a67 · Mar 18, 2026 · 7 filesMessage 68 · AdequateTriage 12Details
Commit message · Joost Jager

Add deferred bool to ChainMonitor

Add a `deferred` parameter to `ChainMonitor::new` and
`ChainMonitor::new_async_beta`. When set to true, the Watch trait
methods (watch_channel and update_channel) will unimplemented!() for
now. All existing callers pass false to preserve current behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

68/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
boot or update path