LL
← All projectsLightning Labs

LND

Go implementation of a complete Lightning Network node.

BitcoinLightning NetworkNormal
Repository coverage

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

141security candidates194second-pass queue1285AI analyses
78commits · 30 days
173commits · 60 days
599commits · 180 days
1237commits · 365 days
Backfill bands
Aug 5 → Feb 6405 seen5 candidatesComplete
Feb 6 → Jun 6665 seen28 candidatesComplete
Jun 6 → Jul 689 seen4 candidatesComplete
Jul 6 → Aug 569 seen0 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.

67/100 average clarity
318Strong · 80–100
646Adequate · 60–79
391Thin · 40–59
31Opaque · 0–39
1security candidate 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.
Olaoluwa Osuntokun20942204474
Elle Mouton26832268167
ziggie44416413165
Yong28513171
LNBiG111173
Jared Tobin909171
bitromortac531051069
yyforyongyu83861068
Erick Cestari26726070
Andras Banki-Horvath11311072
Gijs van Dam33230073
ziggieXXX2026070
Analysis record

Published AI watches

Last scanned 29 minutes ago

Moderate 62 AI analysisMessage 58 · Thin
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11212 from ziggie1984/disable-legacy-channels

This change stops LND from opening new Lightning channels using the old 'legacy' commitment format. The legacy format makes it harder to recover funds if something goes wrong, because the money owed to you is tied to a secret key that chan…

Prevents opening new channels with the legacy commitment type, whose tweaked to_remote output complicates data-loss recoveryCloses a negotiation path where an empty channel_type TLV bypassed feature checks and forced a legacy channelAdds explicit RPC and wire rejection with a dedicated error code
112cb5f3by ziggieXXX+265−4716 files
Vendor flagged security relevance
Moderate 56 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11223 from gijswijs/legacy-dust-retribution-fix

This update fixes a bug in how LND handles old-style punishment transactions when a channel partner tries to cheat. Previously, tiny (dust) HTLCs were left as blank placeholder entries in the punishment data, which could cause the node to …

nil-pointer dereference risk in breach retribution pathlegacy revocation log handling inconsistency with modern formatdefensive hardening added for trimmed/dust HTLCs
500ca51fby ziggieXXX+168−146 files
No security note in commit
Moderate 62 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11190 from Roasbeef/zpay32-reject-duplicate-payment-hashes

This change tightens how LND reads Lightning invoices (BOLT 11). Previously, if an invoice contained more than one payment hash field, LND would silently keep the first one and ignore the rest. Now it rejects the invoice entirely. The rele…

Behavior change from 'use first duplicate field' to 'reject duplicate fields'New error type ErrDuplicatePaymentHash returned on duplicate payment hash fieldsMalformed/unsupported-length duplicate payment hash now treated as duplicate and rejected
86306f89by Yong+147−106 files
No security note in commit
Moderate 62 AI analysisMessage 98 · Strong
LL Lightning LabsLND BitcoinLightning Network

zpay32: reject duplicate payment hash fields

This change tightens how LND reads Lightning invoices. Previously, if an invoice contained more than one payment hash field, LND would silently keep the first valid one and ignore the rest. Now it rejects such invoices outright. This preve…

Behavioral change from silent first-field acceptance to explicit rejection of duplicate payment hash fieldsPrevents invoice parsing from depending on field ordering when multiple payment hashes are presentCovers malformed first field + valid second field, closing a potential bypass
e2f27063by Olaoluwa Osuntokun+147−106 files
Vendor flagged security relevance
Moderate 53 AI analysisMessage 58 · Thin
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11132 from yyforyongyu/task-11129-pong

This change fixes how LND answers network 'ping' messages from other Lightning nodes. Previously, LND would sometimes silently ignore valid pings to limit reply traffic, which violates the Lightning protocol (BOLT 1) and could make a peer …

Protocol compliance fix: BOLT 1 requires a Pong for every valid PingRemoved silent suppression of Pong replies that could cause peer timeout/misbehaviorUnified rate limiting now accounts for amplification bandwidth, not just ping count
d3d1f1d0by Olaoluwa Osuntokun+274−1715 files
Vendor flagged security relevance
Low 33 AI analysisMessage 90 · Strong
LL Lightning LabsLND BitcoinLightning Network

itest: stop creating legacy channels

This commit updates LND's integration tests to stop using an obsolete 'legacy' channel type and adds a test confirming that LND now rejects that legacy type. The commit message says the real fix is elsewhere in the same pull request: previ…

Deprecated commitment format (legacy) is now rejected by RPCTest added to verify legacy channel type is refusedUnused legacy node configuration flag removed
03d8b09dby ziggie+24−85 files
No security note in commit
Moderate 60 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11198 from gijswijs/amp-setlocal-reconstruction-fix

This change fixes a bug in LND's handling of AMP (Atomic Multi-Path) payments. Previously, if one partial payment set failed to reconstruct its secret preimage, the entire invoice was canceled, including unrelated partial payment sets from…

Denial-of-service against reusable static AMP invoices by causing unrelated accepted HTLC sets to be canceledIncorrect invoice state transition from set-local failure to global invoice cancellationAvailability impact on multi-payer AMP invoice scenarios
88959aecby Olaoluwa Osuntokun+155−44 files
Vendor flagged security relevance
Low 29 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11200 from ziggie1984/build-go-1.27.1

This commit updates the Go programming language version used to build LND from 1.25.13/1.26.6 to 1.26.8 (language version) and 1.27.1 (toolchain). It also regenerates many automatically generated RPC files and adjusts linter settings. The …

Go version bump may indirectly address unlisted runtime/standard-library security fixesLarge regenerated protobuf files suggest dependency/toolchain refresh rather than logic changeLinter configuration expanded to suppress new checks, consistent with a toolchain upgrade
ef4820e5by Olaoluwa Osuntokun+4932−412670 files
No security note in commit
Informational 15 AI analysisMessage 92 · Strong
LL Lightning LabsLND BitcoinLightning Network

build: adopt focused golangci-lint v2.13 checks

This commit is a routine build-maintenance change. It updates the project's Go linter configuration to a newer version and fixes the resulting style warnings: a WebSocket header spelling and several documentation comments that didn't start…

bada7ea3by ziggie+27−1911 files
No security note in commit
Informational 15 AI analysisMessage 68 · Adequate
LL Lightning LabsLND BitcoinLightning Network

lnrpc: regenerate protos with Go 1.27

This commit is a housekeeping change that regenerates automatically generated RPC binding files using a newer Go compiler version. The only differences are in code comments (doc-comment formatting), not in actual program logic or API behav…

