graph/db: version ForEachSourceNodeChannel
Add a gossip version parameter to ForEachSourceNodeChannel in the Store interface and both KV/SQL implementations. The VersionedGraph wrapper delegates with its baked-in version. Convert the testAddChannelEdgeShellNodes and testForEachSourceNodeChannel tests to run against both v1 and v2 gossip versions.
This commit is contained in:
6 files changed
+85
-59
No files matched your search
+8
-8
@@ -587,14 +587,6 @@ func (c *ChannelGraph) UpdateEdgePolicy(ctx context.Context,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEachSourceNodeChannel iterates through all channels of the source node.
|
|
||||||
func (c *ChannelGraph) ForEachSourceNodeChannel(ctx context.Context,
|
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
|
||||||
otherNode *models.Node) error, reset func()) error {
|
|
||||||
|
|
||||||
return c.db.ForEachSourceNodeChannel(ctx, cb, reset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForEachNodeChannel iterates through all channels of the given node.
|
// ForEachNodeChannel iterates through all channels of the given node.
|
||||||
func (c *ChannelGraph) ForEachNodeChannel(ctx context.Context,
|
func (c *ChannelGraph) ForEachNodeChannel(ctx context.Context,
|
||||||
v lnwire.GossipVersion, nodePub route.Vertex,
|
v lnwire.GossipVersion, nodePub route.Vertex,
|
||||||
@@ -906,6 +898,14 @@ func (c *VersionedGraph) HasChannelEdge(chanID uint64) (bool, bool, error) {
|
|||||||
return c.db.HasChannelEdge(c.v, chanID)
|
return c.db.HasChannelEdge(c.v, chanID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForEachSourceNodeChannel iterates through all channels of the source node.
|
||||||
|
func (c *VersionedGraph) ForEachSourceNodeChannel(ctx context.Context,
|
||||||
|
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
||||||
|
otherNode *models.Node) error, reset func()) error {
|
||||||
|
|
||||||
|
return c.db.ForEachSourceNodeChannel(ctx, c.v, cb, reset)
|
||||||
|
}
|
||||||
|
|
||||||
// ForEachNodeChannel iterates through all channels of the given node.
|
// ForEachNodeChannel iterates through all channels of the given node.
|
||||||
func (c *VersionedGraph) ForEachNodeChannel(ctx context.Context,
|
func (c *VersionedGraph) ForEachNodeChannel(ctx context.Context,
|
||||||
nodePub route.Vertex, cb func(*models.ChannelEdgeInfo,
|
nodePub route.Vertex, cb func(*models.ChannelEdgeInfo,
|
||||||
|
|||||||
+57
-38
@@ -154,6 +154,14 @@ var versionedTests = []versionedTest{
|
|||||||
name: "incomplete channel policies",
|
name: "incomplete channel policies",
|
||||||
test: testIncompleteChannelPolicies,
|
test: testIncompleteChannelPolicies,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "add channel edge shell nodes",
|
||||||
|
test: testAddChannelEdgeShellNodes,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "for each source node channel",
|
||||||
|
test: testForEachSourceNodeChannel,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "partial node",
|
name: "partial node",
|
||||||
test: testPartialNode,
|
test: testPartialNode,
|
||||||
@@ -1605,16 +1613,16 @@ func testAddEdgeProof(t *testing.T, v lnwire.GossipVersion) {
|
|||||||
require.NotNil(t, dbEdge2.AuthProof)
|
require.NotNil(t, dbEdge2.AuthProof)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestForEachSourceNodeChannel tests that the ForEachSourceNodeChannel
|
// testForEachSourceNodeChannel tests that the ForEachSourceNodeChannel
|
||||||
// correctly iterates through the channels of the set source node.
|
// correctly iterates through the channels of the set source node.
|
||||||
func TestForEachSourceNodeChannel(t *testing.T) {
|
func testForEachSourceNodeChannel(t *testing.T, v lnwire.GossipVersion) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
ctx := t.Context()
|
ctx := t.Context()
|
||||||
|
|
||||||
graph := MakeTestGraph(t)
|
graph := NewVersionedGraph(MakeTestGraph(t), v)
|
||||||
|
|
||||||
// Create a source node (A) and set it as such in the DB.
|
// Create a source node (A) and set it as such in the DB.
|
||||||
nodeA := createTestVertex(t, lnwire.GossipVersion1)
|
nodeA := createTestVertex(t, v)
|
||||||
require.NoError(t, graph.SetSourceNode(ctx, nodeA))
|
require.NoError(t, graph.SetSourceNode(ctx, nodeA))
|
||||||
|
|
||||||
// Now, create a few more nodes (B, C, D) along with some channels
|
// Now, create a few more nodes (B, C, D) along with some channels
|
||||||
@@ -1630,32 +1638,40 @@ func TestForEachSourceNodeChannel(t *testing.T) {
|
|||||||
// outgoing policy but for the A-C channel, we will set only an incoming
|
// outgoing policy but for the A-C channel, we will set only an incoming
|
||||||
// policy.
|
// policy.
|
||||||
|
|
||||||
nodeB := createTestVertex(t, lnwire.GossipVersion1)
|
nodeB := createTestVertex(t, v)
|
||||||
nodeC := createTestVertex(t, lnwire.GossipVersion1)
|
nodeC := createTestVertex(t, v)
|
||||||
nodeD := createTestVertex(t, lnwire.GossipVersion1)
|
nodeD := createTestVertex(t, v)
|
||||||
|
|
||||||
abEdge, abPolicy1, abPolicy2 := createChannelEdge(nodeA, nodeB)
|
abEdge, _ := createEdge(v, 100, 0, 0, 0, nodeA, nodeB)
|
||||||
require.NoError(t, graph.AddChannelEdge(ctx, abEdge))
|
require.NoError(t, graph.AddChannelEdge(ctx, abEdge))
|
||||||
acEdge, acPolicy1, acPolicy2 := createChannelEdge(nodeA, nodeC)
|
acEdge, _ := createEdge(v, 200, 0, 0, 1, nodeA, nodeC)
|
||||||
require.NoError(t, graph.AddChannelEdge(ctx, acEdge))
|
require.NoError(t, graph.AddChannelEdge(ctx, acEdge))
|
||||||
bdEdge, _, _ := createChannelEdge(nodeB, nodeD)
|
bdEdge, _ := createEdge(v, 300, 0, 0, 2, nodeB, nodeD)
|
||||||
require.NoError(t, graph.AddChannelEdge(ctx, bdEdge))
|
require.NoError(t, graph.AddChannelEdge(ctx, bdEdge))
|
||||||
|
|
||||||
// Figure out which of the policies returned above are node A's so that
|
newPolicy := func(edge *models.ChannelEdgeInfo, fromNode,
|
||||||
// we know which to persist.
|
toNode route.Vertex) *models.ChannelEdgePolicy {
|
||||||
//
|
|
||||||
// First, set the outgoing policy for the A-B channel.
|
isNode1 := bytes.Equal(fromNode[:], edge.NodeKey1Bytes[:])
|
||||||
abPolicyAOutgoing := abPolicy1
|
policy := newEdgePolicy(
|
||||||
if !bytes.Equal(abPolicy1.ToNode[:], nodeB.PubKeyBytes[:]) {
|
v, edge.ChannelID, nextUpdateTime().Unix(), isNode1,
|
||||||
abPolicyAOutgoing = abPolicy2
|
)
|
||||||
|
policy.ToNode = toNode
|
||||||
|
policy.SigBytes = testSig.Serialize()
|
||||||
|
|
||||||
|
return policy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First, set the outgoing policy for the A-B channel.
|
||||||
|
abPolicyAOutgoing := newPolicy(
|
||||||
|
abEdge, nodeA.PubKeyBytes, nodeB.PubKeyBytes,
|
||||||
|
)
|
||||||
require.NoError(t, graph.UpdateEdgePolicy(ctx, abPolicyAOutgoing))
|
require.NoError(t, graph.UpdateEdgePolicy(ctx, abPolicyAOutgoing))
|
||||||
|
|
||||||
// Now, set the incoming policy for the A-C channel.
|
// Now, set the incoming policy for the A-C channel.
|
||||||
acPolicyAIncoming := acPolicy1
|
acPolicyAIncoming := newPolicy(
|
||||||
if !bytes.Equal(acPolicy1.ToNode[:], nodeA.PubKeyBytes[:]) {
|
acEdge, nodeC.PubKeyBytes, nodeA.PubKeyBytes,
|
||||||
acPolicyAIncoming = acPolicy2
|
)
|
||||||
}
|
|
||||||
require.NoError(t, graph.UpdateEdgePolicy(ctx, acPolicyAIncoming))
|
require.NoError(t, graph.UpdateEdgePolicy(ctx, acPolicyAIncoming))
|
||||||
|
|
||||||
type sourceNodeChan struct {
|
type sourceNodeChan struct {
|
||||||
@@ -1677,21 +1693,24 @@ func TestForEachSourceNodeChannel(t *testing.T) {
|
|||||||
|
|
||||||
// Now, we'll use the ForEachSourceNodeChannel and assert that it
|
// Now, we'll use the ForEachSourceNodeChannel and assert that it
|
||||||
// returns the expected data in the call-back.
|
// returns the expected data in the call-back.
|
||||||
err := graph.ForEachSourceNodeChannel(ctx, func(chanPoint wire.OutPoint,
|
err := graph.ForEachSourceNodeChannel(
|
||||||
havePolicy bool, otherNode *models.Node) error {
|
ctx, func(chanPoint wire.OutPoint, havePolicy bool,
|
||||||
|
otherNode *models.Node) error {
|
||||||
|
|
||||||
require.Contains(t, expectedSrcChans, chanPoint)
|
require.Contains(t, expectedSrcChans, chanPoint)
|
||||||
expected := expectedSrcChans[chanPoint]
|
expected := expectedSrcChans[chanPoint]
|
||||||
|
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t, expected.otherNode[:], otherNode.PubKeyBytes[:],
|
t, expected.otherNode[:],
|
||||||
)
|
otherNode.PubKeyBytes[:],
|
||||||
require.Equal(t, expected.havePolicy, havePolicy)
|
)
|
||||||
|
require.Equal(t, expected.havePolicy, havePolicy)
|
||||||
|
|
||||||
delete(expectedSrcChans, chanPoint)
|
delete(expectedSrcChans, chanPoint)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, func() {})
|
}, func() {},
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Empty(t, expectedSrcChans)
|
require.Empty(t, expectedSrcChans)
|
||||||
}
|
}
|
||||||
@@ -4106,25 +4125,25 @@ func TestPruneGraphNodes(t *testing.T) {
|
|||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestAddChannelEdgeShellNodes tests that when we attempt to add a ChannelEdge
|
// testAddChannelEdgeShellNodes tests that when we attempt to add a ChannelEdge
|
||||||
// to the graph, one or both of the nodes the edge involves aren't found in the
|
// to the graph, one or both of the nodes the edge involves aren't found in the
|
||||||
// database, then shell edges are created for each node if needed.
|
// database, then shell edges are created for each node if needed.
|
||||||
func TestAddChannelEdgeShellNodes(t *testing.T) {
|
func testAddChannelEdgeShellNodes(t *testing.T, v lnwire.GossipVersion) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
ctx := t.Context()
|
ctx := t.Context()
|
||||||
|
|
||||||
graph := NewVersionedGraph(MakeTestGraph(t), lnwire.GossipVersion1)
|
graph := NewVersionedGraph(MakeTestGraph(t), v)
|
||||||
|
|
||||||
// To start, we'll create two nodes, and only add one of them to the
|
// To start, we'll create two nodes, and only add one of them to the
|
||||||
// channel graph.
|
// channel graph.
|
||||||
node1 := createTestVertex(t, lnwire.GossipVersion1)
|
node1 := createTestVertex(t, v)
|
||||||
require.NoError(t, graph.SetSourceNode(ctx, node1))
|
require.NoError(t, graph.SetSourceNode(ctx, node1))
|
||||||
node2 := createTestVertex(t, lnwire.GossipVersion1)
|
node2 := createTestVertex(t, v)
|
||||||
|
|
||||||
// We'll now create an edge between the two nodes, as a result, node2
|
// We'll now create an edge between the two nodes, as a result, node2
|
||||||
// should be inserted into the database as a shell node.
|
// should be inserted into the database as a shell node.
|
||||||
edgeInfo, _ := createEdge(
|
edgeInfo, _ := createEdge(
|
||||||
lnwire.GossipVersion1, 100, 0, 0, 0, node1, node2,
|
v, 100, 0, 0, 0, node1, node2,
|
||||||
)
|
)
|
||||||
require.NoError(t, graph.AddChannelEdge(ctx, edgeInfo))
|
require.NoError(t, graph.AddChannelEdge(ctx, edgeInfo))
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ type Store interface { //nolint:interfacebloat
|
|||||||
// node, executing the passed callback on each. The call-back is
|
// node, executing the passed callback on each. The call-back is
|
||||||
// provided with the channel's outpoint, whether we have a policy for
|
// provided with the channel's outpoint, whether we have a policy for
|
||||||
// the channel and the channel peer's node information.
|
// the channel and the channel peer's node information.
|
||||||
ForEachSourceNodeChannel(ctx context.Context,
|
ForEachSourceNodeChannel(ctx context.Context, v lnwire.GossipVersion,
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
||||||
otherNode *models.Node) error,
|
otherNode *models.Node) error,
|
||||||
reset func()) error
|
reset func()) error
|
||||||
|
|||||||
@@ -3722,8 +3722,13 @@ func (c *KVStore) ForEachNodeChannel(_ context.Context,
|
|||||||
// channel's outpoint, whether we have a policy for the channel and the channel
|
// channel's outpoint, whether we have a policy for the channel and the channel
|
||||||
// peer's node information.
|
// peer's node information.
|
||||||
func (c *KVStore) ForEachSourceNodeChannel(_ context.Context,
|
func (c *KVStore) ForEachSourceNodeChannel(_ context.Context,
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
v lnwire.GossipVersion, cb func(chanPoint wire.OutPoint,
|
||||||
otherNode *models.Node) error, reset func()) error {
|
havePolicy bool, otherNode *models.Node) error,
|
||||||
|
reset func()) error {
|
||||||
|
|
||||||
|
if v != lnwire.GossipVersion1 {
|
||||||
|
return ErrVersionNotSupportedForKVDB
|
||||||
|
}
|
||||||
|
|
||||||
return kvdb.View(c.db, func(tx kvdb.RTx) error {
|
return kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||||
nodes := tx.ReadBucket(nodeBucket)
|
nodes := tx.ReadBucket(nodeBucket)
|
||||||
|
|||||||
@@ -902,20 +902,19 @@ func (s *SQLStore) updateEdgeCache(e *models.ChannelEdgePolicy,
|
|||||||
//
|
//
|
||||||
// NOTE: part of the Store interface.
|
// NOTE: part of the Store interface.
|
||||||
func (s *SQLStore) ForEachSourceNodeChannel(ctx context.Context,
|
func (s *SQLStore) ForEachSourceNodeChannel(ctx context.Context,
|
||||||
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
v lnwire.GossipVersion, cb func(chanPoint wire.OutPoint,
|
||||||
otherNode *models.Node) error, reset func()) error {
|
havePolicy bool, otherNode *models.Node) error,
|
||||||
|
reset func()) error {
|
||||||
|
|
||||||
return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
|
||||||
nodeID, nodePub, err := s.getSourceNode(
|
nodeID, nodePub, err := s.getSourceNode(ctx, db, v)
|
||||||
ctx, db, lnwire.GossipVersion1,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch source node: %w",
|
return fmt.Errorf("unable to fetch source node: %w",
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return forEachNodeChannel(
|
return forEachNodeChannel(
|
||||||
ctx, db, s.cfg, lnwire.GossipVersion1, nodeID,
|
ctx, db, s.cfg, v, nodeID,
|
||||||
func(info *models.ChannelEdgeInfo,
|
func(info *models.ChannelEdgeInfo,
|
||||||
outPolicy *models.ChannelEdgePolicy,
|
outPolicy *models.ChannelEdgePolicy,
|
||||||
_ *models.ChannelEdgePolicy) error {
|
_ *models.ChannelEdgePolicy) error {
|
||||||
@@ -937,8 +936,8 @@ func (s *SQLStore) ForEachSourceNodeChannel(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, otherNode, err := getNodeByPubKey(
|
_, otherNode, err := getNodeByPubKey(
|
||||||
ctx, s.cfg.QueryCfg, db,
|
ctx, s.cfg.QueryCfg, db, v,
|
||||||
lnwire.GossipVersion1, otherNodePub,
|
otherNodePub,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch "+
|
return fmt.Errorf("unable to fetch "+
|
||||||
|
|||||||
@@ -1128,7 +1128,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
|||||||
DefaultRoutingPolicy: cc.RoutingPolicy,
|
DefaultRoutingPolicy: cc.RoutingPolicy,
|
||||||
ForAllOutgoingChannels: func(ctx context.Context,
|
ForAllOutgoingChannels: func(ctx context.Context,
|
||||||
cb func(*models.ChannelEdgeInfo,
|
cb func(*models.ChannelEdgeInfo,
|
||||||
*models.ChannelEdgePolicy) error,
|
*models.ChannelEdgePolicy) error,
|
||||||
reset func()) error {
|
reset func()) error {
|
||||||
|
|
||||||
return s.v1Graph.ForEachNodeChannel(
|
return s.v1Graph.ForEachNodeChannel(
|
||||||
@@ -3576,7 +3576,10 @@ func (s *server) establishPersistentConnections(ctx context.Context) error {
|
|||||||
graphAddrs[pubStr] = n
|
graphAddrs[pubStr] = n
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err = s.graphDB.ForEachSourceNodeChannel(
|
|
||||||
|
// TODO(elle): for now, we only fetch our V1 channels. This should be
|
||||||
|
// updated to fetch channels across all versions.
|
||||||
|
err = s.v1Graph.ForEachSourceNodeChannel(
|
||||||
ctx, forEachSrcNodeChan, func() {
|
ctx, forEachSrcNodeChan, func() {
|
||||||
clear(graphAddrs)
|
clear(graphAddrs)
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in new issue
Block a user