Skip to content

[g175] graph/db: add v2 gossip support for channel policies#10542

Open
ellemouton wants to merge 16 commits intolightningnetwork:elle-g175Prep-basefrom
ellemouton:g175-db-6
Open

[g175] graph/db: add v2 gossip support for channel policies#10542
ellemouton wants to merge 16 commits intolightningnetwork:elle-g175Prep-basefrom
ellemouton:g175-db-6

Conversation

@ellemouton
Copy link
Collaborator

PR Description

This PR extends the graph database layer to support gossip v2 (1.75) channel policies, building on the foundation established in #10339, #10379, and #10380. This work is part of the larger gossip 1.75 implementation effort tracked in #10293.

Context

This PR completes the channel policy layer of the gossip v2 database preparation work:

Together, these changes enable LND to store and retrieve Taproot channel announcements with Schnorr signature aggregation, though v2 gossip remains disabled at the network level pending completion of validation and gossiper subsystem work.

Key Changes

Model Extensions

  • Add v2 fields to ChannelEdgePolicy: Version, LastBlockHeight, SecondPeer, DisableFlags, ExtraSignedFields
  • Add version-aware methods: IsNode1(), IsDisabled(), String()
  • New ChanEdgePolicyFromWire constructor for converting wire messages to policies

Database Operations

  • Update ForEachChannel, ForEachNodeChannel, and HasChannelEdge to accept gossip version parameter
  • Version-specific staleness checks in UpsertChannelPolicy:
    • V1: timestamp comparison with > (strict ordering)
    • V2: block height comparison with >= (allows same-block updates)
  • Version-aware reject cache for tracking rejected policies per version

Store Implementations

  • KVStore: Explicitly rejects v2 operations with ErrVersionNotSupportedForKVDB
  • SQLStore: Full v1 and v2 support with version-specific field mapping and policy reconstruction

Abstractions

  • Extended VersionedGraph with policy-specific methods that use configured gossip version
  • Refactored CachedEdgePolicy to use explicit boolean fields (HasMaxHTLC, IsNode1, IsDisabled) instead of bitfields for clarity and version-agnostic caching
  • Updated all call sites to explicitly specify GossipVersion1

@gemini-code-assist
Copy link

Summary of Changes

Hello @ellemouton, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the graph database layer to incorporate full support for Gossip V2 channel policies, building upon previous work to prepare for the 1.75 specification. The changes enable the storage and retrieval of Taproot channel announcements with Schnorr signature aggregation, laying crucial groundwork for future network-level activation of V2 gossip. The modifications ensure the database can correctly handle and differentiate between V1 and V2 policy updates, maintaining compatibility while introducing new capabilities.