dd523108by ziggie+4501−369826 files
No security note in commit
Informational 20 AI analysisMessage 100 · Strong
LL Lightning LabsLND BitcoinLightning Network

build: fix Go 1.27 compatibility

This commit is a routine build-and-test maintenance patch to make the LND codebase compile and pass tests with the upcoming Go 1.27 release. It upgrades the project's custom linter tool, refreshes many indirect tool dependencies, adjusts o…

No production code changesNo vulnerability fix or CVE reference presentDependency-only refresh in tools module (development tooling)
6b54a387by ziggie+365−3706 files
No security note in commit
Informational 15 AI analysisMessage 80 · Strong
LL Lightning LabsLND BitcoinLightning Network

build: bump Go language and toolchain versions

This commit is a routine maintenance update that changes which version of the Go programming language is used to build the lnd project. It does not change any application logic, fix a bug, or address a security vulnerability. The project i…

b1f9ca66by ziggie+39−3930 files
No security note in commit
Moderate 60 AI analysisMessage 83 · Strong
LL Lightning LabsLND BitcoinLightning Network

invoices: cancel only the failing AMP set on reconstruction failure

This commit fixes a bug in LND's invoice handling for reusable AMP (Atomic Multi-Path) invoices. Previously, if one payment set failed to reconstruct its preimage, the entire invoice was canceled, even though other valid payment sets on th…

Denial-of-service-like availability impact: a malicious or buggy payer could cause a whole reusable AMP invoice to be canceled, blocking legitimate concurrent payersSet-local failure incorrectly escalated to invoice-global cancellationRegression test added for concurrent-set survival after reconstruction failure
d74ab6faby Gijs van Dam+141−42 files
No security note in commit
Low 34 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11061 from bitromortac/2604-bolt12-1f

This commit adds the missing cryptographic signature layer for BOLT 12 offers in LND. It builds a Merkle tree from the message fields, signs that tree with a BIP-340 Schnorr signature, and now rejects invoice requests and invoices whose si…

Adds BIP-340 Schnorr signature verification for BOLT 12 invoice_request and invoice messagesMerkle tree commits to canonical re-encoded TLV records; non-minimal feature/amount encodings now rejected to preserve byte-exactnessSignature TLV type 240 and reserved range 240-1000 excluded from the signed Merkle root
1049d301by Yong+2076−7815 files
Vendor flagged security relevance
Low 35 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11125 from bhandras/codex/reorg-aware-output-lock-20260825

This commit adds a new optional wallet feature to LND that lets users lock UTXOs until the transaction spending them reaches a chosen confirmation depth, instead of relying on a wall-clock timeout. It is a feature addition with safety chec…

New RPC fields release_after_spend_confs and confirmed_spend_height added to LeaseOutput and FundPsbtCustom lock ID enforced as required for confirmation-controlled FundPsbt leases; all-zero and reserved internal IDs rejectedCapability check (ResolveOutputLeaser) prevents silent downgrade to time-only lease when confirmation control is requested
80dde144by Yong+1293−10021 files
No security note in commit
Informational 19 AI analysisMessage 58 · Thin
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #10812 from ziggie1984/chanstate-kv-store-move

This commit is a large internal code reorganization for the LND Lightning node. It moves channel state storage logic from the `channeldb` package into a new `chanstate` package, while keeping the same database keys, serialization formats, …

Large refactoring with no change to cryptographic or consensus-critical logicCodec serialization moved verbatim to new package; wire format unchangedDatabase bucket keys and TLV record types preserved
62b0a073by Olaoluwa Osuntokun+3923−310924 files
No security note in commit
Low 25 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #10804 from GeorgeTsagk/close-immediately-itest-lnd-7c38

This change fixes a data-handling bug in LND's channel-opening code. When opening a Lightning channel using an optional 'auxiliary funding controller' (used for custom channel types such as Taproot Assets), the funding manager was previous…

Data-correctness fix in funding handshake: negotiated channel configs now exposed to auxiliary funding controllerAuxiliary funding controller receives incomplete channel state before patch, complete state after patchNo explicit security claim, CVE, or advisory referenced in commit or supplied materials
1e127653by Olaoluwa Osuntokun+291−254 files
No security note in commit
Moderate 60 AI analysisMessage 88 · Strong
LL Lightning LabsLND BitcoinLightning Network

bolt12: verify invoice_request and invoice signatures on read

This change makes LND's BOLT 12 invoice and invoice-request reader actually check that the digital signature is valid, instead of only checking that a signature field exists. Before, an attacker could craft or modify a BOLT 12 message and …

Missing cryptographic verification on parsed BOLT 12 messages replaced with BIP-340 Schnorr signature verificationReader accepted any 64-byte placeholder signature before the patchNew negative tests verify rejection of wrong-signer and tampered Merkle-root fields
aa8bd19fby bitromortac+272−723 files
Vendor flagged security relevance
Informational 15 AI analysisMessage 78 · Adequate
LL Lightning LabsLND BitcoinLightning Network

itest: cover confirmation-controlled leases

This commit only adds a new integration test for an existing feature called confirmation-controlled leases. It does not change production code, so it cannot introduce a security vulnerability or fix one directly. The test exercises how lon…

a1ab4e92by Andras Banki-Horvath+152−02 files
No security note in commit
Moderate 68 AI analysisMessage 73 · Adequate
LL Lightning LabsLND BitcoinLightning Network

Merge pull request #11122 from gijswijs/websocket-proxy-hardening

This update fixes two security-related bugs in LND's REST WebSocket proxy. First, a specially crafted WebSocket protocol header could crash the proxy (a panic). Second, the proxy previously had no limit on how large an incoming WebSocket m…

panic fix in request header parsingunbounded incoming WebSocket message read now cappedincorrect header value assignment possible before fix
c662f853by Yong+227−104 files
Vendor flagged security relevance
Repository ledger

Explore captured commits

Expand any commit for its author, full message, clarity score, changed files, triage signals, analysis, and source link.

Security candidatelnwallet/rpcwallet: accept zero-value WitnessUtxo entries in remote-sign prepby Olaoluwa Osuntokun · 9f31668b · May 19, 2026 · 1 fileMessage 85 · StrongLow 43Details
Commit message · Olaoluwa Osuntokun

lnwallet/rpcwallet: accept zero-value WitnessUtxo entries in remote-sign prep

