Previously we had db and application logic mixed on the db level.
We now move the config option KeepFailedPaymentAttempts to the
ChannelRouter level and move it out of the db level.
We are now not supporting the LegacyPayload for the onion packet
anymore. All payments and their onion payload need to be tlv
encoded. The sql backend assumes tlv so we have to always set the
in memory presentation of a hop where the legacy parameter is still
available but deprecated to false, otherwise the hops will not be
equal and unit tests for the sql backend will fail when switched
on in the next commits.
Add a gossip version parameter to ForEachNodeDirectedChannel on the
Store interface and both DB implementations (KVStore, SQLStore). The
NodeTraverser and routing.Graph interfaces remain unversioned since
pathfinding operates on the merged cross-version cache view.
The cache population in populateCache is updated in the same commit
because it is logically atomic with the versioning changes: the graph
cache is the unversioned, merged view used by pathfinding, so it must
be populated with data from all gossip versions. Without this change,
only v1 data would be loaded into the cache, making v2 nodes and
channels invisible to pathfinding.
Add ChanEdgePolicyFromWire to construct ChannelEdgePolicy from channel
update messages, centralizing v1/v2 field mapping.
Update call sites to use the helper:
- discovery/gossiper: handleChanUpdate
- graph/builder: ApplyChannelUpdate
- routing/router_test: ApplyChannelUpdate test helper
This consolidates update-to-policy conversion logic across versions.
Replace MessageFlags and ChannelFlags bitfields in CachedEdgePolicy
with explicit boolean fields to improve clarity and support both v1
and v2 channel updates:
- Replace MessageFlags with HasMaxHTLC boolean.
- Replace ChannelFlags with IsNode1 and IsDisabled booleans.
- Update NewCachedPolicy to extract these fields version-appropriately:
- For v1: derive from MessageFlags and ChannelFlags bits.
- For v2: derive from policy.SecondPeer and policy.DisableFlags.
Update all call sites that used method calls IsNode1() and IsDisabled()
to instead access the fields directly. This includes:
- graph_cache.go: policy direction and disable checks
- unified_edges.go: HasMaxHTLC and IsDisabled checks
- Tests: policy construction and assertions
This refactoring improves readability by making the cached policy's
state explicit rather than encoded in bitfields, and enables seamless
support for both gossip protocol versions.
Extend ChannelEdgePolicy to support v2 channel updates by adding:
- Version field to track gossip protocol version (v1 or v2).
- LastBlockHeight for v2's block-height-based timestamps.
- SecondPeer flag to indicate which peer announced the policy in v2.
- DisableFlags for v2-specific channel disable signaling.
- ExtraSignedFields map for v2 extra signed TLV data.
Add version-aware methods:
- IsNode1() determines if the policy was announced by node_1, handling
both v1 (via ChannelFlags direction bit) and v2 (via SecondPeer).
- IsDisabled() checks disable status using ChannelFlags for v1 and
DisableFlags for v2.
- String() provides version-appropriate string representations.
The new fields use zero values for v1 compatibility (Version defaults
to GossipVersion1, LastBlockHeight to 0, SecondPeer to false). This
lays the groundwork for v2 policy support; a subsequent commit will
handle reading and writing these fields from/to the database.
This makes it clear what fields must/can be set for a V1 channel.
Introduce NewV1Channel constructor to create v1 channel edges with
proper initialization and validation. The constructor:
- Takes required fields (chanID, chainHash, node keys) as parameters
- Takes v1-specific fields (bitcoin keys, extra opaque data) via
ChannelV1Fields struct
- Accepts optional fields (capacity, channel point, features, proof)
via functional options (WithCapacity, WithChannelPoint, etc.)
- Validates that if an AuthProof is provided, its version matches the
channel version
This makes it clear which fields are required vs optional for v1
channels and prevents incorrectly initialized channel edges. All
tests and production code updated to use the constructor.
Also update it to more closely match the persisted version which has the
v1 and v2 only fields as optional.
Refactor ChannelAuthProof to support both v1 and v2 channel
announcements:
- Add Version field to distinguish v1 from v2 proofs
- Wrap v1-specific fields (NodeSig1/2, BitcoinSig1/2) in fn.Option
since v2 doesn't use them
- Add optional Signature field for v2's single schnorr signature
- Add constructor functions NewV1ChannelAuthProof and
NewV2ChannelAuthProof to enforce correct initialization
- Add getter methods (NodeSig1(), BitcoinSig1(), etc.) that safely
unwrap options, returning empty slices when not present
The IsEmpty() check is updated to handle both versions correctly.
Both stores validate v1-only for now.
And set it to V1 version everywhere.
Add a Version field to ChannelEdgeInfo to distinguish between v1 and
v2 channel announcements. Set it to GossipVersion1 for all existing
channels.
Both KV and SQL stores now validate that only v1 channels are
currently supported, returning an error for v2 channels. The KV store
automatically sets version to v1 when deserializing (since all
persisted channels in KV format are v1).
This versioning is essential for handling the different field
requirements and validation logic between v1 and v2 channels.
Remove the cached parsed signature field and its lazy getter method
from ChannelEdgePolicy. This field was unused throughout the codebase
and the signature is already stored as raw bytes in SigBytes.
The SetSigBytes method is updated to remove the cache invalidation
logic.
HasNode currently is very v1 specific since it returns a time.Time
timestamp which is specific to V1 node announcements. However, it is
mostly only used for the "exists" return value. So here we split it up
into HasNode which just checks existence and HasV1Node which retains the
same behavaiour as before.
This increases the minimum CLTV delta allowed for invoice creation to
provide more headroom above DefaultFinalCltvRejectDelta (19 blocks).
The previous value of 18 was below the reject threshold, which could
allow users to create invoices with CLTV deltas that would be rejected
when receiving payments.
This commit improves TLV decoding safety and consistency across multiple
packages by enforcing fixed-length requirements and adding unit tests to
prevent malformed TLV records from being accepted.
Changes include:
- lnwire:
* Enforce 8-byte length in Fee TLV decoder.
* Enforce PubNonceSize in Musig2Nonce TLV decoder.
* Enforce 8-byte length in ShortChannelID TLV decoder.
* Added roundtrip and invalid length tests for Fee, Musig2Nonce,
and ShortChannelID records.
- routing/route:
* Enforce Vertex TLV length (33 bytes).
* Added encode/decode and invalid length tests for Vertex.
- tlv:
* Enforce correct length in DBytes33 decoder (33 bytes).
* Added tests ensuring all fixed-size primitive decoders reject
incorrect TLV lengths.
By strictly validating TLV lengths, we prevent malformed or corrupted
TLV records from being silently accepted, improving protocol safety.
When creating a missing edge, we need to populate the funding script too
so that the graph builder can update its ChainView appropriately. We use
the MakeFundingScript helper from the funding package which ensures that
we are using the same logic for creating a funding script as is used for
any of the channels that we own.
We now allow the mission control manager to skip over deserializable
errors. We cannot repair this these results but we just skip over
it so we can startup properly.
When fetchAll() encounters entries that fail to deserialize, in
addition to skipping them, now also:
- Delete the corrupted entries from the database
- Remove them from the in-memory keysMap and keys tracking structures
This prevents corrupted entries from:
- Being counted toward maxRecords, which would cause valid entries
to be pruned prematurely
- Persisting in the database indefinitely
- Causing inaccurate entry counts in startup logs
Use the new feature of Go 1.24, fix linter warnings.
This change was produced by:
- running golangci-lint run --fix
- sed 's/context.Background/t.Context/' -i `git grep -l context.Background | grep test.go`
- manually fixing broken tests
- itest, lntest: use ht.Context() where ht or hn is available
- in HarnessNode.Stop() we keep using context.Background(), because it is
called from a cleanup handler in which t.Context() is canceled already.