Highlights

  • ChannelEdgePolicy Model Extension: The ChannelEdgePolicy model has been extended to support Gossip V2 (1.75) specific fields, including Version, LastBlockHeight, SecondPeer, DisableFlags, and ExtraSignedFields. New version-aware methods like IsNode1(), IsDisabled(), and String() have been added, along with a ChanEdgePolicyFromWire constructor to convert wire messages to policies.
  • Database Operations Update: Core database operations such as ForEachChannel, ForEachNodeChannel, and HasChannelEdge now accept a gossip version parameter. UpsertChannelPolicy includes version-specific staleness checks, using timestamp comparison for V1 and block height comparison for V2. The reject cache has also been made version-aware.
  • Store Implementation Differentiation: The KVStore explicitly rejects V2 operations with an ErrVersionNotSupportedForKVDB error, maintaining its V1-only scope. The SQLStore, however, now provides full support for both V1 and V2 policies, handling version-specific field mapping and policy reconstruction.
  • Abstraction Layer Refinement: The VersionedGraph interface has been extended with policy-specific methods that leverage the configured gossip version. The CachedEdgePolicy model has been refactored to use explicit boolean fields (HasMaxHTLC, IsNode1, IsDisabled) instead of bitfields for improved clarity and version-agnostic caching. All relevant call sites have been updated to explicitly specify GossipVersion1 where appropriate.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • discovery/gossiper.go
    • Updated handleChanUpdate to use the new models.ChanEdgePolicyFromWire constructor for creating channel edge policies from wire messages.
  • graph/builder.go
    • Modified ApplyChannelUpdate to utilize models.ChanEdgePolicyFromWire for policy creation.
    • Updated addEdge and updateEdge to pass GossipVersion1 to HasChannelEdge and introduced HasV1ChannelEdge for V1-specific checks.
    • Changed ForEachOutgoingChannels, IsKnownEdge, IsZombieEdge, and IsStaleEdgePolicy to explicitly pass GossipVersion1 or use HasV1ChannelEdge.
  • graph/builder_test.go
    • Added Version: lnwire.GossipVersion1 to ChannelEdgePolicy initializations in various tests.
    • Updated calls to HasChannelEdge to include the GossipVersion1 parameter.
  • graph/db/benchmark_test.go
    • Modified ForEachChannel calls in benchmarks to explicitly pass lnwire.GossipVersion1.
  • graph/db/graph.go
    • Updated ForEachNodeChannel, ForEachChannel, and HasChannelEdge methods to accept a lnwire.GossipVersion parameter.
    • Introduced HasV1ChannelEdge for V1-specific channel edge existence checks.
    • Added new HasChannelEdge, ForEachNodeChannel, and ForEachChannel methods to VersionedGraph that use its internal gossip version.
  • graph/db/graph_cache.go
    • Refactored AddChannel and UpdatePolicy to use the new explicit boolean fields (IsDisabled, IsNode1) on CachedEdgePolicy instead of bitfield checks.
    • Updated NewCachedPolicy to correctly map V1 and V2 ChannelEdgePolicy fields to the CachedEdgePolicy's new boolean flags.
  • graph/db/graph_test.go
    • Added Version field to ChannelEdgePolicy in test helper functions (createChannelEdge, newEdgePolicy).
    • Updated HasChannelEdge calls in tests to pass lnwire.GossipVersion1.
    • Introduced testEdgePolicyCRUD and testIncompleteChannelPolicies to test version-aware policy handling.
    • Modified compareEdgePolicies to be version-aware, comparing V1 and V2 specific fields appropriately.
  • graph/db/interfaces.go
    • Updated the Store interface for ForEachNodeChannel, ForEachChannel, and HasChannelEdge to include a lnwire.GossipVersion parameter.
    • Added HasV1ChannelEdge to the Store interface for V1-specific checks.
  • graph/db/kv_store.go
    • Modified ForEachChannel, ForEachNodeChannel, and updateEdgePolicy to return ErrVersionNotSupportedForKVDB if a version other than GossipVersion1 is used.
    • Renamed HasChannelEdge to HasV1ChannelEdge and introduced a new HasChannelEdge method that accepts a lnwire.GossipVersion parameter.
    • Updated rejectCache operations (remove, insert, get) to be version-aware using a new rejectCacheKey.
  • graph/db/models/cached_edge_policy.go
    • Replaced MessageFlags and ChannelFlags with explicit boolean fields: HasMaxHTLC, IsNode1, IsDisabled.
    • Updated NewCachedPolicy to correctly populate these new boolean fields based on the ChannelEdgePolicy's version.
  • graph/db/models/channel_edge_policy.go
    • Added new fields: Version, LastBlockHeight, SecondPeer, DisableFlags, ExtraSignedFields to support Gossip V2.
    • Introduced ChanEdgePolicyFromWire constructor to create ChannelEdgePolicy from lnwire.ChannelUpdate messages, handling both V1 and V2.
    • Updated IsNode1() and IsDisabled() methods to be version-aware, checking appropriate flags based on the policy's version.
    • Modified String() method to provide version-specific human-readable output.
  • graph/db/reject_cache.go
    • Extended rejectCacheEntry with upd1BlockHeight and upd2BlockHeight for V2 policies.
    • Added helper functions newRejectCacheEntryV1, newRejectCacheEntryV2, updateRejectCacheEntryV1, updateRejectCacheEntryV2 for version-specific entry creation and updates.
    • Introduced rejectCacheKey struct to make the cache version-aware, and updated get, insert, and remove methods to use this key.
  • graph/db/reject_cache_test.go
    • Updated calls to rejectCache methods (get, insert, remove) to include lnwire.GossipVersion1.
  • graph/db/sql_store.go
    • Modified updateEdgeCache to handle version-specific updates for rejectCacheEntry (timestamps for V1, block heights for V2).
    • Updated ForEachNodeChannel and ForEachChannel to accept a lnwire.GossipVersion parameter.
    • Refactored updateChanEdgePolicy to handle V1 and V2 policy fields and update logic, including version-specific staleness checks.
    • Renamed HasChannelEdge to HasV1ChannelEdge and implemented a new version-aware HasChannelEdge method.
    • Updated buildChanPolicy and related functions to be version-aware, correctly extracting and populating fields based on the policy version.
  • graph/notifications_test.go
    • Added Version: lnwire.GossipVersion1 to randEdgePolicy.
  • netann/chan_status_manager_test.go
    • Added Version: lnwire.GossipVersion1 to ChannelEdgePolicy in createEdgePolicies and ApplyChannelUpdate mock.
  • routing/localchans/manager.go
    • Added Version: lnwire.GossipVersion1 to ChannelEdgePolicy in createEdge.
  • routing/localchans/manager_test.go
    • Added Version: lnwire.GossipVersion1 to expectedEdge in TestCreateEdgeLower and TestCreateEdgeHigher.
  • routing/pathfind_test.go
    • Added Version: lnwire.GossipVersion1 to ChannelEdgePolicy in parseTestGraph and createTestGraphFromChannels.
  • routing/router_test.go
    • Added Version: lnwire.GossipVersion1 to ChannelEdgePolicy in TestAddEdgeUnknownVertexes and mockGraphBuilder.ApplyChannelUpdate.
  • routing/unified_edges.go
    • Updated amtInRange to use u.policy.HasMaxHTLC instead of u.policy.MessageFlags.HasMaxHtlc().
    • Updated getEdgeNetwork to use edge.policy.IsDisabled instead of edge.policy.IsDisabled() and edge.policy.HasMaxHTLC instead of edge.policy.MessageFlags.HasMaxHtlc().
  • routing/unified_edges_test.go
    • Updated CachedEdgePolicy initializations to use HasMaxHTLC instead of MessageFlags.
  • rpcserver.go
    • Changed the graph database access in DescribeGraph from r.server.graphDB to r.server.v1Graph to explicitly use the V1 graph.
  • server.go
    • Updated ForEachNodeChannel call in newServer to use s.v1Graph instead of s.graphDB.
  • sqldb/sqlc/graph.sql.go
    • Updated generated Go code to include Policy1BlockHeight, Policy1DisableFlags, Policy2BlockHeight, Policy2DisableFlags in various channel policy queries.
    • Modified UpsertEdgePolicyParams to include BlockHeight and DisableFlags.
    • Adjusted the UpsertEdgePolicy SQL query to handle version-specific update conditions (last_update for V1, block_height for V2).
  • sqldb/sqlc/queries/graph.sql
    • Modified SQL queries to select block_height and disable_flags for channel policies.
    • Updated the UpsertEdgePolicy SQL statement to insert and update block_height and disable_flags, and to apply version-specific WHERE clauses for staleness checks (comparing last_update for V1 and block_height for V2).
