lnd/docs/release-notes/release-notes-0.21.2.md
Olaoluwa Osuntokun 2bcb7572de
discovery: bound channel range reply buffering
In this commit, we cap each QueryChannelRange response at 100,000 SCIDs
across all streamed replies. The existing reply-count limit did not track
the aggregate decoded working set, so memory use varied with the encoding
and composition of the reply stream.

We count raw SCIDs before timestamp filtering, charge replies using the
received encoding type, and release all accumulated range state on any
error. This bounds both memory and CPU work while still leaving headroom
above the current graph.

(cherry picked from commit ceff94fadd)
2026-08-03 18:57:23 -03:00

4.5 KiB

Release Notes

Bug Fixes

  • Fixed several bugs in onion message decoding where messages that should have been rejected per BOLT 4 were instead accepted, or a valid TLV was dropped.

  • Fixes a bug that could allow the RBF closer to be used with incompatible aux channels.

  • Fixes a payment migration failure caused by historical routes containing a blinded total amount without encrypted recipient data. The migration now normalizes the orphaned total, and SendToRouteV2 rejects new routes with the same invalid field combination. This also affects callers replaying an affected historical route returned by ListPayments or TrackPayment.

  • Fixed a channeldb migration bug where databases initialized without a persisted metadata/dbp version key could skip later mandatory migrations. This recovers such databases from the last known v0.20-era mandatory version so the v0.21 waiting proof migration runs without replaying older migrations against an already-initialized database.

  • Bounded the memory used while syncing the channel graph. A peer replying to our query_channel_range could previously make us buffer an unpredictable number of short channel IDs, as the only limit was a coarse 67MB cap on the bytes a single zlib-compressed reply could decompress to. Replies are now capped at a precise number of short channel IDs, both per-message and in aggregate across a single query, and the accumulated reply state is released as soon as any reply fails validation so that a peer cannot pin it by deliberately forcing an error.

New Features

Functional Enhancements

RPC Additions

  • The HTLC interceptor now exposes the next hop of a blinded route that identifies it by node ID (next_node_id) rather than by channel.

lncli Additions

Improvements

Functional Updates

RPC Updates

  • ForwardHtlcInterceptRequest.outgoing_requested_chan_id now holds a reserved sentinel value (18446744073709551615, all bits set) when the HTLC interceptor reports a blinded forward that identifies the next hop by node ID. The sender of such a forward requests no channel, so a zero value here would make a client that detects the exit hop by a zero channel ID classify the forward as a final receive. Clients that switch on this field must handle the sentinel and read outgoing_requested_node_id for the next hop.

lncli Updates

Breaking Changes

Performance Improvements

Deprecations

⚠️ Warning: Deprecated fields in lnrpc.Hop will be removed in release version 0.22

⚠️ Warning: The deprecated fee rate option --sat_per_byte will be removed in release version 0.22

Technical and Architectural Updates

BOLT Spec Updates

  • Fixed an issue where an lnd node acting as a relaying node (including the introduction node) in a blinded path failed to forward the payment when the next hop was identified by node ID (next_node_id) rather than a short channel ID. The next hop's public key is now resolved to one of our channels with that peer using non-strict forwarding.

Testing

Database

Code Health

Robustness

Tooling and Documentation

Contributors (Alphabetical Order)

  • bitromortac
  • Jared Tobin
  • Olaoluwa Osuntokun