Before forwarding a SignOutputRaw request to the remote signer instance,
remoteSign rebuilds a PSBT from the unsigned transaction and annotates
every input with a WitnessUtxo (so the downstream walletkit.SignPsbt
call accepts it — taproot sighash computation requires the prev output
of every input, not just the one being signed).

For non-signed inputs the prep stage first asks the watch-only wallet
about the outpoint via FetchOutpointInfo, then — when the wallet does
not own or track the outpoint — falls back to the sign descriptor's
PrevOutputFetcher. The fallback previously required `utxo.Value != 0`,
which silently dropped legitimate zero-value entries on the floor and
left the corresponding PSBT input bare.

The walletkit.SignPsbt entry point on the remote signer then rejected
the PSBT with "input (index=N) doesn't specify any UTXO info" because
input N had neither a WitnessUtxo nor a NonWitnessUtxo annotation.

BIP-322 (signing virtual transactions for message attestation) is the
canonical hitter: its to_spend output is mandated by the BIP to be
exactly value=0 with the message commitment as pk_script, and that
output is referenced as input 0 of every BIP-322 to_sign transaction.
Any caller that drives a BIP-322 sign through a remote-signer LND
deployment was failing for this reason.

The validation we actually want is that the fetched prev output is
representable as a usable WitnessUtxo: non-nil and with a non-empty
pk_script. Drop the Value check; the zero-value case is well-formed
and the resulting PSBT input will serialize cleanly. The fetched-but-
empty-pk_script case continues to be rejected (a WitnessUtxo with
empty PkScript is malformed at PSBT serialization), and the warning
log when no fallback resolves the outpoint is preserved verbatim.

Lift the WitnessUtxo-population loop out of remoteSign into a
package-level helper so the resolution policy is unit-testable without
spinning up a real wallet + remote signer pair. The helper takes a
fetchOutpointInfoFn callback that mirrors
lnwallet.WalletController.FetchOutpointInfo. No behavior change for
the wallet-owns-it path or the no-fallback path.

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 boundaryupdate trustsigning or wallet path
AI analysis · Low 43/100

This commit fixes a bug in LND's remote-signing setup where zero-value previous transaction outputs were wrongly ignored when preparing a PSBT for a remote signer. The most concrete affected use case is BIP-322 message attestation, where the protocol requires a zero-value output. Because of the bug, the remote signer would refuse to sign, causing a functional failure rather than a loss of funds. The patch removes the mistaken zero-value check and adds a unit-testable helper function.

Security candidatelnwallet/rpcwallet: add unit tests for WitnessUtxo population helperby Olaoluwa Osuntokun · 6bb2c6f5 · May 19, 2026 · 1 fileMessage 83 · StrongInformational 15Details
Commit message · Olaoluwa Osuntokun

lnwallet/rpcwallet: add unit tests for WitnessUtxo population helper

Cover the four resolution branches plus the BIP-322 regression case:

- wallet-owns-it: FetchOutpointInfo returns a Utxo, helper writes
the matching WitnessUtxo into the PSBT input.
- external-fallback: wallet returns ErrNotMine, helper writes the
WitnessUtxo from the sign descriptor's PrevOutputFetcher.
- zero-value-fallback: same as above with the fetched entry's Value
set to zero. This is the BIP-322 to_spend shape (input 0 of every
BIP-322 to_sign references a virtual prev whose Value is mandated
to be zero); the helper must populate the WitnessUtxo rather than
silently skip it.
- no-fallback: wallet returns ErrNotMine and no PrevOutputFetcher
is provided; the helper leaves the input bare and the warning log
fires (asserted only by absence of a populated WitnessUtxo).
- empty-pk_script-fallback: the fetcher returns a non-nil entry
with an empty PkScript; the helper rejects it as unusable (the
PSBT WitnessUtxo serializer requires a non-empty script) and
leaves the input bare.

The signed input (signDesc.InputIndex) is intentionally left untouched
by the helper — that input is the one the caller's main path will
populate later — and the tests cross-check that invariant on the
wallet-owns-it case.

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
signing boundarysigning or wallet path
AI analysis · Informational 15/100

This commit only adds new unit tests for an existing helper function in LND's RPC wallet code. It does not change any production logic, so it cannot introduce a security vulnerability or directly fix one in the code being committed. The tests document and verify how the helper populates PSBT witness UTXO data, including a regression test for BIP-322 zero-value outputs.

Security candidatelnrpc: remove deprecated Send* RPC server implementationsby Erick Cestari · 3ff87913 · May 18, 2026 · 1 fileMessage 73 · AdequateInformational 15Details
Commit message · Erick Cestari

lnrpc: remove deprecated Send* RPC server implementations

Remove handler implementations and macaroon permission entries for the
now-deleted lnrpc RPCs: SendPayment, SendPaymentSync, SendToRoute, and
SendToRouteSync.

Also remove the dead payment infrastructure that was exclusively used by
these handlers: paymentStream, rpcPaymentRequest, rpcPaymentIntent,
extractPaymentIntent, dispatchPaymentIntent, sendPayment, and
sendPaymentSync.

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

This commit removes old, unused code paths for sending Lightning payments through the main RPC server. These RPCs (SendPayment, SendPaymentSync, SendToRoute, SendToRouteSync) were already deleted from the service definition in a prior change, so this patch only cleans up the leftover server-side implementations and their macaroon permissions. There is no security vulnerability here; it is routine code deletion of dead functionality.

Security candidaterouterrpc: remove deprecated SendPayment, SendToRoute, TrackPayment implsby Erick Cestari · c7dd0a99 · May 18, 2026 · 2 filesMessage 73 · AdequateLow 37Details
Commit message · Erick Cestari

routerrpc: remove deprecated SendPayment, SendToRoute, TrackPayment impls

Remove the SendPayment, SendToRoute, and TrackPayment shim methods from
router_server_deprecated.go that delegated to their V2 counterparts.
Remove their macaroon permission entries from router_server.go and the
now-unused legacyTrackPaymentServer wrapper.

73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
credential or privilege state
AI analysis · Low 37/100

This commit removes three old, deprecated payment RPC methods (SendPayment, SendToRoute, and TrackPayment) from the LND Lightning node's router service. These methods were already replaced by newer V2 versions and were only thin wrappers around them. Removing them reduces the amount of code that could contain bugs and removes their access permissions, but it may also break older client software that still calls these methods.

Security candidatedocs: add v0.21.0 RC testing guides for humans and agentsby saubyk · 2d0187c6 · May 13, 2026 · 12 filesMessage 95 · StrongInformational 15Details
Commit message · saubyk

docs: add v0.21.0 RC testing guides for humans and agents