Activity
  • The pull request introduces significant changes to support Gossip V2 channel policies, indicating a planned and structured development effort.
  • The detailed PR description outlines the context, key changes, and how this PR fits into a larger implementation effort, suggesting thorough planning by the author.
  • The extensive modifications across multiple files, including core database logic, models, and tests, show a comprehensive approach to integrating V2 support.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@lightninglabs-deploy
Copy link
Collaborator

🔴 PR Severity: CRITICAL

Auto-classified | 15 production files | ~1,004 lines changed (excl. tests/generated)

🔴 Critical (2 files)
  • server.go - Core server coordination
  • rpcserver.go - Core RPC server coordination
🟠 High (13 files)
  • discovery/gossiper.go - Gossip protocol implementation
  • graph/builder.go - Network graph builder
  • graph/db/graph.go - Graph database operations
  • graph/db/graph_cache.go - Graph caching layer
  • graph/db/interfaces.go - Graph database interfaces
  • graph/db/kv_store.go - Key-value store for graph data
  • graph/db/models/cached_edge_policy.go - Edge policy caching models
  • graph/db/models/channel_edge_policy.go - Channel edge policy models (93 additions)
  • graph/db/reject_cache.go - Rejection cache for graph updates
  • graph/db/sql_store.go - SQL-based graph storage (347 additions)
  • sqldb/sqlc/queries/graph.sql - Graph SQL queries
  • routing/localchans/manager.go - Local channel management for routing
  • routing/unified_edges.go - Unified edge handling for routing

Analysis

This PR adds v2 gossip support for channel policies, which is a significant enhancement to the Lightning Network graph management system.

