graph/db: cross-version graph Store#10656
graph/db: cross-version graph Store#10656ellemouton wants to merge 12 commits intolightningnetwork:masterfrom
Conversation
|
Warning Gemini encountered an error creating the summary. You can try again by commenting |
5337e61 to
cbe9436
Compare
f6937d1 to
fe7a97b
Compare
6a07ff9 to
d455707
Compare
bitromortac
left a comment
There was a problem hiding this comment.
Nice work, cool to see that both versions are used as a source 🎉 (have a few nits that optionally could be fixed)
| // GetVersions for a non-existent SCID should return empty. | ||
| versions, err = store.GetVersionsBySCID(ctx, 999999) | ||
| require.NoError(t, err) | ||
| require.Empty(t, versions) |
There was a problem hiding this comment.
we could add a test for the v2 channel
graph/db/sql_store.go
Outdated
| if !exists { | ||
| entry = &nodeEntry{} | ||
| nodesByPub[pub] = entry | ||
| order = append(order, pub) |
There was a problem hiding this comment.
Memory-wise this is not a huge regression because the sql db anyhow fetches all the rows at once?
There was a problem hiding this comment.
Addressed by replacing the whole-graph materialization with paginated preferred-row traversal. The SQL side now pages over distinct logical keys and streams one preferred node/channel at a time.
graph/db/graph_test.go
Outdated
| require.False(t, features.IsEmpty(), | ||
| "both-version node should have features") |
There was a problem hiding this comment.
nit: we could make the test more strict by changing one of the feature vectors and compare against it
There was a problem hiding this comment.
Done. The test now assigns distinct v1/v2 feature vectors and asserts that the v2 feature vector is the one returned
d455707 to
4620278
Compare
|
Made two main follow-up changes after review:
That keeps the prefer-highest cross-version behavior, but avoids whole-graph collection in memory on large SQL-backed networks. |
Add version-aware range types for channel and node update horizon queries. V1 gossip uses unix timestamps for ordering while v2 uses block heights, so each range type validates that the correct bound type is provided for the requested gossip version. These types will be used in follow-up commits to version the NodeUpdatesInHorizon and ChanUpdatesInHorizon Store methods.
Replace the (startTime, endTime time.Time) parameters on NodeUpdatesInHorizon and ChanUpdatesInHorizon with (v GossipVersion, r NodeUpdateRange/ChanUpdateRange). The range types enforce version-correct bounds at the type level: v1 uses unix timestamps, v2 uses block heights. The KV store rejects non-v1 versions since it only stores v1 data. The SQL store handles v1 queries; v2 block-height range queries are added in the following commits. VersionedGraph wrappers supply the version from the embedded field, so callers only pass the range.
Add the SQL indexes needed by the new v2 horizon sync paths: - graph_nodes(version, block_height, pub_key) - graph_channel_policies(version, block_height, channel_id) - graph_channel_policies(version, last_update, channel_id) These support the block-height node horizon scan and the policy-driven channel horizon scans without degrading to broad table scans. The index changes are added directly to migration 9 because no released version contains that migration yet, so it is still safe to edit it in place.
Add SQL queries for v2 node and channel horizon lookups that use block heights instead of unix timestamps. For channels, also reshape the horizon query so it starts from matching policy rows and then hydrates the candidate channels, which keeps the work proportional to the matching update set rather than the full graph. Regenerate sqlc for the new query surface.
Hook the new v2 block-height horizon queries into the SQL store's NodeUpdatesInHorizon and ChanUpdatesInHorizon implementations. This replaces the temporary "not yet implemented" SQL v2 horizon paths, adds the block-height pagination cursor handling needed for channels, and covers the end-to-end behavior with SQL backend tests.
Add a gossip version parameter to FilterKnownChanIDs on the Store interface so that it can filter channel IDs for the correct gossip version. The KV store rejects non-v1 versions. Move the zombie-revival logic from ChannelGraph into VersionedGraph so that FilterKnownChanIDs is only exposed on VersionedGraph (which supplies the version from its embedded field). This means callers no longer need to pass a version explicitly.
4620278 to
c3c0e14
Compare
Add four new Store interface methods: - FetchChannelEdgesByIDPreferHighest: version-agnostic channel lookup that returns the highest available gossip version. - FetchChannelEdgesByOutpointPreferHighest: same but keyed by outpoint. - GetVersionsBySCID: returns which gossip versions exist for a SCID. - GetVersionsByOutpoint: same but keyed by outpoint. The KV store implementations delegate to v1 since that's the only version it supports. The SQL store implementations iterate over versions from highest to lowest (for PreferHighest) or lowest to highest (for GetVersions). These will be used in follow-up commits to make ChannelGraph callers version-agnostic.
Add dedicated SQL pagination queries for cross-version graph traversal so SQL backends can stream one logical node or channel at a time without loading and merging both gossip versions in memory. ListPreferredNodesPaginated first pages over distinct pubkeys across the v1 and v2 node tables. For each pubkey it then picks exactly one stored row in this order: v2 with a signature, v1 with a signature, bare v2, then bare v1. That keeps traversal on the highest usable version while still falling back when the preferred row is missing auth data. ListPreferredChannelsWithPoliciesPaginated does the same for channel SCIDs. It first pages over distinct SCIDs across both channel versions, then selects one channel row per SCID in this order: v2 with at least one matching-version policy, v1 with at least one matching-version policy, bare v2, then bare v1. This avoids a higher-version channel without policy data hiding a lower-version channel that is actually usable for traversal. Regenerate sqlc for the new query surface.
Change the graph traversal entry points to return one logical node or channel across all stored gossip versions instead of forcing callers to iterate a single version at a time. For SQL backends, ForEachNode now uses the prefer-highest node query and returns one row per pubkey, preferring the highest announced version and falling back to the highest-version shell node when no signed announcement exists. ForEachChannel now uses the prefer-highest channel query and returns one row per SCID, preferring the highest version with matching policy data and otherwise falling back to the highest stored channel row. Update the ChannelGraph and VersionedGraph wrappers to use the new version-agnostic store methods, keep the KV implementation on its v1-only behavior, and cover the SQL no-cache traversal paths with dedicated prefer-highest tests.
…rappers Switch FetchChannelEdgesByID and FetchChannelEdgesByOutpoint on ChannelGraph to use the PreferHighest store variants so that callers get the highest available gossip version without needing to specify one. Also add GetVersionsBySCID and GetVersionsByOutpoint convenience wrappers on ChannelGraph that delegate to the corresponding Store methods.
Update ForEachNodeDirectedChannel and FetchNodeFeatures on ChannelGraph to iterate across all gossip versions (highest first) instead of hardcoding v1. This ensures that channels announced via v2 are preferred over v1 and that v2 features are used when available.
c3c0e14 to
1ef529b
Compare
Summary
Make the graph
Storeinterface cross-version so that query methods workacross gossip v1 and v2, enabling callers to interact with the graph without
needing to know which gossip version announced a given node or channel.
This is part of the Gossip 1.75 epic.
Key changes
Version-aware horizon queries:
NodeUpdatesInHorizonandChanUpdatesInHorizonnow take a gossip version and a typed range(
NodeUpdateRange/ChanUpdateRange) that enforces v1=timestamps vsv2=block-heights at the type level. Full SQL implementations for both
versions.
Cross-version iteration:
ForEachNodeandForEachChanneliterateacross all gossip versions, yielding each unique node/channel exactly once
(highest version preferred).
PreferHighest fetch helpers:
FetchChannelEdgesByIDPreferHighest,FetchChannelEdgesByOutpointPreferHighestreturn the highest availablegossip version for a channel without the caller specifying one.
GetVersions queries:
GetVersionsBySCIDandGetVersionsByOutpointreport which gossip versions exist for a given channel.
Version-aware FilterKnownChanIDs: Now takes a gossip version parameter.
Zombie-revival logic moved from
ChannelGraphintoVersionedGraphsocallers through that type don't need to pass a version explicitly.
Prefer-highest node traversal:
ForEachNodeDirectedChannelandFetchNodeFeaturesonChannelGraphiterate across all versions (v2first), so pathfinding prefers v2-announced channels and features.