Adds docs/testing-guides/v0.21.0/ with a per-feature guide for the
v0.21.0-beta.rc1 release. Each guide follows a fixed template
(prereqs, setup, scenarios with concrete pass/fail signals, failure
investigation) so RC testers and automated agents can work through
them predictably.

Coverage:
- Headline features: production taproot channels, RBF taproot
coop-close, payment store KV->SQL migration, onion messaging +
rate limiting.
- High-risk regressions / breaking changes: closed-channel
tombstone (sqlite/postgres downgrade trap), reorg-safe channel
closes + MinCLTVDelta raise, chain_params network-mismatch DB
guard, GetDebugInfo log opt-in.
- New RPCs / operator features: payment-adjacent RPCs bundle,
multiple read-only middleware interceptors.

This is a first draft intended for community review on the PR.
payment-sql-migration.md carries a TBD callout for the
SkipNativeSQLMigration rescue-path behavior, pending developer
confirmation.

95/100 · StrongMessage clarity
✓ Specific, 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
update trustdocumentation-only discount
AI analysis · Informational 15/100

This commit only adds documentation: a set of release-candidate testing guides for the upcoming LND v0.21.0 release. No source code, configuration defaults, RPC behavior, or database logic is changed. The new Markdown files describe how testers (human or automated) can verify new features such as taproot channels, onion-message rate limiting, and a payment-store migration. Because nothing executable is modified, the commit itself does not introduce a security vulnerability or fix one.

Security candidatelntest: pin pre-v30 mempool policy defaults in itest bitcoindby ziggie · 6914ea0b · Apr 23, 2026 · 1 fileMessage 83 · StrongInformational 14Details
Commit message · ziggie

lntest: pin pre-v30 mempool policy defaults in itest bitcoind

Bitcoind v30 lowered the default minrelaytxfee and incrementalrelayfee
from 1000 sat/kvB (1 sat/vB) to 100 sat/kvB. The itest suite was
written against the old defaults and the lower values cascade into:

- integer sat/vByte assertions losing precision below 1 sat/vB, and
- RBF bump thresholds that alter sweeper/bumpfee replacement timing.

Pin the old defaults in the itest bitcoind backend so the existing
tests keep passing without per-test adaptation. Running against the
new defaults is still worth doing, but that is a separate exercise
that should not be bundled with the v30 version bump.

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
access control
AI analysis · Informational 14/100

This change only adjusts the settings used for internal testing of LND with a Bitcoin Core backend. It pins older Bitcoin Core fee defaults so that existing automated tests continue to produce the same results after Bitcoin Core v30 changed its defaults. It does not change production LND code, user-facing behavior, or network consensus rules, and it does not fix a security vulnerability.

Security candidateonionmessage: add token-bucket rate limiter primitivesby Olaoluwa Osuntokun · d95bcbfa · Apr 15, 2026 · 3 filesMessage 95 · StrongModerate 61Details
Commit message · Olaoluwa Osuntokun

onionmessage: add token-bucket rate limiter primitives

The existing per-peer actor mailbox (capacity 50, RED from depth 40) only
bounds in-flight queue depth. It does not cap throughput: a peer that
drains its actor quickly can saturate our Sphinx unwrap CPU, replay-DB
writes, and outbound forwarding bandwidth without ever tripping RED. At
spec-max onion message sizes (~32 KiB per sphinx packet) a single
well-behaved-draining peer is enough to push multiple Mbps of unpaid
forwarded traffic through us, and aggregate fan-in from many peers
multiplies that into tens of Mbps — an amount of bandwidth that is very
much out of proportion for a side channel on a payment routing node.

This commit adds the building blocks for two token-bucket limiters that
will be wired into the onion message ingress path in a follow-up commit:
a process-wide global limiter and a per-peer registry. Both drop (rather
than wait) on over-limit so that a hostile peer cannot grow our
goroutine or memory footprint simply by sustaining above-threshold
traffic. The per-peer registry keys buckets on the peer's compressed
pubkey, creates them lazily, and retains them for the lifetime of the
process so a peer cannot reset its burst by cycling the connection;
cardinality is bounded by the live channel-peer count (the ingress call
site gates on having a channel before allocating per-peer state), so no
time-based GC is needed.

A minimal RateLimiter interface is introduced so that callers and tests
can substitute noop or alternate implementations without reaching into
x/time/rate directly, and a small countingLimiter wrapper keeps an
atomic drop counter plus a one-shot first-drop flag for observability.
A rate of zero (or a non-positive burst) yields a noop limiter,
providing a clean "disabled" mode without branching at the call site.

On top of those, a single IngressLimiter interface composes the
per-peer and global buckets behind one surface so that callers —
notably the peer readHandler — only thread one object through Config
and call one method per incoming onion message. Drop reasons are
surfaced as sentinel errors (ErrPeerRateLimit, ErrGlobalRateLimit)
wrapped in fn.Result[fn.Unit] so callers match on them with errors.Is
rather than comparing free-form strings. The stock implementation
encodes the load-bearing ordering — per-peer first, then global —
inside AllowN so that a hostile peer whose own bucket is already empty
cannot burn global tokens on every rejected attempt and starve
legitimate peers.

Default constants targeting roughly ~5 Mbps worst-case ingress at
spec-max message sizes are added alongside the existing mailbox
defaults.

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
secure hardware boundary
AI analysis · Moderate 61/100

This commit adds new rate-limiting building blocks for LND's onion message handling. It does not yet wire them into live message processing, so by itself it cannot stop an attack. The code is clearly preparing to fix a denial-of-service risk: a single peer (or many peers together) could currently flood a routing node with large, unpaid onion messages and consume CPU, database writes, and outbound bandwidth. The new primitives cap per-peer and total incoming onion-message bytes using token buckets, and they drop excess traffic immediately rather than queuing it.

Security candidatepeer: gate onion message ingress on having an open channelby Olaoluwa Osuntokun · c0827e8e · Apr 15, 2026 · 9 filesMessage 95 · StrongHigh 76Details
Commit message · Olaoluwa Osuntokun

peer: gate onion message ingress on having an open channel

Onion message forwarding is an unpaid side channel. Without any peer
qualification the byte-bucket limiters added in the previous commits are
our only defense against a Sybil attacker: an attacker that can cheaply
spin up N identities and burn a full per-peer byte budget on each one
saturates the global bucket and converts the aggregate cap into a
service-denial primitive against legitimate channel peers. This was
raised on PR review — the per-peer cap is good, but the global cap on
its own is a Sybil multiplier if peer identity is free. The proper fix
is to make new identities cost real capital, which is what requiring a
funded channel does.

