From 2c083bc0172465f5e3cbaebd1796dc746364aad1 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Tue, 22 Oct 2024 14:35:37 +0200 Subject: [PATCH] multi: let chan and graph db implement AddrSource Then use both to construct a multiAddrSource AddrSource and use that around the code-base. --- channeldb/db.go | 61 ++++++++------------------------------------ channeldb/db_test.go | 32 +++++++++++------------ graph/db/graph.go | 26 +++++++++++++++++++ server.go | 6 +++-- 4 files changed, 55 insertions(+), 70 deletions(-) diff --git a/channeldb/db.go b/channeldb/db.go index ef6e899a4..09cb61ea5 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -34,7 +34,6 @@ import ( "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/routing/route" ) const ( @@ -1343,64 +1342,24 @@ func (c *ChannelStateDB) RestoreChannelShells(channelShells ...*ChannelShell) er return nil } -// AddrsForNode consults the graph and channel database for all addresses known -// to the passed node public key. +// AddrsForNode consults the channel database for all addresses known to the +// passed node public key. The returned boolean indicates if the given node is +// unknown to the channel DB or not. +// +// NOTE: this is part of the AddrSource interface. func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error) { - var ( - // addrs holds the collection of deduplicated addresses we know - // of for the node. - addrs = make(map[string]net.Addr) - - // known keeps track of if any of the backing sources know of - // this node. - known bool - ) - - // First, query the channel DB for its known addresses. linkNode, err := d.channelStateDB.linkNodeDB.FetchLinkNode(nodePub) + // Only if the error is something other than ErrNodeNotFound do we + // return it. switch { - // If we get back a ErrNodeNotFound error, then this just means that the - // channel DB does not know of the error, but we don't error out here - // because we still want to check the graph db. case err != nil && !errors.Is(err, ErrNodeNotFound): return false, nil, err - // A nil error means the node is known. - case err == nil: - known = true - for _, addr := range linkNode.Addresses { - addrs[addr.String()] = addr - } + case errors.Is(err, ErrNodeNotFound): + return false, nil, nil } - // We'll also query the graph for this peer to see if they have any - // addresses that we don't currently have stored within the link node - // database. - pubKey, err := route.NewVertexFromBytes(nodePub.SerializeCompressed()) - if err != nil { - return false, nil, err - } - graphNode, err := d.graph.FetchLightningNode(pubKey) - switch { - // We don't consider it an error if the graph is unaware of the node. - case err != nil && !errors.Is(err, graphdb.ErrGraphNodeNotFound): - return false, nil, err - - // If we do find the node, we add its addresses to our deduplicated set. - case err == nil: - known = true - for _, addr := range graphNode.Addresses { - addrs[addr.String()] = addr - } - } - - // Convert the deduplicated set into a list. - dedupedAddrs := make([]net.Addr, 0, len(addrs)) - for _, addr := range addrs { - dedupedAddrs = append(dedupedAddrs, addr) - } - - return known, dedupedAddrs, nil + return true, linkNode.Addresses, nil } // AbandonChannel attempts to remove the target channel from the open channel diff --git a/channeldb/db_test.go b/channeldb/db_test.go index 6717058ce..bc7e3809c 100644 --- a/channeldb/db_test.go +++ b/channeldb/db_test.go @@ -185,9 +185,10 @@ func TestFetchClosedChannelForID(t *testing.T) { } } -// TestAddrsForNode tests the we're able to properly obtain all the addresses -// for a target node. -func TestAddrsForNode(t *testing.T) { +// TestMultiSourceAddrsForNode tests the we're able to properly obtain all the +// addresses for a target node from multiple backends - in this case, the +// channel db and graph db. +func TestMultiSourceAddrsForNode(t *testing.T) { t.Parallel() fullDB, err := MakeTestDB(t) @@ -201,9 +202,7 @@ func TestAddrsForNode(t *testing.T) { testNode := createTestVertex(t) require.NoError(t, err, "unable to create test node") testNode.Addresses = []net.Addr{testAddr} - if err := graph.SetSourceNode(testNode); err != nil { - t.Fatalf("unable to set source node: %v", err) - } + require.NoError(t, graph.SetSourceNode(testNode)) // Next, we'll make a link node with the same pubkey, but with an // additional address. @@ -213,28 +212,27 @@ func TestAddrsForNode(t *testing.T) { fullDB.channelStateDB.linkNodeDB, wire.MainNet, nodePub, anotherAddr, ) - if err := linkNode.Sync(); err != nil { - t.Fatalf("unable to sync link node: %v", err) - } + require.NoError(t, linkNode.Sync()) + + // Create a multi-backend address source from the channel db and graph + // db. + addrSource := NewMultiAddrSource(fullDB, graph) // Now that we've created a link node, as well as a vertex for the // node, we'll query for all its addresses. - _, nodeAddrs, err := fullDB.AddrsForNode(nodePub) + known, nodeAddrs, err := addrSource.AddrsForNode(nodePub) require.NoError(t, err, "unable to obtain node addrs") + require.True(t, known) expectedAddrs := make(map[string]struct{}) expectedAddrs[testAddr.String()] = struct{}{} expectedAddrs[anotherAddr.String()] = struct{}{} // Finally, ensure that all the expected addresses are found. - if len(nodeAddrs) != len(expectedAddrs) { - t.Fatalf("expected %v addrs, got %v", - len(expectedAddrs), len(nodeAddrs)) - } + require.Len(t, nodeAddrs, len(expectedAddrs)) + for _, addr := range nodeAddrs { - if _, ok := expectedAddrs[addr.String()]; !ok { - t.Fatalf("unexpected addr: %v", addr) - } + require.Contains(t, expectedAddrs, addr.String()) } } diff --git a/graph/db/graph.go b/graph/db/graph.go index a4c0a2017..b7c4671a3 100644 --- a/graph/db/graph.go +++ b/graph/db/graph.go @@ -414,6 +414,32 @@ func (c *ChannelGraph) NewPathFindTx() (kvdb.RTx, error) { return c.db.BeginReadTx() } +// AddrsForNode returns all known addresses for the target node public key that +// the graph DB is aware of. The returned boolean indicates if the given node is +// unknown to the graph DB or not. +// +// NOTE: this is part of the channeldb.AddrSource interface. +func (c *ChannelGraph) AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, + error) { + + pubKey, err := route.NewVertexFromBytes(nodePub.SerializeCompressed()) + if err != nil { + return false, nil, err + } + + node, err := c.FetchLightningNode(pubKey) + // We don't consider it an error if the graph is unaware of the node. + switch { + case err != nil && !errors.Is(err, ErrGraphNodeNotFound): + return false, nil, err + + case errors.Is(err, ErrGraphNodeNotFound): + return false, nil, nil + } + + return true, node.Addresses, nil +} + // ForEachChannel iterates through all the channel edges stored within the // graph and invokes the passed callback for each edge. The callback takes two // edges as since this is a directed graph, both the in/out edges are visited. diff --git a/server.go b/server.go index 70b7d68f8..d441624b6 100644 --- a/server.go +++ b/server.go @@ -607,12 +607,14 @@ func newServer(cfg *Config, listenAddrs []net.Addr, HtlcInterceptor: invoiceHtlcModifier, } + addrSource := channeldb.NewMultiAddrSource(dbs.ChanStateDB, dbs.GraphDB) + s := &server{ cfg: cfg, implCfg: implCfg, graphDB: dbs.GraphDB.ChannelGraph(), chanStateDB: dbs.ChanStateDB.ChannelStateDB(), - addrSource: dbs.ChanStateDB, + addrSource: addrSource, miscDB: dbs.ChanStateDB, invoicesDB: dbs.InvoiceDB, cc: cc, @@ -1629,7 +1631,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, // static backup of the latest channel state. chanNotifier := &channelNotifier{ chanNotifier: s.channelNotifier, - addrs: dbs.ChanStateDB, + addrs: s.addrSource, } backupFile := chanbackup.NewMultiFile(cfg.BackupFilePath) startingChans, err := chanbackup.FetchStaticChanBackups(