Severity rationale:

  • Base severity: HIGH - The majority of changes are in graph/db/* (network graph maintenance) and routing/* (payment pathfinding), which are HIGH severity areas
  • Bumped to CRITICAL due to >500 production lines changed (~1,004 lines excluding tests and auto-generated files)
  • Additional critical touches: server.go and rpcserver.go, though changes are minimal (3 and 9 lines respectively)

Key areas of concern:

  1. Graph database modifications - Extensive changes to how channel policies are stored and retrieved (sql_store.go +347 lines)
  2. Wire protocol changes - Adding v2 gossip support affects how nodes communicate channel policies
  3. Caching layer updates - Changes to edge policy caching could impact performance and consistency
  4. SQL schema evolution - New queries in graph.sql that modify database access patterns

Recommended review focus:

  • Backward compatibility with v1 gossip
  • Database migration path (if applicable)
  • Edge cases in policy caching with mixed v1/v2 nodes
  • Performance implications of SQL store changes

To override, add a severity-override-{critical,high,medium,low} label.

@ellemouton ellemouton self-assigned this Feb 3, 2026
@ellemouton
Copy link
Collaborator Author

@claude review this

@codex review this

@lightninglabs-deploy
Copy link
Collaborator

🔴 PR Severity: CRITICAL

Manual classification | 28 files | 1,674 lines changed

🔴 Critical (2 files)
  • server.go - Core server coordination
  • rpcserver.go - Core RPC server coordination
🟠 High (12 files)
  • graph/db/graph.go - Network graph database maintenance
  • graph/db/kv_store.go - Graph key-value store operations
  • graph/db/sql_store.go - Graph SQL store operations (347 additions, 96 deletions)
  • graph/db/interfaces.go - Graph database interfaces
  • graph/db/graph_cache.go - Graph caching layer
  • graph/db/reject_cache.go - Rejection cache logic
  • graph/db/models/channel_edge_policy.go - Channel policy models (93 additions)
  • graph/db/models/cached_edge_policy.go - Cached policy models
  • graph/builder.go - Graph builder coordination
  • discovery/gossiper.go - Gossip protocol handling
  • sqldb/sqlc/graph.sql.go - Auto-generated SQL code (138 additions)
  • sqldb/sqlc/queries/graph.sql - SQL schema changes (62 additions, 13 deletions)
🟡 Medium (3 files)
  • routing/unified_edges.go - Unified edge handling
  • routing/localchans/manager.go - Local channel management
  • netann/chan_status_manager_test.go - Test file
🟢 Low (11 files)
  • docs/release-notes/release-notes-0.21.0.md - Release notes
  • graph/db/benchmark_test.go - Benchmark tests
  • graph/db/graph_test.go - Graph tests (223 additions, 103 deletions)
  • graph/db/graph_cache_test.go - Cache tests
  • graph/db/reject_cache_test.go - Rejection cache tests
  • graph/builder_test.go - Builder tests
  • graph/notifications_test.go - Notification tests
  • routing/localchans/manager_test.go - Manager tests
  • routing/pathfind_test.go - Pathfinding tests
  • routing/router_test.go - Router tests
  • routing/unified_edges_test.go - Unified edges tests

Analysis

This PR adds v2 gossip support for channel policies and is classified as CRITICAL due to:

  1. Core Server Impact: Changes to server.go and rpcserver.go affect core daemon coordination and RPC handling, requiring expert review.

  2. Database Schema Changes: Modifications to SQL schema (sqldb/sqlc/queries/graph.sql) with 62 additions and 13 deletions are always critical, as they affect data persistence and migration paths.

  3. Extensive Graph Database Changes: The PR touches 8 graph/db files with significant logic changes:

    • sql_store.go: 347 additions, 96 deletions
    • channel_edge_policy.go: 93 additions (model changes)
    • graph_test.go: 223 additions (substantial test expansion)
  4. Scope Triggers:

    • ✓ >20 files changed (excluding tests: ~17 non-test files, borderline)
    • ✓ >500 lines changed (excluding tests/auto-generated: ~800+ lines)
    • ✓ Multiple distinct critical/high packages (server, rpcserver, graph/db, sqldb, routing, discovery)
  5. Protocol Impact: This adds v2 gossip support, which affects:

    • How channel policies are stored and retrieved (graph/db)
    • How gossip messages are processed (discovery/gossiper.go)
    • How routing decisions are made (routing/* files)
    • Core server initialization and RPC handling

Concerns:

  • Database migration path needs careful review
  • Backward compatibility with v1 gossip
  • Concurrent access patterns in graph cache
  • Impact on routing performance with new policy models

This requires expert review from maintainers familiar with the Lightning gossip protocol, graph database layer, and SQL schema evolution.


To override, add a severity-override-{critical,high,medium,low} label.

@claude
Copy link

claude bot commented Feb 3, 2026

Claude encountered an error —— View job

Command failed: git fetch origin --depth=20 g175-db-6

I'll analyze this and get back to you.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR adds support for gossip v2 channel policies to the graph database layer. This is a significant change that touches many parts of the codebase, including the database schema, data models, and graph traversal logic. The changes are well-structured, with clear separation between v1 and v2 logic, especially in the sql_store and the new version-aware model constructors. The refactoring of CachedEdgePolicy to use boolean fields instead of bitmasks is a nice improvement for readability. My review focuses on ensuring documentation for new and modified exported functions is sufficiently detailed as per the project's style guide. Overall, this is a solid step towards full gossip v2 support.

return c.db.DisabledChannelIDs()
}

// HasV1ChannelEdge returns true if the database knows of a channel edge.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment for HasV1ChannelEdge is a bit brief. To align with the style guide's emphasis on detailed comments for exported functions, consider expanding it to explain what the function does and what its return values represent, similar to the comment for this function in the Store interface.

Suggested change
// HasV1ChannelEdge returns true if the database knows of a channel edge.
// HasV1ChannelEdge returns true if the database knows of a v1 channel edge
// with the passed channel ID, and false otherwise. If an edge with that
// ID is found within the graph, then two time stamps representing the
// last time the edge was updated for both directed edges are returned
// along with the boolean. If it is not found, then the zombie index is
// checked and its result is returned as the second boolean.
References
  1. Exported functions require detailed comments for the caller. (link)

return c.db.HasV1ChannelEdge(chanID)
}

// HasChannelEdge returns true if the database knows of a channel edge.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment for HasChannelEdge is a bit brief. To align with the style guide's emphasis on detailed comments for exported functions, consider expanding it to explain what the function does and what its return values represent, similar to the comment for this function in the Store interface.

// HasChannelEdge returns true if the database knows of a channel edge
// with the passed channel ID and gossip version, and false otherwise.
// If it is not found, then the zombie index is checked and its result
// is returned as the second boolean.
References
  1. Exported functions require detailed comments for the caller. (link)

return c.db.HasChannelEdge(c.v, chanID)
}

// ForEachNodeChannel iterates through all channels of the given node.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment for ForEachNodeChannel is a bit brief. To align with the style guide's emphasis on detailed comments for exported functions, consider expanding it to explain what the function does, its parameters, and what is passed to the callback, similar to the comment for this function in the Store interface.

// ForEachNodeChannel iterates through all channels of the given node for the
// graph's gossip version, executing the passed callback with an edge info
// structure and the policies of each end of the channel. The first edge
// policy is the outgoing edge *to* the connecting node, while the second is
// the incoming edge *from* the connecting node. If the callback returns an
// error, then the iteration is halted with the error propagated back up to
// the caller.
//
// NOTE: Unknown policies are passed into the callback as nil values.
References
  1. Exported functions require detailed comments for the caller. (link)

return c.db.ForEachNodeChannel(ctx, c.v, nodePub, cb, reset)
}

// ForEachChannel iterates through all channel edges stored within the graph.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment for ForEachChannel is a bit brief. To align with the style guide's emphasis on detailed comments for exported functions, consider expanding it to explain what the function does and what is passed to the callback, similar to the comment for this function in the Store interface.

// ForEachChannel iterates through all channel edges stored within the graph for
// the graph's gossip version.
//
// NOTE: If an edge can't be found, or wasn't advertised, then a nil
// pointer for that particular channel edge routing policy will be
// passed into the callback.
References
  1. Exported functions require detailed comments for the caller. (link)

@lightninglabs-deploy
Copy link
Collaborator

🔴 PR Severity: CRITICAL

PR #10542 | 30 files | 1,679 lines changed (1,009 non-test/non-generated)

🔴 Critical (2 files)
  • server.go - Core server coordination, integrating v2 gossip support
  • rpcserver.go - Core RPC server coordination for policy updates
🟠 High (13 files)
  • graph/db/graph.go - Network graph maintenance, v2 policy storage
  • graph/db/graph_cache.go - Graph caching layer modifications
  • graph/db/interfaces.go - Graph database interface changes
  • graph/db/kv_store.go - Key-value store for graph data
  • graph/db/models/cached_edge_policy.go - Edge policy caching models
  • graph/db/models/channel_edge_policy.go - Core channel edge policy models (93 additions)
  • graph/db/reject_cache.go - Reject cache for invalid policies
  • graph/db/sql_store.go - SQL storage layer (347 additions - largest change)
  • sqldb/sqlc/queries/graph.sql - SQL queries for graph operations
  • graph/builder.go - Network graph builder logic
  • discovery/gossiper.go - Gossip protocol handling
  • routing/unified_edges.go - Routing edge unification
  • routing/localchans/manager.go - Local channel management
🟢 Low (1 file)
  • docs/release-notes/release-notes-0.21.0.md - Release notes documentation
📝 Test/Generated Files (14 files - excluded from severity calculation)

Test files: graph/db/graph_test.go, graph/db/graph_cache_test.go, graph/db/reject_cache_test.go, graph/db/benchmark_test.go, graph/builder_test.go, graph/notifications_test.go, routing/unified_edges_test.go, routing/pathfind_test.go, routing/router_test.go, routing/localchans/manager_test.go, autopilot/prefattach_test.go, netann/chan_status_manager_test.go, lnrpc/invoicesrpc/addinvoice_test.go

Auto-generated: sqldb/sqlc/graph.sql.go

Analysis

This PR adds v2 gossip support for channel policies, which is a critical change that touches:

  1. Core Server Files: Changes to server.go and rpcserver.go immediately elevate this to critical severity, as these coordinate the entire LND server operation.

  2. Extensive Graph Database Changes: The PR modifies 13 high-severity files across the graph database layer, including major changes to:

    • SQL storage layer (347 additions in sql_store.go)
    • Channel edge policy models (93 additions)
    • Graph persistence and caching mechanisms
  3. Size Trigger: With 1,009 non-test/non-generated lines changed (exceeding the 500-line threshold), this PR would be bumped up one severity level even without the critical files.

  4. Protocol Addition: Adding v2 gossip support is a protocol-level change that affects how channel policies are stored, validated, and propagated across the network. This requires expert review to ensure:

    • Backward compatibility with v1 gossip
    • Correct SQL schema changes and data migrations
    • Proper handling in the gossip protocol and routing logic
    • No edge cases in policy storage/retrieval

Recommendation: This PR requires thorough review by engineers familiar with the gossip protocol, graph database architecture, and core server coordination logic.


To override, add a severity-override-{critical,high,medium,low} label.

@saubyk saubyk added this to v0.21 Feb 3, 2026
@saubyk saubyk moved this to In progress in v0.21 Feb 3, 2026
@ellemouton
Copy link
Collaborator Author

@claude review this

@claude
Copy link

claude bot commented Feb 4, 2026

Claude encountered an error —— View job

Command failed: git fetch origin --depth=20 g175-db-6

I'll analyze this and get back to you.

Extend channel policy queries and structs to support v2-specific fields:

- Add BlockHeight field to track the block height for v2 policy updates.
- Add DisableFlags field for v2 channel disable messages.

Both fields are nullable (sql.NullInt64/Int16) to maintain backwards
compatibility with v1 channels. The fields are initialized as null in
updateChanEdgePolicy and threaded through all policy-related queries
(GetChannelBySCIDWithPolicies, ListChannelsByNodeID, UpsertEdgePolicy,
etc.) and the extractChannelPolicies helper.

This commit includes both the hand-written SQL query updates and the
corresponding sqlc-generated Go code.
@lightninglabs-deploy
Copy link
Collaborator

🔴 PR Severity: CRITICAL

PR #10542 by @ellemouton | 30 files | 1,682 lines changed

🔴 Critical (2 files)
  • server.go - Core server coordination with v2 gossip integration
  • rpcserver.go - Core RPC server modifications for channel policy queries
🟠 High (11 files)
  • discovery/gossiper.go - Gossip protocol changes for v2 channel policies
  • graph/builder.go - Network graph builder modifications
  • graph/db/graph.go - Core graph database operations with v2 policy support
  • graph/db/graph_cache.go - Graph caching layer updates
  • graph/db/interfaces.go - Graph database interface changes
  • graph/db/kv_store.go - Key-value storage for graph data
  • graph/db/models/cached_edge_policy.go - Cached edge policy model changes
  • graph/db/models/channel_edge_policy.go - Channel edge policy model with v2 support (93 additions)
  • graph/db/reject_cache.go - Reject cache implementation updates
  • graph/db/sql_store.go - SQL storage implementation (347 additions, significant refactoring)
  • routing/unified_edges.go - Unified edges for routing
🟡 Medium (3 files)
  • sqldb/sqlc/queries/graph.sql - SQL query definitions for graph operations
  • routing/localchans/manager.go - Local channel manager integration
  • docs/release-notes/release-notes-0.21.0.md - Release notes update
🟢 Low/Test (14 files)

Test files and auto-generated code (excluded from severity calculation)

Analysis

This PR adds v2 gossip support for channel policies, which is a substantial architectural change touching critical infrastructure:

Critical Concerns:

  1. Core Server Integration: Changes to server.go and rpcserver.go affect the main coordination and RPC serving logic
  2. Graph Database Refactoring: Extensive modifications to the graph database layer (sql_store.go with 347 additions) that handles channel policy persistence
  3. Wire Format Changes: Introduction of v2 channel policy support affects how the node stores and retrieves channel policies from the database

Risk Factors:

  • The PR touches the core graph database abstraction layer, which is used throughout the routing and gossip subsystems
  • Changes span multiple critical packages: graph/db, discovery, routing, and server coordination
  • Large line count in graph/db/sql_store.go (347 additions) suggests significant refactoring of database operations
  • Database schema and query changes in SQL layer could affect data integrity

Recommendation:
This PR requires expert review from maintainers familiar with:

  • The graph database architecture and SQL store implementation
  • The gossip protocol and channel policy announcement handling
  • Database migration patterns and backward compatibility considerations

The changes appear well-structured based on the affected files, but the scope and depth warrant careful scrutiny given the critical nature of channel policy storage and retrieval.


To override, add a severity-override-{critical,high,medium,low} label.

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.
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.
Add ChanEdgePolicyFromWire helper function that constructs a ChannelEdgePolicy from a channel update message (v1 or v2), centralizing version-specific field mapping.

Update call sites that previously constructed ChannelEdgePolicy manually from channel update messages to use the new helper:

- discovery/gossiper: handleChanUpdate

- graph/builder: ApplyChannelUpdate

This refactoring consolidates update-to-policy conversion logic and ensures consistent handling across gossip protocol versions.
Update buildChanPolicy and related functions in both KV and SQL stores
to properly construct ChannelEdgePolicy with version-specific fields:

KVStore changes:
- Reject non-v1 policies in updateEdgePolicy and serializeChanEdgePolicy
  since KV store only supports v1 gossip protocol.
- Set Version to GossipVersion1 when deserializing policies from KV.

SQLStore changes:
- Add isNode1 parameter to buildChanPolicy functions to properly set
  SecondPeer field (v2 uses SecondPeer instead of ChannelFlags direction).
- Extract Version from database and populate version-specific fields:
  - For v1: MessageFlags, ChannelFlags, LastUpdate, ExtraOpaqueData
  - For v2: DisableFlags, LastBlockHeight, ExtraSignedFields
- Thread isNode1 through buildChanPolicyWithBatchData and
  buildCachedChanPolicies call sites.

This enables the SQL store to read and reconstruct both v1 and v2
channel policies from the database with proper field mapping.
Update test helper functions and comparison logic to support both v1
and v2 channel edge policies:

- Extend newEdgePolicy to accept version and isNode1 parameters and
  populate version-specific fields:
  - For v1: LastUpdate, MessageFlags, ChannelFlags, ExtraOpaqueData
  - For v2: LastBlockHeight, SecondPeer, DisableFlags, ExtraSignedFields
- Update copyEdgePolicy to copy all v2 fields
- Make compareEdgePolicies version-aware:
  - Check Version field first
  - For v2: compare LastBlockHeight, SecondPeer, DisableFlags, ExtraSignedFields
  - For v1: compare LastUpdate, MessageFlags, ChannelFlags, ExtraOpaqueData
- Update all newEdgePolicy call sites to pass version and isNode1

This enables tests to create and compare both v1 and v2 channel policies
correctly without hard-coding version assumptions.
Add a new HasChannelEdge method that takes a gossip version parameter
and returns only existence and zombie status, without timestamp data.
This supports both v1 and v2 gossip protocols.

The original HasChannelEdge method is renamed to HasV1ChannelEdge to
preserve v1-specific functionality for callers that need timestamp
information. All call sites are updated accordingly.

The SQL store implementation now handles both gossip versions, using
timestamps for v1 and block heights for v2 policies, with proper
reject cache support for both versions.
Update ForEachChannel to accept a gossip version parameter, allowing
callers to specify which gossip version's channels should be iterated.
This change prepares the graph database for supporting multiple gossip
versions while maintaining backward compatibility.

The KVStore implementation validates that only GossipVersion1 is
requested, returning ErrVersionNotSupportedForKVDB for other versions.
The SQLStore implementation validates known versions and passes the
version through to the underlying paginated query.

Update VersionedGraph to include a ForEachChannel method that
automatically uses its configured gossip version, and update the
DescribeGraph RPC handler to use the v1Graph instead of the global
graphDB.
Regenerate sqlc code from graph.sql queries.
Update the UpsertChannelPolicy query to apply different staleness
checks based on gossip version. For v1 policies, continue checking
last_update timestamps. For v2 policies, check block_height instead,
using >= comparison to handle policies from the same block.

The version-specific WHERE clause ensures that policy updates are only
applied when they contain newer information according to the versioning
scheme appropriate for that gossip version.
Convert testEdgePolicyCRUD to a versioned test that runs against both
v1 and v2 gossip versions. Update the test to use version-specific
edge creation helpers and to test version-specific fields and flag
behavior (ChannelFlags/MessageFlags for v1, DisableFlags/
ExtraSignedFields for v2).

Add equalExtraSignedFields helper to properly compare extra signed
fields maps, treating empty and nil maps as equivalent.
Convert testIncompleteChannelPolicies to a versioned test that runs
against both v1 and v2 gossip versions. Update the test to use
version-specific edge creation and VersionedGraph for channel iteration.

Refactor the test to use require assertions instead of t.Fatalf for
consistency with project conventions, and simplify the policy checking
logic with require.Equal comparisons.

Add a helper function newTestEdgePolicy to create properly versioned
edge policies with correct direction indicators (ChannelFlags for v1,
implicitly via isNode1 parameter for v2). This ensures policies are
created with version-appropriate field values.
Update ForEachNodeChannel to accept a gossip version parameter,
allowing callers to specify which gossip version's channels should be
iterated. This change mirrors the approach taken in ForEachChannel and
prepares the graph database for supporting multiple gossip versions
while maintaining backward compatibility.

The Store interface is updated to include the version parameter, and
both KVStore and SQLStore implementations are updated accordingly:

- KVStore validates that only GossipVersion1 is requested, returning
  ErrVersionNotSupportedForKVDB for other versions.
- SQLStore passes the version through to the underlying node query,
  enabling version-specific channel iteration.

The ChannelGraph wrapper is updated to accept and pass through the
version parameter. VersionedGraph gains a ForEachNodeChannel method
that automatically uses its configured gossip version, providing a
clean interface for version-specific operations.

Update all call sites to explicitly pass lnwire.GossipVersion1, except
for the local channel manager in server.go which now uses the v1Graph
directly (matching the pattern used in other parts of the codebase).
@lightninglabs-deploy
Copy link
Collaborator

🔴 PR Severity: CRITICAL

Base: HIGH | 30 files | 1684 lines changed | Bumped due to: >20 files + substantial graph database changes

🟠 High (11 files)
  • graph/db/sql_store.go - SQL store for graph data (347 additions, 96 deletions) - major refactoring for v2 gossip support
  • graph/db/models/channel_edge_policy.go - Channel policy models (93 additions) - new v2 policy structures
  • graph/db/graph.go - Network graph database operations (42 additions) - core graph data handling
  • graph/db/kv_store.go - Key-value store for graph data (59 additions) - storage layer changes
  • graph/db/reject_cache.go - Reject cache logic (87 additions) - cache management for rejected updates
  • graph/db/interfaces.go - Graph database interfaces (18 additions) - interface modifications
  • graph/db/models/cached_edge_policy.go - Cached policy models (29 additions)
  • graph/builder.go - Graph builder coordination (16 additions)
  • discovery/gossiper.go - Gossip protocol handling (6 additions, 13 deletions)
  • sqldb/sqlc/graph.sql.go - Auto-generated SQL code (138 additions)
  • sqldb/sqlc/queries/graph.sql - SQL queries for graph (62 additions)
🟡 Medium (2 files)
  • server.go - Core server coordination (2 additions, 1 deletion) - minor integration changes
  • rpcserver.go - RPC server (5 additions, 4 deletions) - minor integration changes
🟢 Low (17 files)

Test files and documentation:

  • autopilot/prefattach_test.go
  • graph/builder_test.go
  • graph/db/benchmark_test.go
  • graph/db/graph_cache_test.go
  • graph/db/graph_test.go
  • graph/db/reject_cache_test.go
  • graph/notifications_test.go
  • lnrpc/invoicesrpc/addinvoice_test.go
  • netann/chan_status_manager_test.go
  • routing/localchans/manager_test.go
  • routing/pathfind_test.go
  • routing/router_test.go
  • routing/unified_edges_test.go
  • routing/unified_edges.go (3 additions, minor)
  • routing/localchans/manager.go (1 addition, minor)
  • graph/db/graph_cache.go (6 additions, minor)
  • docs/release-notes/release-notes-0.21.0.md

Analysis

This PR adds v2 gossip support for channel policies, involving substantial changes to the graph database layer. While the individual files are classified as HIGH severity (graph/, discovery/, sqldb/*), the PR meets multiple criteria for bumping to CRITICAL:

  1. Scope: 30 total files changed (>20 file threshold)
  2. Complexity: Significant refactoring of graph database storage with ~700 non-test/non-generated lines changed
  3. Core Infrastructure: Changes affect how channel policies are stored and retrieved, which is fundamental to routing decisions
  4. Multi-layer Impact: Touches SQL storage, KV storage, caching layers, and gossip protocol handling

Key Concerns:

  • The sql_store.go changes (347 additions) represent major restructuring of graph data persistence
  • New v2 policy structures in channel_edge_policy.go (93 additions) alter core data models
  • Changes span storage backends (SQL + KV), cache layers, and network protocol handling
  • Network graph integrity is critical for routing; bugs could lead to payment failures or incorrect pathfinding

Recommendation: This PR requires expert review from someone deeply familiar with lnd's graph database architecture, gossip protocol implementation, and the v2 gossip specification.


To override, add a severity-override-{critical,high,medium,low} label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

2 participants