graph/db+sqldb: impl IsPublicNode

Which lets us run `TestNodeIsPublic` against our SQL DB backends.
Note that we need to tweak the tests a little bit so that
`AddLightningNode` for the same node is always called with a newer
LastUpdate time else it will fail the SQL constraint that only allows
the upsert if the update is newer than the persisted one.
This commit is contained in:
Elle Mouton committed 2025-06-24 21:04:36 +02:00
1 parent acae165f0a
commit f1da3812de
5 files changed
+90 -9

No files matched your search

+21 -9
View File
@@ -73,13 +73,11 @@ var (
)
func createLightningNode(priv *btcec.PrivateKey) *models.LightningNode {
updateTime := prand.Int63()
pub := priv.PubKey().SerializeCompressed()
n := &models.LightningNode{
HaveNodeAnnouncement: true,
AuthSigBytes: testSig.Serialize(),
LastUpdate: time.Unix(updateTime, 0),
LastUpdate: time.Unix(nextUpdateTime(), 0),
Color: color.RGBA{1, 2, 3, 0},
Alias: "kek" + hex.EncodeToString(pub),
Features: testFeatures,
@@ -3439,6 +3437,20 @@ func TestNodePruningUpdateIndexDeletion(t *testing.T) {
}
}
var (
updateTime = prand.Int63()
updateTimeMu sync.Mutex
)
func nextUpdateTime() int64 {
updateTimeMu.Lock()
defer updateTimeMu.Unlock()
updateTime++
return updateTime
}
// TestNodeIsPublic ensures that we properly detect nodes that are seen as
// public within the network graph.
func TestNodeIsPublic(t *testing.T) {
@@ -3453,19 +3465,19 @@ func TestNodeIsPublic(t *testing.T) {
// We'll need to create a separate database and channel graph for each
// participant to replicate real-world scenarios (private edges being in
// some graphs but not others, etc.).
aliceGraph := MakeTestGraph(t)
aliceGraph := MakeTestGraphNew(t)
aliceNode := createTestVertex(t)
if err := aliceGraph.SetSourceNode(ctx, aliceNode); err != nil {
t.Fatalf("unable to set source node: %v", err)
}
bobGraph := MakeTestGraph(t)
bobGraph := MakeTestGraphNew(t)
bobNode := createTestVertex(t)
if err := bobGraph.SetSourceNode(ctx, bobNode); err != nil {
t.Fatalf("unable to set source node: %v", err)
}
carolGraph := MakeTestGraph(t)
carolGraph := MakeTestGraphNew(t)
carolNode := createTestVertex(t)
if err := carolGraph.SetSourceNode(ctx, carolNode); err != nil {
t.Fatalf("unable to set source node: %v", err)
@@ -3481,13 +3493,13 @@ func TestNodeIsPublic(t *testing.T) {
graphs := []*ChannelGraph{aliceGraph, bobGraph, carolGraph}
for _, graph := range graphs {
for _, node := range nodes {
node.LastUpdate = time.Unix(nextUpdateTime(), 0)
err := graph.AddLightningNode(ctx, node)
require.NoError(t, err)
}
for _, edge := range edges {
if err := graph.AddChannelEdge(ctx, edge); err != nil {
t.Fatalf("unable to add edge: %v", err)
}
err := graph.AddChannelEdge(ctx, edge)
require.NoError(t, err)
}
}
+24
View File
@@ -62,6 +62,7 @@ type SQLQueries interface {
GetNodesByLastUpdateRange(ctx context.Context, arg sqlc.GetNodesByLastUpdateRangeParams) ([]sqlc.Node, error)
ListNodesPaginated(ctx context.Context, arg sqlc.ListNodesPaginatedParams) ([]sqlc.Node, error)
ListNodeIDsAndPubKeys(ctx context.Context, arg sqlc.ListNodeIDsAndPubKeysParams) ([]sqlc.ListNodeIDsAndPubKeysRow, error)
IsPublicV1Node(ctx context.Context, pubKey []byte) (bool, error)
DeleteNodeByPubKey(ctx context.Context, arg sqlc.DeleteNodeByPubKeyParams) (sql.Result, error)
GetExtraNodeTypes(ctx context.Context, nodeID int64) ([]sqlc.NodeExtraType, error)
@@ -1990,6 +1991,29 @@ func (s *SQLStore) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
return channelID, nil
}
// IsPublicNode is a helper method that determines whether the node with the
// given public key is seen as a public node in the graph from the graph's
// source node's point of view.
//
// NOTE: part of the V1Store interface.
func (s *SQLStore) IsPublicNode(pubKey [33]byte) (bool, error) {
ctx := context.TODO()
var isPublic bool
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
var err error
isPublic, err = db.IsPublicV1Node(ctx, pubKey[:])
return err
}, sqldb.NoOpReset)
if err != nil {
return false, fmt.Errorf("unable to check if node is "+
"public: %w", err)
}
return isPublic, nil
}
// FetchChanInfos returns the set of channel edges that correspond to the passed
// channel ID's. If an edge is the query is unknown to the database, it will
// skipped and the result will contain only those edges that exist at the time