This commit adds a channel-presence gate as the first check in
allowOnionMessage, ahead of both the per-peer and the global rate
limiters. Messages from peers that do not have at least one fully
open channel with us are dropped with a new dropReasonNoChannel
sentinel and never allocate any rate limiter state — the gate runs
before either limiter is consulted, so no-channel peers cannot burn
tokens on any bucket. Pending channels are deliberately excluded from
the check: they are represented as nil values in the activeChannels
map, are cheap to open and prone to getting stuck, and so do not
provide the capital-cost guarantee the Sybil defense depends on.
Existing Brontide cleanup paths (StopOnionActorIfExists,
OnionPeerLimiter.Forget) already handle teardown on peer disconnect;
nothing new is needed there because the gate keeps no-channel peers
from ever allocating per-peer state in the first place.

For the hot path we cannot afford to iterate the activeChannels
registry on every incoming onion message, so Brontide now carries a
numActiveChans atomic.Int32 that shadows the count of non-pending
entries in activeChannels. hasActiveChannels is a single atomic Load
and is therefore O(1). The counter is maintained in lockstep with
activeChannels at every mutation site: loadActiveChannels increments
it as it populates the registry during Start(); addActiveChannel uses
a new lnutils.SyncMap.Swap method (a thin typed wrapper around
sync.Map.Swap) to atomically replace any prior entry so that both
brand-new channels and pending-to-active promotions bump the counter
by exactly one; WipeChannel and handleRemovePendingChannel both use
LoadAndDelete so they can inspect the prior value and only decrement
when the removed entry was non-nil. Under race, this keeps the
counter and the map consistent even when RPC WipeChannel races with
the channelManager goroutine.

The accompanying unit tests cover: the no-channel drop path at the
allowOnionMessage level, asserting that neither the global stub
counter nor the per-peer limiter's dropped counter move when the
gate fires; the subsequent channel-gained path on the same peer,
asserting the same message is accepted once hasChannel flips; and a
focused Brontide-level test that walks the counter through initial
emptiness, a pending-only state (counter must stay at zero), a
pending-to-active promotion via direct Store + Add, the pending
delete path through handleRemovePendingChannel (must not underflow),
and the active delete path through LoadAndDelete + Add(-1) that
WipeChannel uses internally. Running with -race confirms the
Swap/LoadAndDelete patterns keep the counter and the map in sync
under concurrent access.

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 languagesecure hardware boundary
AI analysis · High 76/100

This change closes a denial-of-service weakness in LND's onion-message forwarding. Previously, an attacker could create unlimited free peer identities and burn through the global byte-budget reserved for onion messages, starving real peers. The patch now requires a peer to share at least one funded, fully open Lightning channel before any onion message is accepted, so each attacker identity must lock up real bitcoin. It also adds a fast O(1) atomic counter so this check does not slow down every incoming message.

Security candidatelnwallet: regenerate taproot test vectors with secret noncesby Olaoluwa Osuntokun · 50981dfc · Apr 13, 2026 · 1 fileMessage 83 · StrongInformational 12Details
Commit message · Olaoluwa Osuntokun

lnwallet: regenerate taproot test vectors with secret nonces

Regenerate the test vectors JSON to include local_sec_nonce and
remote_sec_nonce fields alongside the existing public nonces. The local
nonce fields now correctly correspond to local's verification nonce for
their own commitment transaction, matching the commitment tx stored in
the test vector.

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
defensive validationfuzzing or regression evidencenonce handlingsigning or wallet path
AI analysis · Informational 12/100

This commit only updates test data in a JSON file used for automated tests of Lightning's new taproot channel features. It adds secret nonce values and corrects public nonce values so the test vectors match the expected commitment transactions. There is no change to production wallet or network code, so it does not introduce a security vulnerability or fix one in running software.

Security candidatemulti: add custom nonce rand support to MuSig2 sessionsby Olaoluwa Osuntokun · 08c42b19 · Apr 13, 2026 · 3 filesMessage 88 · StrongInformational 19Details
Commit message · Olaoluwa Osuntokun

multi: add custom nonce rand support to MuSig2 sessions

In this commit, we add the ability to inject a custom random source
for generating JIT (Just-In-Time) signing nonces in MuSig2 sessions.
By default, MuSig2 signing nonces are generated using crypto/rand,
which makes signatures non-deterministic across runs. For test vector
generation, we need fully reproducible signatures from a fixed seed.

A new `customNonceRand` field is threaded through `MusigSession`,
`MusigSessionCfg`, `MusigPairSession`, and exposed via the
`WithCustomSigningRand` channel option. When set, the custom reader
is passed to `musig2.WithCustomRand()` during JIT nonce generation
in `SignCommit`. All existing callers pass `fn.None[io.Reader]()` to
preserve the current behavior of using the system CSPRNG.

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
entropy or randomnesssigning boundaryfuzzing or regression evidencesigning or wallet path
AI analysis · Informational 19/100

This change adds a hidden switch that lets developers plug in a custom random source when creating MuSig2 signing nonces, mainly so tests can produce exactly the same signatures every time. In normal operation the switch is left empty, so the code still uses the operating system's cryptographic random generator. The patch itself is a test-infrastructure feature, not a fix for an active security bug, but any future misuse of the switch could weaken signature security.

Security candidatelnwallet: add taproot channel test vector generatorby Olaoluwa Osuntokun · 38c415a9 · Apr 13, 2026 · 2 filesMessage 83 · StrongInformational 15Details
Commit message · Olaoluwa Osuntokun

lnwallet: add taproot channel test vector generator

In this commit, we add a test vector generator and verifier for
taproot channel constructions. All vectors are derived
deterministically from a single 32-byte seed using SHA256(seed ||
label) for key derivation, ensuring any implementation can reproduce
them independently.

The generator covers two areas:

Script vectors decompose the full tapscript trees for every output
type: funding (MuSig2 aggregated key), to_local (delay + revocation
leaves), to_remote (1-block CSV leaf), anchors (OP_16 OP_CSV),
offered/accepted HTLCs on both local and remote commits, and
second-level HTLC transactions. Each entry captures the raw leaf
scripts, leaf hashes, tapscript root, internal key, output key, and
pkScript.

Transaction vectors produce full serialized commitment transactions
and HTLC resolution transactions for three scenarios: a simple
commitment with no HTLCs, a commitment with five untrimmed HTLCs,
and the same HTLCs at a higher fee rate causing some to be trimmed.

