Bump main - #1
Merged
Merged
Conversation
LDK and the chanmon_consistency fuzz target have grown in complexity recently and thus require more iterations than previously assumed to fully settle the state of all active channels.
If we have pending updates to send to our counterparty on reestablishment, while also pending a `splice_locked` send, then we must send our `splice_locked` first as the pending updates are considering the post-splice-locked state.
A stale ChannelManager can be reloaded after a monitor update has already completed in a prior runtime and released its post-update messages to the counterparty. The latest ChannelMonitor is not stale, but the serialized manager may still contain the old in-flight monitor state and `monitor_pending_*` resend flags from before the completion action ran. This becomes observable when startup monitor-completion background events are interleaved with splice promotion. On reload, the completed monitor update is queued as a background event. If a splice confirmation is processed before that background event fully resumes the channel, splice promotion can create a new `RenegotiatedFundingLocked` monitor update. The old completion is then blocked behind the new in-flight splice update. Once the channel reconnects and the splice update completes, `monitor_updating_restored` may consume the stale `monitor_pending_revoke_and_ack` / `monitor_pending_commitment_signed` flags and release a duplicate `revoke_and_ack` or `commitment_signed`. The peer's `channel_reestablish` commitment numbers are authoritative for this case. If `next_remote_commitment_number` says the peer is not waiting for a `revoke_and_ack`, clear `monitor_pending_revoke_and_ack`. Likewise, if `next_local_commitment_number` says the peer already has our latest `commitment_signed`, clear `monitor_pending_commitment_signed`.
…eestablish-fixes `splice_locked` + `channel_reestablish` bug fixes
LSPS5 resets notification cooldowns when a peer reconnects so clients can receive prompt wake-ups after coming online. A peer can otherwise churn connections to clear the webhook cooldown repeatedly, turning the LSP into an amplification source for registered notification URLs. Rate-limit how often peer lifecycle events may clear notification cooldowns while keeping the first reset immediate. Also make LSPSDateTime elapsed-time calculation directional so backwards clock movement does not make future timestamps look expired. Co-Authored-By: HAL 9000 This finding was discovered by Project Loupe
AnchorDescriptor::previous_utxo is used for coin selection and PSBT witness_utxo metadata. For keyed anchors it should describe the on-chain P2WSH anchor output instead of the witness script so wallets can validate and sign the package. Co-Authored-By: HAL 9000 This finding was discovered by Project Loupe
get_supportable_anchor_channels estimates how much each reserve UTXO can contribute after spending fees. Include the base input weight in that fee so UTXOs just below the public per-channel reserve are not counted as supporting another anchor channel. Co-Authored-By: HAL 9000 This finding was discovered by Project Loupe
When a used async receive offer's refreshed static invoice is persisted, advance the recorded invoice creation time. This keeps the refresh threshold anchored to the newest invoice instead of making the offer look stale on every timer tick. Add coverage that a used offer does not enqueue another ServeStaticInvoice immediately after the server confirms the refresh. Co-Authored-By: HAL 9000 This finding was discovered by Project Loupe
When a JIT channel open fails, release queued intercepted HTLCs through the intercept API so they are not held until expiry. Keep resetting the LSPS2 state if an intercept has already been released. Co-Authored-By: HAL 9000 This finding was discovered by Project Loupe
Reserve write versions while holding the per-path lock map mutex so cleanup cannot remove the version state between version allocation and lock reference acquisition. Add a regression test for the ordering invariant. Co-Authored-By: HAL 9000 This finding was discovered by Project Loupe
…hannel-open-failed Release LSPS2 intercepted HTLCs on open failure
…erve-input-weight Account for UTXO base weight in anchor reserve checks
Introduce fields `pending_fee_msat` for `RecentPaymentDetails::Pending` and `fee_paid_msat` for `RecentPaymentDetails::Fulfilled`.
…vious-utxo-p2wsh Return P2WSH script pubkey for keyed anchor prevouts
Move the version-allocation ordering note to the allocation it describes so the cleanup invariant is easier to follow. Co-Authored-By: HAL 9000
Exercise the stale-write race through the stored filesystem bytes so the regression test covers the user-visible overwrite bug. Co-Authored-By: HAL 9000
…ntity-check Reject quantity of 0 for offers with bounded quantity
InvoiceRequest and Refund have payer metadata consisting of an encrypted payment id and, originally, a nonce used to derive the payer signing keys and authenticate any corresponding invoices. The nonce was elided to save space once it was included in the OffersContext of blinded reply paths, but that means verifying a Bolt12Invoice requires state outside the invoice itself. Upcoming payment proofs (lightningdevkit#4297) need the invoice signing keys derivable from the invoice request alone, so include the nonce in the payer metadata again and verify invoices using it rather than the context's nonce. This breaks verification of invoices for invoice requests and refunds with blinded paths created by prior versions, as their payer metadata lacks the nonce; such payments will fail and must be retried with a new payment id. Refunds without blinded paths are unaffected, as their metadata always included the nonce. Co-Authored-By: Claude <noreply@anthropic.com>
…consistency-fixes Splice fixes for `chanmon_consistency` fuzz target
Allow integrations to intercept blinded onion-message hops that identify the next node by short channel id, so LSPS-style protocols can resolve those hops out of band instead of dropping the message. Co-Authored-By: HAL 9000
When the OnionMessenger intercepts an onion message to forward, it now reports which peer sent us the message via a new `prev_hop` field, so handlers can apply source-based policy when deciding whether to forward. `prev_hop` is `None` when the forward is enqueued by a message handler (the BOLT 12 static-invoice-server flow), which isn't given the sending node; otherwise it is the node we received the message from. Co-Authored-By: Claude <noreply@anthropic.com>
…-invoice-refresh Avoid repeated refreshes for persisted async invoices
Route chanmon broadcasts through an explicit harness mempool so relay, mining, wallet updates, and chain delivery share one path. This lets broadcast transactions enter the mempool before a modeled block confirms them. On restart, sync loaded monitors and managers from their own persisted best blocks so raw monitors catch up without rewinding ChannelManager state. Cap modeled mining before unresolved HTLC timeout deadlines and use the LDK anti-reorg depth for setup confirmations.
…sage-origin Report the sending peer in `Event::OnionMessageIntercepted`
The owned `Waker` wake method assumed it had the only reference to the sender as the `Waker` is owned at that point, however our `Waker`s can be `clone`d, leaving multiple references to the inner `Sender` (held in an `Arc`). Thus, the `&mut` cast is technically undefined behavior. However, as this patch demonstrates, its only use is in calling an `&self` method which derefs an internal `Arc` in tokio, so its highly unlikely to lead to miscompilation. Reported by Project Loupe.
…aliasing Remove unnecessary (and incorrect) `&mut` cast in net-tokio
Now that the payer nonce is included in the payer metadata of InvoiceRequest and Refund, Bolt12Invoice verification no longer needs the nonce from the blinded path's OffersContext. Remove it from OffersContext::OutboundPaymentForOffer and OffersContext::OutboundPaymentForRefund, along with enqueue_invoice_request's nonce parameter, which only existed to supply it. The nonce in RetryableInvoiceRequest is no longer used either but is still persisted -- and retained when reading state written by prior versions -- so that such versions can retry the payment and verify the resulting invoice after a downgrade. The payment_id is kept in both variants, however. While no longer needed to confirm the invoice is for an invoice request or refund we created, it is checked against the payment id recovered from a received Bolt12Invoice's payer metadata to ensure the invoice arrived over the blinded path created for that payment. This prevents an attacker from reusing the blinded path of one of our payments to deliver another payment's invoice and correlate the two as ours. Co-Authored-By: Claude <noreply@anthropic.com>
`Borrow`'d values are required to `Hash` identically to the original object so that a `Borrow`ed key can be used in place of an owned one in a `HashMap` lookup. We'd violated this on our `Payment*` types, which we fix here. Note that changing the `Hash` implementation is generally not considered an API-breaking change and this seems like a useful fix. Reported by Project Loupe.
In ae62fa3 we removed an incorrect `&mut`, but failed to actually resolve the mut aliasing bug - there remained a deref of a `*mut` which is similarly invalid. Here we actually fix the bug and also DRY up code marginally. Reported by Project Loupe.
…ayer-nonce Include `Nonce` in `payer_metadata` again
In the previous commit we started handling the new `DNSSECError` onion messages and using them to expose when a BIP 353 resolution over onion messages should be considered failed due to all of our queries having filed. However, queries can also fail if all of our queries either errored or returned bogus proofs, or if we received a valid proof which proved there is no BIP 353 record or `Offer`. Here we consider such failures and expose them as well.
lightning/blips#71 updated the DNSSEC resolution bLIP to include an explicit error message when DNS(SEC) resolution was attempted but failed, allowing for faster fallback to LN-Address (for clients that do) and faster payment failure. Here we add service-side support for generating the error messages, informing requesters that their resolutions have failed. Largely written by an LLM
We intended to apply DNSSEC proof validity tests to constrain them to within two hours of the latest block header time, but the code landed with a two minute gap instead. Given DNSSEC proof validity is usually many hours and grace periods are used to ensure records close to expiry aren't used, this is somewhat unlikely to have bitten anyone.
This better captures what the method actually does.
from block-connection-logging into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4813 Reviewed-by: Matt Corallo <matt@noreply.gitea.bitcoin.ninja>
…sed resolution' (#4814) from 2026-07-353-errs into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4814 Reviewed-by: Val Wallace <val@noreply.gitea.bitcoin.ninja>
…th ways When selecting a channel to reference a compact (DirectedShortChannelId) introduction node, only consider channels that are enabled in both directions. Disabled channels cannot be used to reach the introduction node, and such channels may linger in the local network graph long after being disabled or even closed (e.g., when sourcing gossip from rapid gossip sync, which never removes closed channels). Previously, the oldest channel of the introduction node was selected unconditionally, which could produce blinded paths that senders cannot resolve or route to, silently breaking long-lived paths such as those embedded in BOLT 12 offers. If no enabled channel is found, the NodeId encoding is kept. Fixes #4826.
…806) from outbound-htlc-forward-correlation into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4806 Reviewed-by: jkczyz <jkczyz@noreply.gitea.bitcoin.ninja>
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.
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.
Register every send as pending, then move immediate outcomes through one strict pending-to-resolved transition. Reuse that transition for terminal events and manager rollback, while handling repeated terminal events only after confirming the payment was already resolved. Keep abandoned payments pending while they still have outbound HTLC state, including holding-cell HTLCs. Later success checks need complete tracker state and must reject terminal events for payments the harness never recorded.
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.
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.
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.
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.
This was apparently missed in 1f7b249
…enabled both ways' (#4828) from fix-offer-compact-intro-node into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4828 Reviewed-by: Matt Corallo <matt@noreply.git.rust-bitcoin.org>
…(#4829) from 2026-07-4197-doc-updates into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4829 Reviewed-by: wpaulino <wpaulino@noreply.git.rust-bitcoin.org>
…ccessors + tweak bounds handling' (#4824) from 2026-07-prob-access-debug-assert into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4824 Reviewed-by: Val Wallace <val@noreply.git.rust-bitcoin.org>
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.
…alculation' (#4833) from fix_overfunded_sweep into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4833
from fuzz-force-close-inflight-no-target-htlc into main Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4800 Reviewed-by: wpaulino <wpaulino@noreply.git.rust-bitcoin.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.