From ba6222b52188d75aa2d13dee7f752bb630aae258 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 19 Nov 2025 12:20:21 +0200 Subject: [PATCH] multi: add and use V1 constructor for models.ChannelEdgeInfo This makes it clear what fields must/can be set for a V1 channel. Introduce NewV1Channel constructor to create v1 channel edges with proper initialization and validation. The constructor: - Takes required fields (chanID, chainHash, node keys) as parameters - Takes v1-specific fields (bitcoin keys, extra opaque data) via ChannelV1Fields struct - Accepts optional fields (capacity, channel point, features, proof) via functional options (WithCapacity, WithChannelPoint, etc.) - Validates that if an AuthProof is provided, its version matches the channel version This makes it clear which fields are required vs optional for v1 channels and prevents incorrectly initialized channel edges. All tests and production code updated to use the constructor. --- autopilot/prefattach_test.go | 23 +- discovery/gossiper.go | 33 ++- discovery/gossiper_test.go | 14 +- graph/builder_test.go | 340 +++++++++++++-------------- graph/db/channel_cache_test.go | 15 +- graph/db/graph_test.go | 310 ++++++++++++++---------- graph/db/kv_store.go | 11 +- graph/db/models/channel_edge_info.go | 93 ++++++++ graph/db/sql_store.go | 55 +++-- graph/notifications_test.go | 155 ++++++------ lnrpc/devrpc/dev_server.go | 23 +- lnrpc/invoicesrpc/addinvoice_test.go | 16 +- netann/chan_status_manager_test.go | 21 +- netann/channel_announcement_test.go | 28 +-- routing/localchans/manager.go | 41 +++- routing/localchans/manager_test.go | 145 +++++++----- routing/pathfind_test.go | 66 +++--- routing/router_test.go | 39 ++- 18 files changed, 853 insertions(+), 575 deletions(-) diff --git a/autopilot/prefattach_test.go b/autopilot/prefattach_test.go index a4026d73d..30ec7ffc6 100644 --- a/autopilot/prefattach_test.go +++ b/autopilot/prefattach_test.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" graphdb "github.com/lightningnetwork/lnd/graph/db" "github.com/lightningnetwork/lnd/graph/db/models" "github.com/lightningnetwork/lnd/lnwire" @@ -492,16 +493,20 @@ func (d *testDBGraph) addRandChannel(node1, node2 *btcec.PublicKey, } chanID := randChanID() - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - Capacity: capacity, - Features: lnwire.EmptyFeatureVector(), + nodeKey1 := route.NewVertex(lnNode1) + nodeKey2 := route.NewVertex(lnNode2) + btcKey1 := route.NewVertex(lnNode1) + btcKey2 := route.NewVertex(lnNode2) + edge, err := models.NewV1Channel( + chanID.ToUint64(), chainhash.Hash{}, nodeKey1, nodeKey2, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithCapacity(capacity), + ) + if err != nil { + return nil, nil, err } - copy(edge.NodeKey1Bytes[:], lnNode1.SerializeCompressed()) - copy(edge.NodeKey2Bytes[:], lnNode2.SerializeCompressed()) - copy(edge.BitcoinKey1Bytes[:], lnNode1.SerializeCompressed()) - copy(edge.BitcoinKey2Bytes[:], lnNode2.SerializeCompressed()) if err := d.db.AddChannelEdge(ctx, edge); err != nil { return nil, nil, err diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 2cbd4e873..b26435c56 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -2818,19 +2818,26 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, // With the proof validated (if necessary), we can now store it within // the database for our path finding and syncing needs. - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: scid.ToUint64(), - ChainHash: ann.ChainHash, - NodeKey1Bytes: ann.NodeID1, - NodeKey2Bytes: ann.NodeID2, - BitcoinKey1Bytes: ann.BitcoinKey1, - BitcoinKey2Bytes: ann.BitcoinKey2, - AuthProof: proof, - Features: lnwire.NewFeatureVector( - ann.Features, lnwire.Features, - ), - ExtraOpaqueData: ann.ExtraOpaqueData, + edge, err := models.NewV1Channel( + scid.ToUint64(), ann.ChainHash, ann.NodeID1, ann.NodeID2, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: ann.BitcoinKey1, + BitcoinKey2Bytes: ann.BitcoinKey2, + ExtraOpaqueData: ann.ExtraOpaqueData, + }, + models.WithChanProof(proof), models.WithFeatures(ann.Features), + ) + if err != nil { + key := newRejectCacheKey( + ann.GossipVersion(), + scid.ToUint64(), + sourceToPub(nMsg.source), + ) + _, _ = d.recentRejects.Put(key, &cachedReject{}) + + log.Errorf("unable to create channel edge: %v", err) + nMsg.err <- err + return nil, false } // If there were any optional message fields provided, we'll include diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index efb7307da..b1231b0e3 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -272,11 +272,15 @@ func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) ( return nil, nil, nil, graphdb.ErrEdgeNotFound } - return &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - NodeKey1Bytes: pubKeys[0], - NodeKey2Bytes: pubKeys[1], - }, nil, nil, graphdb.ErrZombieEdge + zombieEdge, err := models.NewV1Channel( + 0, chainhash.Hash{}, pubKeys[0], pubKeys[1], + &models.ChannelV1Fields{}, + ) + if err != nil { + return nil, nil, nil, err + } + + return zombieEdge, nil, nil, graphdb.ErrZombieEdge } edges := r.edges[chanID.ToUint64()] diff --git a/graph/builder_test.go b/graph/builder_test.go index f2648a002..25b2d28b1 100644 --- a/graph/builder_test.go +++ b/graph/builder_test.go @@ -17,10 +17,10 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" - "github.com/lightningnetwork/lnd/fn/v2" graphdb "github.com/lightningnetwork/lnd/graph/db" "github.com/lightningnetwork/lnd/graph/db/models" "github.com/lightningnetwork/lnd/htlcswitch" @@ -65,18 +65,17 @@ func TestAddProof(t *testing.T) { ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) // After utxo was recreated adding the edge without the proof. - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: nil, - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some(script), - } - copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1 := route.NewVertex(bitcoinKey1) + btcKey2 := route.NewVertex(bitcoinKey2) + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + node1.PubKeyBytes, node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithFundingScript(script), + ) + require.NoError(t, err) require.NoError(t, ctx.builder.AddEdge(ctxb, edge)) // Now we'll attempt to update the proof and check that it has been @@ -152,17 +151,20 @@ func TestIgnoreChannelEdgePolicyForUnknownChannel(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: pub1, - NodeKey2Bytes: pub2, - BitcoinKey1Bytes: pub1, - BitcoinKey2Bytes: pub2, - AuthProof: nil, - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some(script), - } + pub1Vertex, err := route.NewVertexFromBytes(pub1[:]) + require.NoError(t, err) + pub2Vertex, err := route.NewVertexFromBytes(pub2[:]) + require.NoError(t, err) + + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + pub1Vertex, pub2Vertex, &models.ChannelV1Fields{ + BitcoinKey1Bytes: pub1Vertex, + BitcoinKey2Bytes: pub2Vertex, + }, models.WithFundingScript(script), + ) + require.NoError(t, err) + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, @@ -274,43 +276,42 @@ func TestWakeUpOnStaleBranch(t *testing.T) { node1 := createTestNode(t) node2 := createTestNode(t) - edge1 := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID1, - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some(fundingScript1), - } - copy(edge1.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge1.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1, err := route.NewVertexFromBytes( + bitcoinKey1.SerializeCompressed(), + ) + require.NoError(t, err) + btcKey2, err := route.NewVertexFromBytes( + bitcoinKey2.SerializeCompressed(), + ) + require.NoError(t, err) + + edge1, err := models.NewV1Channel( + chanID1, *chaincfg.SimNetParams.GenesisHash, + node1.PubKeyBytes, node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(models.NewV1ChannelAuthProof( + testSig.Serialize(), testSig.Serialize(), + testSig.Serialize(), testSig.Serialize(), + )), models.WithFundingScript(fundingScript1), + ) + require.NoError(t, err) if err := ctx.builder.AddEdge(ctxb, edge1); err != nil { t.Fatalf("unable to add edge: %v", err) } - edge2 := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID2, - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some(fundingScript2), - } - copy(edge2.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge2.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + edge2, err := models.NewV1Channel( + chanID2, *chaincfg.SimNetParams.GenesisHash, node1.PubKeyBytes, + node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(models.NewV1ChannelAuthProof( + testSig.Serialize(), testSig.Serialize(), + testSig.Serialize(), testSig.Serialize(), + )), models.WithFundingScript(fundingScript2), + ) + require.NoError(t, err) if err := ctx.builder.AddEdge(ctxb, edge2); err != nil { t.Fatalf("unable to add edge: %v", err) @@ -486,47 +487,39 @@ func TestDisconnectedBlocks(t *testing.T) { node1 := createTestNode(t) node2 := createTestNode(t) - edge1 := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID1, - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - BitcoinKey1Bytes: node1.PubKeyBytes, - BitcoinKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some([]byte{}), - } - copy(edge1.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge1.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1 := route.NewVertex(bitcoinKey1) + btcKey2 := route.NewVertex(bitcoinKey2) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edge1, err := models.NewV1Channel( + chanID1, *chaincfg.SimNetParams.GenesisHash, node1.PubKeyBytes, + node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(proof), + models.WithFundingScript([]byte{}), + ) + require.NoError(t, err) if err := ctx.builder.AddEdge(ctxb, edge1); err != nil { t.Fatalf("unable to add edge: %v", err) } - edge2 := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID2, - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - BitcoinKey1Bytes: node1.PubKeyBytes, - BitcoinKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some([]byte{}), - } - copy(edge2.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge2.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + edge2, err := models.NewV1Channel( + chanID2, *chaincfg.SimNetParams.GenesisHash, node1.PubKeyBytes, + node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(proof), + models.WithFundingScript([]byte{}), + ) + require.NoError(t, err) if err := ctx.builder.AddEdge(ctxb, edge2); err != nil { t.Fatalf("unable to add edge: %v", err) @@ -644,24 +637,28 @@ func TestChansClosedOfflinePruneGraph(t *testing.T) { node1 := createTestNode(t) node2 := createTestNode(t) - edge1 := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID1.ToUint64(), - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - ChannelPoint: *chanUTXO, - Capacity: chanValue, - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some(script), - } - copy(edge1.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge1.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1 := route.NewVertex(bitcoinKey1) + btcKey2 := route.NewVertex(bitcoinKey2) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edge1, err := models.NewV1Channel( + chanID1.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + node1.PubKeyBytes, node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(proof), + models.WithCapacity(chanValue), + models.WithChannelPoint(*chanUTXO), + models.WithFundingScript(script), + ) + require.NoError(t, err) + if err := ctx.builder.AddEdge(ctxb, edge1); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -1068,17 +1065,15 @@ func TestIsStaleNode(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: pub1, - NodeKey2Bytes: pub2, - BitcoinKey1Bytes: pub1, - BitcoinKey2Bytes: pub2, - AuthProof: nil, - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some(script), - } + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + pub1, pub2, &models.ChannelV1Fields{ + BitcoinKey1Bytes: pub1, + BitcoinKey2Bytes: pub2, + }, models.WithFundingScript(script), + ) + require.NoError(t, err) + if err := ctx.builder.AddEdge(ctxb, edge); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -1149,17 +1144,16 @@ func TestIsKnownEdge(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: pub1, - NodeKey2Bytes: pub2, - BitcoinKey1Bytes: pub1, - BitcoinKey2Bytes: pub2, - AuthProof: nil, - FundingScript: fn.Some(script), - Features: lnwire.EmptyFeatureVector(), - } + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, pub1, + pub2, &models.ChannelV1Fields{ + BitcoinKey1Bytes: pub1, + BitcoinKey2Bytes: pub2, + }, + models.WithFundingScript(script), + ) + require.NoError(t, err) + if err := ctx.builder.AddEdge(ctxb, edge); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -1210,17 +1204,15 @@ func TestIsStaleEdgePolicy(t *testing.T) { t.Fatalf("router failed to detect fresh edge policy") } - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: pub1, - NodeKey2Bytes: pub2, - BitcoinKey1Bytes: pub1, - BitcoinKey2Bytes: pub2, - AuthProof: nil, - Features: lnwire.EmptyFeatureVector(), - FundingScript: fn.Some(script), - } + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, pub1, + pub2, &models.ChannelV1Fields{ + BitcoinKey1Bytes: pub1, + BitcoinKey2Bytes: pub2, + }, models.WithFundingScript(script), + ) + require.NoError(t, err) + if err := ctx.builder.AddEdge(ctxb, edge); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -1523,19 +1515,27 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: edge.ChannelID, - AuthProof: &testAuthProof, - ChannelPoint: fundingPoint, - Capacity: btcutil.Amount(edge.Capacity), - Features: lnwire.EmptyFeatureVector(), - } + var node1Vertex, node2Vertex route.Vertex + copy(node1Vertex[:], node1Bytes) + copy(node2Vertex[:], node2Bytes) - copy(edgeInfo.NodeKey1Bytes[:], node1Bytes) - copy(edgeInfo.NodeKey2Bytes[:], node2Bytes) - copy(edgeInfo.BitcoinKey1Bytes[:], node1Bytes) - copy(edgeInfo.BitcoinKey2Bytes[:], node2Bytes) + var btcKey1, btcKey2 route.Vertex + copy(btcKey1[:], node1Bytes) + copy(btcKey2[:], node2Bytes) + + edgeInfo, err := models.NewV1Channel( + edge.ChannelID, *chaincfg.SimNetParams.GenesisHash, + node1Vertex, node2Vertex, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, + models.WithChanProof(&testAuthProof), + models.WithChannelPoint(fundingPoint), + models.WithCapacity(btcutil.Amount(edge.Capacity)), + ) + if err != nil { + return nil, err + } shortID := lnwire.NewShortChanIDFromInt(edge.ChannelID) links[shortID] = &mockLink{ @@ -1544,7 +1544,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( ), } - err = graph.AddChannelEdge(ctx, &edgeInfo) + err = graph.AddChannelEdge(ctx, edgeInfo) if err != nil && !errors.Is(err, graphdb.ErrEdgeAlreadyExist) { return nil, err } @@ -1584,12 +1584,12 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( } // We also store the channel IDs info for each of the node. - node1Vertex, err := route.NewVertexFromBytes(node1Bytes) + node1Vertex, err = route.NewVertexFromBytes(node1Bytes) if err != nil { return nil, err } - node2Vertex, err := route.NewVertexFromBytes(node2Bytes) + node2Vertex, err = route.NewVertexFromBytes(node2Bytes) if err != nil { return nil, err } @@ -1895,21 +1895,21 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: channelID, - AuthProof: &testAuthProof, - ChannelPoint: *fundingPoint, - Capacity: testChannel.Capacity, - - NodeKey1Bytes: node1Vertex, - BitcoinKey1Bytes: node1Vertex, - NodeKey2Bytes: node2Vertex, - BitcoinKey2Bytes: node2Vertex, - Features: lnwire.EmptyFeatureVector(), + edgeInfo, err := models.NewV1Channel( + channelID, *chaincfg.SimNetParams.GenesisHash, + node1Vertex, node2Vertex, &models.ChannelV1Fields{ + BitcoinKey1Bytes: node1Vertex, + BitcoinKey2Bytes: node2Vertex, + }, + models.WithChanProof(&testAuthProof), + models.WithChannelPoint(*fundingPoint), + models.WithCapacity(testChannel.Capacity), + ) + if err != nil { + return nil, err } - err = graph.AddChannelEdge(ctx, &edgeInfo) + err = graph.AddChannelEdge(ctx, edgeInfo) if err != nil && !errors.Is(err, graphdb.ErrEdgeAlreadyExist) { diff --git a/graph/db/channel_cache_test.go b/graph/db/channel_cache_test.go index 04f6d0331..27ff65432 100644 --- a/graph/db/channel_cache_test.go +++ b/graph/db/channel_cache_test.go @@ -4,8 +4,9 @@ import ( "reflect" "testing" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/lightningnetwork/lnd/graph/db/models" - "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" ) // TestChannelCache checks the behavior of the channelCache with respect to @@ -100,10 +101,14 @@ func assertHasChanEntries(t *testing.T, c *channelCache, start, end uint64) { // channelForInt generates a unique ChannelEdge given an integer. func channelForInt(i uint64) ChannelEdge { + info, err := models.NewV1Channel( + i, chainhash.Hash{}, route.Vertex{}, route.Vertex{}, + &models.ChannelV1Fields{}, + ) + if err != nil { + panic(err) + } return ChannelEdge{ - Info: &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: i, - }, + Info: info, } } diff --git a/graph/db/graph_test.go b/graph/db/graph_test.go index fcae25e8a..c9e703f4d 100644 --- a/graph/db/graph_test.go +++ b/graph/db/graph_test.go @@ -379,7 +379,7 @@ func TestPartialNode(t *testing.T) { // Create an edge attached to these nodes and add it to the graph. edgeInfo, _ := createEdge(140, 0, 0, 0, &node1, &node2) - require.NoError(t, graph.AddChannelEdge(ctx, &edgeInfo)) + require.NoError(t, graph.AddChannelEdge(ctx, edgeInfo)) // Both of the nodes should now be in both the graph (as partial/shell) // nodes _and_ the cache should also have an awareness of both nodes. @@ -562,31 +562,50 @@ func TestEdgeInsertionDeletion(t *testing.T) { require.NoError(t, err, "unable to generate node key") node2Pub, err := node2.PubKey() require.NoError(t, err, "unable to generate node key") - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID, - ChainHash: *chaincfg.MainNetParams.GenesisHash, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - ChannelPoint: outpoint, - Capacity: 9000, - } - copy(edgeInfo.NodeKey1Bytes[:], node1Pub.SerializeCompressed()) - copy(edgeInfo.NodeKey2Bytes[:], node2Pub.SerializeCompressed()) - copy(edgeInfo.BitcoinKey1Bytes[:], node1Pub.SerializeCompressed()) - copy(edgeInfo.BitcoinKey2Bytes[:], node2Pub.SerializeCompressed()) - require.NoError(t, graph.AddChannelEdge(ctx, &edgeInfo)) - assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo) + node1Vertex, err := route.NewVertexFromBytes( + node1Pub.SerializeCompressed(), + ) + require.NoError(t, err) + node2Vertex, err := route.NewVertexFromBytes( + node2Pub.SerializeCompressed(), + ) + require.NoError(t, err) + + btcKey1, err := route.NewVertexFromBytes( + node1Pub.SerializeCompressed(), + ) + require.NoError(t, err) + btcKey2, err := route.NewVertexFromBytes( + node2Pub.SerializeCompressed(), + ) + require.NoError(t, err) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edgeInfo, err := models.NewV1Channel( + chanID, *chaincfg.MainNetParams.GenesisHash, node1Vertex, + node2Vertex, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, + models.WithChanProof(proof), + models.WithChannelPoint(outpoint), + models.WithCapacity(9000), + ) + require.NoError(t, err) + + require.NoError(t, graph.AddChannelEdge(ctx, edgeInfo)) + assertEdgeWithNoPoliciesInCache(t, graph, edgeInfo) // Show that trying to insert the same channel again will return the // expected error. - err = graph.AddChannelEdge(ctx, &edgeInfo) + err = graph.AddChannelEdge(ctx, edgeInfo) require.ErrorIs(t, err, ErrEdgeAlreadyExist) // Ensure that both policies are returned as unknown (nil). @@ -623,7 +642,7 @@ func TestEdgeInsertionDeletion(t *testing.T) { } func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32, - node1, node2 *models.Node) (models.ChannelEdgeInfo, + node1, node2 *models.Node) (*models.ChannelEdgeInfo, lnwire.ShortChannelID) { shortChanID := lnwire.ShortChannelID{ @@ -638,26 +657,37 @@ func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32, node1Pub, _ := node1.PubKey() node2Pub, _ := node2.PubKey() - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: shortChanID.ToUint64(), - ChainHash: *chaincfg.MainNetParams.GenesisHash, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - ChannelPoint: outpoint, - Capacity: 9000, - ExtraOpaqueData: make([]byte, 0), - Features: lnwire.EmptyFeatureVector(), - } - copy(edgeInfo.NodeKey1Bytes[:], node1Pub.SerializeCompressed()) - copy(edgeInfo.NodeKey2Bytes[:], node2Pub.SerializeCompressed()) - copy(edgeInfo.BitcoinKey1Bytes[:], node1Pub.SerializeCompressed()) - copy(edgeInfo.BitcoinKey2Bytes[:], node2Pub.SerializeCompressed()) + node1Vertex, _ := route.NewVertexFromBytes( + node1Pub.SerializeCompressed(), + ) + node2Vertex, _ := route.NewVertexFromBytes( + node2Pub.SerializeCompressed(), + ) + btcKey1, _ := route.NewVertexFromBytes( + node1Pub.SerializeCompressed(), + ) + btcKey2, _ := route.NewVertexFromBytes( + node2Pub.SerializeCompressed(), + ) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edgeInfo, _ := models.NewV1Channel( + shortChanID.ToUint64(), *chaincfg.MainNetParams.GenesisHash, + node1Vertex, node2Vertex, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + ExtraOpaqueData: make([]byte, 0), + }, + models.WithChanProof(proof), models.WithChannelPoint(outpoint), + models.WithCapacity(9000), + ) return edgeInfo, shortChanID } @@ -716,20 +746,20 @@ func TestDisconnectBlockAtHeight(t *testing.T) { edgeInfo3, _ := createEdge(height-1, 0, 0, 2, node1, node2) // Now add all these new edges to the database. - if err := graph.AddChannelEdge(ctx, &edgeInfo); err != nil { + if err := graph.AddChannelEdge(ctx, edgeInfo); err != nil { t.Fatalf("unable to create channel edge: %v", err) } - if err := graph.AddChannelEdge(ctx, &edgeInfo2); err != nil { + if err := graph.AddChannelEdge(ctx, edgeInfo2); err != nil { t.Fatalf("unable to create channel edge: %v", err) } - if err := graph.AddChannelEdge(ctx, &edgeInfo3); err != nil { + if err := graph.AddChannelEdge(ctx, edgeInfo3); err != nil { t.Fatalf("unable to create channel edge: %v", err) } - assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo) - assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo2) - assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo3) + assertEdgeWithNoPoliciesInCache(t, graph, edgeInfo) + assertEdgeWithNoPoliciesInCache(t, graph, edgeInfo2) + assertEdgeWithNoPoliciesInCache(t, graph, edgeInfo3) // Call DisconnectBlockAtHeight, which should prune every channel // that has a funding height of 'height' or greater. @@ -739,7 +769,7 @@ func TestDisconnectBlockAtHeight(t *testing.T) { } assertNoEdge(t, graph, edgeInfo.ChannelID) assertNoEdge(t, graph, edgeInfo2.ChannelID) - assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo3) + assertEdgeWithNoPoliciesInCache(t, graph, edgeInfo3) // The two edges should have been removed. if len(removed) != 2 { @@ -898,35 +928,50 @@ func createChannelEdge(node1, node2 *models.Node, // Add the new edge to the database, this should proceed without any // errors. - edgeInfo := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID, - ChainHash: *chaincfg.MainNetParams.GenesisHash, - ChannelPoint: outpoint, - Capacity: 1000, - ExtraOpaqueData: []byte{ - 1, 1, 1, - 2, 2, 2, 2, - 3, 3, 3, 3, 3, - }, - Features: lnwire.EmptyFeatureVector(), - } - copy(edgeInfo.NodeKey1Bytes[:], firstNode[:]) - copy(edgeInfo.NodeKey2Bytes[:], secondNode[:]) - copy(edgeInfo.BitcoinKey1Bytes[:], firstNode[:]) - copy(edgeInfo.BitcoinKey2Bytes[:], secondNode[:]) + var node1Key, node2Key route.Vertex + copy(node1Key[:], firstNode[:]) + copy(node2Key[:], secondNode[:]) + extraData := []byte{ + 1, 1, 1, + 2, 2, 2, 2, + 3, 3, 3, 3, 3, + } + + var edgeInfo *models.ChannelEdgeInfo if opts.skipProofs { + edgeInfo, _ = models.NewV1Channel( + chanID, *chaincfg.MainNetParams.GenesisHash, node1Key, + node2Key, &models.ChannelV1Fields{ + BitcoinKey1Bytes: node1Key, + BitcoinKey2Bytes: node2Key, + ExtraOpaqueData: extraData, + }, models.WithChannelPoint(outpoint), + models.WithCapacity(1000), + ) + return edgeInfo, nil, nil } - edgeInfo.AuthProof = models.NewV1ChannelAuthProof( + proof := models.NewV1ChannelAuthProof( testSig.Serialize(), testSig.Serialize(), testSig.Serialize(), testSig.Serialize(), ) + edgeInfo, _ = models.NewV1Channel( + chanID, *chaincfg.MainNetParams.GenesisHash, node1Key, node2Key, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: node1Key, + BitcoinKey2Bytes: node2Key, + ExtraOpaqueData: extraData, + }, + models.WithChanProof(proof), + models.WithChannelPoint(outpoint), + models.WithCapacity(1000), + ) + edge1 := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: chanID, @@ -1780,25 +1825,29 @@ func fillTestGraph(t testing.TB, graph *ChannelGraph, numNodes, Index: 0, } - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID, - ChainHash: *chaincfg.MainNetParams.GenesisHash, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - ChannelPoint: op, - Capacity: 1000, - } - copy(edgeInfo.NodeKey1Bytes[:], node1.PubKeyBytes[:]) - copy(edgeInfo.NodeKey2Bytes[:], node2.PubKeyBytes[:]) - copy(edgeInfo.BitcoinKey1Bytes[:], node1.PubKeyBytes[:]) - copy(edgeInfo.BitcoinKey2Bytes[:], node2.PubKeyBytes[:]) - err := graph.AddChannelEdge(ctx, &edgeInfo) + var node1Key, node2Key route.Vertex + copy(node1Key[:], node1.PubKeyBytes[:]) + copy(node2Key[:], node2.PubKeyBytes[:]) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edgeInfo, err := models.NewV1Channel( + chanID, *chaincfg.MainNetParams.GenesisHash, + node1Key, node2Key, &models.ChannelV1Fields{ + BitcoinKey1Bytes: node1Key, + BitcoinKey2Bytes: node2Key, + }, + models.WithChanProof(proof), + models.WithChannelPoint(op), + models.WithCapacity(1000), + ) + require.NoError(t, err) + err = graph.AddChannelEdge(ctx, edgeInfo) require.NoError(t, err) // Create and add an edge with random data that points @@ -1963,28 +2012,31 @@ func TestGraphPruning(t *testing.T) { channelPoints = append(channelPoints, &op) - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID, - ChainHash: *chaincfg.MainNetParams.GenesisHash, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - ChannelPoint: op, - Capacity: 1000, - } - copy(edgeInfo.NodeKey1Bytes[:], graphNodes[i].PubKeyBytes[:]) - copy(edgeInfo.NodeKey2Bytes[:], graphNodes[i+1].PubKeyBytes[:]) - copy(edgeInfo.BitcoinKey1Bytes[:], graphNodes[i].PubKeyBytes[:]) - copy( - edgeInfo.BitcoinKey2Bytes[:], - graphNodes[i+1].PubKeyBytes[:], + var node1Key, node2Key route.Vertex + copy(node1Key[:], graphNodes[i].PubKeyBytes[:]) + copy(node2Key[:], graphNodes[i+1].PubKeyBytes[:]) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), ) - if err := graph.AddChannelEdge(ctx, &edgeInfo); err != nil { + + edgeInfo, err := models.NewV1Channel( + chanID, *chaincfg.MainNetParams.GenesisHash, + node1Key, node2Key, &models.ChannelV1Fields{ + BitcoinKey1Bytes: node1Key, + BitcoinKey2Bytes: node2Key, + }, + models.WithChanProof(proof), + models.WithChannelPoint(op), + models.WithCapacity(1000), + ) + if err != nil { + t.Fatalf("unable to create edge: %v", err) + } + if err := graph.AddChannelEdge(ctx, edgeInfo); err != nil { t.Fatalf("unable to add node: %v", err) } @@ -2140,10 +2192,10 @@ func TestHighestChanID(t *testing.T) { edge1, _ := createEdge(10, 0, 0, 0, node1, node2) edge2, chanID2 := createEdge(100, 0, 0, 0, node1, node2) - if err := graph.AddChannelEdge(ctx, &edge1); err != nil { + if err := graph.AddChannelEdge(ctx, edge1); err != nil { t.Fatalf("unable to create channel edge: %v", err) } - if err := graph.AddChannelEdge(ctx, &edge2); err != nil { + if err := graph.AddChannelEdge(ctx, edge2); err != nil { t.Fatalf("unable to create channel edge: %v", err) } @@ -2160,7 +2212,7 @@ func TestHighestChanID(t *testing.T) { // If we add another edge, then the current best chan ID should be // updated as well. edge3, chanID3 := createEdge(1000, 0, 0, 0, node1, node2) - if err := graph.AddChannelEdge(ctx, &edge3); err != nil { + if err := graph.AddChannelEdge(ctx, edge3); err != nil { t.Fatalf("unable to create channel edge: %v", err) } bestID, err = graph.HighestChanID(ctx) @@ -2216,7 +2268,7 @@ func TestChanUpdatesInHorizon(t *testing.T) { uint32(i*10), 0, 0, 0, node1, node2, ) - if err := graph.AddChannelEdge(ctx, &channel); err != nil { + if err := graph.AddChannelEdge(ctx, channel); err != nil { t.Fatalf("unable to create channel edge: %v", err) } @@ -2245,7 +2297,7 @@ func TestChanUpdatesInHorizon(t *testing.T) { } edges = append(edges, ChannelEdge{ - Info: &channel, + Info: channel, Policy1: edge1, Policy2: edge2, }) @@ -2683,7 +2735,7 @@ func TestChanUpdatesInHorizonBoundaryConditions(t *testing.T) { uint32(i*10), 0, 0, 0, node1, node2, ) require.NoError( - t, graph.AddChannelEdge(ctx, &channel), + t, graph.AddChannelEdge(ctx, channel), ) edge1 := newEdgePolicy( @@ -2851,7 +2903,7 @@ func TestFilterKnownChanIDs(t *testing.T) { uint32(i*10), 0, 0, 0, node1, node2, ) - if err := graph.AddChannelEdge(ctx, &channel); err != nil { + if err := graph.AddChannelEdge(ctx, channel); err != nil { t.Fatalf("unable to create channel edge: %v", err) } @@ -2866,7 +2918,7 @@ func TestFilterKnownChanIDs(t *testing.T) { channel, chanID := createEdge( uint32(i*10+1), 0, 0, 0, node1, node2, ) - if err := graph.AddChannelEdge(ctx, &channel); err != nil { + if err := graph.AddChannelEdge(ctx, channel); err != nil { t.Fatalf("unable to create channel edge: %v", err) } err := graph.DeleteChannelEdges(false, true, channel.ChannelID) @@ -3027,7 +3079,7 @@ func TestStressTestChannelGraphAPI(t *testing.T) { ) newChan := &chanInfo{ - info: channel, + info: *channel, id: chanID, } chans = append(chans, newChan) @@ -3339,12 +3391,12 @@ func TestFilterChannelRange(t *testing.T) { channel1, chanID1 := createEdge( chanHeight, uint32(i+1), 0, 0, node1, node2, ) - require.NoError(t, graph.AddChannelEdge(ctx, &channel1)) + require.NoError(t, graph.AddChannelEdge(ctx, channel1)) channel2, chanID2 := createEdge( chanHeight, uint32(i+2), 0, 0, node1, node2, ) - require.NoError(t, graph.AddChannelEdge(ctx, &channel2)) + require.NoError(t, graph.AddChannelEdge(ctx, channel2)) chanInfo1 := NewChannelUpdateInfo( chanID1, time.Time{}, time.Time{}, @@ -3520,7 +3572,7 @@ func TestFetchChanInfos(t *testing.T) { uint32(i*10), 0, 0, 0, node1, node2, ) - if err := graph.AddChannelEdge(ctx, &channel); err != nil { + if err := graph.AddChannelEdge(ctx, channel); err != nil { t.Fatalf("unable to create channel edge: %v", err) } @@ -3544,7 +3596,7 @@ func TestFetchChanInfos(t *testing.T) { } edges = append(edges, ChannelEdge{ - Info: &channel, + Info: channel, Policy1: edge1, Policy2: edge2, }) @@ -3561,7 +3613,7 @@ func TestFetchChanInfos(t *testing.T) { zombieChan, zombieChanID := createEdge( 666, 0, 0, 0, node1, node2, ) - if err := graph.AddChannelEdge(ctx, &zombieChan); err != nil { + if err := graph.AddChannelEdge(ctx, zombieChan); err != nil { t.Fatalf("unable to create channel edge: %v", err) } err := graph.DeleteChannelEdges(false, true, zombieChan.ChannelID) @@ -3614,7 +3666,7 @@ func TestIncompleteChannelPolicies(t *testing.T) { uint32(0), 0, 0, 0, node1, node2, ) - if err := graph.AddChannelEdge(ctx, &channel); err != nil { + if err := graph.AddChannelEdge(ctx, channel); err != nil { t.Fatalf("unable to create channel edge: %v", err) } @@ -3718,7 +3770,7 @@ func TestChannelEdgePruningUpdateIndexDeletion(t *testing.T) { // With the two nodes created, we'll now create a random channel, as // well as two edges in the database with distinct update times. edgeInfo, chanID := createEdge(100, 0, 0, 0, node1, node2) - if err := graph.AddChannelEdge(ctx, &edgeInfo); err != nil { + if err := graph.AddChannelEdge(ctx, edgeInfo); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -3867,7 +3919,7 @@ func TestPruneGraphNodes(t *testing.T) { // We'll now add a new edge to the graph, but only actually advertise // the edge of *one* of the nodes. edgeInfo, chanID := createEdge(100, 0, 0, 0, node1, node2) - if err := graph.AddChannelEdge(ctx, &edgeInfo); err != nil { + if err := graph.AddChannelEdge(ctx, edgeInfo); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -3916,7 +3968,7 @@ func TestAddChannelEdgeShellNodes(t *testing.T) { // We'll now create an edge between the two nodes, as a result, node2 // should be inserted into the database as a shell node. edgeInfo, _ := createEdge(100, 0, 0, 0, node1, node2) - require.NoError(t, graph.AddChannelEdge(ctx, &edgeInfo)) + require.NoError(t, graph.AddChannelEdge(ctx, edgeInfo)) // Ensure that node1 was inserted as a full node, while node2 only has // a shell node present. @@ -3930,7 +3982,7 @@ func TestAddChannelEdgeShellNodes(t *testing.T) { // Show that attempting to add the channel again will result in an // error. - err = graph.AddChannelEdge(ctx, &edgeInfo) + err = graph.AddChannelEdge(ctx, edgeInfo) require.ErrorIs(t, err, ErrEdgeAlreadyExist) // Show that updating the shell node to a full node record works. @@ -4049,7 +4101,7 @@ func TestNodeIsPublic(t *testing.T) { // After creating all of our nodes and edges, we'll add them to each // participant's graph. nodes := []*models.Node{aliceNode, bobNode, carolNode} - edges := []*models.ChannelEdgeInfo{&aliceBobEdge, &bobCarolEdge} + edges := []*models.ChannelEdgeInfo{aliceBobEdge, bobCarolEdge} graphs := []*ChannelGraph{aliceGraph, bobGraph, carolGraph} for _, graph := range graphs { for _, node := range nodes { @@ -4131,7 +4183,7 @@ func TestNodeIsPublic(t *testing.T) { } bobCarolEdge.AuthProof = nil - if err := graph.AddChannelEdge(ctx, &bobCarolEdge); err != nil { + if err := graph.AddChannelEdge(ctx, bobCarolEdge); err != nil { t.Fatalf("unable to add edge: %v", err) } } @@ -4634,7 +4686,7 @@ func TestBatchedAddChannelEdge(t *testing.T) { // Create a third edge, this with a block height of 155. edgeInfo3, _ := createEdge(height-1, 0, 0, 2, node1, node2) - edges := []models.ChannelEdgeInfo{edgeInfo, edgeInfo2, edgeInfo3} + edges := []models.ChannelEdgeInfo{*edgeInfo, *edgeInfo2, *edgeInfo3} errChan := make(chan error, len(edges)) errTimeout := errors.New("timeout adding batched channel") diff --git a/graph/db/kv_store.go b/graph/db/kv_store.go index b137c6240..14185f11a 100644 --- a/graph/db/kv_store.go +++ b/graph/db/kv_store.go @@ -3950,11 +3950,14 @@ func (c *KVStore) FetchChannelEdgesByID(chanID uint64) ( // populate the edge info with the public keys of each // party as this is the only information we have about // it and return an error signaling so. - edgeInfo = &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - NodeKey1Bytes: pubKey1, - NodeKey2Bytes: pubKey2, + zombieEdge, err := models.NewV1Channel( + 0, chainhash.Hash{}, pubKey1, pubKey2, + &models.ChannelV1Fields{}, + ) + if err != nil { + return err } + edgeInfo = zombieEdge return ErrZombieEdge } diff --git a/graph/db/models/channel_edge_info.go b/graph/db/models/channel_edge_info.go index 4c783a6a9..7e872c5cd 100644 --- a/graph/db/models/channel_edge_info.go +++ b/graph/db/models/channel_edge_info.go @@ -76,6 +76,99 @@ type ChannelEdgeInfo struct { ExtraOpaqueData []byte } +// EdgeModifier is a functional option that modifies a ChannelEdgeInfo. +type EdgeModifier func(*ChannelEdgeInfo) + +// WithChannelPoint sets the channel point (funding outpoint) on the edge. +func WithChannelPoint(cp wire.OutPoint) EdgeModifier { + return func(e *ChannelEdgeInfo) { + e.ChannelPoint = cp + } +} + +// WithFeatures sets the feature vector on the edge. +func WithFeatures(f *lnwire.RawFeatureVector) EdgeModifier { + return func(e *ChannelEdgeInfo) { + e.Features = lnwire.NewFeatureVector(f, lnwire.Features) + } +} + +// WithCapacity sets the capacity on the edge. +func WithCapacity(c btcutil.Amount) EdgeModifier { + return func(e *ChannelEdgeInfo) { + e.Capacity = c + } +} + +// WithChanProof sets the authentication proof on the edge. +func WithChanProof(proof *ChannelAuthProof) EdgeModifier { + return func(e *ChannelEdgeInfo) { + e.AuthProof = proof + } +} + +// WithFundingScript sets the funding script on the edge. +func WithFundingScript(script []byte) EdgeModifier { + return func(e *ChannelEdgeInfo) { + e.FundingScript = fn.Some(script) + } +} + +// ChannelV1Fields contains the fields that are specific to v1 channel +// announcements. +type ChannelV1Fields struct { + // BitcoinKey1Bytes is the raw public key of the first node. + BitcoinKey1Bytes route.Vertex + + // BitcoinKey2Bytes is the raw public key of the second node. + BitcoinKey2Bytes route.Vertex + + // ExtraOpaqueData is the set of data that was appended to this + // message, some of which we may not actually know how to iterate or + // parse. By holding onto this data, we ensure that we're able to + // properly validate the set of signatures that cover these new fields, + // and ensure we're able to make upgrades to the network in a forwards + // compatible manner. + ExtraOpaqueData []byte +} + +// NewV1Channel creates a new ChannelEdgeInfo for a v1 channel announcement. +// It takes the required fields for all channels (chanID, chainHash, node keys) +// and v1-specific fields, along with optional modifiers for setting additional +// fields like capacity, channel point, features, and auth proof. +// +// The constructor validates that if an AuthProof is provided via modifiers, its +// version matches the channel version (v1). +func NewV1Channel(chanID uint64, chainHash chainhash.Hash, node1, + node2 route.Vertex, v1Fields *ChannelV1Fields, + opts ...EdgeModifier) (*ChannelEdgeInfo, error) { + + edge := &ChannelEdgeInfo{ + Version: lnwire.GossipVersion1, + NodeKey1Bytes: node1, + NodeKey2Bytes: node2, + BitcoinKey1Bytes: v1Fields.BitcoinKey1Bytes, + BitcoinKey2Bytes: v1Fields.BitcoinKey2Bytes, + ChannelID: chanID, + ChainHash: chainHash, + Features: lnwire.EmptyFeatureVector(), + ExtraOpaqueData: v1Fields.ExtraOpaqueData, + } + + for _, opt := range opts { + opt(edge) + } + + // Validate some fields after the options have been applied. + if edge.AuthProof != nil && edge.AuthProof.Version != edge.Version { + return nil, fmt.Errorf("channel auth proof version %d does "+ + "not match channel version %d", edge.AuthProof.Version, + edge.Version) + } + + return edge, nil +} + // NodeKey1 is the identity public key of the "first" node that was involved in // the creation of this channel. A node is considered "first" if the // lexicographical ordering the its serialized public key is "smaller" than diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go index 253582669..0ef5855bf 100644 --- a/graph/db/sql_store.go +++ b/graph/db/sql_store.go @@ -2038,11 +2038,22 @@ func (s *SQLStore) FetchChannelEdgesByID(chanID uint64) ( // populate the edge info with the public keys of each // party as this is the only information we have about // it. - edge = &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, + node1, err := route.NewVertexFromBytes(zombie.NodeKey1) + if err != nil { + return err } - copy(edge.NodeKey1Bytes[:], zombie.NodeKey1) - copy(edge.NodeKey2Bytes[:], zombie.NodeKey2) + node2, err := route.NewVertexFromBytes(zombie.NodeKey2) + if err != nil { + return err + } + zombieEdge, err := models.NewV1Channel( + 0, chainhash.Hash{}, node1, node2, + &models.ChannelV1Fields{}, + ) + if err != nil { + return err + } + edge = zombieEdge return ErrZombieEdge } else if err != nil { @@ -4467,22 +4478,28 @@ func buildEdgeInfoWithBatchData(chain chainhash.Hash, recs = make([]byte, 0) } - var btcKey1, btcKey2 route.Vertex - copy(btcKey1[:], dbChan.BitcoinKey1) - copy(btcKey2[:], dbChan.BitcoinKey2) + btcKey1, err := route.NewVertexFromBytes(dbChan.BitcoinKey1) + if err != nil { + return nil, err + } + btcKey2, err := route.NewVertexFromBytes(dbChan.BitcoinKey2) + if err != nil { + return nil, err + } - channel := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChainHash: chain, - ChannelID: byteOrder.Uint64(dbChan.Scid), - NodeKey1Bytes: node1, - NodeKey2Bytes: node2, - BitcoinKey1Bytes: btcKey1, - BitcoinKey2Bytes: btcKey2, - ChannelPoint: *op, - Capacity: btcutil.Amount(dbChan.Capacity.Int64), - Features: fv, - ExtraOpaqueData: recs, + channel, err := models.NewV1Channel( + byteOrder.Uint64(dbChan.Scid), chain, node1, node2, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + ExtraOpaqueData: recs, + }, + models.WithChannelPoint(*op), + models.WithCapacity(btcutil.Amount(dbChan.Capacity.Int64)), + models.WithFeatures(fv.RawFeatureVector), + ) + if err != nil { + return nil, err } // We always set all the signatures at the same time, so we can diff --git a/graph/notifications_test.go b/graph/notifications_test.go index fab5b4ce6..b086fc562 100644 --- a/graph/notifications_test.go +++ b/graph/notifications_test.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" @@ -447,24 +448,27 @@ func TestEdgeUpdateNotification(t *testing.T) { // Finally, to conclude our test set up, we'll create a channel // update to announce the created channel between the two nodes. - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - ChannelPoint: *chanPoint, - Capacity: chanValue, - FundingScript: fn.Some(script), - } - copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1 := route.NewVertex(bitcoinKey1) + btcKey2 := route.NewVertex(bitcoinKey2) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + node1.PubKeyBytes, node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(proof), + models.WithChannelPoint(*chanPoint), + models.WithCapacity(chanValue), + models.WithFundingScript(script), + ) + require.NoError(t, err) if err := ctx.builder.AddEdge(ctxb, edge); err != nil { t.Fatalf("unable to add edge: %v", err) @@ -642,22 +646,25 @@ func TestNodeUpdateNotification(t *testing.T) { testFeaturesBuf := new(bytes.Buffer) require.NoError(t, testFeatures.Encode(testFeaturesBuf)) - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - Features: lnwire.EmptyFeatureVector(), - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - FundingScript: fn.Some(script), - } - copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1 := route.NewVertex(bitcoinKey1) + btcKey2 := route.NewVertex(bitcoinKey2) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + node1.PubKeyBytes, node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(proof), + models.WithFundingScript(script), + ) + require.NoError(t, err) // Adding the edge will add the nodes to the graph, but with no info // except the pubkey known. @@ -829,24 +836,28 @@ func TestNotificationCancellation(t *testing.T) { // to the client. ntfnClient.Cancel() - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - ChannelPoint: *chanPoint, - Capacity: chanValue, - FundingScript: fn.Some(script), - } - copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1 := route.NewVertex(bitcoinKey1) + btcKey2 := route.NewVertex(bitcoinKey2) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + node1.PubKeyBytes, node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(proof), + models.WithChannelPoint(*chanPoint), + models.WithCapacity(chanValue), + models.WithFundingScript(script), + ) + require.NoError(t, err) + if err := ctx.builder.AddEdge(ctxb, edge); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -906,24 +917,28 @@ func TestChannelCloseNotification(t *testing.T) { // Finally, to conclude our test set up, we'll create a channel // announcement to announce the created channel between the two nodes. - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: node1.PubKeyBytes, - NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: models.NewV1ChannelAuthProof( - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - testSig.Serialize(), - ), - Features: lnwire.EmptyFeatureVector(), - ChannelPoint: *chanUtxo, - Capacity: chanValue, - FundingScript: fn.Some(script), - } - copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed()) - copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) + btcKey1 := route.NewVertex(bitcoinKey1) + btcKey2 := route.NewVertex(bitcoinKey2) + + proof := models.NewV1ChannelAuthProof( + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + testSig.Serialize(), + ) + + edge, err := models.NewV1Channel( + chanID.ToUint64(), *chaincfg.SimNetParams.GenesisHash, + node1.PubKeyBytes, node2.PubKeyBytes, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, models.WithChanProof(proof), + models.WithChannelPoint(*chanUtxo), + models.WithCapacity(chanValue), + models.WithFundingScript(script), + ) + require.NoError(t, err) + if err := ctx.builder.AddEdge(ctxb, edge); err != nil { t.Fatalf("unable to add edge: %v", err) } diff --git a/lnrpc/devrpc/dev_server.go b/lnrpc/devrpc/dev_server.go index 31db5fe0a..7dee1627a 100644 --- a/lnrpc/devrpc/dev_server.go +++ b/lnrpc/devrpc/dev_server.go @@ -224,7 +224,6 @@ func (s *Server) ImportGraph(ctx context.Context, // Obtain the pointer to the global singleton channel graph. graphDB := s.cfg.GraphDB - var err error for _, rpcNode := range graph.Nodes { pubKeyBytes, err := parsePubKey(rpcNode.PubKey) if err != nil { @@ -273,19 +272,12 @@ func (s *Server) ImportGraph(ctx context.Context, for _, rpcEdge := range graph.Edges { rpcEdge := rpcEdge - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: rpcEdge.ChannelId, - ChainHash: *s.cfg.ActiveNetParams.GenesisHash, - Capacity: btcutil.Amount(rpcEdge.Capacity), - } - - edge.NodeKey1Bytes, err = parsePubKey(rpcEdge.Node1Pub) + node1, err := parsePubKey(rpcEdge.Node1Pub) if err != nil { return nil, err } - edge.NodeKey2Bytes, err = parsePubKey(rpcEdge.Node2Pub) + node2, err := parsePubKey(rpcEdge.Node2Pub) if err != nil { return nil, err } @@ -294,7 +286,16 @@ func (s *Server) ImportGraph(ctx context.Context, if err != nil { return nil, err } - edge.ChannelPoint = *channelPoint + + edge, err := models.NewV1Channel( + rpcEdge.ChannelId, *s.cfg.ActiveNetParams.GenesisHash, + node1, node2, &models.ChannelV1Fields{}, + models.WithCapacity(btcutil.Amount(rpcEdge.Capacity)), + models.WithChannelPoint(*channelPoint), + ) + if err != nil { + return nil, err + } if err := graphDB.AddChannelEdge(ctx, edge); err != nil { return nil, fmt.Errorf("unable to add edge %v: %w", diff --git a/lnrpc/invoicesrpc/addinvoice_test.go b/lnrpc/invoicesrpc/addinvoice_test.go index ceab2bec4..ca83f8bab 100644 --- a/lnrpc/invoicesrpc/addinvoice_test.go +++ b/lnrpc/invoicesrpc/addinvoice_test.go @@ -6,10 +6,12 @@ import ( "testing" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/graph/db/models" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/zpay32" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -305,10 +307,16 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - NodeKey1Bytes: selectedPolicy, - }, + func() *models.ChannelEdgeInfo { + edge, err := models.NewV1Channel( + 0, chainhash.Hash{}, selectedPolicy, + route.Vertex{}, + &models.ChannelV1Fields{}, + ) + require.NoError(h.t, err) + + return edge + }(), &models.ChannelEdgePolicy{ FeeBaseMSat: 1000, FeeProportionalMillionths: 20, diff --git a/netann/chan_status_manager_test.go b/netann/chan_status_manager_test.go index 1ec7cea23..5265d317f 100644 --- a/netann/chan_status_manager_test.go +++ b/netann/chan_status_manager_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" graphdb "github.com/lightningnetwork/lnd/graph/db" @@ -19,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/netann" + "github.com/lightningnetwork/lnd/routing/route" "github.com/stretchr/testify/require" ) @@ -100,12 +102,19 @@ func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel, // bit. dir2 |= lnwire.ChanUpdateDirection - return &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelPoint: channel.FundingOutpoint, - NodeKey1Bytes: pubkey1, - NodeKey2Bytes: pubkey2, - }, + pubkey1Vertex, err := route.NewVertexFromBytes(pubkey1[:]) + require.NoError(t, err) + pubkey2Vertex, err := route.NewVertexFromBytes(pubkey2[:]) + require.NoError(t, err) + + edgeInfo, err := models.NewV1Channel( + channel.ShortChanID().ToUint64(), chainhash.Hash{}, + pubkey1Vertex, pubkey2Vertex, &models.ChannelV1Fields{}, + models.WithChannelPoint(channel.FundingOutpoint), + ) + require.NoError(t, err) + + return edgeInfo, &models.ChannelEdgePolicy{ ChannelID: channel.ShortChanID().ToUint64(), ChannelFlags: dir1, diff --git a/netann/channel_announcement_test.go b/netann/channel_announcement_test.go index 02d1d5617..c46b90a9d 100644 --- a/netann/channel_announcement_test.go +++ b/netann/channel_announcement_test.go @@ -46,21 +46,19 @@ func TestCreateChanAnnouncement(t *testing.T) { expChanAnn.BitcoinSig1.ToSignatureBytes(), expChanAnn.BitcoinSig2.ToSignatureBytes(), ) - chanInfo := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChainHash: expChanAnn.ChainHash, - ChannelID: expChanAnn.ShortChannelID.ToUint64(), - ChannelPoint: wire.OutPoint{Index: 1}, - Capacity: btcutil.SatoshiPerBitcoin, - NodeKey1Bytes: key, - NodeKey2Bytes: key, - BitcoinKey1Bytes: key, - BitcoinKey2Bytes: key, - Features: lnwire.NewFeatureVector( - features, lnwire.Features, - ), - ExtraOpaqueData: expChanAnn.ExtraOpaqueData, - } + chanInfo, err := models.NewV1Channel( + expChanAnn.ShortChannelID.ToUint64(), expChanAnn.ChainHash, + key, key, &models.ChannelV1Fields{ + BitcoinKey1Bytes: key, + BitcoinKey2Bytes: key, + ExtraOpaqueData: expChanAnn.ExtraOpaqueData, + }, + models.WithChanProof(chanProof), + models.WithChannelPoint(wire.OutPoint{Index: 1}), + models.WithCapacity(btcutil.SatoshiPerBitcoin), + models.WithFeatures(features), + ) + require.NoError(t, err) chanAnn, _, _, err := CreateChanAnnouncement( chanProof, chanInfo, nil, nil, ) diff --git a/routing/localchans/manager.go b/routing/localchans/manager.go index f47e34a16..cc86d82cc 100644 --- a/routing/localchans/manager.go +++ b/routing/localchans/manager.go @@ -18,6 +18,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing" + "github.com/lightningnetwork/lnd/routing/route" ) // Manager manages the node's local channels. The only operation that is @@ -328,20 +329,36 @@ func (r *Manager) createEdge(channel *channeldb.OpenChannel, "script: %v", err) } - info := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: shortChanID.ToUint64(), - ChainHash: channel.ChainHash, - Features: lnwire.EmptyFeatureVector(), - Capacity: channel.Capacity, - ChannelPoint: channel.FundingOutpoint, - FundingScript: fn.Some(fundingScript), + nodeKey1, err := route.NewVertexFromBytes(nodeKey1Bytes) + if err != nil { + return nil, nil, err + } + nodeKey2, err := route.NewVertexFromBytes(nodeKey2Bytes) + if err != nil { + return nil, nil, err + } + bitcoinKey1, err := route.NewVertexFromBytes(bitcoinKey1Bytes) + if err != nil { + return nil, nil, err + } + bitcoinKey2, err := route.NewVertexFromBytes(bitcoinKey2Bytes) + if err != nil { + return nil, nil, err } - copy(info.NodeKey1Bytes[:], nodeKey1Bytes) - copy(info.NodeKey2Bytes[:], nodeKey2Bytes) - copy(info.BitcoinKey1Bytes[:], bitcoinKey1Bytes) - copy(info.BitcoinKey2Bytes[:], bitcoinKey2Bytes) + info, err := models.NewV1Channel( + shortChanID.ToUint64(), channel.ChainHash, nodeKey1, nodeKey2, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: bitcoinKey1, + BitcoinKey2Bytes: bitcoinKey2, + }, + models.WithCapacity(channel.Capacity), + models.WithChannelPoint(channel.FundingOutpoint), + models.WithFundingScript(fundingScript), + ) + if err != nil { + return nil, nil, err + } // Construct a dummy channel edge policy with default values that will // be updated with the new values in the call to processChan below. diff --git a/routing/localchans/manager_test.go b/routing/localchans/manager_test.go index 108fe0a7a..6196330bd 100644 --- a/routing/localchans/manager_test.go +++ b/routing/localchans/manager_test.go @@ -13,13 +13,13 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/discovery" - "github.com/lightningnetwork/lnd/fn/v2" "github.com/lightningnetwork/lnd/funding" "github.com/lightningnetwork/lnd/graph/db/models" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing" + "github.com/lightningnetwork/lnd/routing/route" "github.com/stretchr/testify/require" ) @@ -211,11 +211,21 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - Capacity: chanCap, - ChannelPoint: chanPointValid, - }, + //nolint:ll + edgeInfo: func() *models.ChannelEdgeInfo { + info, err := models.NewV1Channel( + 0, + chainhash.Hash{}, + route.Vertex{}, + route.Vertex{}, + &models.ChannelV1Fields{}, + models.WithCapacity(chanCap), + models.WithChannelPoint(chanPointValid), + ) + require.NoError(t, err) + + return info + }(), }, }, specifiedChanPoints: []wire.OutPoint{chanPointValid}, @@ -230,11 +240,21 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - Capacity: chanCap, - ChannelPoint: chanPointValid, - }, + //nolint:ll + edgeInfo: func() *models.ChannelEdgeInfo { + info, err := models.NewV1Channel( + 0, + chainhash.Hash{}, + route.Vertex{}, + route.Vertex{}, + &models.ChannelV1Fields{}, + models.WithCapacity(chanCap), + models.WithChannelPoint(chanPointValid), + ) + require.NoError(t, err) + + return info + }(), }, }, specifiedChanPoints: []wire.OutPoint{}, @@ -249,11 +269,22 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - Capacity: chanCap, - ChannelPoint: chanPointValid, - }, + //nolint:ll + edgeInfo: func() *models.ChannelEdgeInfo { + info, err := models.NewV1Channel( + 0, + chainhash.Hash{}, + route.Vertex{}, + route.Vertex{}, + &models.ChannelV1Fields{}, + models.WithCapacity(chanCap), + models.WithChannelPoint(chanPointValid), + ) + + require.NoError(t, err) + + return info + }(), }, }, specifiedChanPoints: []wire.OutPoint{chanPointMissing}, @@ -272,11 +303,22 @@ func TestManager(t *testing.T) { newPolicy: noMaxHtlcPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - Capacity: chanCap, - ChannelPoint: chanPointValid, - }, + //nolint:ll + edgeInfo: func() *models.ChannelEdgeInfo { + info, err := models.NewV1Channel( + 0, + chainhash.Hash{}, + route.Vertex{}, + route.Vertex{}, + &models.ChannelV1Fields{}, + models.WithCapacity(chanCap), + models.WithChannelPoint(chanPointValid), + ) + + require.NoError(t, err) + + return info + }(), }, }, specifiedChanPoints: []wire.OutPoint{chanPointValid}, @@ -395,23 +437,19 @@ func TestCreateEdgeLower(t *testing.T) { fundingScript, err := funding.MakeFundingScript(channel) require.NoError(t, err) - expectedInfo := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: 8, - ChainHash: channel.ChainHash, - Features: lnwire.EmptyFeatureVector(), - Capacity: 9, - ChannelPoint: channel.FundingOutpoint, - NodeKey1Bytes: sp, - NodeKey2Bytes: rp, - BitcoinKey1Bytes: [33]byte( - localMultisigKey.SerializeCompressed()), - BitcoinKey2Bytes: [33]byte( - remoteMultisigKey.SerializeCompressed()), - AuthProof: nil, - ExtraOpaqueData: nil, - FundingScript: fn.Some(fundingScript), - } + btcKey1 := route.NewVertex(localMultisigKey) + btcKey2 := route.NewVertex(remoteMultisigKey) + expectedInfo, err := models.NewV1Channel( + 8, channel.ChainHash, sp, rp, &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, + models.WithCapacity(9), + models.WithChannelPoint(channel.FundingOutpoint), + models.WithFundingScript(fundingScript), + ) + require.NoError(t, err) + expectedEdge := &models.ChannelEdgePolicy{ ChannelID: 8, LastUpdate: timestamp, @@ -489,23 +527,20 @@ func TestCreateEdgeHigher(t *testing.T) { fundingScript, err := funding.MakeFundingScript(channel) require.NoError(t, err) - expectedInfo := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: 8, - ChainHash: channel.ChainHash, - Features: lnwire.EmptyFeatureVector(), - Capacity: 9, - ChannelPoint: channel.FundingOutpoint, - NodeKey1Bytes: rp, - NodeKey2Bytes: sp, - BitcoinKey1Bytes: [33]byte( - remoteMultisigKey.SerializeCompressed()), - BitcoinKey2Bytes: [33]byte( - localMultisigKey.SerializeCompressed()), - AuthProof: nil, - ExtraOpaqueData: nil, - FundingScript: fn.Some(fundingScript), - } + btcKey1 := route.NewVertex(remoteMultisigKey) + btcKey2 := route.NewVertex(localMultisigKey) + expectedInfo, err := models.NewV1Channel( + 8, channel.ChainHash, rp, sp, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, + models.WithCapacity(9), + models.WithChannelPoint(channel.FundingOutpoint), + models.WithFundingScript(fundingScript), + ) + require.NoError(t, err) + expectedEdge := &models.ChannelEdgePolicy{ ChannelID: 8, LastUpdate: timestamp, diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index bbb31fdaf..ed291a6aa 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -19,6 +19,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" sphinx "github.com/lightningnetwork/lightning-onion" @@ -345,19 +346,28 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: edge.ChannelID, - AuthProof: &testAuthProof, - ChannelPoint: fundingPoint, - Features: lnwire.EmptyFeatureVector(), - Capacity: btcutil.Amount(edge.Capacity), - } + var node1Vertex, node2Vertex route.Vertex + copy(node1Vertex[:], node1Bytes) + copy(node2Vertex[:], node2Bytes) - copy(edgeInfo.NodeKey1Bytes[:], node1Bytes) - copy(edgeInfo.NodeKey2Bytes[:], node2Bytes) - copy(edgeInfo.BitcoinKey1Bytes[:], node1Bytes) - copy(edgeInfo.BitcoinKey2Bytes[:], node2Bytes) + var btcKey1, btcKey2 route.Vertex + copy(btcKey1[:], node1Bytes) + copy(btcKey2[:], node2Bytes) + + edgeInfo, err := models.NewV1Channel( + edge.ChannelID, *chaincfg.SimNetParams.GenesisHash, + node1Vertex, node2Vertex, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: btcKey1, + BitcoinKey2Bytes: btcKey2, + }, + models.WithChanProof(&testAuthProof), + models.WithChannelPoint(fundingPoint), + models.WithCapacity(btcutil.Amount(edge.Capacity)), + ) + if err != nil { + return nil, err + } shortID := lnwire.NewShortChanIDFromInt(edge.ChannelID) links[shortID] = &mockLink{ @@ -366,7 +376,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( ), } - err = graph.AddChannelEdge(ctx, &edgeInfo) + err = graph.AddChannelEdge(ctx, edgeInfo) if err != nil && !errors.Is(err, graphdb.ErrEdgeAlreadyExist) { return nil, err } @@ -396,12 +406,12 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( } // We also store the channel IDs info for each of the node. - node1Vertex, err := route.NewVertexFromBytes(node1Bytes) + node1Vertex, err = route.NewVertexFromBytes(node1Bytes) if err != nil { return nil, err } - node2Vertex, err := route.NewVertexFromBytes(node2Bytes) + node2Vertex, err = route.NewVertexFromBytes(node2Bytes) if err != nil { return nil, err } @@ -678,21 +688,21 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: channelID, - AuthProof: &testAuthProof, - ChannelPoint: *fundingPoint, - Capacity: testChannel.Capacity, - Features: lnwire.EmptyFeatureVector(), - - NodeKey1Bytes: node1Vertex, - BitcoinKey1Bytes: node1Vertex, - NodeKey2Bytes: node2Vertex, - BitcoinKey2Bytes: node2Vertex, + edgeInfo, err := models.NewV1Channel( + channelID, *chaincfg.SimNetParams.GenesisHash, + node1Vertex, node2Vertex, &models.ChannelV1Fields{ + BitcoinKey1Bytes: node1Vertex, + BitcoinKey2Bytes: node2Vertex, + }, + models.WithChanProof(&testAuthProof), + models.WithChannelPoint(*fundingPoint), + models.WithCapacity(testChannel.Capacity), + ) + if err != nil { + return nil, err } - err = graph.AddChannelEdge(ctx, &edgeInfo) + err = graph.AddChannelEdge(ctx, edgeInfo) if err != nil && !errors.Is(err, graphdb.ErrEdgeAlreadyExist) { return nil, err } diff --git a/routing/router_test.go b/routing/router_test.go index bb0b2f85c..6f9d2c3f3 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -2738,16 +2738,14 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { ) require.NoError(t, err, "unable to create channel edge") - edge := &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - NodeKey1Bytes: pub1, - NodeKey2Bytes: pub2, - BitcoinKey1Bytes: pub1, - BitcoinKey2Bytes: pub2, - Features: lnwire.EmptyFeatureVector(), - AuthProof: nil, - } + edge, err := models.NewV1Channel( + chanID.ToUint64(), chainhash.Hash{}, pub1, pub2, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: pub1, + BitcoinKey2Bytes: pub2, + }, + ) + require.NoError(t, err) require.NoError(t, ctx.graph.AddChannelEdge(ctxb, edge)) // We must add the edge policy to be able to use the edge for route @@ -2819,16 +2817,17 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { 10000, 510) require.NoError(t, err, "unable to create channel edge") - edge = &models.ChannelEdgeInfo{ - Version: lnwire.GossipVersion1, - ChannelID: chanID.ToUint64(), - Features: lnwire.EmptyFeatureVector(), - AuthProof: nil, - } - copy(edge.NodeKey1Bytes[:], node1Bytes) - edge.NodeKey2Bytes = node2Bytes - copy(edge.BitcoinKey1Bytes[:], node1Bytes) - edge.BitcoinKey2Bytes = node2Bytes + node1Vertex, err := route.NewVertexFromBytes(node1Bytes) + require.NoError(t, err) + + edge, err = models.NewV1Channel( + chanID.ToUint64(), chainhash.Hash{}, node1Vertex, node2Bytes, + &models.ChannelV1Fields{ + BitcoinKey1Bytes: node1Vertex, + BitcoinKey2Bytes: node2Bytes, + }, + ) + require.NoError(t, err) require.NoError(t, ctx.graph.AddChannelEdge(ctxb, edge))