To generate: go test -run TestTaprootVectors ./lnwallet/ -args -generate-taproot-vectors
To verify: go test -run TestTaprootVectors ./lnwallet/

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
secret or key materialfuzzing or regression evidencesigning or wallet path
AI analysis · Informational 15/100

This commit only adds new test code and a JSON file of expected test outputs for Taproot Lightning channels. It does not change any production logic, network behavior, or wallet handling. There is no security issue in the commit itself.

Security candidatelnwallet: add 3rd-party signature verification for taproot test vectorsby Olaoluwa Osuntokun · 77da917c · Apr 13, 2026 · 1 fileMessage 88 · StrongInformational 12Details
Commit message · Olaoluwa Osuntokun

lnwallet: add 3rd-party signature verification for taproot test vectors

In this commit, we add a `signature_verification` sub-test to the
taproot test vector verifier that performs full script execution against
both the commitment transaction and all HTLC resolution transactions.

This uses `txscript.NewEngine` to execute the taproot witness programs
exactly as a Bitcoin node would, providing an independent check that all
signatures in the test vectors are cryptographically valid. For the
commitment transaction, we verify its witness against the funding output
pkScript. For each HTLC resolution transaction, we verify its witness
against the corresponding commitment output it spends.

This catches issues that the structural comparison tests (hex matching)
cannot: for instance, a transaction can have the correct structure but
carry an invalid signature if the sighash was computed over the wrong
prevout or if the wrong key was used for signing. Running the full
script engine also validates the control block, the tap leaf hash, and
the overall taproot spend path.

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 boundarydefensive validationfuzzing or regression evidencesigning or wallet path
AI analysis · Informational 12/100

This commit only adds a new test to the project's test suite. It does not change any production code, user-facing behavior, or network protocol. The new test cryptographically checks that example transactions in the project's test data carry valid Bitcoin signatures. It is a defensive quality improvement, not a fix for a known bug or vulnerability.

Security candidatelnwallet: regenerate test vectors with BIP-340 HTLC signaturesby Olaoluwa Osuntokun · 1866770f · Apr 13, 2026 · 1 fileMessage 83 · StrongInformational 15Details
Commit message · Olaoluwa Osuntokun

lnwallet: regenerate test vectors with BIP-340 HTLC signatures

Regenerate the test vector JSON with HTLC second-level transaction
signatures that use BIP-340 standard nonce derivation (zero auxrand)
instead of RFC6979. This makes the HTLC signatures reproducible across
different Schnorr implementations. The commitment transaction MuSig2
signatures are unchanged.

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
signing boundaryfuzzing or regression evidencesigning or wallet path
AI analysis · Informational 15/100

This commit only updates test data in a single JSON file. It changes the example signatures used in automated tests so they are generated with a standard BIP-340 nonce method instead of an older RFC6979 method. No production wallet code, protocol logic, or user-facing behavior is changed. There is no security vulnerability here.

Security candidatelnwallet: emit actual MuSig2 partial sigs and nonces in test vectorsby Olaoluwa Osuntokun · fa97946f · Apr 13, 2026 · 1 fileMessage 88 · StrongInformational 18Details
Commit message · Olaoluwa Osuntokun

lnwallet: emit actual MuSig2 partial sigs and nonces in test vectors

In this commit, we fix the taproot test vector generator to capture and
emit the real MuSig2 partial signatures and public nonces rather than
the dummy `CommitSig` value which is zeroed out for taproot channels.

Previously, the generator was reading from `CommitSig.ToSignatureBytes()`
which yielded a minimal DER encoding of `(0, 0)` (the 8-byte string
`3006020100020100`). For taproot channels the actual signature lives in
the `PartialSig` field of the `CommitSigs` struct, which carries both
the 32-byte partial sig scalar and the 66-byte compressed public nonce
needed by the verifier to reconstruct the combined signature.

We now unwrap the `PartialSig` from both the local and remote commitment
signatures, extract the nonce and sig bytes, and include `local_nonce`
and `remote_nonce` fields alongside `remote_partial_sig` in the emitted
JSON. This gives other implementations (eclair, CLN, etc.) all the
material they need to independently verify commitment transaction
signatures using their own MuSig2 libraries.

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 boundaryfuzzing or regression evidencesigning or wallet path
AI analysis · Informational 18/100

This commit fixes a test-data generator used by the LND Lightning node. Previously, the generator wrote a placeholder zero-value signature into its JSON test vectors for Taproot channels. Now it writes the real partial signature and public nonce values that other Lightning implementations need to independently check those test vectors. This is a test tooling fix, not a live security bug in production code.

Security candidatelnwallet: regenerate taproot channel test vectorsby Olaoluwa Osuntokun · 70f189ff · Apr 13, 2026 · 1 fileMessage 78 · AdequateInformational 18Details
Commit message · Olaoluwa Osuntokun

lnwallet: regenerate taproot channel test vectors

Regenerate `test_vectors_taproot.json` to reflect the corrected test
vector generator. Changes include actual 32-byte MuSig2 partial
signatures (replacing the dummy 8-byte DER stubs), 66-byte public
nonces for both local and remote parties, corrected HTLC sig-to-
transaction mapping sorted by BIP 69 output index, proper HTLC-success
witness layout with preimage in the correct witness slot, and the
updated trimming test case which now trims 3 of the 5 test HTLCs below
the 2500 sat dust limit (down from 5 HTLC outputs to 2).

78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Why it was queued
signing boundaryfuzzing or regression evidencesigning or wallet path
AI analysis · Informational 18/100

This commit only updates a single JSON file of test vectors for taproot Lightning channels. It replaces placeholder signature data with realistic values, fixes the order of test transactions, and adjusts a dust-limit test case. There is no change to production wallet or node code, so it does not directly affect live funds or network security. It is essentially a correction to the project's test fixtures.

Security candidatelnwallet: add secret nonce stashing to MusigSession for test vectorsby Olaoluwa Osuntokun · 2148445c · Apr 13, 2026 · 1 fileMessage 83 · StrongInformational 18Details
Commit message · Olaoluwa Osuntokun

lnwallet: add secret nonce stashing to MusigSession for test vectors

In this commit, we add the ability for MusigSession to capture and
expose the raw 97-byte MuSig2 secret nonce generated during JIT signing
nonce creation. This is gated behind the customNonceRand option, so it
only activates in test vector generation mode.

The stashed secret nonce is consumed on read (cleared after access) to
prevent accidental nonce reuse. This enables interop test vectors to
include the raw secret nonces, allowing other implementations to replay
the MuSig2 signing process without needing to match the exact nonce
derivation algorithm used by btcd's musig2 library.

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
signing boundaryfuzzing or regression evidencenonce handlingsigning or wallet path
AI analysis · Informational 18/100

