Every captured commit receives deterministic security triage and a separate communication-quality score. Security candidates and broader second-pass signals receive full-patch Ollama analysis.
Message quality measures whether a commit identifies its scope, purpose, rationale, testing, and supporting references. It does not change the security-severity score.
This commit changes how the Lightning networking code handles oversized encrypted messages. Previously, certain conditions would cause the program to crash with a panic. Now the code returns errors instead, which is a defensive improvement…
panic-to-error conversion for oversized message encryption/decryptiondenial-of-service hardening against oversized peer messagesdebug_assert retained to preserve test coverage of invariant violations
This commit simply updates the 'repository' web links in 15 package metadata files from GitHub to a self-hosted Forgejo instance. It does not change any program code, build logic, dependencies, or security behavior. There is no security is…
This commit fixes a bug in the Lightning Dev Kit where, after a disconnection, a node could fail to retransmit a 'splice_locked' message to a peer that was still waiting for transaction signatures. Without this retransmission, the two peer…
Protocol state desynchronization between channel peers after reconnectionMissing retransmission of splice_locked for 0-conf splice channelsPotential channel unusability or stuck splice negotiation
This commit fixes a small accounting bug in how the Lightning wallet estimates the size (and therefore transaction fee) of a special Bitcoin transaction that sweeps funds back to the user after a channel closes. The old code always assumed…
debug assertion failure possible in development/testing buildstransaction weight/fee estimate overestimation up to 3 WUconstant replaced with per-descriptor length computation
This commit changes the project's internal code-review workflow. It stops automatically assigning a human reviewer when a pull request is opened; instead, contributors must manually click a button to request a reviewer after first addressi…
This commit fixes a bug in LDK's Lightning channel reconnection logic after a splice (a way to resize a channel's on-chain funds). If one peer had already received the splice signatures but the other had not, and then they disconnected and…
Protocol-state inconsistency on reconnection after splice signature exchangePotential channel stall/force-close due to quiescence not being exited before commitment updateFuzzer-discovered edge case in Lightning splicing retransmission
This commit adds a new option for Lightning invoice creators to explicitly tell payers not to use multi-path payments (MPP) when paying an invoice. It does not change any enforcement rules; it only changes what feature bits are advertised …
New API surface for feature advertisement controlExplicit documentation that the method does not enforce single-HTLC receipt, shifting enforcement responsibility to callersNo removal or weakening of existing validation logic
This commit adjusts the project's continuous integration (CI) test script to pin an older version of a build-time helper crate called `jobserver` when using older Rust compilers. It is a build compatibility fix, not a security patch, and d…
This commit 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…
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
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…
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
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
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…
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
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
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
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…
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
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
Expand any commit for its author, full message, clarity score, changed files, triage signals, analysis, and source link.
Lower-priorityMerge PR 'Only fetch TXIDs instead of entire block during gossip verification' (#4846)by Matt Corallo · ebe7a447 · Aug 5, 2026 · 5 filesMessage 91 · StrongTriage 0Details
Commit message · Matt Corallo
Merge PR 'Only fetch TXIDs instead of entire block during gossip verification' (#4846)
from gossip-verify-rpc into main
Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4846 Reviewed-by: Matt Corallo <matt@noreply.git.rust-bitcoin.org>
91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Lower-priorityAdd test framework coverage of `Listen` block connection replaysby Matt Corallo · bf6ad23e · Aug 5, 2026 · 2 filesMessage 83 · StrongTriage 0Details
Commit message · Matt Corallo
Add test framework coverage of `Listen` block connection replays
While this should generally be equivalent to receiving a block duplicatively via the `best_block_updated` + `transactions_confirmed` methods, its good to add explicit test coverage for the newly-supported (but always documented...) connection mode.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Lower-priorityUpdate functional test block connection to detect block replaysby Matt Corallo · 477facb4 · Aug 5, 2026 · 3 filesMessage 83 · StrongTriage 0Details
Commit message · Matt Corallo
Update functional test block connection to detect block replays
In cases where we replay a block, the functional test framework shouldn't consider it a new block and re-add it to the tracked blockchain in `Node`s.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Lower-priorityCorrect HTLC confusion on unrevoked counterparty commitment txsby Matt Corallo · f06a08a6 · Aug 4, 2026 · 2 filesMessage 73 · AdequateTriage 8Details
Commit message · Matt Corallo
Correct HTLC confusion on unrevoked counterparty commitment txs
When we see an HTLC on an unrevoked counterparty commitment transaction we check if it has a corresponding `HTLCSource` when deciding whether it is likely from a revoked counterparty commitment transaction. This is insufficient, however, and can result in us assuming that an HTLC is on a revoked counterparty commitment (and thus is safe to fail back based on a loose HTLC match) rather than on a live one.
Here we correct this check and also expand several debug assertions that validated the detection of the claim style against the HTLC type into full-blown assertions. If we end up hitting these, they're almost certainly an indication that something has gone horribly wrong and either keys have leaked or the node software is confused and continuing would be unsafe.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
defensive validation
AI review queuedAvoid oversized relayed failure messagesby Matt Corallo · 6b1dfb1a · Aug 4, 2026 · 1 fileMessage 78 · AdequateTriage 5Details
Commit message · Matt Corallo
Avoid oversized relayed failure messages
A downstream peer could send a maximum-sized update_fail_htlc without attribution data. Adding attribution data while relaying the failure made the message exceed the Noise framing limit and panic during encryption.
Drop the attribution data again when adding it would push the relayed failure over the wire limit, while preserving attribution for packets that fit. The message length is derived from serialized_length on the message and on the attribution data itself rather than from hardcoded field sizes, which also lets us replace a stale assertion on the maximum failure data length. Add a regression test for relaying a maximum-sized failure and correct the existing size test to include the message type.
Reported by Project Loupe.
Co-Authored-By: Elias Rohrer <dev@tnull.de> Co-Authored-By: HAL 9000
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 evidencesecond-pass: broader security terminology
Security candidateReturn `Err`s` instead of panicking on oversized messagesby Matt Corallo · 08f12bc7 · Aug 4, 2026 · 3 filesMessage 85 · StrongLow 47Details
Commit message · Matt Corallo
Return `Err`s` instead of panicking on oversized messages
While this code should remain unreachable as it likely indicates we're going to end up force-closing a channel due to being unable to communicate with a peer, we shouldn't bring down the whole process for it if we can avoid it.
Instead, at least return an `Err` so we can figure out what to do with it in `PeerManager`.
Co-Authored-By: Claude <noreply@anthropic.com>
85/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
Why it was queued
cryptography-sensitive path
AI analysis · Low 47/100
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. However, one important call site still uses `.expect("TODO: Handled in the next commit")`, meaning the crash risk is not fully removed there yet. The commit is a partial patch toward making the node more resilient against denial-of-service from malformed or oversized peer traffic.
Lower-priorityAvoid panicking when attempting to send an oversized messageby Matt Corallo · c5fdc3bf · Aug 4, 2026 · 1 fileMessage 85 · StrongTriage 0Details
Commit message · Matt Corallo
Avoid panicking when attempting to send an oversized message
While this code should remain unreachable as it likely indicates we're going to end up force-closing a channel due to being unable to communicate with a peer, we shouldn't bring down the whole process for it if we can avoid it.
Co-Authored-By: Claude <noreply@anthropic.com>
85/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
AI review queuedReject attempts to advance one-hop blinded forward pathsby Matt Corallo · 969a40cf · Aug 4, 2026 · 4 filesMessage 83 · StrongTriage 5Details
Commit message · Matt Corallo
Reject attempts to advance one-hop blinded forward paths
A malicious reply path can contain a single decryptable forward hop. Advancing that path removed its only hop, causing onion construction to panic when a handler attempted to respond.
Reject paths with fewer than two hops before attempting to advance them. The regression test exercises the untrusted response path and verifies that it returns an error without panicking.
Reported by Project Loupe.
Test written by: Elias Rohrer <dev@tnull.de>, which was Co-Authored-By: HAL 9000
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Why it was queued
fuzzing or regression evidencesecond-pass: broader security terminology
lightning-types: replace Zl/Zp separators in `PrintableString`
`PrintableString` replaces control (`Cc`), "other" (`C*`, including `Cf`), and unassigned codepoints with U+FFFD, but U+2028 LINE SEPARATOR (`Zl`) and U+2029 PARAGRAPH SEPARATOR (`Zp`) passed through verbatim: `char::is_control` is `Cc`-only and the generated tables in `unicode.rs` only cover the top-level `C` categories. Many terminals and log viewers render U+2028/U+2029 as hard line breaks, so a peer-controlled string (node alias, BOLT 12 description/issuer/ payer_note, `peer_msg`) could inject forged log lines that appear sanitised.
Extend `contrib/gen_unicode_general_category.py` to also emit a `Zl`/`Zp` separator predicate and regenerate `unicode.rs` from the same UnicodeData 17.0.0 the existing tables were built from, then filter on the new predicate in `PrintableString`. `Zs` is deliberately excluded as it contains U+0020 SPACE. Add a regression test mirroring the existing bidi-override test.
Found by a Loupe scan, tracked by the Bitcoin Security Council: https://github.com/bitcoin-security-council/findings/pull/180
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
Why it was queued
fuzzing or regression evidence
Lower-priorityApply the unfunded channel peer limit to all unaccepted channelsby Matt Corallo · 56a4ee43 · Aug 4, 2026 · 2 filesMessage 73 · AdequateTriage 0Details
Commit message · Matt Corallo
Apply the unfunded channel peer limit to all unaccepted channels
If a peer floods us with channel requests, we previously failed to enforce `MAX_UNFUNDED_CHANNEL_PEERS` as we considered the peer to have some channels once it has more than one request pending.
Instead, we have to make sure we reject such channels by looking at pending channels as well.
Co-Authored-By: Claude <noreply@anthropic.com>
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI review queuedAllow filtered block rescans at the current tipby Elias Rohrer · 686f9860 · Aug 4, 2026 · 3 filesMessage 88 · StrongTriage 0Details
Commit message · Elias Rohrer
Allow filtered block rescans at the current tip
A valid same-block replay through Listen could panic OutputSweeper and ChannelManager because both required every filtered_block_connected call to advance the chain.
Treat callbacks matching the current tip as rescans, process their additional transaction data, and skip the duplicate best-block update while retaining chain-order checks for new blocks.
Fixes #3920
Reported by Project Loupe
Co-Authored-By: HAL 9000
88/100 · StrongMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Links an issue, advisory, or supporting reference
Why it was queued
second-pass: broader security terminology
AI review queuedAvoid panic when reorged claims cannot mergeby Matt Corallo · f1dc8487 · Aug 4, 2026 · 2 filesMessage 78 · AdequateTriage 5Details
Commit message · Matt Corallo
Avoid panic when reorged claims cannot merge
Previously, a deep reorg could resurrect an HTLC package at a height where it was no longer mergeable with its surviving claim. This caused `OnchainTxHandler::blocks_disconnected` to panic on an assertion.
When merging fails, we now preserve the resurrected package in `locktimed_packages` so normal block processing registers and broadcasts it as an independent claim. Add a regression test covering the reorg and subsequent broadcast.
Thanks to Kyle W. Santiago for reporting this issue.
Co-authored-by: Elias Rohrer <dev@tnull.de>
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 evidencesecond-pass: broader security terminology
✓ Descriptive subject✓ Names a concrete action or component! No meaningful explanatory body
Why it was queued
seed or entropy pathsigning or wallet path
AI analysis · Informational 15/100
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 issue here.
Lower-priorityAccount for message type prefix len in prevtx length enforcementby Wilmer Paulino · d29e1415 · Jul 31, 2026 · 1 fileMessage 73 · AdequateTriage 0Details
Commit message · Wilmer Paulino
Account for message type prefix len in prevtx length enforcement
Lightning wire messages have a maximum size of 65535 bytes, which already accounts for the required two-byte message type prefix. Our `TxAddInput::prevtx` length enforcement relied solely on the `serialized_length` of the message, which does not account for the prefix.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Retransmit splice_locked for 0-conf channels missing tx_signatures
When a 0-conf channel successfully negotiates a 0-conf splice only for one peer and a disconnection happens prior to the other peer receiving `tx_signatures`, we'd previously fail to handle the inferred `splice_locked` upon reconnection via the `my_current_funding_locked_txid` TLV since the peer had not considered the splice fully negotiated yet. In this case, an explicit retransmission of `splice_locked` is required as per the BOLT-2 requirement:
> Each node: > - If option_zeroconf has been negotiated: > - SHOULD send splice_locked immediately after exchanging tx_signatures.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
signing boundary
AI analysis · Moderate 54/100
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 peers could get stuck and not agree on the new channel funding, potentially leaving the channel unusable or in an inconsistent state. The fix ensures the required message is resent so both nodes converge correctly.
bolt12: add pay_for_bolt12_invoice for externally-sourced invoices
Adds a new pay_for_bolt12_invoice method that pays a BOLT 12 invoice without requiring it to have been requested through LDK. Unlike the existing send_payment_for_bolt12_invoice, this method:
- Does not verify that the invoice was previously requested by LDK. - Accepts a caller-supplied payment_id (no deduplication by invoice). - Supports an optional partial amount_msats for multi-payer MPP flows, where multiple senders each contribute a portion of the invoice total. The onion total_msat is always set to the full invoice amount so the recipient can validate the MPP payment correctly.
Also adds OptionalBolt12PaymentParams and Bolt12PaymentError, and deprecates send_payment_for_bolt12_invoice and manually_handle_bolt12_invoices in favour of the new flow.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Include to_self_delay size in DelayedPaymentOutput weight calculation
SpendableOutputDescriptor::create_spendable_outputs_psbt estimated the witness weight of a to_local (DelayedPaymentOutput) input using MAX_WITNESS_LENGTH, which assumes the maximum 4-byte OP_CSV push of to_self_delay in the redeemscript. The real push can be as small as 1 byte for small to_self_delays, causing the estimate to overshoot by up to 3 WU. If this overshoot occurred in addition to a short signature, the max-overshoot debug_assert in KeysManager::spend_spendable_outputs would fail.
Add DelayedPaymentOutput::max_witness_length, which computes the witness length from the descriptor's actual to_self_delay, and use it in place of the MAX_WITNESS_LENGTH constant. This produces a more accurate weight estimate so that the debug_assert in spend_spendable_outputs never fails.
This bug was discovered using Smite.
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
signing boundarysigning or wallet path
AI analysis · Low 26/100
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 the largest possible 4-byte encoding of a delay value, even when the real value used only 1 byte. That could make the fee estimate slightly too high and, in rare cases with a short digital signature, trigger an internal debug-only assertion failure. The fix computes the exact size based on the actual delay value and adds a regression test. It is not a remote exploit and does not risk loss of funds.
AI review queuedCorrect docs on `ChannelSigner::get_per_commitment_point`by Matt Corallo · 5057809b · Jul 28, 2026 · 1 fileMessage 65 · AdequateTriage 12Details
Commit message · Matt Corallo
Correct docs on `ChannelSigner::get_per_commitment_point`
This was apparently missed in 1f7b24900d16c841d55fc83e0e2057e241d5e
65/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides an explanatory body
Why it was queued
signing or wallet pathsecond-pass: security-sensitive path
Lower-priorityfuzz: allow empty-channel force close with in-flight paymentsby Joost Jager · dbb12502 · Jul 28, 2026 · 1 fileMessage 83 · StrongTriage 5Details
Commit message · Joost Jager
fuzz: allow empty-channel force close with in-flight payments
The chanmon harness can now force-close a target channel as long as that channel itself has no pending HTLCs, even when another channel still carries an in-flight payment. When an explicit close succeeds, mark pending payments that routed over the closed channel as allowed to fail.
This is the narrowest extension beyond globally HTLC-free closes. It covers a payment that crossed one hop before its next, still-empty channel is closed, without yet modeling force closes of channels that themselves contain HTLCs. Route-aware failure tracking limits the allowance to affected payments.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Start pending payments at MustSucceed and require every tracked PaymentFailed to follow an observed failure source. Cover receiver rejection, corruption, local send failure, local inbound forwarding failures, and the receive-side CLTV buffer.
Local inbound failures are classified when forwarding leaves an inbound HTLC waiting for its removal revoke, before the failure can reach the payer. For relayed failures, use OutboundHTLCDetails::source to retain exact inbound channel and HTLC IDs with the payment hash. This prevents same-hash MPP parts from being mistaken for a local failure root.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Rename the send-state query and local variables to describe whether LDK still has pending work. Route the existing pending-payment registration through one helper without changing which sends are tracked.
Later payment invariants must apply consistently to direct, forwarded, and MPP sends. Centralizing this lifecycle decision keeps tracking changes from diverging between send helpers.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Carry each send's minimum final CLTV expiry into payment registration. Thread PaymentTracker through HTLC message delivery and separate PaymentFailed from ProbeFailed dispatch.
A later invariant commit uses this context to classify failure roots. Keeping the plumbing separate reduces its behavioral review even though the minimum expiry remains temporarily unread.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Keep each hop ChannelId beside its SCID and retain the complete set of paths while a payment is pending. This is mechanical preparation; the new fields are intentionally not interpreted yet.
SCIDs remain the route-building input, while explicit closes identify channels by ChannelId. Carrying both representations in one path model lets a later force-close allowance match affected payments without reconstructing routes or maintaining parallel bookkeeping.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Build direct, forwarded, and MPP routes from a shared per-path hop description. Derive route fees and node metadata from that description, and increase the CLTV delta by 100 for each successive hop.
Later failure tracking needs to describe the exact route that was sent. Keeping route construction and bookkeeping on one representation prevents them from drifting and prepares the tracker to retain more per-hop failure context.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification