multi: further decouple graph

To further separate the channel graph from the channel state, we
refactor the AddrsForNode method to use the graphs's public methods
instead of directly accessing any buckets. This makes sure that we can
have the channel state cached with just its buckets while not using a
kvdb level cache for the graph.
At the same time we refactor the graph's test to also be less dependent
upon the channel state DB.
This commit is contained in:
Oliver Gugger committed 2021-09-29 17:00:03 +02:00
1 parent 11cf4216e4
commit d6fa912188
10 files changed
+254 -214

No files matched your search

+1 -1
View File
@@ -85,7 +85,7 @@ func (g *dbRoutingTx) sourceNode() route.Vertex {
func (g *dbRoutingTx) fetchNodeFeatures(nodePub route.Vertex) (
*lnwire.FeatureVector, error) {
targetNode, err := g.graph.FetchLightningNode(g.tx, nodePub)
targetNode, err := g.graph.FetchLightningNode(nodePub)
switch err {
// If the node exists and has features, return them directly.
+37 -23
View File
@@ -23,6 +23,7 @@ import (
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
@@ -148,26 +149,36 @@ type testChan struct {
// makeTestGraph creates a new instance of a channeldb.ChannelGraph for testing
// purposes. A callback which cleans up the created temporary directories is
// also returned and intended to be executed after the test completes.
func makeTestGraph() (*channeldb.ChannelGraph, func(), error) {
func makeTestGraph() (*channeldb.ChannelGraph, kvdb.Backend, func(), error) {
// First, create a temporary directory to be used for the duration of
// this test.
tempDirName, err := ioutil.TempDir("", "channeldb")
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
// Next, create channeldb for the first time.
cdb, err := channeldb.Open(tempDirName)
// Next, create channelgraph for the first time.
backend, backendCleanup, err := kvdb.GetTestBackend(tempDirName, "cgr")
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
cleanUp := func() {
cdb.Close()
os.RemoveAll(tempDirName)
backendCleanup()
_ = os.RemoveAll(tempDirName)
}
return cdb.ChannelGraph(), cleanUp, nil
opts := channeldb.DefaultOptions()
graph, err := channeldb.NewChannelGraph(
backend, opts.RejectCacheSize, opts.ChannelCacheSize,
opts.BatchCommitInterval,
)
if err != nil {
cleanUp()
return nil, nil, nil, err
}
return graph, backend, cleanUp, nil
}
// parseTestGraph returns a fully populated ChannelGraph given a path to a JSON
@@ -197,7 +208,7 @@ func parseTestGraph(path string) (*testGraphInstance, error) {
testAddrs = append(testAddrs, testAddr)
// Next, create a temporary graph database for usage within the test.
graph, cleanUp, err := makeTestGraph()
graph, graphBackend, cleanUp, err := makeTestGraph()
if err != nil {
return nil, err
}
@@ -381,11 +392,12 @@ func parseTestGraph(path string) (*testGraphInstance, error) {
}
return &testGraphInstance{
graph: graph,
cleanUp: cleanUp,
aliasMap: aliasMap,
privKeyMap: privKeyMap,
channelIDs: channelIDs,
graph: graph,
graphBackend: graphBackend,
cleanUp: cleanUp,
aliasMap: aliasMap,
privKeyMap: privKeyMap,
channelIDs: channelIDs,
}, nil
}
@@ -447,8 +459,9 @@ type testChannel struct {
}
type testGraphInstance struct {
graph *channeldb.ChannelGraph
cleanUp func()
graph *channeldb.ChannelGraph
graphBackend kvdb.Backend
cleanUp func()
// aliasMap is a map from a node's alias to its public key. This type is
// provided in order to allow easily look up from the human memorable alias
@@ -482,7 +495,7 @@ func createTestGraphFromChannels(testChannels []*testChannel, source string) (
testAddrs = append(testAddrs, testAddr)
// Next, create a temporary graph database for usage within the test.
graph, cleanUp, err := makeTestGraph()
graph, graphBackend, cleanUp, err := makeTestGraph()
if err != nil {
return nil, err
}
@@ -671,10 +684,11 @@ func createTestGraphFromChannels(testChannels []*testChannel, source string) (
}
return &testGraphInstance{
graph: graph,
cleanUp: cleanUp,
aliasMap: aliasMap,
privKeyMap: privKeyMap,
graph: graph,
graphBackend: graphBackend,
cleanUp: cleanUp,
aliasMap: aliasMap,
privKeyMap: privKeyMap,
}, nil
}
@@ -2120,7 +2134,7 @@ func TestPathFindSpecExample(t *testing.T) {
// Carol, so we set "B" as the source node so path finding starts from
// Bob.
bob := ctx.aliases["B"]
bobNode, err := ctx.graph.FetchLightningNode(nil, bob)
bobNode, err := ctx.graph.FetchLightningNode(bob)
if err != nil {
t.Fatalf("unable to find bob: %v", err)
}
@@ -2170,7 +2184,7 @@ func TestPathFindSpecExample(t *testing.T) {
// Next, we'll set A as the source node so we can assert that we create
// the proper route for any queries starting with Alice.
alice := ctx.aliases["A"]
aliceNode, err := ctx.graph.FetchLightningNode(nil, alice)
aliceNode, err := ctx.graph.FetchLightningNode(alice)
if err != nil {
t.Fatalf("unable to find alice: %v", err)
}
+4 -2
View File
@@ -2505,8 +2505,10 @@ func (r *ChannelRouter) GetChannelByID(chanID lnwire.ShortChannelID) (
// within the graph.
//
// NOTE: This method is part of the ChannelGraphSource interface.
func (r *ChannelRouter) FetchLightningNode(node route.Vertex) (*channeldb.LightningNode, error) {
return r.cfg.Graph.FetchLightningNode(nil, node)
func (r *ChannelRouter) FetchLightningNode(
node route.Vertex) (*channeldb.LightningNode, error) {
return r.cfg.Graph.FetchLightningNode(node)
}
// ForEachNode is used to iterate over every node in router topology.
+8 -16
View File
@@ -125,8 +125,7 @@ func createTestCtxFromGraphInstanceAssumeValid(t *testing.T,
}
mc, err := NewMissionControl(
graphInstance.graph.Database(), route.Vertex{},
mcConfig,
graphInstance.graphBackend, route.Vertex{}, mcConfig,
)
require.NoError(t, err, "failed to create missioncontrol")
@@ -188,7 +187,6 @@ func createTestCtxFromGraphInstanceAssumeValid(t *testing.T,
cleanUp := func() {
ctx.router.Stop()
graphInstance.cleanUp()
}
return ctx, cleanUp
@@ -197,17 +195,10 @@ func createTestCtxFromGraphInstanceAssumeValid(t *testing.T,
func createTestCtxSingleNode(t *testing.T,
startingHeight uint32) (*testCtx, func()) {
var (
graph *channeldb.ChannelGraph
sourceNode *channeldb.LightningNode
cleanup func()
err error
)
graph, cleanup, err = makeTestGraph()
graph, graphBackend, cleanup, err := makeTestGraph()
require.NoError(t, err, "failed to make test graph")
sourceNode, err = createTestNode()
sourceNode, err := createTestNode()
require.NoError(t, err, "failed to create test node")
require.NoError(t,
@@ -215,8 +206,9 @@ func createTestCtxSingleNode(t *testing.T,
)
graphInstance := &testGraphInstance{
graph: graph,
cleanUp: cleanup,
graph: graph,
graphBackend: graphBackend,
cleanUp: cleanup,
}
return createTestCtxFromGraphInstance(
@@ -1577,7 +1569,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
t.Fatalf("unable to find any routes: %v", err)
}
copy1, err := ctx.graph.FetchLightningNode(nil, pub1)
copy1, err := ctx.graph.FetchLightningNode(pub1)
if err != nil {
t.Fatalf("unable to fetch node: %v", err)
}
@@ -1586,7 +1578,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
t.Fatalf("fetched node not equal to original")
}
copy2, err := ctx.graph.FetchLightningNode(nil, pub2)
copy2, err := ctx.graph.FetchLightningNode(pub2)
if err != nil {
t.Fatalf("unable to fetch node: %v", err)
}