This commit adds a test-only feature that lets LND temporarily save the secret random number (nonce) used in MuSig2 signing when running in a special test-vector generation mode. The saved value is automatically erased after one read to prevent accidental reuse. There is no indication this feature is active in normal production code, and the change is explicitly described as being for interoperability test vectors only.

Security candidatelnwallet: add MuSig2 secret nonces and partial sig replay to test vectorsby Olaoluwa Osuntokun · 4c225ddf · Apr 13, 2026 · 1 fileMessage 88 · StrongInformational 12Details
Commit message · Olaoluwa Osuntokun

lnwallet: add MuSig2 secret nonces and partial sig replay to test vectors

In this commit, we extend the taproot test vector generator and verifier
to include MuSig2 secret nonces and a full partial signature replay
test.

For the generator, we now capture the correct nonces for each
commitment transaction: local's verification nonce (from LocalSession)
for local's own commitment, and remote's JIT signing nonce (from
RemoteSession) for the same commitment. Previously, the local nonce was
incorrectly captured from the RemoteSession, which corresponds to a
different commitment transaction.

The new musig2_partial_sig_replay test sub-suite verifies three
properties for each test case:

1. The remote partial sig can be independently reproduced from the
secret nonce and private key using musig2.Sign().

2. The local partial sig can be independently produced and verified
using the local secret nonce.

3. Both partial sigs combine (via the Session API) into the exact
Schnorr signature present in the commitment transaction witness.

This enables interop implementations to validate their MuSig2 signing
logic against the test vectors without needing to match nonce derivation
algorithms across different secp256k1 libraries.

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
secret or key materialsigning boundarydefensive validationfuzzing or regression evidencenonce handlingsigning or wallet path
AI analysis · Informational 12/100

This commit only changes test code. It improves the test-vector generator for taproot channels so it records the correct MuSig2 secret nonces, and adds a new test that replays the signing process to confirm the produced signatures match the ones stored in the test vectors. There is no change to production wallet or signing logic, so it does not introduce or fix a live security vulnerability.

Security candidatelnwallet: use BIP-340 nonce derivation for HTLC sigs in test vectorsby Olaoluwa Osuntokun · 63450b85 · Apr 13, 2026 · 1 fileMessage 88 · StrongInformational 19Details
Commit message · Olaoluwa Osuntokun

lnwallet: use BIP-340 nonce derivation for HTLC sigs in test vectors

btcd's schnorr.Sign defaults to RFC6979 nonce derivation, while
libsecp256k1 (used by eclair, CLN, etc) uses BIP-340's standard
nonce derivation with zero auxrand. Both are deterministic but produce
different signatures for the same key and message, causing HTLC
signature mismatches in interop test vectors.

This commit introduces a bip340Signer wrapper that overrides
SignOutputRaw for taproot script path spends to use
schnorr.CustomNonce([32]byte{}) — matching BIP-340 deterministic
signing behavior. The wrapper is only used in the test vector
generator; production signing paths are unchanged.

Note that MuSig2 commitment signatures were already using BIP-340
nonces internally (via the musig2.Sign path), so only the HTLC
second-level transaction signatures were affected.

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 boundaryfuzzing or regression evidencesigning or wallet path
AI analysis · Informational 19/100

This commit changes only a test file in LND. It makes the test-vector generator produce HTLC signatures using the same nonce math as other Lightning implementations (Eclair, Core Lightning), so cross-implementation test vectors match. Production signing code is not touched, so real user funds or network behavior are unaffected. There is no security vulnerability being fixed here; it is a test-infrastructure consistency change.

Security candidatelnwallet: fix HTLC sig-to-transaction mapping in test vector generatorby Olaoluwa Osuntokun · b78de44d · Apr 13, 2026 · 1 fileMessage 100 · StrongInformational 24Details
Commit message · Olaoluwa Osuntokun

lnwallet: fix HTLC sig-to-transaction mapping in test vector generator

In this commit, we fix two interrelated bugs in the way HTLC signatures
are associated with their corresponding second-level transactions in the
taproot test vector generator.

The first issue was that HtlcSigs are sorted by BIP 69 output index
(matching the commitment transaction's output ordering), but the old
code was assigning signatures using the iteration order of incoming
HTLCs followed by outgoing HTLCs. This meant timeout transaction
signatures were getting paired with success transactions and vice versa
whenever the output ordering didn't happen to match the incoming-first
iteration order. This is the root cause of the invalid HTLC-timeout
signatures that eclair reported when cross-validating.

We now collect all HTLC entries (both incoming and outgoing) into a
single slice, sort them by their commitment output index, then zip them
against the HtlcSigs array so each signature lines up with the correct
second-level transaction.

The second issue was in the HTLC-success preimage extraction path. The
old code read the witness script from index [4] (the control block) and
used a hardcoded byte offset of 69 to locate the payment hash, then
wrote the preimage into index [3] (overwriting the script). The correct
taproot witness layout is [remoteSig, localSig, preimage, script,
controlBlock], so the script lives at [3] and the preimage slot is [2].
We now use `txscript.ScriptTokenizer` to walk the script opcodes and
find OP_HASH160 followed by the 20-byte push data, which is far more
robust than relying on fragile byte offsets that break if the script
template ever changes.

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

This commit fixes bugs in a test-data generator used by LND, not in the live Lightning node software itself. The generator produces sample HTLC (multi-hop payment) resolution transactions and signatures that other implementations use to cross-check compatibility. The old code paired signatures with the wrong transactions when HTLC outputs were not ordered 'incoming first,' and it also read preimages from the wrong witness slot using a hardcoded byte offset. These bugs caused invalid test vectors, which another implementation (Eclair) noticed during cross-validation. The fix only changes test code, so it does not create or close a real attack path against running LND nodes.

Security candidateinput: add production taproot HTLC succeed input constructorby Olaoluwa Osuntokun · 0720abca · Apr 13, 2026 · 1 fileMessage 78 · AdequateInformational 17Details
Commit message · Olaoluwa Osuntokun

input: add production taproot HTLC succeed input constructor

This commit adds MakeTaprootHtlcSucceedInputFinal, a new input constructor
specifically for creating HTLC success inputs that use production taproot
witness types. This function parallels the existing MakeTaprootHtlcSucceedInput
but creates inputs with the TaprootHtlcAcceptedRemoteSuccessFinal witness type
instead of the staging variant.

The new constructor follows the same pattern and signature as its staging
counterpart, ensuring consistency in the input creation API. This allows
contract resolvers to create the appropriate input type based on whether
they are handling a staging or production taproot channel, ensuring that
the correct witness generation logic is applied during transaction creation.

This addition provides the necessary infrastructure for production taproot
channels to properly construct inputs for sweeping HTLC outputs on remote
commitment transactions with the optimized script structure.

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

This commit adds a new helper function in LND for creating a specific kind of Bitcoin transaction input used when claiming a Lightning HTLC (a payment locked by a hash/time condition) on a production taproot channel. It mirrors an existing staging-channel helper but uses the final/production witness type. There is no direct evidence in the commit of a security vulnerability; it appears to be infrastructure for an upcoming or recently enabled feature.

Security candidateactor: add CompleteWith and AwaitFuture generic package-level helpersby Olaoluwa Osuntokun · 4e0992fa · Apr 11, 2026 · 2 filesMessage 73 · AdequateInformational 15Details
Commit message · Olaoluwa Osuntokun

actor: add CompleteWith and AwaitFuture generic package-level helpers

In this commit, we add two package-level generic helpers to the actor
module as part of the broader chan error -> Future[error] migration in
the discovery package.

CompleteWith[T](p Promise[T], val T) is a one-liner convenience wrapper
over p.Complete(fn.Ok(val)). It lets callers complete a promise with a
plain value without constructing an fn.Result inline, which cuts noise
at every completion site.

AwaitFuture[T](ctx, f Future[T]) (T, error) provides the symmetric
receive side: it blocks until the future resolves or the context is
cancelled and returns the value and any context error unpacked from
the fn.Result, matching the (val, err) convention callers expect.

Both functions are deliberately thin (no policy, no timeout, no new
state) so they compose freely with higher-level helpers built on top,
e.g. discovery.AwaitGossipResult.

go.mod is updated to pin the actor module via a local replace directive
so the rest of the lnd module picks up these additions without waiting
for a tagged release.

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

This commit adds two small helper functions to an internal actor package and updates the Go module file to use the local copy of that package. There is no security-relevant change; it is purely a code cleanup and convenience addition for future development work.

Security candidategraph/db: add gossip version parameter to FilterKnownChanIDsby Elle Mouton · 12f8e509 · Apr 9, 2026 · 5 filesMessage 78 · AdequateLow 27Details
Commit message · Elle Mouton

graph/db: add gossip version parameter to FilterKnownChanIDs

Add an explicit lnwire.GossipVersion parameter to FilterKnownChanIDs
on the Store interface, SQLStore, KVStore, and ChannelGraph. Since
FilterKnownChanIDs is always called from a version-scoped ChanSeries
context, a single version parameter is cleaner than per-item version
reads. A convenience wrapper on VersionedGraph preserves the existing
ChanSeries call-site signature by threading c.v automatically.

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
signing boundary
AI analysis · Low 27/100

This commit refactors how a Lightning Network routing database method, FilterKnownChanIDs, receives the gossip protocol version. Previously the version was read from each individual channel record; now it is passed explicitly from the version-scoped wrapper. The change also adds a sanity check that zombie channels returned by the database match the expected gossip version, and updates tests to cover both v1 and v2 gossip. It is a defensive correctness improvement rather than a clear-cut fix for an active vulnerability.

Security candidateci: use GITHUB_TOKEN instead of PAT for PR severity workflowby ziggie · 77c566f2 · Apr 8, 2026 · 1 fileMessage 97 · StrongLow 32Details
Commit message · ziggie

ci: use GITHUB_TOKEN instead of PAT for PR severity workflow

The PR severity classifier only needs to run `gh pr view`, `gh pr edit`
(labels), and `gh pr comment`. All three operations are fully covered by
the built-in GITHUB_TOKEN given the existing permissions block:

permissions:
contents: read
pull-requests: write
issues: write

The workflow uses `pull_request_target`, which runs in the base repo
context, so GITHUB_TOKEN has write access even for fork PRs.

Inspection of the claude-code-action@v1 source confirmed that the only
internal call that would require `contents: write` is branch deletion,
which is never exercised here because Claude's tools are locked down to
`gh pr view/edit/comment` via --allowedTools.

This removes the dependency on the PR_SEVERITY_BOT_TOKEN PAT secret.

97/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Uses a recognizable type or scope✓ Provides detailed explanatory context✓ Explains rationale or failure mode
Why it was queued
credential or privilege statedocumentation-only discount
AI analysis · Low 32/100

This commit changes a GitHub Actions workflow so it uses the automatically provided GITHUB_TOKEN instead of a long-lived personal access token (PAT) named PR_SEVERITY_BOT_TOKEN. The workflow labels and comments on pull requests. The change reduces the risk that a leaked or overly powerful PAT could be misused, and it is a security-hardening improvement rather than a fix for an active vulnerability.

Security candidategraph/db: convert TestLightningNodeSigVerification to versioned testby Elle Mouton · a9c9e765 · Apr 7, 2026 · 1 fileMessage 83 · StrongInformational 15Details
Commit message · Elle Mouton

graph/db: convert TestLightningNodeSigVerification to versioned test

Rename to testLightningNodeSigVerification and add it to the
versionedTests table so it runs against both v1 and v2. The signing
step is version-specific (ECDSA for v1, Schnorr for v2) while the
verification path is shared.

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
signing boundarydefensive validation
AI analysis · Informational 15/100

This commit only changes a test file. It renames an existing test and makes it run against two versions of the software's gossip protocol, adding Schnorr signature coverage for the newer version. There is no change to production code, so it does not introduce or fix a security vulnerability in the running software.

Security candidatelnwire: validate MuSig2 nonces in LocalNoncesData decodeby Erick Cestari · 05f04f74 · Mar 31, 2026 · 2 filesMessage 65 · AdequateModerate 59Details
Commit message · Erick Cestari

lnwire: validate MuSig2 nonces in LocalNoncesData decode

Validate each nonce in decodeLocalNoncesData with
ValidateMusig2Nonce to reject malformed entries.

65/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides an explanatory body
Why it was queued
defensive validationnonce handling
AI analysis · Moderate 59/100

This change adds a safety check when LND reads stored MuSig2 cryptographic nonces from disk or network data. Previously, a malformed or all-zero nonce could be loaded silently; now the decoder rejects it. MuSig2 nonces are used in multi-signature Bitcoin transactions for the Lightning Network, so bad nonces could in theory lead to failed channel operations or, in worst-case cryptographic scenarios, weaken security guarantees.