diff --git a/autopilot/graph.go b/autopilot/graph.go index 0b062a535..74b04c503 100644 --- a/autopilot/graph.go +++ b/autopilot/graph.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/btcutil" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -53,6 +54,8 @@ func ChannelGraphFromDatabase(db *channeldb.ChannelGraph) ChannelGraph { // channeldb.LightningNode. The wrapper method implement the autopilot.Node // interface. type dbNode struct { + db *channeldb.ChannelGraph + tx kvdb.RTx node *channeldb.LightningNode @@ -67,7 +70,7 @@ var _ Node = (*dbNode)(nil) // will be returned in serialized compressed format. // // NOTE: Part of the autopilot.Node interface. -func (d dbNode) PubKey() [33]byte { +func (d *dbNode) PubKey() [33]byte { return d.node.PubKeyBytes } @@ -75,7 +78,7 @@ func (d dbNode) PubKey() [33]byte { // peer is known to be listening on. // // NOTE: Part of the autopilot.Node interface. -func (d dbNode) Addrs() []net.Addr { +func (d *dbNode) Addrs() []net.Addr { return d.node.Addresses } @@ -85,32 +88,42 @@ func (d dbNode) Addrs() []net.Addr { // describes the active channel. // // NOTE: Part of the autopilot.Node interface. -func (d dbNode) ForEachChannel(cb func(ChannelEdge) error) error { - return d.node.ForEachChannel(d.tx, func(tx kvdb.RTx, - ei *channeldb.ChannelEdgeInfo, ep, _ *channeldb.ChannelEdgePolicy) error { +func (d *dbNode) ForEachChannel(cb func(ChannelEdge) error) error { + return d.db.ForEachNodeChannel(d.tx, d.node.PubKeyBytes, + func(tx kvdb.RTx, ei *models.ChannelEdgeInfo, ep, + _ *models.ChannelEdgePolicy) error { - // Skip channels for which no outgoing edge policy is available. - // - // TODO(joostjager): Ideally the case where channels have a nil - // policy should be supported, as autopilot is not looking at - // the policies. For now, it is not easily possible to get a - // reference to the other end LightningNode object without - // retrieving the policy. - if ep == nil { - return nil - } + // Skip channels for which no outgoing edge policy is + // available. + // + // TODO(joostjager): Ideally the case where channels + // have a nil policy should be supported, as autopilot + // is not looking at the policies. For now, it is not + // easily possible to get a reference to the other end + // LightningNode object without retrieving the policy. + if ep == nil { + return nil + } - edge := ChannelEdge{ - ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID), - Capacity: ei.Capacity, - Peer: dbNode{ - tx: tx, - node: ep.Node, - }, - } + node, err := d.db.FetchLightningNode(tx, ep.ToNode) + if err != nil { + return err + } - return cb(edge) - }) + edge := ChannelEdge{ + ChanID: lnwire.NewShortChanIDFromInt( + ep.ChannelID, + ), + Capacity: ei.Capacity, + Peer: &dbNode{ + tx: tx, + db: d.db, + node: node, + }, + } + + return cb(edge) + }) } // ForEachNode is a higher-order function that should be called once for each @@ -127,7 +140,8 @@ func (d *databaseChannelGraph) ForEachNode(cb func(Node) error) error { return nil } - node := dbNode{ + node := &dbNode{ + db: d.db, tx: tx, node: n, } @@ -150,7 +164,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, return nil, err } - dbNode, err := d.db.FetchLightningNode(vertex) + dbNode, err := d.db.FetchLightningNode(nil, vertex) switch { case err == channeldb.ErrGraphNodeNotFound: fallthrough @@ -222,7 +236,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, } chanID := randChanID() - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), Capacity: capacity, } @@ -230,7 +244,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, if err := d.db.AddChannelEdge(edge); err != nil { return nil, nil, err } - edgePolicy := &channeldb.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: chanID.ToUint64(), LastUpdate: time.Now(), @@ -246,7 +260,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil { return nil, nil, err } - edgePolicy = &channeldb.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: chanID.ToUint64(), LastUpdate: time.Now(), @@ -265,14 +279,16 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, return &ChannelEdge{ ChanID: chanID, Capacity: capacity, - Peer: dbNode{ + Peer: &dbNode{ + db: d.db, node: vertex1, }, }, &ChannelEdge{ ChanID: chanID, Capacity: capacity, - Peer: dbNode{ + Peer: &dbNode{ + db: d.db, node: vertex2, }, }, diff --git a/channeldb/channel_cache_test.go b/channeldb/channel_cache_test.go index d776c1318..7cb857293 100644 --- a/channeldb/channel_cache_test.go +++ b/channeldb/channel_cache_test.go @@ -3,6 +3,8 @@ package channeldb import ( "reflect" "testing" + + "github.com/lightningnetwork/lnd/channeldb/models" ) // TestChannelCache checks the behavior of the channelCache with respect to @@ -98,7 +100,7 @@ func assertHasChanEntries(t *testing.T, c *channelCache, start, end uint64) { // channelForInt generates a unique ChannelEdge given an integer. func channelForInt(i uint64) ChannelEdge { return ChannelEdge{ - Info: &ChannelEdgeInfo{ + Info: &models.ChannelEdgeInfo{ ChannelID: i, }, } diff --git a/channeldb/db.go b/channeldb/db.go index bf170e2ba..d1b9f684e 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -1351,7 +1351,7 @@ func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, if err != nil { return nil, err } - graphNode, err := d.graph.FetchLightningNode(pubKey) + graphNode, err := d.graph.FetchLightningNode(nil, pubKey) if err != nil && err != ErrGraphNodeNotFound { return nil, err } else if err == ErrGraphNodeNotFound { diff --git a/channeldb/graph.go b/channeldb/graph.go index 8367aaf68..c0cbc3287 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -16,12 +16,12 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/aliasmgr" "github.com/lightningnetwork/lnd/batch" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" @@ -161,9 +161,6 @@ const ( // would be possible for a node to create a ton of updates and slowly // fill our disk, and also waste bandwidth due to relaying. MaxAllowedExtraOpaqueBytes = 10000 - - // feeRateParts is the total number of parts used to express fee rates. - feeRateParts = 1e6 ) // ChannelGraph is a persistent, on-disk graph representation of the Lightning @@ -231,8 +228,8 @@ func NewChannelGraph(db kvdb.Backend, rejectCacheSize, chanCacheSize int, return nil, err } - err = g.ForEachChannel(func(info *ChannelEdgeInfo, - policy1, policy2 *ChannelEdgePolicy) error { + err = g.ForEachChannel(func(info *models.ChannelEdgeInfo, + policy1, policy2 *models.ChannelEdgePolicy) error { g.graphCache.AddChannel(info, policy1, policy2) @@ -258,10 +255,10 @@ type channelMapKey struct { // getChannelMap loads all channel edge policies from the database and stores // them in a map. func (c *ChannelGraph) getChannelMap(edges kvdb.RBucket) ( - map[channelMapKey]*ChannelEdgePolicy, error) { + map[channelMapKey]*models.ChannelEdgePolicy, error) { // Create a map to store all channel edge policies. - channelMap := make(map[channelMapKey]*ChannelEdgePolicy) + channelMap := make(map[channelMapKey]*models.ChannelEdgePolicy) err := kvdb.ForAll(edges, func(k, edgeBytes []byte) error { // Skip embedded buckets. @@ -411,8 +408,8 @@ func (c *ChannelGraph) NewPathFindTx() (kvdb.RTx, error) { // NOTE: If an edge can't be found, or wasn't advertised, then a nil pointer // for that particular channel edge routing policy will be passed into the // callback. -func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdgeInfo, - *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { +func (c *ChannelGraph) ForEachChannel(cb func(*models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, *models.ChannelEdgePolicy) error) error { return c.db.View(func(tx kvdb.RTx) error { edges := tx.ReadBucket(edgeBucket) @@ -459,16 +456,14 @@ func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdgeInfo, }, func() {}) } -// ForEachNodeChannel iterates through all channels of a given node, executing the -// passed callback with an edge info structure and the policies of each end -// of the channel. The first edge policy is the outgoing edge *to* the -// connecting node, while the second is the incoming edge *from* the -// connecting node. If the callback returns an error, then the iteration is -// halted with the error propagated back up to the caller. +// ForEachNodeDirectedChannel iterates through all channels of a given node, +// executing the passed callback on the directed edge representing the channel +// and its incoming policy. If the callback returns an error, then the iteration +// is halted with the error propagated back up to the caller. // // Unknown policies are passed into the callback as nil values. -func (c *ChannelGraph) ForEachNodeChannel(tx kvdb.RTx, node route.Vertex, - cb func(channel *DirectedChannel) error) error { +func (c *ChannelGraph) ForEachNodeDirectedChannel(tx kvdb.RTx, + node route.Vertex, cb func(channel *DirectedChannel) error) error { if c.graphCache != nil { return c.graphCache.ForEachChannel(node, cb) @@ -483,12 +478,12 @@ func (c *ChannelGraph) ForEachNodeChannel(tx kvdb.RTx, node route.Vertex, return err } - dbCallback := func(tx kvdb.RTx, e *ChannelEdgeInfo, p1, - p2 *ChannelEdgePolicy) error { + dbCallback := func(tx kvdb.RTx, e *models.ChannelEdgeInfo, p1, + p2 *models.ChannelEdgePolicy) error { - var cachedInPolicy *CachedEdgePolicy + var cachedInPolicy *models.CachedEdgePolicy if p2 != nil { - cachedInPolicy = NewCachedPolicy(p2) + cachedInPolicy = models.NewCachedPolicy(p2) cachedInPolicy.ToNodePubKey = toNodeCallback cachedInPolicy.ToNodeFeatures = toNodeFeatures } @@ -521,7 +516,7 @@ func (c *ChannelGraph) FetchNodeFeatures( } // Fallback that uses the database. - targetNode, err := c.FetchLightningNode(node) + targetNode, err := c.FetchLightningNode(nil, node) switch err { // If the node exists and has features, return them directly. case nil: @@ -557,44 +552,50 @@ func (c *ChannelGraph) ForEachNodeCached(cb func(node route.Vertex, return c.ForEachNode(func(tx kvdb.RTx, node *LightningNode) error { channels := make(map[uint64]*DirectedChannel) - err := node.ForEachChannel(tx, func(tx kvdb.RTx, - e *ChannelEdgeInfo, p1 *ChannelEdgePolicy, - p2 *ChannelEdgePolicy) error { + err := c.ForEachNodeChannel(tx, node.PubKeyBytes, + func(tx kvdb.RTx, e *models.ChannelEdgeInfo, + p1 *models.ChannelEdgePolicy, + p2 *models.ChannelEdgePolicy) error { - toNodeCallback := func() route.Vertex { - return node.PubKeyBytes - } - toNodeFeatures, err := c.FetchNodeFeatures( - node.PubKeyBytes, - ) - if err != nil { - return err - } + toNodeCallback := func() route.Vertex { + return node.PubKeyBytes + } + toNodeFeatures, err := c.FetchNodeFeatures( + node.PubKeyBytes, + ) + if err != nil { + return err + } - var cachedInPolicy *CachedEdgePolicy - if p2 != nil { - cachedInPolicy := NewCachedPolicy(p2) - cachedInPolicy.ToNodePubKey = toNodeCallback - cachedInPolicy.ToNodeFeatures = toNodeFeatures - } + var cachedInPolicy *models.CachedEdgePolicy + if p2 != nil { + cachedInPolicy = + models.NewCachedPolicy(p2) + cachedInPolicy.ToNodePubKey = + toNodeCallback + cachedInPolicy.ToNodeFeatures = + toNodeFeatures + } - directedChannel := &DirectedChannel{ - ChannelID: e.ChannelID, - IsNode1: node.PubKeyBytes == e.NodeKey1Bytes, - OtherNode: e.NodeKey2Bytes, - Capacity: e.Capacity, - OutPolicySet: p1 != nil, - InPolicy: cachedInPolicy, - } + directedChannel := &DirectedChannel{ + ChannelID: e.ChannelID, + IsNode1: node.PubKeyBytes == + e.NodeKey1Bytes, + OtherNode: e.NodeKey2Bytes, + Capacity: e.Capacity, + OutPolicySet: p1 != nil, + InPolicy: cachedInPolicy, + } - if node.PubKeyBytes == e.NodeKey2Bytes { - directedChannel.OtherNode = e.NodeKey1Bytes - } + if node.PubKeyBytes == e.NodeKey2Bytes { + directedChannel.OtherNode = + e.NodeKey1Bytes + } - channels[e.ChannelID] = directedChannel + channels[e.ChannelID] = directedChannel - return nil - }) + return nil + }) if err != nil { return err } @@ -679,7 +680,6 @@ func (c *ChannelGraph) ForEachNode( if err != nil { return err } - node.db = c.db // Execute the callback, the transaction will abort if // this returns an error. @@ -777,7 +777,6 @@ func (c *ChannelGraph) sourceNode(nodes kvdb.RBucket) (*LightningNode, error) { if err != nil { return nil, err } - node.db = c.db return &node, nil } @@ -967,7 +966,7 @@ func (c *ChannelGraph) deleteLightningNode(nodes kvdb.RwBucket, // involved in creation of the channel, and the set of features that the channel // supports. The chanPoint and chanID are used to uniquely identify the edge // globally within the database. -func (c *ChannelGraph) AddChannelEdge(edge *ChannelEdgeInfo, +func (c *ChannelGraph) AddChannelEdge(edge *models.ChannelEdgeInfo, op ...batch.SchedulerOption) error { var alreadyExists bool @@ -1010,7 +1009,9 @@ func (c *ChannelGraph) AddChannelEdge(edge *ChannelEdgeInfo, // addChannelEdge is the private form of AddChannelEdge that allows callers to // utilize an existing db transaction. -func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx, edge *ChannelEdgeInfo) error { +func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx, + edge *models.ChannelEdgeInfo) error { + // Construct the channel's primary key which is the 8-byte channel ID. var chanKey [8]byte binary.BigEndian.PutUint64(chanKey[:], edge.ChannelID) @@ -1186,8 +1187,9 @@ func (c *ChannelGraph) HasChannelEdge( return ErrGraphNodeNotFound } - e1, e2, err := fetchChanEdgePolicies(edgeIndex, edges, nodes, - channelID[:], c.db) + e1, e2, err := fetchChanEdgePolicies( + edgeIndex, edges, channelID[:], + ) if err != nil { return err } @@ -1220,7 +1222,7 @@ func (c *ChannelGraph) HasChannelEdge( // In order to maintain this constraints, we return an error in the scenario // that an edge info hasn't yet been created yet, but someone attempts to update // it. -func (c *ChannelGraph) UpdateChannelEdge(edge *ChannelEdgeInfo) error { +func (c *ChannelGraph) UpdateChannelEdge(edge *models.ChannelEdgeInfo) error { // Construct the channel's primary key which is the 8-byte channel ID. var chanKey [8]byte binary.BigEndian.PutUint64(chanKey[:], edge.ChannelID) @@ -1265,12 +1267,13 @@ const ( // with the current UTXO state. A slice of channels that have been closed by // the target block are returned if the function succeeds without error. func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint, - blockHash *chainhash.Hash, blockHeight uint32) ([]*ChannelEdgeInfo, error) { + blockHash *chainhash.Hash, blockHeight uint32) ( + []*models.ChannelEdgeInfo, error) { c.cacheMu.Lock() defer c.cacheMu.Unlock() - var chansClosed []*ChannelEdgeInfo + var chansClosed []*models.ChannelEdgeInfo err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { // First grab the edges bucket which houses the information @@ -1518,8 +1521,8 @@ func (c *ChannelGraph) pruneGraphNodes(nodes kvdb.RwBucket, // set to the last prune height valid for the remaining chain. // Channels that were removed from the graph resulting from the // disconnected block are returned. -func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInfo, - error) { +func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ( + []*models.ChannelEdgeInfo, error) { // Every channel having a ShortChannelID starting at 'height' // will no longer be confirmed. @@ -1541,7 +1544,7 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf defer c.cacheMu.Unlock() // Keep track of the channels that are removed from the graph. - var removedChans []*ChannelEdgeInfo + var removedChans []*models.ChannelEdgeInfo if err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { edges, err := tx.CreateTopLevelBucket(edgeBucket) @@ -1848,15 +1851,23 @@ func (c *ChannelGraph) HighestChanID() (uint64, error) { // edge as well as each of the known advertised edge policies. type ChannelEdge struct { // Info contains all the static information describing the channel. - Info *ChannelEdgeInfo + Info *models.ChannelEdgeInfo // Policy1 points to the "first" edge policy of the channel containing // the dynamic information required to properly route through the edge. - Policy1 *ChannelEdgePolicy + Policy1 *models.ChannelEdgePolicy // Policy2 points to the "second" edge policy of the channel containing // the dynamic information required to properly route through the edge. - Policy2 *ChannelEdgePolicy + Policy2 *models.ChannelEdgePolicy + + // Node1 is "node 1" in the channel. This is the node that would have + // produced Policy1 if it exists. + Node1 *LightningNode + + // Node2 is "node 2" in the channel. This is the node that would have + // produced Policy2 if it exists. + Node2 *LightningNode } // ChanUpdatesInHorizon returns all the known channel edges which have at least @@ -1938,12 +1949,11 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime, return fmt.Errorf("unable to fetch info for "+ "edge with chan_id=%v: %v", chanID, err) } - edgeInfo.db = c.db // With the static information obtained, we'll now // fetch the dynamic policy info. edge1, edge2, err := fetchChanEdgePolicies( - edgeIndex, edges, nodes, chanID, c.db, + edgeIndex, edges, chanID, ) if err != nil { chanID := byteOrder.Uint64(chanID) @@ -1952,6 +1962,20 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime, err) } + node1, err := fetchLightningNode( + nodes, edgeInfo.NodeKey1Bytes[:], + ) + if err != nil { + return err + } + + node2, err := fetchLightningNode( + nodes, edgeInfo.NodeKey2Bytes[:], + ) + if err != nil { + return err + } + // Finally, we'll collate this edge with the rest of // edges to be returned. edgesSeen[chanIDInt] = struct{}{} @@ -1959,6 +1983,8 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime, Info: &edgeInfo, Policy1: edge1, Policy2: edge2, + Node1: &node1, + Node2: &node2, } edgesInHorizon = append(edgesInHorizon, channel) edgesToCache[chanIDInt] = channel @@ -2035,7 +2061,6 @@ func (c *ChannelGraph) NodeUpdatesInHorizon(startTime, if err != nil { return err } - node.db = c.db nodesInHorizon = append(nodesInHorizon, node) } @@ -2270,12 +2295,25 @@ func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) { case err != nil: return err } - edgeInfo.db = c.db // With the static information obtained, we'll now // fetch the dynamic policy info. edge1, edge2, err := fetchChanEdgePolicies( - edgeIndex, edges, nodes, cidBytes[:], c.db, + edgeIndex, edges, cidBytes[:], + ) + if err != nil { + return err + } + + node1, err := fetchLightningNode( + nodes, edgeInfo.NodeKey1Bytes[:], + ) + if err != nil { + return err + } + + node2, err := fetchLightningNode( + nodes, edgeInfo.NodeKey2Bytes[:], ) if err != nil { return err @@ -2285,6 +2323,8 @@ func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) { Info: &edgeInfo, Policy1: edge1, Policy2: edge2, + Node1: &node1, + Node2: &node2, }) } return nil @@ -2299,7 +2339,7 @@ func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) { } func delEdgeUpdateIndexEntry(edgesBucket kvdb.RwBucket, chanID uint64, - edge1, edge2 *ChannelEdgePolicy) error { + edge1, edge2 *models.ChannelEdgePolicy) error { // First, we'll fetch the edge update index bucket which currently // stores an entry for the channel we're about to delete. @@ -2355,9 +2395,7 @@ func (c *ChannelGraph) delChannelEdge(edges, edgeIndex, chanIndex, zombieIndex, // we delete the edges themselves so we can access their last update // times. cid := byteOrder.Uint64(chanID) - edge1, edge2, err := fetchChanEdgePolicies( - edgeIndex, edges, nodes, chanID, nil, - ) + edge1, edge2, err := fetchChanEdgePolicies(edgeIndex, edges, chanID) if err != nil { return err } @@ -2438,8 +2476,8 @@ func (c *ChannelGraph) delChannelEdge(edges, edgeIndex, chanIndex, zombieIndex, // the channel. If the channel were to be marked zombie again, it would be // marked with the correct lagging channel since we received an update from only // one side. -func makeZombiePubkeys(info *ChannelEdgeInfo, - e1, e2 *ChannelEdgePolicy) ([33]byte, [33]byte) { +func makeZombiePubkeys(info *models.ChannelEdgeInfo, + e1, e2 *models.ChannelEdgePolicy) ([33]byte, [33]byte) { switch { // If we don't have either edge policy, we'll return both pubkeys so @@ -2469,7 +2507,7 @@ func makeZombiePubkeys(info *ChannelEdgeInfo, // updated, otherwise it's the second node's information. The node ordering is // determined by the lexicographical ordering of the identity public keys of the // nodes on either side of the channel. -func (c *ChannelGraph) UpdateEdgePolicy(edge *ChannelEdgePolicy, +func (c *ChannelGraph) UpdateEdgePolicy(edge *models.ChannelEdgePolicy, op ...batch.SchedulerOption) error { var ( @@ -2517,7 +2555,9 @@ func (c *ChannelGraph) UpdateEdgePolicy(edge *ChannelEdgePolicy, return c.chanScheduler.Execute(r) } -func (c *ChannelGraph) updateEdgeCache(e *ChannelEdgePolicy, isUpdate1 bool) { +func (c *ChannelGraph) updateEdgeCache(e *models.ChannelEdgePolicy, + isUpdate1 bool) { + // If an entry for this channel is found in reject cache, we'll modify // the entry with the updated timestamp for the direction that was just // written. If the edge doesn't exist, we'll load the cache entry lazily @@ -2549,7 +2589,7 @@ func (c *ChannelGraph) updateEdgeCache(e *ChannelEdgePolicy, isUpdate1 bool) { // buckets using an existing database transaction. The returned boolean will be // true if the updated policy belongs to node1, and false if the policy belonged // to node2. -func updateEdgePolicy(tx kvdb.RwTx, edge *ChannelEdgePolicy, +func updateEdgePolicy(tx kvdb.RwTx, edge *models.ChannelEdgePolicy, graphCache *GraphCache) (bool, error) { edges := tx.ReadWriteBucket(edgeBucket) @@ -2560,10 +2600,6 @@ func updateEdgePolicy(tx kvdb.RwTx, edge *ChannelEdgePolicy, if edgeIndex == nil { return false, ErrEdgeNotFound } - nodes, err := tx.CreateTopLevelBucket(nodeBucket) - if err != nil { - return false, err - } // Create the channelID key be converting the channel ID // integer into a byte slice. @@ -2593,7 +2629,7 @@ func updateEdgePolicy(tx kvdb.RwTx, edge *ChannelEdgePolicy, // Finally, with the direction of the edge being updated // identified, we update the on-disk edge representation. - err = putChanEdgePolicy(edges, nodes, edge, fromNode, toNode) + err := putChanEdgePolicy(edges, edge, fromNode, toNode) if err != nil { return false, err } @@ -2657,8 +2693,6 @@ type LightningNode struct { // compatible manner. ExtraOpaqueData []byte - db kvdb.Backend - // TODO(roasbeef): discovery will need storage to keep it's last IP // address and re-announce if interface changes? @@ -2740,15 +2774,18 @@ func (l *LightningNode) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement, // isPublic determines whether the node is seen as public within the graph from // the source node's point of view. An existing database transaction can also be // specified. -func (l *LightningNode) isPublic(tx kvdb.RTx, sourcePubKey []byte) (bool, error) { +func (c *ChannelGraph) isPublic(tx kvdb.RTx, nodePub route.Vertex, + sourcePubKey []byte) (bool, error) { + // In order to determine whether this node is publicly advertised within // the graph, we'll need to look at all of its edges and check whether // they extend to any other node than the source node. errDone will be // used to terminate the check early. nodeIsPublic := false errDone := errors.New("done") - err := l.ForEachChannel(tx, func(_ kvdb.RTx, info *ChannelEdgeInfo, - _, _ *ChannelEdgePolicy) error { + err := c.ForEachNodeChannel(tx, nodePub, func(tx kvdb.RTx, + info *models.ChannelEdgeInfo, _ *models.ChannelEdgePolicy, + _ *models.ChannelEdgePolicy) error { // If this edge doesn't extend to the source node, we'll // terminate our search as we can now conclude that the node is @@ -2780,12 +2817,13 @@ func (l *LightningNode) isPublic(tx kvdb.RTx, sourcePubKey []byte) (bool, error) // FetchLightningNode attempts to look up a target node by its identity public // key. If the node isn't found in the database, then ErrGraphNodeNotFound is -// returned. -func (c *ChannelGraph) FetchLightningNode(nodePub route.Vertex) ( +// returned. An optional transaction may be provided. If none is provided, then +// a new one will be created. +func (c *ChannelGraph) FetchLightningNode(tx kvdb.RTx, nodePub route.Vertex) ( *LightningNode, error) { var node *LightningNode - err := kvdb.View(c.db, func(tx kvdb.RTx) error { + fetch := func(tx kvdb.RTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. nodes := tx.ReadBucket(nodeBucket) @@ -2807,14 +2845,26 @@ func (c *ChannelGraph) FetchLightningNode(nodePub route.Vertex) ( if err != nil { return err } - n.db = c.db node = &n return nil - }, func() { - node = nil - }) + } + + if tx == nil { + err := kvdb.View( + c.db, fetch, func() { + node = nil + }, + ) + if err != nil { + return nil, err + } + + return node, nil + } + + err := fetch(tx) if err != nil { return nil, err } @@ -2858,8 +2908,8 @@ func (n *graphCacheNode) Features() *lnwire.FeatureVector { // // Unknown policies are passed into the callback as nil values. func (n *graphCacheNode) ForEachChannel(tx kvdb.RTx, - cb func(kvdb.RTx, *ChannelEdgeInfo, *ChannelEdgePolicy, - *ChannelEdgePolicy) error) error { + cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy) error) error { return nodeTraversal(tx, n.pubKeyBytes[:], nil, cb) } @@ -2919,13 +2969,10 @@ func (c *ChannelGraph) HasLightningNode(nodePub [33]byte) (time.Time, bool, erro // nodeTraversal is used to traverse all channels of a node given by its // public key and passes channel information into the specified callback. func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend, - cb func(kvdb.RTx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { + cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy) error) error { traversal := func(tx kvdb.RTx) error { - nodes := tx.ReadBucket(nodeBucket) - if nodes == nil { - return ErrGraphNotFound - } edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNotFound @@ -2961,10 +3008,9 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend, if err != nil { return err } - edgeInfo.db = db outgoingPolicy, err := fetchChanEdgePolicy( - edges, chanID, nodePub, nodes, + edges, chanID, nodePub, ) if err != nil { return err @@ -2976,7 +3022,7 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend, } incomingPolicy, err := fetchChanEdgePolicy( - edges, chanID, otherNode[:], nodes, + edges, chanID, otherNode[:], ) if err != nil { return err @@ -3003,10 +3049,10 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend, return traversal(tx) } -// ForEachChannel iterates through all channels of this node, executing the -// passed callback with an edge info structure and the policies of each end -// of the channel. The first edge policy is the outgoing edge *to* the -// connecting node, while the second is the incoming edge *from* the +// ForEachNodeChannel iterates through all channels of the given node, +// executing the passed callback with an edge info structure and the policies +// of each end of the channel. The first edge policy is the outgoing edge *to* +// the connecting node, while the second is the incoming edge *from* the // connecting node. If the callback returns an error, then the iteration is // halted with the error propagated back up to the caller. // @@ -3016,209 +3062,28 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend, // should be passed as the first argument. Otherwise the first argument should // be nil and a fresh transaction will be created to execute the graph // traversal. -func (l *LightningNode) ForEachChannel(tx kvdb.RTx, - cb func(kvdb.RTx, *ChannelEdgeInfo, *ChannelEdgePolicy, - *ChannelEdgePolicy) error) error { +func (c *ChannelGraph) ForEachNodeChannel(tx kvdb.RTx, nodePub route.Vertex, + cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy) error) error { - nodePub := l.PubKeyBytes[:] - db := l.db - - return nodeTraversal(tx, nodePub, db, cb) -} - -// ChannelEdgeInfo represents a fully authenticated channel along with all its -// unique attributes. Once an authenticated channel announcement has been -// processed on the network, then an instance of ChannelEdgeInfo encapsulating -// the channels attributes is stored. The other portions relevant to routing -// policy of a channel are stored within a ChannelEdgePolicy for each direction -// of the channel. -type ChannelEdgeInfo struct { - // ChannelID is the unique channel ID for the channel. The first 3 - // bytes are the block height, the next 3 the index within the block, - // and the last 2 bytes are the output index for the channel. - ChannelID uint64 - - // ChainHash is the hash that uniquely identifies the chain that this - // channel was opened within. - // - // TODO(roasbeef): need to modify db keying for multi-chain - // * must add chain hash to prefix as well - ChainHash chainhash.Hash - - // NodeKey1Bytes is the raw public key of the first node. - NodeKey1Bytes [33]byte - nodeKey1 *btcec.PublicKey - - // NodeKey2Bytes is the raw public key of the first node. - NodeKey2Bytes [33]byte - nodeKey2 *btcec.PublicKey - - // BitcoinKey1Bytes is the raw public key of the first node. - BitcoinKey1Bytes [33]byte - bitcoinKey1 *btcec.PublicKey - - // BitcoinKey2Bytes is the raw public key of the first node. - BitcoinKey2Bytes [33]byte - bitcoinKey2 *btcec.PublicKey - - // Features is an opaque byte slice that encodes the set of channel - // specific features that this channel edge supports. - Features []byte - - // AuthProof is the authentication proof for this channel. This proof - // contains a set of signatures binding four identities, which attests - // to the legitimacy of the advertised channel. - AuthProof *ChannelAuthProof - - // ChannelPoint is the funding outpoint of the channel. This can be - // used to uniquely identify the channel within the channel graph. - ChannelPoint wire.OutPoint - - // Capacity is the total capacity of the channel, this is determined by - // the value output in the outpoint that created this channel. - Capacity btcutil.Amount - - // 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 - - db kvdb.Backend -} - -// AddNodeKeys is a setter-like method that can be used to replace the set of -// keys for the target ChannelEdgeInfo. -func (c *ChannelEdgeInfo) AddNodeKeys(nodeKey1, nodeKey2, bitcoinKey1, - bitcoinKey2 *btcec.PublicKey) { - - c.nodeKey1 = nodeKey1 - copy(c.NodeKey1Bytes[:], c.nodeKey1.SerializeCompressed()) - - c.nodeKey2 = nodeKey2 - copy(c.NodeKey2Bytes[:], nodeKey2.SerializeCompressed()) - - c.bitcoinKey1 = bitcoinKey1 - copy(c.BitcoinKey1Bytes[:], c.bitcoinKey1.SerializeCompressed()) - - c.bitcoinKey2 = bitcoinKey2 - copy(c.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) -} - -// 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 -// that of the other node involved in channel creation. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) NodeKey1() (*btcec.PublicKey, error) { - if c.nodeKey1 != nil { - return c.nodeKey1, nil - } - - key, err := btcec.ParsePubKey(c.NodeKey1Bytes[:]) - if err != nil { - return nil, err - } - c.nodeKey1 = key - - return key, nil -} - -// NodeKey2 is the identity public key of the "second" node that was -// involved in the creation of this channel. A node is considered -// "second" if the lexicographical ordering the its serialized public -// key is "larger" than that of the other node involved in channel -// creation. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) NodeKey2() (*btcec.PublicKey, error) { - if c.nodeKey2 != nil { - return c.nodeKey2, nil - } - - key, err := btcec.ParsePubKey(c.NodeKey2Bytes[:]) - if err != nil { - return nil, err - } - c.nodeKey2 = key - - return key, nil -} - -// BitcoinKey1 is the Bitcoin multi-sig key belonging to the first -// node, that was involved in the funding transaction that originally -// created the channel that this struct represents. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) BitcoinKey1() (*btcec.PublicKey, error) { - if c.bitcoinKey1 != nil { - return c.bitcoinKey1, nil - } - - key, err := btcec.ParsePubKey(c.BitcoinKey1Bytes[:]) - if err != nil { - return nil, err - } - c.bitcoinKey1 = key - - return key, nil -} - -// BitcoinKey2 is the Bitcoin multi-sig key belonging to the second -// node, that was involved in the funding transaction that originally -// created the channel that this struct represents. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) BitcoinKey2() (*btcec.PublicKey, error) { - if c.bitcoinKey2 != nil { - return c.bitcoinKey2, nil - } - - key, err := btcec.ParsePubKey(c.BitcoinKey2Bytes[:]) - if err != nil { - return nil, err - } - c.bitcoinKey2 = key - - return key, nil -} - -// OtherNodeKeyBytes returns the node key bytes of the other end of -// the channel. -func (c *ChannelEdgeInfo) OtherNodeKeyBytes(thisNodeKey []byte) ( - [33]byte, error) { - - switch { - case bytes.Equal(c.NodeKey1Bytes[:], thisNodeKey): - return c.NodeKey2Bytes, nil - case bytes.Equal(c.NodeKey2Bytes[:], thisNodeKey): - return c.NodeKey1Bytes, nil - default: - return [33]byte{}, fmt.Errorf("node not participating in this channel") - } + return nodeTraversal(tx, nodePub[:], c.db, cb) } // FetchOtherNode attempts to fetch the full LightningNode that's opposite of // the target node in the channel. This is useful when one knows the pubkey of // one of the nodes, and wishes to obtain the full LightningNode for the other // end of the channel. -func (c *ChannelEdgeInfo) FetchOtherNode(tx kvdb.RTx, - thisNodeKey []byte) (*LightningNode, error) { +func (c *ChannelGraph) FetchOtherNode(tx kvdb.RTx, + channel *models.ChannelEdgeInfo, thisNodeKey []byte) (*LightningNode, + error) { // Ensure that the node passed in is actually a member of the channel. var targetNodeBytes [33]byte switch { - case bytes.Equal(c.NodeKey1Bytes[:], thisNodeKey): - targetNodeBytes = c.NodeKey2Bytes - case bytes.Equal(c.NodeKey2Bytes[:], thisNodeKey): - targetNodeBytes = c.NodeKey1Bytes + case bytes.Equal(channel.NodeKey1Bytes[:], thisNodeKey): + targetNodeBytes = channel.NodeKey2Bytes + case bytes.Equal(channel.NodeKey2Bytes[:], thisNodeKey): + targetNodeBytes = channel.NodeKey1Bytes default: return nil, fmt.Errorf("node not participating in this channel") } @@ -3236,7 +3101,6 @@ func (c *ChannelEdgeInfo) FetchOtherNode(tx kvdb.RTx, if err != nil { return err } - node.db = c.db targetNode = &node @@ -3255,271 +3119,19 @@ func (c *ChannelEdgeInfo) FetchOtherNode(tx kvdb.RTx, return targetNode, err } -// ChannelAuthProof is the authentication proof (the signature portion) for a -// channel. Using the four signatures contained in the struct, and some -// auxiliary knowledge (the funding script, node identities, and outpoint) nodes -// on the network are able to validate the authenticity and existence of a -// channel. Each of these signatures signs the following digest: chanID || -// nodeID1 || nodeID2 || bitcoinKey1|| bitcoinKey2 || 2-byte-feature-len || -// features. -type ChannelAuthProof struct { - // nodeSig1 is a cached instance of the first node signature. - nodeSig1 *ecdsa.Signature - - // NodeSig1Bytes are the raw bytes of the first node signature encoded - // in DER format. - NodeSig1Bytes []byte - - // nodeSig2 is a cached instance of the second node signature. - nodeSig2 *ecdsa.Signature - - // NodeSig2Bytes are the raw bytes of the second node signature - // encoded in DER format. - NodeSig2Bytes []byte - - // bitcoinSig1 is a cached instance of the first bitcoin signature. - bitcoinSig1 *ecdsa.Signature - - // BitcoinSig1Bytes are the raw bytes of the first bitcoin signature - // encoded in DER format. - BitcoinSig1Bytes []byte - - // bitcoinSig2 is a cached instance of the second bitcoin signature. - bitcoinSig2 *ecdsa.Signature - - // BitcoinSig2Bytes are the raw bytes of the second bitcoin signature - // encoded in DER format. - BitcoinSig2Bytes []byte -} - -// Node1Sig is the signature using the identity key of the node that is first -// in a lexicographical ordering of the serialized public keys of the two nodes -// that created the channel. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) Node1Sig() (*ecdsa.Signature, error) { - if c.nodeSig1 != nil { - return c.nodeSig1, nil - } - - sig, err := ecdsa.ParseSignature(c.NodeSig1Bytes) - if err != nil { - return nil, err - } - - c.nodeSig1 = sig - - return sig, nil -} - -// Node2Sig is the signature using the identity key of the node that is second -// in a lexicographical ordering of the serialized public keys of the two nodes -// that created the channel. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) Node2Sig() (*ecdsa.Signature, error) { - if c.nodeSig2 != nil { - return c.nodeSig2, nil - } - - sig, err := ecdsa.ParseSignature(c.NodeSig2Bytes) - if err != nil { - return nil, err - } - - c.nodeSig2 = sig - - return sig, nil -} - -// BitcoinSig1 is the signature using the public key of the first node that was -// used in the channel's multi-sig output. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) BitcoinSig1() (*ecdsa.Signature, error) { - if c.bitcoinSig1 != nil { - return c.bitcoinSig1, nil - } - - sig, err := ecdsa.ParseSignature(c.BitcoinSig1Bytes) - if err != nil { - return nil, err - } - - c.bitcoinSig1 = sig - - return sig, nil -} - -// BitcoinSig2 is the signature using the public key of the second node that -// was used in the channel's multi-sig output. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) BitcoinSig2() (*ecdsa.Signature, error) { - if c.bitcoinSig2 != nil { - return c.bitcoinSig2, nil - } - - sig, err := ecdsa.ParseSignature(c.BitcoinSig2Bytes) - if err != nil { - return nil, err - } - - c.bitcoinSig2 = sig - - return sig, nil -} - -// IsEmpty check is the authentication proof is empty Proof is empty if at -// least one of the signatures are equal to nil. -func (c *ChannelAuthProof) IsEmpty() bool { - return len(c.NodeSig1Bytes) == 0 || - len(c.NodeSig2Bytes) == 0 || - len(c.BitcoinSig1Bytes) == 0 || - len(c.BitcoinSig2Bytes) == 0 -} - -// ChannelEdgePolicy represents a *directed* edge within the channel graph. For -// each channel in the database, there are two distinct edges: one for each -// possible direction of travel along the channel. The edges themselves hold -// information concerning fees, and minimum time-lock information which is -// utilized during path finding. -type ChannelEdgePolicy struct { - // SigBytes is the raw bytes of the signature of the channel edge - // policy. We'll only parse these if the caller needs to access the - // signature for validation purposes. Do not set SigBytes directly, but - // use SetSigBytes instead to make sure that the cache is invalidated. - SigBytes []byte - - // sig is a cached fully parsed signature. - sig *ecdsa.Signature - - // ChannelID is the unique channel ID for the channel. The first 3 - // bytes are the block height, the next 3 the index within the block, - // and the last 2 bytes are the output index for the channel. - ChannelID uint64 - - // LastUpdate is the last time an authenticated edge for this channel - // was received. - LastUpdate time.Time - - // MessageFlags is a bitfield which indicates the presence of optional - // fields (like max_htlc) in the policy. - MessageFlags lnwire.ChanUpdateMsgFlags - - // ChannelFlags is a bitfield which signals the capabilities of the - // channel as well as the directed edge this update applies to. - ChannelFlags lnwire.ChanUpdateChanFlags - - // TimeLockDelta is the number of blocks this node will subtract from - // the expiry of an incoming HTLC. This value expresses the time buffer - // the node would like to HTLC exchanges. - TimeLockDelta uint16 - - // MinHTLC is the smallest value HTLC this node will forward, expressed - // in millisatoshi. - MinHTLC lnwire.MilliSatoshi - - // MaxHTLC is the largest value HTLC this node will forward, expressed - // in millisatoshi. - MaxHTLC lnwire.MilliSatoshi - - // FeeBaseMSat is the base HTLC fee that will be charged for forwarding - // ANY HTLC, expressed in mSAT's. - FeeBaseMSat lnwire.MilliSatoshi - - // FeeProportionalMillionths is the rate that the node will charge for - // HTLCs for each millionth of a satoshi forwarded. - FeeProportionalMillionths lnwire.MilliSatoshi - - // Node is the LightningNode that this directed edge leads to. Using - // this pointer the channel graph can further be traversed. - Node *LightningNode - - // 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 - - db kvdb.Backend -} - -// Signature is a channel announcement signature, which is needed for proper -// edge policy announcement. -// -// NOTE: By having this method to access an attribute, we ensure we only need -// to fully deserialize the signature if absolutely necessary. -func (c *ChannelEdgePolicy) Signature() (*ecdsa.Signature, error) { - if c.sig != nil { - return c.sig, nil - } - - sig, err := ecdsa.ParseSignature(c.SigBytes) - if err != nil { - return nil, err - } - - c.sig = sig - - return sig, nil -} - -// SetSigBytes updates the signature and invalidates the cached parsed -// signature. -func (c *ChannelEdgePolicy) SetSigBytes(sig []byte) { - c.SigBytes = sig - c.sig = nil -} - -// IsDisabled determines whether the edge has the disabled bit set. -func (c *ChannelEdgePolicy) IsDisabled() bool { - return c.ChannelFlags.IsDisabled() -} - -// ComputeFee computes the fee to forward an HTLC of `amt` milli-satoshis over -// the passed active payment channel. This value is currently computed as -// specified in BOLT07, but will likely change in the near future. -func (c *ChannelEdgePolicy) ComputeFee( - amt lnwire.MilliSatoshi) lnwire.MilliSatoshi { - - return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts -} - -// divideCeil divides dividend by factor and rounds the result up. -func divideCeil(dividend, factor lnwire.MilliSatoshi) lnwire.MilliSatoshi { - return (dividend + factor - 1) / factor -} - -// ComputeFeeFromIncoming computes the fee to forward an HTLC given the incoming -// amount. -func (c *ChannelEdgePolicy) ComputeFeeFromIncoming( - incomingAmt lnwire.MilliSatoshi) lnwire.MilliSatoshi { - - return incomingAmt - divideCeil( - feeRateParts*(incomingAmt-c.FeeBaseMSat), - feeRateParts+c.FeeProportionalMillionths, - ) -} - // FetchChannelEdgesByOutpoint attempts to lookup the two directed edges for // the channel identified by the funding outpoint. If the channel can't be // found, then ErrEdgeNotFound is returned. A struct which houses the general // information for the channel itself is returned as well as two structs that // contain the routing policies for the channel in either direction. -func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint, -) (*ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy, error) { +func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) ( + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) { var ( - edgeInfo *ChannelEdgeInfo - policy1 *ChannelEdgePolicy - policy2 *ChannelEdgePolicy + edgeInfo *models.ChannelEdgeInfo + policy1 *models.ChannelEdgePolicy + policy2 *models.ChannelEdgePolicy ) err := kvdb.View(c.db, func(tx kvdb.RTx) error { @@ -3564,14 +3176,11 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint, return err } edgeInfo = &edge - edgeInfo.db = c.db // Once we have the information about the channels' parameters, // we'll fetch the routing policies for each for the directed // edges. - e1, e2, err := fetchChanEdgePolicies( - edgeIndex, edges, nodes, chanID, c.db, - ) + e1, e2, err := fetchChanEdgePolicies(edgeIndex, edges, chanID) if err != nil { return err } @@ -3600,13 +3209,14 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint, // ErrZombieEdge an be returned if the edge is currently marked as a zombie // within the database. In this case, the ChannelEdgePolicy's will be nil, and // the ChannelEdgeInfo will only include the public keys of each node. -func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64, -) (*ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy, error) { +func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) ( + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) { var ( - edgeInfo *ChannelEdgeInfo - policy1 *ChannelEdgePolicy - policy2 *ChannelEdgePolicy + edgeInfo *models.ChannelEdgeInfo + policy1 *models.ChannelEdgePolicy + policy2 *models.ChannelEdgePolicy channelID [8]byte ) @@ -3657,7 +3267,7 @@ func (c *ChannelGraph) 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 = &ChannelEdgeInfo{ + edgeInfo = &models.ChannelEdgeInfo{ NodeKey1Bytes: pubKey1, NodeKey2Bytes: pubKey2, } @@ -3670,12 +3280,11 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64, } edgeInfo = &edge - edgeInfo.db = c.db // Then we'll attempt to fetch the accompanying policies of this // edge. e1, e2, err := fetchChanEdgePolicies( - edgeIndex, edges, nodes, channelID[:], c.db, + edgeIndex, edges, channelID[:], ) if err != nil { return err @@ -3718,7 +3327,7 @@ func (c *ChannelGraph) IsPublicNode(pubKey [33]byte) (bool, error) { return err } - nodeIsPublic, err = node.isPublic(tx, ourPubKey) + nodeIsPublic, err = c.isPublic(tx, node.PubKeyBytes, ourPubKey) return err }, func() { nodeIsPublic = false @@ -3834,11 +3443,6 @@ func (c *ChannelGraph) ChannelView() ([]EdgePoint, error) { return edgePoints, nil } -// NewChannelEdgePolicy returns a new blank ChannelEdgePolicy. -func (c *ChannelGraph) NewChannelEdgePolicy() *ChannelEdgePolicy { - return &ChannelEdgePolicy{db: c.db} -} - // MarkEdgeZombie attempts to mark a channel identified by its channel ID as a // zombie. This method is used on an ad-hoc basis, when channels need to be // marked as zombies outside the normal pruning cycle. @@ -4309,7 +3913,9 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) { return node, nil } -func putChanEdgeInfo(edgeIndex kvdb.RwBucket, edgeInfo *ChannelEdgeInfo, chanID [8]byte) error { +func putChanEdgeInfo(edgeIndex kvdb.RwBucket, + edgeInfo *models.ChannelEdgeInfo, chanID [8]byte) error { + var b bytes.Buffer if _, err := b.Write(edgeInfo.NodeKey1Bytes[:]); err != nil { @@ -4376,58 +3982,58 @@ func putChanEdgeInfo(edgeIndex kvdb.RwBucket, edgeInfo *ChannelEdgeInfo, chanID } func fetchChanEdgeInfo(edgeIndex kvdb.RBucket, - chanID []byte) (ChannelEdgeInfo, error) { + chanID []byte) (models.ChannelEdgeInfo, error) { edgeInfoBytes := edgeIndex.Get(chanID) if edgeInfoBytes == nil { - return ChannelEdgeInfo{}, ErrEdgeNotFound + return models.ChannelEdgeInfo{}, ErrEdgeNotFound } edgeInfoReader := bytes.NewReader(edgeInfoBytes) return deserializeChanEdgeInfo(edgeInfoReader) } -func deserializeChanEdgeInfo(r io.Reader) (ChannelEdgeInfo, error) { +func deserializeChanEdgeInfo(r io.Reader) (models.ChannelEdgeInfo, error) { var ( err error - edgeInfo ChannelEdgeInfo + edgeInfo models.ChannelEdgeInfo ) if _, err := io.ReadFull(r, edgeInfo.NodeKey1Bytes[:]); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } if _, err := io.ReadFull(r, edgeInfo.NodeKey2Bytes[:]); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } if _, err := io.ReadFull(r, edgeInfo.BitcoinKey1Bytes[:]); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } if _, err := io.ReadFull(r, edgeInfo.BitcoinKey2Bytes[:]); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } edgeInfo.Features, err = wire.ReadVarBytes(r, 0, 900, "features") if err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } - proof := &ChannelAuthProof{} + proof := &models.ChannelAuthProof{} proof.NodeSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") if err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } proof.NodeSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") if err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } proof.BitcoinSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") if err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } proof.BitcoinSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") if err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } if !proof.IsEmpty() { @@ -4436,17 +4042,17 @@ func deserializeChanEdgeInfo(r io.Reader) (ChannelEdgeInfo, error) { edgeInfo.ChannelPoint = wire.OutPoint{} if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } if err := binary.Read(r, byteOrder, &edgeInfo.ChannelID); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } if _, err := io.ReadFull(r, edgeInfo.ChainHash[:]); err != nil { - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } // We'll try and see if there are any opaque bytes left, if not, then @@ -4458,13 +4064,13 @@ func deserializeChanEdgeInfo(r io.Reader) (ChannelEdgeInfo, error) { case err == io.ErrUnexpectedEOF: case err == io.EOF: case err != nil: - return ChannelEdgeInfo{}, err + return models.ChannelEdgeInfo{}, err } return edgeInfo, nil } -func putChanEdgePolicy(edges, nodes kvdb.RwBucket, edge *ChannelEdgePolicy, +func putChanEdgePolicy(edges kvdb.RwBucket, edge *models.ChannelEdgePolicy, from, to []byte) error { var edgeKey [33 + 8]byte @@ -4505,7 +4111,7 @@ func putChanEdgePolicy(edges, nodes kvdb.RwBucket, edge *ChannelEdgePolicy, // TODO(halseth): get rid of these invalid policies in a // migration. oldEdgePolicy, err := deserializeChanEdgePolicy( - bytes.NewReader(edgeBytes), nodes, + bytes.NewReader(edgeBytes), ) if err != nil && err != ErrEdgePolicyOptionalFieldNotFound { return err @@ -4585,7 +4191,7 @@ func putChanEdgePolicyUnknown(edges kvdb.RwBucket, channelID uint64, } func fetchChanEdgePolicy(edges kvdb.RBucket, chanID []byte, - nodePub []byte, nodes kvdb.RBucket) (*ChannelEdgePolicy, error) { + nodePub []byte) (*models.ChannelEdgePolicy, error) { var edgeKey [33 + 8]byte copy(edgeKey[:], nodePub) @@ -4603,7 +4209,7 @@ func fetchChanEdgePolicy(edges kvdb.RBucket, chanID []byte, edgeReader := bytes.NewReader(edgeBytes) - ep, err := deserializeChanEdgePolicy(edgeReader, nodes) + ep, err := deserializeChanEdgePolicy(edgeReader) switch { // If the db policy was missing an expected optional field, we return // nil as if the policy was unknown. @@ -4618,8 +4224,8 @@ func fetchChanEdgePolicy(edges kvdb.RBucket, chanID []byte, } func fetchChanEdgePolicies(edgeIndex kvdb.RBucket, edges kvdb.RBucket, - nodes kvdb.RBucket, chanID []byte, - db kvdb.Backend) (*ChannelEdgePolicy, *ChannelEdgePolicy, error) { + chanID []byte) (*models.ChannelEdgePolicy, *models.ChannelEdgePolicy, + error) { edgeInfo := edgeIndex.Get(chanID) if edgeInfo == nil { @@ -4630,35 +4236,23 @@ func fetchChanEdgePolicies(edgeIndex kvdb.RBucket, edges kvdb.RBucket, // information. We only propagate the error here and below if it's // something other than edge non-existence. node1Pub := edgeInfo[:33] - edge1, err := fetchChanEdgePolicy(edges, chanID, node1Pub, nodes) + edge1, err := fetchChanEdgePolicy(edges, chanID, node1Pub) if err != nil { return nil, nil, err } - // As we may have a single direction of the edge but not the other, - // only fill in the database pointers if the edge is found. - if edge1 != nil { - edge1.db = db - edge1.Node.db = db - } - // Similarly, the second node is contained within the latter // half of the edge information. node2Pub := edgeInfo[33:66] - edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub, nodes) + edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub) if err != nil { return nil, nil, err } - if edge2 != nil { - edge2.db = db - edge2.Node.db = db - } - return edge1, edge2, nil } -func serializeChanEdgePolicy(w io.Writer, edge *ChannelEdgePolicy, +func serializeChanEdgePolicy(w io.Writer, edge *models.ChannelEdgePolicy, to []byte) error { err := wire.WriteVarBytes(w, 0, edge.SigBytes) @@ -4725,9 +4319,7 @@ func serializeChanEdgePolicy(w io.Writer, edge *ChannelEdgePolicy, return nil } -func deserializeChanEdgePolicy(r io.Reader, - nodes kvdb.RBucket) (*ChannelEdgePolicy, error) { - +func deserializeChanEdgePolicy(r io.Reader) (*models.ChannelEdgePolicy, error) { // Deserialize the policy. Note that in case an optional field is not // found, both an error and a populated policy object are returned. edge, deserializeErr := deserializeChanEdgePolicyRaw(r) @@ -4737,19 +4329,13 @@ func deserializeChanEdgePolicy(r io.Reader, return nil, deserializeErr } - // Populate full LightningNode struct. - pub := edge.Node.PubKeyBytes[:] - node, err := fetchLightningNode(nodes, pub) - if err != nil { - return nil, fmt.Errorf("unable to fetch node: %x, %v", pub, err) - } - edge.Node = &node - return edge, deserializeErr } -func deserializeChanEdgePolicyRaw(r io.Reader) (*ChannelEdgePolicy, error) { - edge := &ChannelEdgePolicy{} +func deserializeChanEdgePolicyRaw(r io.Reader) (*models.ChannelEdgePolicy, + error) { + + edge := &models.ChannelEdgePolicy{} var err error edge.SigBytes, err = wire.ReadVarBytes(r, 0, 80, "sig") @@ -4794,13 +4380,9 @@ func deserializeChanEdgePolicyRaw(r io.Reader) (*ChannelEdgePolicy, error) { } edge.FeeProportionalMillionths = lnwire.MilliSatoshi(n) - var pub [33]byte - if _, err := r.Read(pub[:]); err != nil { + if _, err := r.Read(edge.ToNode[:]); err != nil { return nil, err } - edge.Node = &LightningNode{ - PubKeyBytes: pub, - } // We'll try and see if there are any opaque bytes left, if not, then // we'll ignore the EOF error and return the edge as is. diff --git a/channeldb/graph_cache.go b/channeldb/graph_cache.go index 1aae21d06..7bf9c41d9 100644 --- a/channeldb/graph_cache.go +++ b/channeldb/graph_cache.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/btcsuite/btcd/btcutil" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -27,94 +28,9 @@ type GraphCacheNode interface { // error, then the iteration is halted with the error propagated back up // to the caller. ForEachChannel(kvdb.RTx, - func(kvdb.RTx, *ChannelEdgeInfo, *ChannelEdgePolicy, - *ChannelEdgePolicy) error) error -} - -// CachedEdgePolicy is a struct that only caches the information of a -// ChannelEdgePolicy that we actually use for pathfinding and therefore need to -// store in the cache. -type CachedEdgePolicy struct { - // ChannelID is the unique channel ID for the channel. The first 3 - // bytes are the block height, the next 3 the index within the block, - // and the last 2 bytes are the output index for the channel. - ChannelID uint64 - - // MessageFlags is a bitfield which indicates the presence of optional - // fields (like max_htlc) in the policy. - MessageFlags lnwire.ChanUpdateMsgFlags - - // ChannelFlags is a bitfield which signals the capabilities of the - // channel as well as the directed edge this update applies to. - ChannelFlags lnwire.ChanUpdateChanFlags - - // TimeLockDelta is the number of blocks this node will subtract from - // the expiry of an incoming HTLC. This value expresses the time buffer - // the node would like to HTLC exchanges. - TimeLockDelta uint16 - - // MinHTLC is the smallest value HTLC this node will forward, expressed - // in millisatoshi. - MinHTLC lnwire.MilliSatoshi - - // MaxHTLC is the largest value HTLC this node will forward, expressed - // in millisatoshi. - MaxHTLC lnwire.MilliSatoshi - - // FeeBaseMSat is the base HTLC fee that will be charged for forwarding - // ANY HTLC, expressed in mSAT's. - FeeBaseMSat lnwire.MilliSatoshi - - // FeeProportionalMillionths is the rate that the node will charge for - // HTLCs for each millionth of a satoshi forwarded. - FeeProportionalMillionths lnwire.MilliSatoshi - - // ToNodePubKey is a function that returns the to node of a policy. - // Since we only ever store the inbound policy, this is always the node - // that we query the channels for in ForEachChannel(). Therefore, we can - // save a lot of space by not storing this information in the memory and - // instead just set this function when we copy the policy from cache in - // ForEachChannel(). - ToNodePubKey func() route.Vertex - - // ToNodeFeatures are the to node's features. They are never set while - // the edge is in the cache, only on the copy that is returned in - // ForEachChannel(). - ToNodeFeatures *lnwire.FeatureVector -} - -// ComputeFee computes the fee to forward an HTLC of `amt` milli-satoshis over -// the passed active payment channel. This value is currently computed as -// specified in BOLT07, but will likely change in the near future. -func (c *CachedEdgePolicy) ComputeFee( - amt lnwire.MilliSatoshi) lnwire.MilliSatoshi { - - return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts -} - -// ComputeFeeFromIncoming computes the fee to forward an HTLC given the incoming -// amount. -func (c *CachedEdgePolicy) ComputeFeeFromIncoming( - incomingAmt lnwire.MilliSatoshi) lnwire.MilliSatoshi { - - return incomingAmt - divideCeil( - feeRateParts*(incomingAmt-c.FeeBaseMSat), - feeRateParts+c.FeeProportionalMillionths, - ) -} - -// NewCachedPolicy turns a full policy into a minimal one that can be cached. -func NewCachedPolicy(policy *ChannelEdgePolicy) *CachedEdgePolicy { - return &CachedEdgePolicy{ - ChannelID: policy.ChannelID, - MessageFlags: policy.MessageFlags, - ChannelFlags: policy.ChannelFlags, - TimeLockDelta: policy.TimeLockDelta, - MinHTLC: policy.MinHTLC, - MaxHTLC: policy.MaxHTLC, - FeeBaseMSat: policy.FeeBaseMSat, - FeeProportionalMillionths: policy.FeeProportionalMillionths, - } + func(kvdb.RTx, *models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy) error) error } // DirectedChannel is a type that stores the channel information as seen from @@ -142,7 +58,7 @@ type DirectedChannel struct { // In path finding, we're walking backward from the destination to the // source, so we're always interested in the edge that arrives to us // from the other node. - InPolicy *CachedEdgePolicy + InPolicy *models.CachedEdgePolicy } // DeepCopy creates a deep copy of the channel, including the incoming policy. @@ -223,9 +139,9 @@ func (c *GraphCache) AddNode(tx kvdb.RTx, node GraphCacheNode) error { c.AddNodeFeatures(node) return node.ForEachChannel( - tx, func(tx kvdb.RTx, info *ChannelEdgeInfo, - outPolicy *ChannelEdgePolicy, - inPolicy *ChannelEdgePolicy) error { + tx, func(tx kvdb.RTx, info *models.ChannelEdgeInfo, + outPolicy *models.ChannelEdgePolicy, + inPolicy *models.ChannelEdgePolicy) error { c.AddChannel(info, outPolicy, inPolicy) @@ -238,8 +154,8 @@ func (c *GraphCache) AddNode(tx kvdb.RTx, node GraphCacheNode) error { // and policy 2 does not matter, the directionality is extracted from the info // and policy flags automatically. The policy will be set as the outgoing policy // on one node and the incoming policy on the peer's side. -func (c *GraphCache) AddChannel(info *ChannelEdgeInfo, - policy1 *ChannelEdgePolicy, policy2 *ChannelEdgePolicy) { +func (c *GraphCache) AddChannel(info *models.ChannelEdgeInfo, + policy1 *models.ChannelEdgePolicy, policy2 *models.ChannelEdgePolicy) { if info == nil { return @@ -271,7 +187,7 @@ func (c *GraphCache) AddChannel(info *ChannelEdgeInfo, // of node 2 then we have the policy 1 as seen from node 1. if policy1 != nil { fromNode, toNode := info.NodeKey1Bytes, info.NodeKey2Bytes - if policy1.Node.PubKeyBytes != info.NodeKey2Bytes { + if policy1.ToNode != info.NodeKey2Bytes { fromNode, toNode = toNode, fromNode } isEdge1 := policy1.ChannelFlags&lnwire.ChanUpdateDirection == 0 @@ -279,7 +195,7 @@ func (c *GraphCache) AddChannel(info *ChannelEdgeInfo, } if policy2 != nil { fromNode, toNode := info.NodeKey2Bytes, info.NodeKey1Bytes - if policy2.Node.PubKeyBytes != info.NodeKey1Bytes { + if policy2.ToNode != info.NodeKey1Bytes { fromNode, toNode = toNode, fromNode } isEdge1 := policy2.ChannelFlags&lnwire.ChanUpdateDirection == 0 @@ -301,7 +217,7 @@ func (c *GraphCache) updateOrAddEdge(node route.Vertex, edge *DirectedChannel) { // of the from and to node is not strictly important. But we assume that a // channel edge was added beforehand so that the directed channel struct already // exists in the cache. -func (c *GraphCache) UpdatePolicy(policy *ChannelEdgePolicy, fromNode, +func (c *GraphCache) UpdatePolicy(policy *models.ChannelEdgePolicy, fromNode, toNode route.Vertex, edge1 bool) { c.mtx.Lock() @@ -333,7 +249,7 @@ func (c *GraphCache) UpdatePolicy(policy *ChannelEdgePolicy, fromNode, // The other two cases left mean it's the inbound policy for the // node. default: - channel.InPolicy = NewCachedPolicy(policy) + channel.InPolicy = models.NewCachedPolicy(policy) } } @@ -380,7 +296,7 @@ func (c *GraphCache) removeChannelIfFound(node route.Vertex, chanID uint64) { // UpdateChannel updates the channel edge information for a specific edge. We // expect the edge to already exist and be known. If it does not yet exist, this // call is a no-op. -func (c *GraphCache) UpdateChannel(info *ChannelEdgeInfo) { +func (c *GraphCache) UpdateChannel(info *models.ChannelEdgeInfo) { c.mtx.Lock() defer c.mtx.Unlock() diff --git a/channeldb/graph_cache_test.go b/channeldb/graph_cache_test.go index b408ec36d..f2b0c52f9 100644 --- a/channeldb/graph_cache_test.go +++ b/channeldb/graph_cache_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "testing" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -28,9 +29,9 @@ type node struct { pubKey route.Vertex features *lnwire.FeatureVector - edgeInfos []*ChannelEdgeInfo - outPolicies []*ChannelEdgePolicy - inPolicies []*ChannelEdgePolicy + edgeInfos []*models.ChannelEdgeInfo + outPolicies []*models.ChannelEdgePolicy + inPolicies []*models.ChannelEdgePolicy } func (n *node) PubKey() route.Vertex { @@ -41,8 +42,8 @@ func (n *node) Features() *lnwire.FeatureVector { } func (n *node) ForEachChannel(tx kvdb.RTx, - cb func(kvdb.RTx, *ChannelEdgeInfo, *ChannelEdgePolicy, - *ChannelEdgePolicy) error) error { + cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy) error) error { for idx := range n.edgeInfos { err := cb( @@ -70,34 +71,28 @@ func TestGraphCacheAddNode(t *testing.T) { channelFlagA, channelFlagB = 1, 0 } - outPolicy1 := &ChannelEdgePolicy{ + outPolicy1 := &models.ChannelEdgePolicy{ ChannelID: 1000, ChannelFlags: lnwire.ChanUpdateChanFlags(channelFlagA), - Node: &LightningNode{ - PubKeyBytes: nodeB, - Features: lnwire.EmptyFeatureVector(), - }, + ToNode: nodeB, } - inPolicy1 := &ChannelEdgePolicy{ + inPolicy1 := &models.ChannelEdgePolicy{ ChannelID: 1000, ChannelFlags: lnwire.ChanUpdateChanFlags(channelFlagB), - Node: &LightningNode{ - PubKeyBytes: nodeA, - Features: lnwire.EmptyFeatureVector(), - }, + ToNode: nodeA, } node := &node{ pubKey: nodeA, features: lnwire.EmptyFeatureVector(), - edgeInfos: []*ChannelEdgeInfo{{ + edgeInfos: []*models.ChannelEdgeInfo{{ ChannelID: 1000, // Those are direction independent! NodeKey1Bytes: pubKey1, NodeKey2Bytes: pubKey2, Capacity: 500, }}, - outPolicies: []*ChannelEdgePolicy{outPolicy1}, - inPolicies: []*ChannelEdgePolicy{inPolicy1}, + outPolicies: []*models.ChannelEdgePolicy{outPolicy1}, + inPolicies: []*models.ChannelEdgePolicy{inPolicy1}, } cache := NewGraphCache(10) require.NoError(t, cache.AddNode(nil, node)) @@ -144,8 +139,8 @@ func TestGraphCacheAddNode(t *testing.T) { runTest(pubKey2, pubKey1) } -func assertCachedPolicyEqual(t *testing.T, original *ChannelEdgePolicy, - cached *CachedEdgePolicy) { +func assertCachedPolicyEqual(t *testing.T, original *models.ChannelEdgePolicy, + cached *models.CachedEdgePolicy) { require.Equal(t, original.ChannelID, cached.ChannelID) require.Equal(t, original.MessageFlags, cached.MessageFlags) @@ -159,9 +154,6 @@ func assertCachedPolicyEqual(t *testing.T, original *ChannelEdgePolicy, cached.FeeProportionalMillionths, ) require.Equal( - t, - route.Vertex(original.Node.PubKeyBytes), - cached.ToNodePubKey(), + t, route.Vertex(original.ToNode), cached.ToNodePubKey(), ) - require.Equal(t, original.Node.Features, cached.ToNodeFeatures) } diff --git a/channeldb/graph_test.go b/channeldb/graph_test.go index 0afc9ea19..12e20a9e2 100644 --- a/channeldb/graph_test.go +++ b/channeldb/graph_test.go @@ -22,6 +22,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -95,7 +96,6 @@ func createLightningNode(db kvdb.Backend, priv *btcec.PrivateKey) (*LightningNod Alias: "kek" + string(pub[:]), Features: testFeatures, Addresses: testAddrs, - db: db, } copy(n.PubKeyBytes[:], priv.PubKey().SerializeCompressed()) @@ -129,7 +129,6 @@ func TestNodeInsertionAndDeletion(t *testing.T) { Addresses: testAddrs, ExtraOpaqueData: []byte("extra new data"), PubKeyBytes: testPub, - db: graph.db, } // First, insert the node into the graph DB. This should succeed @@ -141,7 +140,7 @@ func TestNodeInsertionAndDeletion(t *testing.T) { // Next, fetch the node from the database to ensure everything was // serialized properly. - dbNode, err := graph.FetchLightningNode(testPub) + dbNode, err := graph.FetchLightningNode(nil, testPub) require.NoError(t, err, "unable to locate node") if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil { @@ -164,7 +163,7 @@ func TestNodeInsertionAndDeletion(t *testing.T) { // Finally, attempt to fetch the node again. This should fail as the // node should have been deleted from the database. - _, err = graph.FetchLightningNode(testPub) + _, err = graph.FetchLightningNode(nil, testPub) if err != ErrGraphNodeNotFound { t.Fatalf("fetch after delete should fail!") } @@ -192,7 +191,7 @@ func TestPartialNode(t *testing.T) { // Next, fetch the node from the database to ensure everything was // serialized properly. - dbNode, err := graph.FetchLightningNode(testPub) + dbNode, err := graph.FetchLightningNode(nil, testPub) require.NoError(t, err, "unable to locate node") if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil { @@ -207,7 +206,6 @@ func TestPartialNode(t *testing.T) { HaveNodeAnnouncement: false, LastUpdate: time.Unix(0, 0), PubKeyBytes: testPub, - db: graph.db, } if err := compareNodes(node, dbNode); err != nil { @@ -223,7 +221,7 @@ func TestPartialNode(t *testing.T) { // Finally, attempt to fetch the node again. This should fail as the // node should have been deleted from the database. - _, err = graph.FetchLightningNode(testPub) + _, err = graph.FetchLightningNode(nil, testPub) if err != ErrGraphNodeNotFound { t.Fatalf("fetch after delete should fail!") } @@ -327,10 +325,10 @@ 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 := ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo{ ChannelID: chanID, ChainHash: key, - AuthProof: &ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -387,7 +385,8 @@ func TestEdgeInsertionDeletion(t *testing.T) { } func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32, - node1, node2 *LightningNode) (ChannelEdgeInfo, lnwire.ShortChannelID) { + node1, node2 *LightningNode) (models.ChannelEdgeInfo, + lnwire.ShortChannelID) { shortChanID := lnwire.ShortChannelID{ BlockHeight: height, @@ -401,10 +400,10 @@ func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32, node1Pub, _ := node1.PubKey() node2Pub, _ := node2.PubKey() - edgeInfo := ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo{ ChannelID: shortChanID.ToUint64(), ChainHash: key, - AuthProof: &ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -556,8 +555,8 @@ func TestDisconnectBlockAtHeight(t *testing.T) { } } -func assertEdgeInfoEqual(t *testing.T, e1 *ChannelEdgeInfo, - e2 *ChannelEdgeInfo) { +func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo, + e2 *models.ChannelEdgeInfo) { if e1.ChannelID != e2.ChannelID { t.Fatalf("chan id's don't match: %v vs %v", e1.ChannelID, @@ -618,19 +617,20 @@ func assertEdgeInfoEqual(t *testing.T, e1 *ChannelEdgeInfo, } } -func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (*ChannelEdgeInfo, - *ChannelEdgePolicy, *ChannelEdgePolicy) { +func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) ( + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy) { var ( - firstNode *LightningNode - secondNode *LightningNode + firstNode [33]byte + secondNode [33]byte ) if bytes.Compare(node1.PubKeyBytes[:], node2.PubKeyBytes[:]) == -1 { - firstNode = node1 - secondNode = node2 + firstNode = node1.PubKeyBytes + secondNode = node2.PubKeyBytes } else { - firstNode = node2 - secondNode = node1 + firstNode = node2.PubKeyBytes + secondNode = node1.PubKeyBytes } // In addition to the fake vertexes we create some fake channel @@ -643,10 +643,10 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (*ChannelEd // Add the new edge to the database, this should proceed without any // errors. - edgeInfo := &ChannelEdgeInfo{ + edgeInfo := &models.ChannelEdgeInfo{ ChannelID: chanID, ChainHash: key, - AuthProof: &ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -656,12 +656,12 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (*ChannelEd Capacity: 1000, ExtraOpaqueData: []byte("new unknown feature"), } - copy(edgeInfo.NodeKey1Bytes[:], firstNode.PubKeyBytes[:]) - copy(edgeInfo.NodeKey2Bytes[:], secondNode.PubKeyBytes[:]) - copy(edgeInfo.BitcoinKey1Bytes[:], firstNode.PubKeyBytes[:]) - copy(edgeInfo.BitcoinKey2Bytes[:], secondNode.PubKeyBytes[:]) + copy(edgeInfo.NodeKey1Bytes[:], firstNode[:]) + copy(edgeInfo.NodeKey2Bytes[:], secondNode[:]) + copy(edgeInfo.BitcoinKey1Bytes[:], firstNode[:]) + copy(edgeInfo.BitcoinKey2Bytes[:], secondNode[:]) - edge1 := &ChannelEdgePolicy{ + edge1 := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: chanID, LastUpdate: time.Unix(433453, 0), @@ -672,11 +672,10 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (*ChannelEd MaxHTLC: 13928598, FeeBaseMSat: 4352345, FeeProportionalMillionths: 3452352, - Node: secondNode, + ToNode: secondNode, ExtraOpaqueData: []byte("new unknown feature2"), - db: db, } - edge2 := &ChannelEdgePolicy{ + edge2 := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: chanID, LastUpdate: time.Unix(124234, 0), @@ -687,9 +686,8 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (*ChannelEd MaxHTLC: 13928598, FeeBaseMSat: 4352345, FeeProportionalMillionths: 90392423, - Node: firstNode, + ToNode: firstNode, ExtraOpaqueData: []byte("new unknown feature1"), - db: db, } return edgeInfo, edge1, edge2 @@ -822,7 +820,7 @@ func assertNodeNotInCache(t *testing.T, g *ChannelGraph, n route.Vertex) { } func assertEdgeWithNoPoliciesInCache(t *testing.T, g *ChannelGraph, - e *ChannelEdgeInfo) { + e *models.ChannelEdgeInfo) { // Let's check the internal view first. require.NotEmpty(t, g.graphCache.nodeChannels[e.NodeKey1Bytes]) @@ -900,7 +898,7 @@ func assertNoEdge(t *testing.T, g *ChannelGraph, chanID uint64) { } func assertEdgeWithPolicyInCache(t *testing.T, g *ChannelGraph, - e *ChannelEdgeInfo, p *ChannelEdgePolicy, policy1 bool) { + e *models.ChannelEdgeInfo, p *models.ChannelEdgePolicy, policy1 bool) { // Check the internal state first. c1, ok := g.graphCache.nodeChannels[e.NodeKey1Bytes][e.ChannelID] @@ -976,16 +974,16 @@ func assertEdgeWithPolicyInCache(t *testing.T, g *ChannelGraph, } } -func randEdgePolicy(chanID uint64, db kvdb.Backend) *ChannelEdgePolicy { +func randEdgePolicy(chanID uint64, db kvdb.Backend) *models.ChannelEdgePolicy { update := prand.Int63() return newEdgePolicy(chanID, db, update) } func newEdgePolicy(chanID uint64, db kvdb.Backend, - updateTime int64) *ChannelEdgePolicy { + updateTime int64) *models.ChannelEdgePolicy { - return &ChannelEdgePolicy{ + return &models.ChannelEdgePolicy{ ChannelID: chanID, LastUpdate: time.Unix(updateTime, 0), MessageFlags: 1, @@ -995,7 +993,6 @@ func newEdgePolicy(chanID uint64, db kvdb.Backend, MaxHTLC: lnwire.MilliSatoshi(prand.Int63()), FeeBaseMSat: lnwire.MilliSatoshi(prand.Int63()), FeeProportionalMillionths: lnwire.MilliSatoshi(prand.Int63()), - db: db, } } @@ -1043,8 +1040,9 @@ func TestGraphTraversal(t *testing.T) { // Iterate through all the known channels within the graph DB, once // again if the map is empty that indicates that all edges have // properly been reached. - err = graph.ForEachChannel(func(ei *ChannelEdgeInfo, _ *ChannelEdgePolicy, - _ *ChannelEdgePolicy) error { + err = graph.ForEachChannel(func(ei *models.ChannelEdgeInfo, + _ *models.ChannelEdgePolicy, + _ *models.ChannelEdgePolicy) error { delete(chanIndex, ei.ChannelID) return nil @@ -1056,30 +1054,38 @@ func TestGraphTraversal(t *testing.T) { // outgoing channels for a particular node. numNodeChans := 0 firstNode, secondNode := nodeList[0], nodeList[1] - err = firstNode.ForEachChannel(nil, func(_ kvdb.RTx, _ *ChannelEdgeInfo, - outEdge, inEdge *ChannelEdgePolicy) error { + err = graph.ForEachNodeChannel(nil, firstNode.PubKeyBytes, + func(_ kvdb.RTx, _ *models.ChannelEdgeInfo, outEdge, + inEdge *models.ChannelEdgePolicy) error { - // All channels between first and second node should have fully - // (both sides) specified policies. - if inEdge == nil || outEdge == nil { - return fmt.Errorf("channel policy not present") - } + // All channels between first and second node should + // have fully (both sides) specified policies. + if inEdge == nil || outEdge == nil { + return fmt.Errorf("channel policy not present") + } - // Each should indicate that it's outgoing (pointed - // towards the second node). - if !bytes.Equal(outEdge.Node.PubKeyBytes[:], secondNode.PubKeyBytes[:]) { - return fmt.Errorf("wrong outgoing edge") - } + // Each should indicate that it's outgoing (pointed + // towards the second node). + if !bytes.Equal( + outEdge.ToNode[:], secondNode.PubKeyBytes[:], + ) { - // The incoming edge should also indicate that it's pointing to - // the origin node. - if !bytes.Equal(inEdge.Node.PubKeyBytes[:], firstNode.PubKeyBytes[:]) { - return fmt.Errorf("wrong outgoing edge") - } + return fmt.Errorf("wrong outgoing edge") + } - numNodeChans++ - return nil - }) + // The incoming edge should also indicate that it's + // pointing to the origin node. + if !bytes.Equal( + inEdge.ToNode[:], firstNode.PubKeyBytes[:], + ) { + + return fmt.Errorf("wrong outgoing edge") + } + + numNodeChans++ + + return nil + }) require.NoError(t, err) require.Equal(t, numChannels, numNodeChans) } @@ -1129,9 +1135,10 @@ func TestGraphTraversalCacheable(t *testing.T) { err = graph.db.View(func(tx kvdb.RTx) error { for _, node := range nodes { err := node.ForEachChannel( - tx, func(tx kvdb.RTx, info *ChannelEdgeInfo, - policy *ChannelEdgePolicy, - policy2 *ChannelEdgePolicy) error { + tx, func(tx kvdb.RTx, + info *models.ChannelEdgeInfo, + policy *models.ChannelEdgePolicy, + policy2 *models.ChannelEdgePolicy) error { //nolint:lll delete(chanIndex, info.ChannelID) return nil @@ -1249,10 +1256,10 @@ func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes, Index: 0, } - edgeInfo := ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo{ ChannelID: chanID, ChainHash: key, - AuthProof: &ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -1272,7 +1279,7 @@ func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes, // from node1 -> node2. edge := randEdgePolicy(chanID, graph.db) edge.ChannelFlags = 0 - edge.Node = node2 + edge.ToNode = node2.PubKeyBytes edge.SigBytes = testSig.Serialize() require.NoError(t, graph.UpdateEdgePolicy(edge)) @@ -1280,7 +1287,7 @@ func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes, // node2 -> node1 this time. edge = randEdgePolicy(chanID, graph.db) edge.ChannelFlags = 1 - edge.Node = node1 + edge.ToNode = node1.PubKeyBytes edge.SigBytes = testSig.Serialize() require.NoError(t, graph.UpdateEdgePolicy(edge)) @@ -1313,8 +1320,9 @@ func assertPruneTip(t *testing.T, graph *ChannelGraph, blockHash *chainhash.Hash func assertNumChans(t *testing.T, graph *ChannelGraph, n int) { numChans := 0 - if err := graph.ForEachChannel(func(*ChannelEdgeInfo, *ChannelEdgePolicy, - *ChannelEdgePolicy) error { + if err := graph.ForEachChannel(func(*models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy) error { numChans++ return nil @@ -1430,10 +1438,10 @@ func TestGraphPruning(t *testing.T) { channelPoints = append(channelPoints, &op) - edgeInfo := ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo{ ChannelID: chanID, ChainHash: key, - AuthProof: &ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -1465,7 +1473,7 @@ func TestGraphPruning(t *testing.T) { // node_i -> node_i+1 edge := randEdgePolicy(chanID, graph.db) edge.ChannelFlags = 0 - edge.Node = graphNodes[i] + edge.ToNode = graphNodes[i].PubKeyBytes edge.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -1475,7 +1483,7 @@ func TestGraphPruning(t *testing.T) { // node_i this time. edge = randEdgePolicy(chanID, graph.db) edge.ChannelFlags = 1 - edge.Node = graphNodes[i] + edge.ToNode = graphNodes[i].PubKeyBytes edge.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -1690,7 +1698,7 @@ func TestChanUpdatesInHorizon(t *testing.T) { chanID.ToUint64(), graph.db, edge1UpdateTime.Unix(), ) edge1.ChannelFlags = 0 - edge1.Node = node2 + edge1.ToNode = node2.PubKeyBytes edge1.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge1); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -1700,7 +1708,7 @@ func TestChanUpdatesInHorizon(t *testing.T) { chanID.ToUint64(), graph.db, edge2UpdateTime.Unix(), ) edge2.ChannelFlags = 1 - edge2.Node = node1 + edge2.ToNode = node1.PubKeyBytes edge2.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge2); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2184,7 +2192,7 @@ func TestFetchChanInfos(t *testing.T) { chanID.ToUint64(), graph.db, updateTime.Unix(), ) edge1.ChannelFlags = 0 - edge1.Node = node2 + edge1.ToNode = node2.PubKeyBytes edge1.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge1); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2194,7 +2202,7 @@ func TestFetchChanInfos(t *testing.T) { chanID.ToUint64(), graph.db, updateTime.Unix(), ) edge2.ChannelFlags = 1 - edge2.Node = node1 + edge2.ToNode = node1.PubKeyBytes edge2.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge2); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2280,29 +2288,30 @@ func TestIncompleteChannelPolicies(t *testing.T) { // Ensure that channel is reported with unknown policies. checkPolicies := func(node *LightningNode, expectedIn, expectedOut bool) { calls := 0 - err := node.ForEachChannel(nil, func(_ kvdb.RTx, _ *ChannelEdgeInfo, - outEdge, inEdge *ChannelEdgePolicy) error { + err := graph.ForEachNodeChannel(nil, node.PubKeyBytes, + func(_ kvdb.RTx, _ *models.ChannelEdgeInfo, outEdge, + inEdge *models.ChannelEdgePolicy) error { - if !expectedOut && outEdge != nil { - t.Fatalf("Expected no outgoing policy") - } + if !expectedOut && outEdge != nil { + t.Fatalf("Expected no outgoing policy") + } - if expectedOut && outEdge == nil { - t.Fatalf("Expected an outgoing policy") - } + if expectedOut && outEdge == nil { + t.Fatalf("Expected an outgoing policy") + } - if !expectedIn && inEdge != nil { - t.Fatalf("Expected no incoming policy") - } + if !expectedIn && inEdge != nil { + t.Fatalf("Expected no incoming policy") + } - if expectedIn && inEdge == nil { - t.Fatalf("Expected an incoming policy") - } + if expectedIn && inEdge == nil { + t.Fatalf("Expected an incoming policy") + } - calls++ + calls++ - return nil - }) + return nil + }) if err != nil { t.Fatalf("unable to scan channels: %v", err) } @@ -2322,7 +2331,7 @@ func TestIncompleteChannelPolicies(t *testing.T) { chanID.ToUint64(), graph.db, updateTime.Unix(), ) edgePolicy.ChannelFlags = 0 - edgePolicy.Node = node2 + edgePolicy.ToNode = node2.PubKeyBytes edgePolicy.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edgePolicy); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2337,7 +2346,7 @@ func TestIncompleteChannelPolicies(t *testing.T) { chanID.ToUint64(), graph.db, updateTime.Unix(), ) edgePolicy.ChannelFlags = 1 - edgePolicy.Node = node1 + edgePolicy.ToNode = node1.PubKeyBytes edgePolicy.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edgePolicy); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2384,7 +2393,7 @@ func TestChannelEdgePruningUpdateIndexDeletion(t *testing.T) { edge1 := randEdgePolicy(chanID.ToUint64(), graph.db) edge1.ChannelFlags = 0 - edge1.Node = node1 + edge1.ToNode = node1.PubKeyBytes edge1.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge1); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2392,7 +2401,7 @@ func TestChannelEdgePruningUpdateIndexDeletion(t *testing.T) { edge2 := randEdgePolicy(chanID.ToUint64(), graph.db) edge2.ChannelFlags = 1 - edge2.Node = node2 + edge2.ToNode = node2.PubKeyBytes edge2.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge2); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2537,7 +2546,7 @@ func TestPruneGraphNodes(t *testing.T) { // points from the first to the second node. edge1 := randEdgePolicy(chanID.ToUint64(), graph.db) edge1.ChannelFlags = 0 - edge1.Node = node1 + edge1.ToNode = node1.PubKeyBytes edge1.SigBytes = testSig.Serialize() if err := graph.UpdateEdgePolicy(edge1); err != nil { t.Fatalf("unable to update edge: %v", err) @@ -2556,7 +2565,7 @@ func TestPruneGraphNodes(t *testing.T) { // Finally, we'll ensure that node3, the only fully unconnected node as // properly deleted from the graph and not another node in its place. - _, err = graph.FetchLightningNode(node3.PubKeyBytes) + _, err = graph.FetchLightningNode(nil, node3.PubKeyBytes) if err == nil { t.Fatalf("node 3 should have been deleted!") } @@ -2590,13 +2599,13 @@ func TestAddChannelEdgeShellNodes(t *testing.T) { // Ensure that node1 was inserted as a full node, while node2 only has // a shell node present. - node1, err = graph.FetchLightningNode(node1.PubKeyBytes) + node1, err = graph.FetchLightningNode(nil, node1.PubKeyBytes) require.NoError(t, err, "unable to fetch node1") if !node1.HaveNodeAnnouncement { t.Fatalf("have shell announcement for node1, shouldn't") } - node2, err = graph.FetchLightningNode(node2.PubKeyBytes) + node2, err = graph.FetchLightningNode(nil, node2.PubKeyBytes) require.NoError(t, err, "unable to fetch node2") if node2.HaveNodeAnnouncement { t.Fatalf("should have shell announcement for node2, but is full") @@ -2698,18 +2707,15 @@ func TestNodeIsPublic(t *testing.T) { // After creating all of our nodes and edges, we'll add them to each // participant's graph. nodes := []*LightningNode{aliceNode, bobNode, carolNode} - edges := []*ChannelEdgeInfo{&aliceBobEdge, &bobCarolEdge} - dbs := []kvdb.Backend{aliceGraph.db, bobGraph.db, carolGraph.db} + edges := []*models.ChannelEdgeInfo{&aliceBobEdge, &bobCarolEdge} graphs := []*ChannelGraph{aliceGraph, bobGraph, carolGraph} - for i, graph := range graphs { + for _, graph := range graphs { for _, node := range nodes { - node.db = dbs[i] if err := graph.AddLightningNode(node); err != nil { t.Fatalf("unable to add node: %v", err) } } for _, edge := range edges { - edge.db = dbs[i] if err := graph.AddChannelEdge(edge); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -2769,7 +2775,7 @@ func TestNodeIsPublic(t *testing.T) { // that allows it to be advertised. Within Alice's graph, we'll // completely remove the edge as it is not possible for her to know of // it without it being advertised. - for i, graph := range graphs { + for _, graph := range graphs { err := graph.DeleteChannelEdges( false, true, bobCarolEdge.ChannelID, ) @@ -2782,7 +2788,6 @@ func TestNodeIsPublic(t *testing.T) { } bobCarolEdge.AuthProof = nil - bobCarolEdge.db = dbs[i] if err := graph.AddChannelEdge(&bobCarolEdge); err != nil { t.Fatalf("unable to add edge: %v", err) } @@ -2908,8 +2913,8 @@ func TestEdgePolicyMissingMaxHtcl(t *testing.T) { } chanID := edgeInfo.ChannelID - from := edge2.Node.PubKeyBytes[:] - to := edge1.Node.PubKeyBytes[:] + from := edge2.ToNode[:] + to := edge1.ToNode[:] // We'll remove the no max_htlc field from the first edge policy, and // all other opaque data, and serialize it. @@ -2945,7 +2950,7 @@ func TestEdgePolicyMissingMaxHtcl(t *testing.T) { return ErrGraphNotFound } - _, err = deserializeChanEdgePolicy(r, nodes) + _, err = deserializeChanEdgePolicy(r) if err != ErrEdgePolicyOptionalFieldNotFound { t.Fatalf("expected "+ "ErrEdgePolicyOptionalFieldNotFound, got %v", @@ -3140,10 +3145,6 @@ func compareNodes(a, b *LightningNode) error { return fmt.Errorf("Alias doesn't match: expected %#v, \n "+ "got %#v", a.Alias, b.Alias) } - if !reflect.DeepEqual(a.db, b.db) { - return fmt.Errorf("db doesn't match: expected %#v, \n "+ - "got %#v", a.db, b.db) - } if !reflect.DeepEqual(a.HaveNodeAnnouncement, b.HaveNodeAnnouncement) { return fmt.Errorf("HaveNodeAnnouncement doesn't match: expected %#v, \n "+ "got %#v", a.HaveNodeAnnouncement, b.HaveNodeAnnouncement) @@ -3158,7 +3159,7 @@ func compareNodes(a, b *LightningNode) error { // compareEdgePolicies is used to compare two ChannelEdgePolices using // compareNodes, so as to exclude comparisons of the Nodes' Features struct. -func compareEdgePolicies(a, b *ChannelEdgePolicy) error { +func compareEdgePolicies(a, b *models.ChannelEdgePolicy) error { if a.ChannelID != b.ChannelID { return fmt.Errorf("ChannelID doesn't match: expected %v, "+ "got %v", a.ChannelID, b.ChannelID) @@ -3200,13 +3201,11 @@ func compareEdgePolicies(a, b *ChannelEdgePolicy) error { return fmt.Errorf("extra data doesn't match: %v vs %v", a.ExtraOpaqueData, b.ExtraOpaqueData) } - if err := compareNodes(a.Node, b.Node); err != nil { - return err - } - if !reflect.DeepEqual(a.db, b.db) { - return fmt.Errorf("db doesn't match: expected %#v, \n "+ - "got %#v", a.db, b.db) + if !bytes.Equal(a.ToNode[:], b.ToNode[:]) { + return fmt.Errorf("ToNode doesn't match: expected %x, got %x", + a.ToNode, b.ToNode) } + return nil } @@ -3252,7 +3251,7 @@ func TestLightningNodeSigVerification(t *testing.T) { // TestComputeFee tests fee calculation based on both in- and outgoing amt. func TestComputeFee(t *testing.T) { var ( - policy = ChannelEdgePolicy{ + policy = models.ChannelEdgePolicy{ FeeBaseMSat: 10000, FeeProportionalMillionths: 30000, } @@ -3326,7 +3325,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 := []ChannelEdgeInfo{edgeInfo, edgeInfo2, edgeInfo3} + edges := []models.ChannelEdgeInfo{edgeInfo, edgeInfo2, edgeInfo3} errChan := make(chan error, len(edges)) errTimeout := errors.New("timeout adding batched channel") @@ -3334,7 +3333,7 @@ func TestBatchedAddChannelEdge(t *testing.T) { var wg sync.WaitGroup for _, edge := range edges { wg.Add(1) - go func(edge ChannelEdgeInfo) { + go func(edge models.ChannelEdgeInfo) { defer wg.Done() select { @@ -3385,7 +3384,7 @@ func TestBatchedUpdateEdgePolicy(t *testing.T) { errTimeout := errors.New("timeout adding batched channel") - updates := []*ChannelEdgePolicy{edge1, edge2} + updates := []*models.ChannelEdgePolicy{edge1, edge2} errChan := make(chan error, len(updates)) @@ -3393,7 +3392,7 @@ func TestBatchedUpdateEdgePolicy(t *testing.T) { var wg sync.WaitGroup for _, update := range updates { wg.Add(1) - go func(update *ChannelEdgePolicy) { + go func(update *models.ChannelEdgePolicy) { defer wg.Done() select { @@ -3441,24 +3440,24 @@ func BenchmarkForEachChannel(b *testing.B) { err = graph.db.View(func(tx kvdb.RTx) error { for _, n := range nodes { - err := n.ForEachChannel( - tx, func(tx kvdb.RTx, - info *ChannelEdgeInfo, - policy *ChannelEdgePolicy, - policy2 *ChannelEdgePolicy) error { + cb := func(tx kvdb.RTx, + info *models.ChannelEdgeInfo, + policy *models.ChannelEdgePolicy, + policy2 *models.ChannelEdgePolicy) error { //nolint:lll - // We need to do something with - // the data here, otherwise the - // compiler is going to optimize - // this away, and we get bogus - // results. - totalCapacity += info.Capacity - maxHTLCs += policy.MaxHTLC - maxHTLCs += policy2.MaxHTLC + // We need to do something with + // the data here, otherwise the + // compiler is going to optimize + // this away, and we get bogus + // results. + totalCapacity += info.Capacity + maxHTLCs += policy.MaxHTLC + maxHTLCs += policy2.MaxHTLC - return nil - }, - ) + return nil + } + + err := n.ForEachChannel(tx, cb) if err != nil { return err } @@ -3470,8 +3469,8 @@ func BenchmarkForEachChannel(b *testing.B) { } } -// TestGraphCacheForEachNodeChannel tests that the ForEachNodeChannel method -// works as expected, and is able to handle nil self edges. +// TestGraphCacheForEachNodeChannel tests that the ForEachNodeDirectedChannel +// method works as expected, and is able to handle nil self edges. func TestGraphCacheForEachNodeChannel(t *testing.T) { graph, err := MakeTestGraph(t) require.NoError(t, err) @@ -3498,11 +3497,13 @@ func TestGraphCacheForEachNodeChannel(t *testing.T) { // We should be able to accumulate the single channel added, even // though we have a nil edge policy here. var numChans int - err = graph.ForEachNodeChannel(nil, node1.PubKeyBytes, - func(channel *DirectedChannel) error { + err = graph.ForEachNodeDirectedChannel(nil, node1.PubKeyBytes, + func(_ *DirectedChannel) error { numChans++ + return nil - }) + }, + ) require.NoError(t, err) require.Equal(t, numChans, 1) diff --git a/channeldb/models/cached_edge_policy.go b/channeldb/models/cached_edge_policy.go new file mode 100644 index 000000000..25bef567e --- /dev/null +++ b/channeldb/models/cached_edge_policy.go @@ -0,0 +1,97 @@ +package models + +import ( + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" +) + +const ( + // feeRateParts is the total number of parts used to express fee rates. + feeRateParts = 1e6 +) + +// CachedEdgePolicy is a struct that only caches the information of a +// ChannelEdgePolicy that we actually use for pathfinding and therefore need to +// store in the cache. +type CachedEdgePolicy struct { + // ChannelID is the unique channel ID for the channel. The first 3 + // bytes are the block height, the next 3 the index within the block, + // and the last 2 bytes are the output index for the channel. + ChannelID uint64 + + // MessageFlags is a bitfield which indicates the presence of optional + // fields (like max_htlc) in the policy. + MessageFlags lnwire.ChanUpdateMsgFlags + + // ChannelFlags is a bitfield which signals the capabilities of the + // channel as well as the directed edge this update applies to. + ChannelFlags lnwire.ChanUpdateChanFlags + + // TimeLockDelta is the number of blocks this node will subtract from + // the expiry of an incoming HTLC. This value expresses the time buffer + // the node would like to HTLC exchanges. + TimeLockDelta uint16 + + // MinHTLC is the smallest value HTLC this node will forward, expressed + // in millisatoshi. + MinHTLC lnwire.MilliSatoshi + + // MaxHTLC is the largest value HTLC this node will forward, expressed + // in millisatoshi. + MaxHTLC lnwire.MilliSatoshi + + // FeeBaseMSat is the base HTLC fee that will be charged for forwarding + // ANY HTLC, expressed in mSAT's. + FeeBaseMSat lnwire.MilliSatoshi + + // FeeProportionalMillionths is the rate that the node will charge for + // HTLCs for each millionth of a satoshi forwarded. + FeeProportionalMillionths lnwire.MilliSatoshi + + // ToNodePubKey is a function that returns the to node of a policy. + // Since we only ever store the inbound policy, this is always the node + // that we query the channels for in ForEachChannel(). Therefore, we can + // save a lot of space by not storing this information in the memory and + // instead just set this function when we copy the policy from cache in + // ForEachChannel(). + ToNodePubKey func() route.Vertex + + // ToNodeFeatures are the to node's features. They are never set while + // the edge is in the cache, only on the copy that is returned in + // ForEachChannel(). + ToNodeFeatures *lnwire.FeatureVector +} + +// ComputeFee computes the fee to forward an HTLC of `amt` milli-satoshis over +// the passed active payment channel. This value is currently computed as +// specified in BOLT07, but will likely change in the near future. +func (c *CachedEdgePolicy) ComputeFee( + amt lnwire.MilliSatoshi) lnwire.MilliSatoshi { + + return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts +} + +// ComputeFeeFromIncoming computes the fee to forward an HTLC given the incoming +// amount. +func (c *CachedEdgePolicy) ComputeFeeFromIncoming( + incomingAmt lnwire.MilliSatoshi) lnwire.MilliSatoshi { + + return incomingAmt - divideCeil( + feeRateParts*(incomingAmt-c.FeeBaseMSat), + feeRateParts+c.FeeProportionalMillionths, + ) +} + +// NewCachedPolicy turns a full policy into a minimal one that can be cached. +func NewCachedPolicy(policy *ChannelEdgePolicy) *CachedEdgePolicy { + return &CachedEdgePolicy{ + ChannelID: policy.ChannelID, + MessageFlags: policy.MessageFlags, + ChannelFlags: policy.ChannelFlags, + TimeLockDelta: policy.TimeLockDelta, + MinHTLC: policy.MinHTLC, + MaxHTLC: policy.MaxHTLC, + FeeBaseMSat: policy.FeeBaseMSat, + FeeProportionalMillionths: policy.FeeProportionalMillionths, + } +} diff --git a/channeldb/models/channel_auth_proof.go b/channeldb/models/channel_auth_proof.go new file mode 100644 index 000000000..134139467 --- /dev/null +++ b/channeldb/models/channel_auth_proof.go @@ -0,0 +1,131 @@ +package models + +import "github.com/btcsuite/btcd/btcec/v2/ecdsa" + +// ChannelAuthProof is the authentication proof (the signature portion) for a +// channel. Using the four signatures contained in the struct, and some +// auxiliary knowledge (the funding script, node identities, and outpoint) nodes +// on the network are able to validate the authenticity and existence of a +// channel. Each of these signatures signs the following digest: chanID || +// nodeID1 || nodeID2 || bitcoinKey1|| bitcoinKey2 || 2-byte-feature-len || +// features. +type ChannelAuthProof struct { + // nodeSig1 is a cached instance of the first node signature. + nodeSig1 *ecdsa.Signature + + // NodeSig1Bytes are the raw bytes of the first node signature encoded + // in DER format. + NodeSig1Bytes []byte + + // nodeSig2 is a cached instance of the second node signature. + nodeSig2 *ecdsa.Signature + + // NodeSig2Bytes are the raw bytes of the second node signature + // encoded in DER format. + NodeSig2Bytes []byte + + // bitcoinSig1 is a cached instance of the first bitcoin signature. + bitcoinSig1 *ecdsa.Signature + + // BitcoinSig1Bytes are the raw bytes of the first bitcoin signature + // encoded in DER format. + BitcoinSig1Bytes []byte + + // bitcoinSig2 is a cached instance of the second bitcoin signature. + bitcoinSig2 *ecdsa.Signature + + // BitcoinSig2Bytes are the raw bytes of the second bitcoin signature + // encoded in DER format. + BitcoinSig2Bytes []byte +} + +// Node1Sig is the signature using the identity key of the node that is first +// in a lexicographical ordering of the serialized public keys of the two nodes +// that created the channel. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the signature if absolutely necessary. +func (c *ChannelAuthProof) Node1Sig() (*ecdsa.Signature, error) { + if c.nodeSig1 != nil { + return c.nodeSig1, nil + } + + sig, err := ecdsa.ParseSignature(c.NodeSig1Bytes) + if err != nil { + return nil, err + } + + c.nodeSig1 = sig + + return sig, nil +} + +// Node2Sig is the signature using the identity key of the node that is second +// in a lexicographical ordering of the serialized public keys of the two nodes +// that created the channel. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the signature if absolutely necessary. +func (c *ChannelAuthProof) Node2Sig() (*ecdsa.Signature, error) { + if c.nodeSig2 != nil { + return c.nodeSig2, nil + } + + sig, err := ecdsa.ParseSignature(c.NodeSig2Bytes) + if err != nil { + return nil, err + } + + c.nodeSig2 = sig + + return sig, nil +} + +// BitcoinSig1 is the signature using the public key of the first node that was +// used in the channel's multi-sig output. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the signature if absolutely necessary. +func (c *ChannelAuthProof) BitcoinSig1() (*ecdsa.Signature, error) { + if c.bitcoinSig1 != nil { + return c.bitcoinSig1, nil + } + + sig, err := ecdsa.ParseSignature(c.BitcoinSig1Bytes) + if err != nil { + return nil, err + } + + c.bitcoinSig1 = sig + + return sig, nil +} + +// BitcoinSig2 is the signature using the public key of the second node that +// was used in the channel's multi-sig output. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the signature if absolutely necessary. +func (c *ChannelAuthProof) BitcoinSig2() (*ecdsa.Signature, error) { + if c.bitcoinSig2 != nil { + return c.bitcoinSig2, nil + } + + sig, err := ecdsa.ParseSignature(c.BitcoinSig2Bytes) + if err != nil { + return nil, err + } + + c.bitcoinSig2 = sig + + return sig, nil +} + +// IsEmpty check is the authentication proof is empty Proof is empty if at +// least one of the signatures are equal to nil. +func (c *ChannelAuthProof) IsEmpty() bool { + return len(c.NodeSig1Bytes) == 0 || + len(c.NodeSig2Bytes) == 0 || + len(c.BitcoinSig1Bytes) == 0 || + len(c.BitcoinSig2Bytes) == 0 +} diff --git a/channeldb/models/channel_edge_info.go b/channeldb/models/channel_edge_info.go new file mode 100644 index 000000000..1afa2d627 --- /dev/null +++ b/channeldb/models/channel_edge_info.go @@ -0,0 +1,187 @@ +package models + +import ( + "bytes" + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// ChannelEdgeInfo represents a fully authenticated channel along with all its +// unique attributes. Once an authenticated channel announcement has been +// processed on the network, then an instance of ChannelEdgeInfo encapsulating +// the channels attributes is stored. The other portions relevant to routing +// policy of a channel are stored within a ChannelEdgePolicy for each direction +// of the channel. +type ChannelEdgeInfo struct { + // ChannelID is the unique channel ID for the channel. The first 3 + // bytes are the block height, the next 3 the index within the block, + // and the last 2 bytes are the output index for the channel. + ChannelID uint64 + + // ChainHash is the hash that uniquely identifies the chain that this + // channel was opened within. + // + // TODO(roasbeef): need to modify db keying for multi-chain + // * must add chain hash to prefix as well + ChainHash chainhash.Hash + + // NodeKey1Bytes is the raw public key of the first node. + NodeKey1Bytes [33]byte + nodeKey1 *btcec.PublicKey + + // NodeKey2Bytes is the raw public key of the first node. + NodeKey2Bytes [33]byte + nodeKey2 *btcec.PublicKey + + // BitcoinKey1Bytes is the raw public key of the first node. + BitcoinKey1Bytes [33]byte + bitcoinKey1 *btcec.PublicKey + + // BitcoinKey2Bytes is the raw public key of the first node. + BitcoinKey2Bytes [33]byte + bitcoinKey2 *btcec.PublicKey + + // Features is an opaque byte slice that encodes the set of channel + // specific features that this channel edge supports. + Features []byte + + // AuthProof is the authentication proof for this channel. This proof + // contains a set of signatures binding four identities, which attests + // to the legitimacy of the advertised channel. + AuthProof *ChannelAuthProof + + // ChannelPoint is the funding outpoint of the channel. This can be + // used to uniquely identify the channel within the channel graph. + ChannelPoint wire.OutPoint + + // Capacity is the total capacity of the channel, this is determined by + // the value output in the outpoint that created this channel. + Capacity btcutil.Amount + + // 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 +} + +// AddNodeKeys is a setter-like method that can be used to replace the set of +// keys for the target ChannelEdgeInfo. +func (c *ChannelEdgeInfo) AddNodeKeys(nodeKey1, nodeKey2, bitcoinKey1, + bitcoinKey2 *btcec.PublicKey) { + + c.nodeKey1 = nodeKey1 + copy(c.NodeKey1Bytes[:], c.nodeKey1.SerializeCompressed()) + + c.nodeKey2 = nodeKey2 + copy(c.NodeKey2Bytes[:], nodeKey2.SerializeCompressed()) + + c.bitcoinKey1 = bitcoinKey1 + copy(c.BitcoinKey1Bytes[:], c.bitcoinKey1.SerializeCompressed()) + + c.bitcoinKey2 = bitcoinKey2 + copy(c.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed()) +} + +// 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 +// that of the other node involved in channel creation. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the pubkey if absolutely necessary. +func (c *ChannelEdgeInfo) NodeKey1() (*btcec.PublicKey, error) { + if c.nodeKey1 != nil { + return c.nodeKey1, nil + } + + key, err := btcec.ParsePubKey(c.NodeKey1Bytes[:]) + if err != nil { + return nil, err + } + c.nodeKey1 = key + + return key, nil +} + +// NodeKey2 is the identity public key of the "second" node that was involved in +// the creation of this channel. A node is considered "second" if the +// lexicographical ordering the its serialized public key is "larger" than that +// of the other node involved in channel creation. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the pubkey if absolutely necessary. +func (c *ChannelEdgeInfo) NodeKey2() (*btcec.PublicKey, error) { + if c.nodeKey2 != nil { + return c.nodeKey2, nil + } + + key, err := btcec.ParsePubKey(c.NodeKey2Bytes[:]) + if err != nil { + return nil, err + } + c.nodeKey2 = key + + return key, nil +} + +// BitcoinKey1 is the Bitcoin multi-sig key belonging to the first node, that +// was involved in the funding transaction that originally created the channel +// that this struct represents. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the pubkey if absolutely necessary. +func (c *ChannelEdgeInfo) BitcoinKey1() (*btcec.PublicKey, error) { + if c.bitcoinKey1 != nil { + return c.bitcoinKey1, nil + } + + key, err := btcec.ParsePubKey(c.BitcoinKey1Bytes[:]) + if err != nil { + return nil, err + } + c.bitcoinKey1 = key + + return key, nil +} + +// BitcoinKey2 is the Bitcoin multi-sig key belonging to the second node, that +// was involved in the funding transaction that originally created the channel +// that this struct represents. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the pubkey if absolutely necessary. +func (c *ChannelEdgeInfo) BitcoinKey2() (*btcec.PublicKey, error) { + if c.bitcoinKey2 != nil { + return c.bitcoinKey2, nil + } + + key, err := btcec.ParsePubKey(c.BitcoinKey2Bytes[:]) + if err != nil { + return nil, err + } + c.bitcoinKey2 = key + + return key, nil +} + +// OtherNodeKeyBytes returns the node key bytes of the other end of the channel. +func (c *ChannelEdgeInfo) OtherNodeKeyBytes(thisNodeKey []byte) ( + [33]byte, error) { + + switch { + case bytes.Equal(c.NodeKey1Bytes[:], thisNodeKey): + return c.NodeKey2Bytes, nil + case bytes.Equal(c.NodeKey2Bytes[:], thisNodeKey): + return c.NodeKey1Bytes, nil + default: + return [33]byte{}, fmt.Errorf("node not participating in " + + "this channel") + } +} diff --git a/channeldb/models/channel_edge_policy.go b/channeldb/models/channel_edge_policy.go new file mode 100644 index 000000000..50ad20c75 --- /dev/null +++ b/channeldb/models/channel_edge_policy.go @@ -0,0 +1,131 @@ +package models + +import ( + "time" + + "github.com/btcsuite/btcd/btcec/v2/ecdsa" + "github.com/lightningnetwork/lnd/lnwire" +) + +// ChannelEdgePolicy represents a *directed* edge within the channel graph. For +// each channel in the database, there are two distinct edges: one for each +// possible direction of travel along the channel. The edges themselves hold +// information concerning fees, and minimum time-lock information which is +// utilized during path finding. +type ChannelEdgePolicy struct { + // SigBytes is the raw bytes of the signature of the channel edge + // policy. We'll only parse these if the caller needs to access the + // signature for validation purposes. Do not set SigBytes directly, but + // use SetSigBytes instead to make sure that the cache is invalidated. + SigBytes []byte + + // sig is a cached fully parsed signature. + sig *ecdsa.Signature + + // ChannelID is the unique channel ID for the channel. The first 3 + // bytes are the block height, the next 3 the index within the block, + // and the last 2 bytes are the output index for the channel. + ChannelID uint64 + + // LastUpdate is the last time an authenticated edge for this channel + // was received. + LastUpdate time.Time + + // MessageFlags is a bitfield which indicates the presence of optional + // fields (like max_htlc) in the policy. + MessageFlags lnwire.ChanUpdateMsgFlags + + // ChannelFlags is a bitfield which signals the capabilities of the + // channel as well as the directed edge this update applies to. + ChannelFlags lnwire.ChanUpdateChanFlags + + // TimeLockDelta is the number of blocks this node will subtract from + // the expiry of an incoming HTLC. This value expresses the time buffer + // the node would like to HTLC exchanges. + TimeLockDelta uint16 + + // MinHTLC is the smallest value HTLC this node will forward, expressed + // in millisatoshi. + MinHTLC lnwire.MilliSatoshi + + // MaxHTLC is the largest value HTLC this node will forward, expressed + // in millisatoshi. + MaxHTLC lnwire.MilliSatoshi + + // FeeBaseMSat is the base HTLC fee that will be charged for forwarding + // ANY HTLC, expressed in mSAT's. + FeeBaseMSat lnwire.MilliSatoshi + + // FeeProportionalMillionths is the rate that the node will charge for + // HTLCs for each millionth of a satoshi forwarded. + FeeProportionalMillionths lnwire.MilliSatoshi + + // ToNode is the public key of the node that this directed edge leads + // to. Using this pub key, the channel graph can further be traversed. + ToNode [33]byte + + // 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 +} + +// Signature is a channel announcement signature, which is needed for proper +// edge policy announcement. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the signature if absolutely necessary. +func (c *ChannelEdgePolicy) Signature() (*ecdsa.Signature, error) { + if c.sig != nil { + return c.sig, nil + } + + sig, err := ecdsa.ParseSignature(c.SigBytes) + if err != nil { + return nil, err + } + + c.sig = sig + + return sig, nil +} + +// SetSigBytes updates the signature and invalidates the cached parsed +// signature. +func (c *ChannelEdgePolicy) SetSigBytes(sig []byte) { + c.SigBytes = sig + c.sig = nil +} + +// IsDisabled determines whether the edge has the disabled bit set. +func (c *ChannelEdgePolicy) IsDisabled() bool { + return c.ChannelFlags.IsDisabled() +} + +// ComputeFee computes the fee to forward an HTLC of `amt` milli-satoshis over +// the passed active payment channel. This value is currently computed as +// specified in BOLT07, but will likely change in the near future. +func (c *ChannelEdgePolicy) ComputeFee( + amt lnwire.MilliSatoshi) lnwire.MilliSatoshi { + + return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts +} + +// divideCeil divides dividend by factor and rounds the result up. +func divideCeil(dividend, factor lnwire.MilliSatoshi) lnwire.MilliSatoshi { + return (dividend + factor - 1) / factor +} + +// ComputeFeeFromIncoming computes the fee to forward an HTLC given the incoming +// amount. +func (c *ChannelEdgePolicy) ComputeFeeFromIncoming( + incomingAmt lnwire.MilliSatoshi) lnwire.MilliSatoshi { + + return incomingAmt - divideCeil( + feeRateParts*(incomingAmt-c.FeeBaseMSat), + feeRateParts+c.FeeProportionalMillionths, + ) +} diff --git a/discovery/chan_series.go b/discovery/chan_series.go index 18f806316..c811017ab 100644 --- a/discovery/chan_series.go +++ b/discovery/chan_series.go @@ -280,10 +280,12 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash, // If this edge has a validated node announcement, that // we haven't yet sent, then we'll send that as well. - nodePub := channel.Policy1.Node.PubKeyBytes - hasNodeAnn := channel.Policy1.Node.HaveNodeAnnouncement + nodePub := channel.Node2.PubKeyBytes + hasNodeAnn := channel.Node2.HaveNodeAnnouncement if _, ok := nodePubsSent[nodePub]; !ok && hasNodeAnn { - nodeAnn, err := channel.Policy1.Node.NodeAnnouncement(true) + nodeAnn, err := channel.Node2.NodeAnnouncement( + true, + ) if err != nil { return nil, err } @@ -297,10 +299,12 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash, // If this edge has a validated node announcement, that // we haven't yet sent, then we'll send that as well. - nodePub := channel.Policy2.Node.PubKeyBytes - hasNodeAnn := channel.Policy2.Node.HaveNodeAnnouncement + nodePub := channel.Node1.PubKeyBytes + hasNodeAnn := channel.Node1.HaveNodeAnnouncement if _, ok := nodePubsSent[nodePub]; !ok && hasNodeAnn { - nodeAnn, err := channel.Policy2.Node.NodeAnnouncement(true) + nodeAnn, err := channel.Node1.NodeAnnouncement( + true, + ) if err != nil { return nil, err } diff --git a/discovery/gossiper.go b/discovery/gossiper.go index eed3cee84..d2d2fb993 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -19,6 +19,7 @@ import ( "github.com/lightningnetwork/lnd/batch" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnpeer" @@ -527,10 +528,10 @@ func New(cfg Config, selfKeyDesc *keychain.KeyDescriptor) *AuthenticatedGossiper // EdgeWithInfo contains the information that is required to update an edge. type EdgeWithInfo struct { // Info describes the channel. - Info *channeldb.ChannelEdgeInfo + Info *models.ChannelEdgeInfo // Edge describes the policy in one direction of the channel. - Edge *channeldb.ChannelEdgePolicy + Edge *models.ChannelEdgePolicy } // PropagateChanPolicyUpdate signals the AuthenticatedGossiper to perform the @@ -1574,8 +1575,8 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { // Iterate over all of our channels and check if any of them fall // within the prune interval or re-broadcast interval. type updateTuple struct { - info *channeldb.ChannelEdgeInfo - edge *channeldb.ChannelEdgePolicy + info *models.ChannelEdgeInfo + edge *models.ChannelEdgePolicy } var ( @@ -1584,8 +1585,8 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { ) err := d.cfg.Router.ForAllOutgoingChannels(func( _ kvdb.RTx, - info *channeldb.ChannelEdgeInfo, - edge *channeldb.ChannelEdgePolicy) error { + info *models.ChannelEdgeInfo, + edge *models.ChannelEdgePolicy) error { // If there's no auth proof attached to this edge, it means // that it is a private channel not meant to be announced to @@ -1790,7 +1791,7 @@ func (d *AuthenticatedGossiper) processChanPolicyUpdate( // remotePubFromChanInfo returns the public key of the remote peer given a // ChannelEdgeInfo that describe a channel we have with them. -func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo, +func remotePubFromChanInfo(chanInfo *models.ChannelEdgeInfo, chanFlags lnwire.ChanUpdateChanFlags) [33]byte { var remotePubKey [33]byte @@ -1813,7 +1814,7 @@ func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo, // assemble the proof and craft the ChannelAnnouncement. func (d *AuthenticatedGossiper) processRejectedEdge( chanAnnMsg *lnwire.ChannelAnnouncement, - proof *channeldb.ChannelAuthProof) ([]networkMsg, error) { + proof *models.ChannelAuthProof) ([]networkMsg, error) { // First, we'll fetch the state of the channel as we know if from the // database. @@ -2022,7 +2023,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement( // processZombieUpdate determines whether the provided channel update should // resurrect a given zombie edge. func (d *AuthenticatedGossiper) processZombieUpdate( - chanInfo *channeldb.ChannelEdgeInfo, msg *lnwire.ChannelUpdate) error { + chanInfo *models.ChannelEdgeInfo, msg *lnwire.ChannelUpdate) error { // The least-significant bit in the flag on the channel update tells us // which edge is being updated. @@ -2125,7 +2126,7 @@ func (d *AuthenticatedGossiper) isMsgStale(msg lnwire.Message) bool { // Otherwise, we'll retrieve the correct policy that we // currently have stored within our graph to check if this // message is stale by comparing its timestamp. - var p *channeldb.ChannelEdgePolicy + var p *models.ChannelEdgePolicy if msg.ChannelFlags&lnwire.ChanUpdateDirection == 0 { p = p1 } else { @@ -2150,8 +2151,8 @@ func (d *AuthenticatedGossiper) isMsgStale(msg lnwire.Message) bool { // updateChannel creates a new fully signed update for the channel, and updates // the underlying graph with the new state. -func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo, - edge *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, +func (d *AuthenticatedGossiper) updateChannel(info *models.ChannelEdgeInfo, + edge *models.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, *lnwire.ChannelUpdate, error) { // Parse the unsigned edge into a channel update. @@ -2239,7 +2240,7 @@ func (d *AuthenticatedGossiper) SyncManager() *SyncManager { // keep-alive update based on the previous channel update processed for the same // direction. func IsKeepAliveUpdate(update *lnwire.ChannelUpdate, - prev *channeldb.ChannelEdgePolicy) bool { + prev *models.ChannelEdgePolicy) bool { // Both updates should be from the same direction. if update.ChannelFlags&lnwire.ChanUpdateDirection != @@ -2428,7 +2429,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, // If this is a remote channel announcement, then we'll validate all // the signatures within the proof as it should be well formed. - var proof *channeldb.ChannelAuthProof + var proof *models.ChannelAuthProof if nMsg.isRemote { if err := routing.ValidateChannelAnn(ann); err != nil { err := fmt.Errorf("unable to validate announcement: "+ @@ -2448,7 +2449,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, // If the proof checks out, then we'll save the proof itself to // the database so we can fetch it later when gossiping with // other nodes. - proof = &channeldb.ChannelAuthProof{ + proof = &models.ChannelAuthProof{ NodeSig1Bytes: ann.NodeSig1.ToSignatureBytes(), NodeSig2Bytes: ann.NodeSig2.ToSignatureBytes(), BitcoinSig1Bytes: ann.BitcoinSig1.ToSignatureBytes(), @@ -2465,7 +2466,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, return nil, false } - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: ann.ShortChannelID.ToUint64(), ChainHash: ann.ChainHash, NodeKey1Bytes: ann.NodeID1, @@ -2816,7 +2817,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg, // being updated. var ( pubKey *btcec.PublicKey - edgeToUpdate *channeldb.ChannelEdgePolicy + edgeToUpdate *models.ChannelEdgePolicy ) direction := upd.ChannelFlags & lnwire.ChanUpdateDirection switch direction { @@ -2905,7 +2906,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg, // different alias. This might mean that SigBytes is incorrect as it // signs a different SCID than the database SCID, but since there will // only be a difference if AuthProof == nil, this is fine. - update := &channeldb.ChannelEdgePolicy{ + update := &models.ChannelEdgePolicy{ SigBytes: upd.Signature.ToSignatureBytes(), ChannelID: chanInfo.ChannelID, LastUpdate: timestamp, @@ -3217,7 +3218,7 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg, // We now have both halves of the channel announcement proof, then // we'll reconstruct the initial announcement so we can validate it // shortly below. - var dbProof channeldb.ChannelAuthProof + var dbProof models.ChannelAuthProof if isFirstNode { dbProof.NodeSig1Bytes = ann.NodeSignature.ToSignatureBytes() dbProof.NodeSig2Bytes = oppProof.NodeSignature.ToSignatureBytes() diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index d364b80ec..a47d98bb9 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -24,6 +24,7 @@ import ( "github.com/lightningnetwork/lnd/batch" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnpeer" @@ -91,8 +92,8 @@ type mockGraphSource struct { mu sync.Mutex nodes []channeldb.LightningNode - infos map[uint64]channeldb.ChannelEdgeInfo - edges map[uint64][]channeldb.ChannelEdgePolicy + infos map[uint64]models.ChannelEdgeInfo + edges map[uint64][]models.ChannelEdgePolicy zombies map[uint64][][33]byte chansToReject map[uint64]struct{} } @@ -100,8 +101,8 @@ type mockGraphSource struct { func newMockRouter(height uint32) *mockGraphSource { return &mockGraphSource{ bestHeight: height, - infos: make(map[uint64]channeldb.ChannelEdgeInfo), - edges: make(map[uint64][]channeldb.ChannelEdgePolicy), + infos: make(map[uint64]models.ChannelEdgeInfo), + edges: make(map[uint64][]models.ChannelEdgePolicy), zombies: make(map[uint64][][33]byte), chansToReject: make(map[uint64]struct{}), } @@ -119,7 +120,7 @@ func (r *mockGraphSource) AddNode(node *channeldb.LightningNode, return nil } -func (r *mockGraphSource) AddEdge(info *channeldb.ChannelEdgeInfo, +func (r *mockGraphSource) AddEdge(info *models.ChannelEdgeInfo, _ ...batch.SchedulerOption) error { r.mu.Lock() @@ -144,14 +145,14 @@ func (r *mockGraphSource) queueValidationFail(chanID uint64) { r.chansToReject[chanID] = struct{}{} } -func (r *mockGraphSource) UpdateEdge(edge *channeldb.ChannelEdgePolicy, +func (r *mockGraphSource) UpdateEdge(edge *models.ChannelEdgePolicy, _ ...batch.SchedulerOption) error { r.mu.Lock() defer r.mu.Unlock() if len(r.edges[edge.ChannelID]) == 0 { - r.edges[edge.ChannelID] = make([]channeldb.ChannelEdgePolicy, 2) + r.edges[edge.ChannelID] = make([]models.ChannelEdgePolicy, 2) } if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 { @@ -168,7 +169,7 @@ func (r *mockGraphSource) CurrentBlockHeight() (uint32, error) { } func (r *mockGraphSource) AddProof(chanID lnwire.ShortChannelID, - proof *channeldb.ChannelAuthProof) error { + proof *models.ChannelAuthProof) error { r.mu.Lock() defer r.mu.Unlock() @@ -190,8 +191,8 @@ func (r *mockGraphSource) ForEachNode(func(node *channeldb.LightningNode) error) } func (r *mockGraphSource) ForAllOutgoingChannels(cb func(tx kvdb.RTx, - i *channeldb.ChannelEdgeInfo, - c *channeldb.ChannelEdgePolicy) error) error { + i *models.ChannelEdgeInfo, + c *models.ChannelEdgePolicy) error) error { r.mu.Lock() defer r.mu.Unlock() @@ -221,15 +222,10 @@ func (r *mockGraphSource) ForAllOutgoingChannels(cb func(tx kvdb.RTx, return nil } -func (r *mockGraphSource) ForEachChannel(func(chanInfo *channeldb.ChannelEdgeInfo, - e1, e2 *channeldb.ChannelEdgePolicy) error) error { - return nil -} - func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) ( - *channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy, - *channeldb.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) { r.mu.Lock() defer r.mu.Unlock() @@ -242,7 +238,7 @@ func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) ( return nil, nil, nil, channeldb.ErrEdgeNotFound } - return &channeldb.ChannelEdgeInfo{ + return &models.ChannelEdgeInfo{ NodeKey1Bytes: pubKeys[0], NodeKey2Bytes: pubKeys[1], }, nil, nil, channeldb.ErrZombieEdge @@ -253,13 +249,13 @@ func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) ( return &chanInfo, nil, nil, nil } - var edge1 *channeldb.ChannelEdgePolicy - if !reflect.DeepEqual(edges[0], channeldb.ChannelEdgePolicy{}) { + var edge1 *models.ChannelEdgePolicy + if !reflect.DeepEqual(edges[0], models.ChannelEdgePolicy{}) { edge1 = &edges[0] } - var edge2 *channeldb.ChannelEdgePolicy - if !reflect.DeepEqual(edges[1], channeldb.ChannelEdgePolicy{}) { + var edge2 *models.ChannelEdgePolicy + if !reflect.DeepEqual(edges[1], models.ChannelEdgePolicy{}) { edge2 = &edges[1] } @@ -359,12 +355,12 @@ func (r *mockGraphSource) IsStaleEdgePolicy(chanID lnwire.ShortChannelID, switch { case flags&lnwire.ChanUpdateDirection == 0 && - !reflect.DeepEqual(edges[0], channeldb.ChannelEdgePolicy{}): + !reflect.DeepEqual(edges[0], models.ChannelEdgePolicy{}): return !timestamp.After(edges[0].LastUpdate) case flags&lnwire.ChanUpdateDirection == 1 && - !reflect.DeepEqual(edges[1], channeldb.ChannelEdgePolicy{}): + !reflect.DeepEqual(edges[1], models.ChannelEdgePolicy{}): return !timestamp.After(edges[1].LastUpdate) @@ -3443,8 +3439,8 @@ out: var edgesToUpdate []EdgeWithInfo err = ctx.router.ForAllOutgoingChannels(func( _ kvdb.RTx, - info *channeldb.ChannelEdgeInfo, - edge *channeldb.ChannelEdgePolicy) error { + info *models.ChannelEdgeInfo, + edge *models.ChannelEdgePolicy) error { edge.TimeLockDelta = uint16(newTimeLockDelta) edgesToUpdate = append(edgesToUpdate, EdgeWithInfo{ diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index cdb79ed13..70095e724 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -104,6 +104,10 @@ eliminate the use of `ScanInvoices`. ## Code Health + +* [Remove database pointers](https://github.com/lightningnetwork/lnd/pull/8117) + from channeldb schema structs. + ## Tooling and Documentation # Contributors (Alphabetical Order) diff --git a/funding/manager.go b/funding/manager.go index bee3f1481..f87db443d 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -524,7 +524,7 @@ type Config struct { // DeleteAliasEdge allows the Manager to delete an alias channel edge // from the graph. It also returns our local to-be-deleted policy. DeleteAliasEdge func(scid lnwire.ShortChannelID) ( - *channeldb.ChannelEdgePolicy, error) + *models.ChannelEdgePolicy, error) // AliasManager is an implementation of the aliasHandler interface that // abstracts away the handling of many alias functions. @@ -3335,7 +3335,7 @@ func (f *Manager) extractAnnounceParams(c *channeldb.OpenChannel) ( func (f *Manager) addToRouterGraph(completeChan *channeldb.OpenChannel, shortChanID *lnwire.ShortChannelID, peerAlias *lnwire.ShortChannelID, - ourPolicy *channeldb.ChannelEdgePolicy) error { + ourPolicy *models.ChannelEdgePolicy) error { chanID := lnwire.NewChanIDFromOutPoint(&completeChan.FundingOutpoint) @@ -4067,7 +4067,7 @@ func (f *Manager) newChanAnnouncement(localPubKey, remotePubKey *btcec.PublicKey, localFundingKey *keychain.KeyDescriptor, remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID, chanID lnwire.ChannelID, fwdMinHTLC, fwdMaxHTLC lnwire.MilliSatoshi, - ourPolicy *channeldb.ChannelEdgePolicy, + ourPolicy *models.ChannelEdgePolicy, chanType channeldb.ChannelType) (*chanAnnouncement, error) { chainHash := *f.cfg.Wallet.Cfg.NetParams.GenesisHash diff --git a/funding/manager_test.go b/funding/manager_test.go index 2c77d377e..d6a0a4427 100644 --- a/funding/manager_test.go +++ b/funding/manager_test.go @@ -550,7 +550,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, OpenChannelPredicate: chainedAcceptor, NotifyPendingOpenChannelEvent: evt.NotifyPendingOpenChannelEvent, DeleteAliasEdge: func(scid lnwire.ShortChannelID) ( - *channeldb.ChannelEdgePolicy, error) { + *models.ChannelEdgePolicy, error) { return nil, nil }, diff --git a/lnrpc/devrpc/dev_server.go b/lnrpc/devrpc/dev_server.go index 462328ea3..afe30b361 100644 --- a/lnrpc/devrpc/dev_server.go +++ b/lnrpc/devrpc/dev_server.go @@ -17,6 +17,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwire" @@ -261,7 +262,7 @@ func (s *Server) ImportGraph(ctx context.Context, for _, rpcEdge := range graph.Edges { rpcEdge := rpcEdge - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: rpcEdge.ChannelId, ChainHash: *s.cfg.ActiveNetParams.GenesisHash, Capacity: btcutil.Amount(rpcEdge.Capacity), @@ -288,8 +289,8 @@ func (s *Server) ImportGraph(ctx context.Context, rpcEdge.ChanPoint, err) } - makePolicy := func(rpcPolicy *lnrpc.RoutingPolicy) *channeldb.ChannelEdgePolicy { - policy := &channeldb.ChannelEdgePolicy{ + makePolicy := func(rpcPolicy *lnrpc.RoutingPolicy) *models.ChannelEdgePolicy { //nolint:lll + policy := &models.ChannelEdgePolicy{ ChannelID: rpcEdge.ChannelId, LastUpdate: time.Unix( int64(rpcPolicy.LastUpdate), 0, diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index f300e4380..8b38b76a2 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -17,6 +17,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -489,7 +490,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, // chanCanBeHopHint returns true if the target channel is eligible to be a hop // hint. func chanCanBeHopHint(channel *HopHintInfo, cfg *SelectHopHintsCfg) ( - *channeldb.ChannelEdgePolicy, bool) { + *models.ChannelEdgePolicy, bool) { // Since we're only interested in our private channels, we'll skip // public ones. @@ -544,7 +545,7 @@ func chanCanBeHopHint(channel *HopHintInfo, cfg *SelectHopHintsCfg) ( // Now, we'll need to determine which is the correct policy for HTLCs // being sent from the remote node. - var remotePolicy *channeldb.ChannelEdgePolicy + var remotePolicy *models.ChannelEdgePolicy if bytes.Equal(remotePub[:], info.NodeKey1Bytes[:]) { remotePolicy = p1 } else { @@ -604,7 +605,7 @@ func newHopHintInfo(c *channeldb.OpenChannel, isActive bool) *HopHintInfo { // newHopHint returns a new hop hint using the relevant data from a hopHintInfo // and a ChannelEdgePolicy. func newHopHint(hopHintInfo *HopHintInfo, - chanPolicy *channeldb.ChannelEdgePolicy) zpay32.HopHint { + chanPolicy *models.ChannelEdgePolicy) zpay32.HopHint { return zpay32.HopHint{ NodeID: hopHintInfo.RemotePubkey, @@ -627,8 +628,8 @@ type SelectHopHintsCfg struct { // FetchChannelEdgesByID attempts to lookup the two directed edges for // the channel identified by the channel ID. - FetchChannelEdgesByID func(chanID uint64) (*channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy, *channeldb.ChannelEdgePolicy, + FetchChannelEdgesByID func(chanID uint64) (*models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) // GetAlias allows the peer's alias SCID to be retrieved for private diff --git a/lnrpc/invoicesrpc/addinvoice_test.go b/lnrpc/invoicesrpc/addinvoice_test.go index 2dcb516a6..1b15921d0 100644 --- a/lnrpc/invoicesrpc/addinvoice_test.go +++ b/lnrpc/invoicesrpc/addinvoice_test.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/zpay32" "github.com/stretchr/testify/mock" @@ -15,9 +16,14 @@ import ( ) type hopHintsConfigMock struct { + t *testing.T mock.Mock } +func newHopHintsConfigMock(t *testing.T) *hopHintsConfigMock { + return &hopHintsConfigMock{t: t} +} + // IsPublicNode mocks node public state lookup. func (h *hopHintsConfigMock) IsPublicNode(pubKey [33]byte) (bool, error) { args := h.Mock.Called(pubKey) @@ -51,8 +57,8 @@ func (h *hopHintsConfigMock) FetchAllChannels() ([]*channeldb.OpenChannel, // FetchChannelEdgesByID attempts to lookup the two directed edges for // the channel identified by the channel ID. func (h *hopHintsConfigMock) FetchChannelEdgesByID(chanID uint64) ( - *channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy, - *channeldb.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) { args := h.Mock.Called(chanID) @@ -64,9 +70,14 @@ func (h *hopHintsConfigMock) FetchChannelEdgesByID(chanID uint64) ( return nil, nil, nil, err } - edgeInfo := args.Get(0).(*channeldb.ChannelEdgeInfo) - policy1 := args.Get(1).(*channeldb.ChannelEdgePolicy) - policy2 := args.Get(2).(*channeldb.ChannelEdgePolicy) + edgeInfo, ok := args.Get(0).(*models.ChannelEdgeInfo) + require.True(h.t, ok) + + policy1, ok := args.Get(1).(*models.ChannelEdgePolicy) + require.True(h.t, ok) + + policy2, ok := args.Get(2).(*models.ChannelEdgePolicy) + require.True(h.t, ok) return edgeInfo, policy1, policy2, err } @@ -215,9 +226,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) h.Mock.On( @@ -253,9 +264,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) alias := lnwire.ShortChannelID{TxPosition: 5} h.Mock.On( @@ -294,15 +305,15 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{ + &models.ChannelEdgeInfo{ NodeKey1Bytes: selectedPolicy, }, - &channeldb.ChannelEdgePolicy{ + &models.ChannelEdgePolicy{ FeeBaseMSat: 1000, FeeProportionalMillionths: 20, TimeLockDelta: 13, }, - &channeldb.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) }, @@ -342,9 +353,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{ + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{ FeeBaseMSat: 1000, FeeProportionalMillionths: 20, TimeLockDelta: 13, @@ -387,9 +398,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{ + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{ FeeBaseMSat: 1000, FeeProportionalMillionths: 20, TimeLockDelta: 13, @@ -428,7 +439,7 @@ func TestShouldIncludeChannel(t *testing.T) { t.Parallel() // Create mock and prime it for the test case. - mock := &hopHintsConfigMock{} + mock := newHopHintsConfigMock(t) if tc.setupMock != nil { tc.setupMock(mock) } @@ -554,9 +565,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) }, maxHopHints: 1, @@ -604,9 +615,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) }, maxHopHints: 10, @@ -655,9 +666,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) }, maxHopHints: 1, @@ -688,9 +699,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) // Prepare the mock for the second channel. @@ -705,9 +716,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) }, maxHopHints: 10, @@ -742,9 +753,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) // Prepare the mock for the second channel. @@ -759,9 +770,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) }, maxHopHints: 10, @@ -797,9 +808,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &channeldb.ChannelEdgeInfo{}, - &channeldb.ChannelEdgePolicy{}, - &channeldb.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo{}, + &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy{}, nil, ) }, maxHopHints: 1, @@ -861,7 +872,7 @@ func TestPopulateHopHints(t *testing.T) { t.Parallel() // Create mock and prime it for the test case. - mock := &hopHintsConfigMock{} + mock := newHopHintsConfigMock(t) if tc.setupMock != nil { tc.setupMock(mock) } diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index feb3d4b85..549443f0f 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -15,6 +15,7 @@ import ( "github.com/btcsuite/btcd/wire" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/feature" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnrpc" @@ -272,7 +273,7 @@ func (r *RouterBackend) parseQueryRoutesRequest(in *lnrpc.QueryRoutesRequest) ( // inside of the path rather than the request's fields. var ( targetPubKey *route.Vertex - routeHintEdges map[route.Vertex][]*channeldb.CachedEdgePolicy + routeHintEdges map[route.Vertex][]*models.CachedEdgePolicy blindedPmt *routing.BlindedPayment // finalCLTVDelta varies depending on whether we're sending to diff --git a/netann/chan_status_manager_test.go b/netann/chan_status_manager_test.go index e068184f8..cb871ba01 100644 --- a/netann/chan_status_manager_test.go +++ b/netann/chan_status_manager_test.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/netann" @@ -65,8 +66,8 @@ func createChannel(t *testing.T) *channeldb.OpenChannel { // our `pubkey` with the direction bit set appropriately in the policies. Our // update will be created with the disabled bit set if startEnabled is false. func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel, - pubkey *btcec.PublicKey, startEnabled bool) (*channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy, *channeldb.ChannelEdgePolicy) { + pubkey *btcec.PublicKey, startEnabled bool) (*models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, *models.ChannelEdgePolicy) { var ( pubkey1 [33]byte @@ -98,18 +99,18 @@ func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel, // bit. dir2 |= lnwire.ChanUpdateDirection - return &channeldb.ChannelEdgeInfo{ + return &models.ChannelEdgeInfo{ ChannelPoint: channel.FundingOutpoint, NodeKey1Bytes: pubkey1, NodeKey2Bytes: pubkey2, }, - &channeldb.ChannelEdgePolicy{ + &models.ChannelEdgePolicy{ ChannelID: channel.ShortChanID().ToUint64(), ChannelFlags: dir1, LastUpdate: time.Now(), SigBytes: testSigBytes, }, - &channeldb.ChannelEdgePolicy{ + &models.ChannelEdgePolicy{ ChannelID: channel.ShortChanID().ToUint64(), ChannelFlags: dir2, LastUpdate: time.Now(), @@ -120,9 +121,9 @@ func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel, type mockGraph struct { mu sync.Mutex channels []*channeldb.OpenChannel - chanInfos map[wire.OutPoint]*channeldb.ChannelEdgeInfo - chanPols1 map[wire.OutPoint]*channeldb.ChannelEdgePolicy - chanPols2 map[wire.OutPoint]*channeldb.ChannelEdgePolicy + chanInfos map[wire.OutPoint]*models.ChannelEdgeInfo + chanPols1 map[wire.OutPoint]*models.ChannelEdgePolicy + chanPols2 map[wire.OutPoint]*models.ChannelEdgePolicy sidToCid map[lnwire.ShortChannelID]wire.OutPoint updates chan *lnwire.ChannelUpdate @@ -133,9 +134,9 @@ func newMockGraph(t *testing.T, numChannels int, g := &mockGraph{ channels: make([]*channeldb.OpenChannel, 0, numChannels), - chanInfos: make(map[wire.OutPoint]*channeldb.ChannelEdgeInfo), - chanPols1: make(map[wire.OutPoint]*channeldb.ChannelEdgePolicy), - chanPols2: make(map[wire.OutPoint]*channeldb.ChannelEdgePolicy), + chanInfos: make(map[wire.OutPoint]*models.ChannelEdgeInfo), + chanPols1: make(map[wire.OutPoint]*models.ChannelEdgePolicy), + chanPols2: make(map[wire.OutPoint]*models.ChannelEdgePolicy), sidToCid: make(map[lnwire.ShortChannelID]wire.OutPoint), updates: make(chan *lnwire.ChannelUpdate, 2*numChannels), } @@ -159,8 +160,8 @@ func (g *mockGraph) FetchAllOpenChannels() ([]*channeldb.OpenChannel, error) { } func (g *mockGraph) FetchChannelEdgesByOutpoint( - op *wire.OutPoint) (*channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy, *channeldb.ChannelEdgePolicy, error) { + op *wire.OutPoint) (*models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) { g.mu.Lock() defer g.mu.Unlock() @@ -209,7 +210,7 @@ func (g *mockGraph) ApplyChannelUpdate(update *lnwire.ChannelUpdate, timestamp := time.Unix(int64(update.Timestamp), 0) - policy := &channeldb.ChannelEdgePolicy{ + policy := &models.ChannelEdgePolicy{ ChannelID: update.ShortChannelID.ToUint64(), ChannelFlags: update.ChannelFlags, LastUpdate: timestamp, @@ -247,8 +248,8 @@ func (g *mockGraph) addChannel(channel *channeldb.OpenChannel) { } func (g *mockGraph) addEdgePolicy(c *channeldb.OpenChannel, - info *channeldb.ChannelEdgeInfo, - pol1, pol2 *channeldb.ChannelEdgePolicy) { + info *models.ChannelEdgeInfo, + pol1, pol2 *models.ChannelEdgePolicy) { g.mu.Lock() defer g.mu.Unlock() diff --git a/netann/channel_announcement.go b/netann/channel_announcement.go index 0ae8d606d..8fc040f6f 100644 --- a/netann/channel_announcement.go +++ b/netann/channel_announcement.go @@ -3,7 +3,7 @@ package netann import ( "bytes" - "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" ) @@ -12,9 +12,9 @@ import ( // function is used to transform out database structs into the corresponding wire // structs for announcing new channels to other peers, or simply syncing up a // peer's initial routing table upon connect. -func CreateChanAnnouncement(chanProof *channeldb.ChannelAuthProof, - chanInfo *channeldb.ChannelEdgeInfo, - e1, e2 *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, +func CreateChanAnnouncement(chanProof *models.ChannelAuthProof, + chanInfo *models.ChannelEdgeInfo, + e1, e2 *models.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, *lnwire.ChannelUpdate, *lnwire.ChannelUpdate, error) { // First, using the parameters of the channel, along with the channel diff --git a/netann/channel_announcement_test.go b/netann/channel_announcement_test.go index bc2460b9a..92a6c74ce 100644 --- a/netann/channel_announcement_test.go +++ b/netann/channel_announcement_test.go @@ -7,7 +7,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -39,13 +39,13 @@ func TestCreateChanAnnouncement(t *testing.T) { ExtraOpaqueData: []byte{0x1}, } - chanProof := &channeldb.ChannelAuthProof{ + chanProof := &models.ChannelAuthProof{ NodeSig1Bytes: expChanAnn.NodeSig1.ToSignatureBytes(), NodeSig2Bytes: expChanAnn.NodeSig2.ToSignatureBytes(), BitcoinSig1Bytes: expChanAnn.BitcoinSig1.ToSignatureBytes(), BitcoinSig2Bytes: expChanAnn.BitcoinSig2.ToSignatureBytes(), } - chanInfo := &channeldb.ChannelEdgeInfo{ + chanInfo := &models.ChannelEdgeInfo{ ChainHash: expChanAnn.ChainHash, ChannelID: expChanAnn.ShortChannelID.ToUint64(), ChannelPoint: wire.OutPoint{Index: 1}, diff --git a/netann/channel_update.go b/netann/channel_update.go index b6555f37b..b93deb1d0 100644 --- a/netann/channel_update.go +++ b/netann/channel_update.go @@ -6,7 +6,7 @@ import ( "time" "github.com/btcsuite/btcd/btcec/v2" - "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" @@ -84,12 +84,12 @@ func SignChannelUpdate(signer lnwallet.MessageSigner, keyLoc keychain.KeyLocator // // NOTE: The passed policies can be nil. func ExtractChannelUpdate(ownerPubKey []byte, - info *channeldb.ChannelEdgeInfo, - policies ...*channeldb.ChannelEdgePolicy) ( + info *models.ChannelEdgeInfo, + policies ...*models.ChannelEdgePolicy) ( *lnwire.ChannelUpdate, error) { // Helper function to extract the owner of the given policy. - owner := func(edge *channeldb.ChannelEdgePolicy) []byte { + owner := func(edge *models.ChannelEdgePolicy) []byte { var pubKey *btcec.PublicKey if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 { pubKey, _ = info.NodeKey1() @@ -117,8 +117,8 @@ func ExtractChannelUpdate(ownerPubKey []byte, // UnsignedChannelUpdateFromEdge reconstructs an unsigned ChannelUpdate from the // given edge info and policy. -func UnsignedChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, - policy *channeldb.ChannelEdgePolicy) *lnwire.ChannelUpdate { +func UnsignedChannelUpdateFromEdge(info *models.ChannelEdgeInfo, + policy *models.ChannelEdgePolicy) *lnwire.ChannelUpdate { return &lnwire.ChannelUpdate{ ChainHash: info.ChainHash, @@ -137,8 +137,8 @@ func UnsignedChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, // ChannelUpdateFromEdge reconstructs a signed ChannelUpdate from the given edge // info and policy. -func ChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, - policy *channeldb.ChannelEdgePolicy) (*lnwire.ChannelUpdate, error) { +func ChannelUpdateFromEdge(info *models.ChannelEdgeInfo, + policy *models.ChannelEdgePolicy) (*lnwire.ChannelUpdate, error) { update := UnsignedChannelUpdateFromEdge(info, policy) diff --git a/netann/interface.go b/netann/interface.go index 79c0c114f..d6cdb46d0 100644 --- a/netann/interface.go +++ b/netann/interface.go @@ -3,6 +3,7 @@ package netann import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" ) // DB abstracts the required database functionality needed by the @@ -18,6 +19,6 @@ type DB interface { type ChannelGraph interface { // FetchChannelEdgesByOutpoint returns the channel edge info and most // recent channel edge policies for a given outpoint. - FetchChannelEdgesByOutpoint(*wire.OutPoint) (*channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy, *channeldb.ChannelEdgePolicy, error) + FetchChannelEdgesByOutpoint(*wire.OutPoint) (*models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) } diff --git a/peer/brontide.go b/peer/brontide.go index d2baf89c6..4c7694085 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -939,7 +939,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) ( // // TODO(roasbeef): can add helper method to get policy for // particular channel. - var selfPolicy *channeldb.ChannelEdgePolicy + var selfPolicy *models.ChannelEdgePolicy if info != nil && bytes.Equal(info.NodeKey1Bytes[:], p.cfg.ServerPubKey[:]) { diff --git a/routing/blinding.go b/routing/blinding.go index 143808646..50d3b6f79 100644 --- a/routing/blinding.go +++ b/routing/blinding.go @@ -5,7 +5,7 @@ import ( "fmt" sphinx "github.com/lightningnetwork/lightning-onion" - "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -99,7 +99,7 @@ func (b *BlindedPayment) toRouteHints() RouteHints { hintCount := len(b.BlindedPath.BlindedHops) - 1 hints := make( - map[route.Vertex][]*channeldb.CachedEdgePolicy, hintCount, + map[route.Vertex][]*models.CachedEdgePolicy, hintCount, ) // Start at the unblinded introduction node, because our pathfinding @@ -116,7 +116,7 @@ func (b *BlindedPayment) toRouteHints() RouteHints { // will ensure that pathfinding provides sufficient fees/delay for the // blinded portion to the introduction node. firstBlindedHop := b.BlindedPath.BlindedHops[1].BlindedNodePub - hints[fromNode] = []*channeldb.CachedEdgePolicy{ + hints[fromNode] = []*models.CachedEdgePolicy{ { TimeLockDelta: b.CltvExpiryDelta, MinHTLC: lnwire.MilliSatoshi(b.HtlcMinimum), @@ -156,14 +156,14 @@ func (b *BlindedPayment) toRouteHints() RouteHints { b.BlindedPath.BlindedHops[nextHopIdx].BlindedNodePub, ) - hint := &channeldb.CachedEdgePolicy{ + hint := &models.CachedEdgePolicy{ ToNodePubKey: func() route.Vertex { return nextNode }, ToNodeFeatures: features, } - hints[fromNode] = []*channeldb.CachedEdgePolicy{ + hints[fromNode] = []*models.CachedEdgePolicy{ hint, } } diff --git a/routing/graph.go b/routing/graph.go index 23bdd41e2..7f344f54a 100644 --- a/routing/graph.go +++ b/routing/graph.go @@ -75,7 +75,7 @@ func (g *CachedGraph) Close() error { func (g *CachedGraph) forEachNodeChannel(nodePub route.Vertex, cb func(channel *channeldb.DirectedChannel) error) error { - return g.graph.ForEachNodeChannel(g.tx, nodePub, cb) + return g.graph.ForEachNodeDirectedChannel(g.tx, nodePub, cb) } // sourceNode returns the source node of the graph. diff --git a/routing/heap.go b/routing/heap.go index 36563bb66..261ced8f9 100644 --- a/routing/heap.go +++ b/routing/heap.go @@ -3,7 +3,7 @@ package routing import ( "container/heap" - "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -39,7 +39,7 @@ type nodeWithDist struct { weight int64 // nextHop is the edge this route comes from. - nextHop *channeldb.CachedEdgePolicy + nextHop *models.CachedEdgePolicy // routingInfoSize is the total size requirement for the payloads field // in the onion packet from this hop towards the final destination. diff --git a/routing/localchans/manager.go b/routing/localchans/manager.go index 3a4e2416a..64641c739 100644 --- a/routing/localchans/manager.go +++ b/routing/localchans/manager.go @@ -31,8 +31,8 @@ type Manager struct { // ForAllOutgoingChannels is required to iterate over all our local // channels. ForAllOutgoingChannels func(cb func(kvdb.RTx, - *channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy) error) error + *models.ChannelEdgeInfo, + *models.ChannelEdgePolicy) error) error // FetchChannel is used to query local channel parameters. Optionally an // existing db tx can be supplied. @@ -73,8 +73,8 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy, // otherwise we'll collect them all. err := r.ForAllOutgoingChannels(func( tx kvdb.RTx, - info *channeldb.ChannelEdgeInfo, - edge *channeldb.ChannelEdgePolicy) error { + info *models.ChannelEdgeInfo, + edge *models.ChannelEdgePolicy) error { // If we have a channel filter, and this channel isn't a part // of it, then we'll skip it. @@ -172,7 +172,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy, // updateEdge updates the given edge with the new schema. func (r *Manager) updateEdge(tx kvdb.RTx, chanPoint wire.OutPoint, - edge *channeldb.ChannelEdgePolicy, + edge *models.ChannelEdgePolicy, newSchema routing.ChannelPolicy) error { // Update forwarding fee scheme and required time lock delta. diff --git a/routing/localchans/manager_test.go b/routing/localchans/manager_test.go index b14093a01..b103ef31f 100644 --- a/routing/localchans/manager_test.go +++ b/routing/localchans/manager_test.go @@ -22,7 +22,7 @@ func TestManager(t *testing.T) { t.Parallel() type channel struct { - edgeInfo *channeldb.ChannelEdgeInfo + edgeInfo *models.ChannelEdgeInfo } var ( @@ -44,7 +44,7 @@ func TestManager(t *testing.T) { MaxHTLC: 5000, } - currentPolicy := channeldb.ChannelEdgePolicy{ + currentPolicy := models.ChannelEdgePolicy{ MinHTLC: minHTLC, MessageFlags: lnwire.ChanUpdateRequiredMaxHtlc, } @@ -107,8 +107,8 @@ func TestManager(t *testing.T) { } forAllOutgoingChannels := func(cb func(kvdb.RTx, - *channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy) error) error { + *models.ChannelEdgeInfo, + *models.ChannelEdgePolicy) error) error { for _, c := range channelSet { if err := cb(nil, c.edgeInfo, ¤tPolicy); err != nil { @@ -152,7 +152,7 @@ func TestManager(t *testing.T) { tests := []struct { name string - currentPolicy channeldb.ChannelEdgePolicy + currentPolicy models.ChannelEdgePolicy newPolicy routing.ChannelPolicy channelSet []channel specifiedChanPoints []wire.OutPoint @@ -166,7 +166,7 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &channeldb.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo{ Capacity: chanCap, ChannelPoint: chanPointValid, }, @@ -183,7 +183,7 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &channeldb.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo{ Capacity: chanCap, ChannelPoint: chanPointValid, }, @@ -200,7 +200,7 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &channeldb.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo{ Capacity: chanCap, ChannelPoint: chanPointValid, }, @@ -221,7 +221,7 @@ func TestManager(t *testing.T) { newPolicy: noMaxHtlcPolicy, channelSet: []channel{ { - edgeInfo: &channeldb.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo{ Capacity: chanCap, ChannelPoint: chanPointValid, }, diff --git a/routing/mock_graph_test.go b/routing/mock_graph_test.go index dfbfd6aba..2ec9a0f98 100644 --- a/routing/mock_graph_test.go +++ b/routing/mock_graph_test.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -193,7 +194,7 @@ func (m *mockGraph) forEachNodeChannel(nodePub route.Vertex, OtherNode: peer, Capacity: channel.capacity, OutPolicySet: true, - InPolicy: &channeldb.CachedEdgePolicy{ + InPolicy: &models.CachedEdgePolicy{ ChannelID: channel.id, ToNodePubKey: func() route.Vertex { return nodePub diff --git a/routing/mock_test.go b/routing/mock_test.go index c24ca2508..6ab8f7083 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -174,13 +175,13 @@ func (m *mockPaymentSessionOld) RequestRoute(_, _ lnwire.MilliSatoshi, } func (m *mockPaymentSessionOld) UpdateAdditionalEdge(_ *lnwire.ChannelUpdate, - _ *btcec.PublicKey, _ *channeldb.CachedEdgePolicy) bool { + _ *btcec.PublicKey, _ *models.CachedEdgePolicy) bool { return false } func (m *mockPaymentSessionOld) GetAdditionalEdgePolicy(_ *btcec.PublicKey, - _ uint64) *channeldb.CachedEdgePolicy { + _ uint64) *models.CachedEdgePolicy { return nil } @@ -676,17 +677,17 @@ func (m *mockPaymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, } func (m *mockPaymentSession) UpdateAdditionalEdge(msg *lnwire.ChannelUpdate, - pubKey *btcec.PublicKey, policy *channeldb.CachedEdgePolicy) bool { + pubKey *btcec.PublicKey, policy *models.CachedEdgePolicy) bool { args := m.Called(msg, pubKey, policy) return args.Bool(0) } func (m *mockPaymentSession) GetAdditionalEdgePolicy(pubKey *btcec.PublicKey, - channelID uint64) *channeldb.CachedEdgePolicy { + channelID uint64) *models.CachedEdgePolicy { args := m.Called(pubKey, channelID) - return args.Get(0).(*channeldb.CachedEdgePolicy) + return args.Get(0).(*models.CachedEdgePolicy) } type mockControlTower struct { diff --git a/routing/notifications.go b/routing/notifications.go index 387bd9126..9d6c4b51f 100644 --- a/routing/notifications.go +++ b/routing/notifications.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" ) @@ -212,7 +213,7 @@ type ClosedChanSummary struct { // createCloseSummaries takes in a slice of channels closed at the target block // height and creates a slice of summaries which of each channel closure. func createCloseSummaries(blockHeight uint32, - closedChans ...*channeldb.ChannelEdgeInfo) []*ClosedChanSummary { + closedChans ...*models.ChannelEdgeInfo) []*ClosedChanSummary { closeSummaries := make([]*ClosedChanSummary, len(closedChans)) for i, closedChan := range closedChans { @@ -333,12 +334,12 @@ func addToTopologyChange(graph *channeldb.ChannelGraph, update *TopologyChange, // We ignore initial channel announcements as we'll only send out // updates once the individual edges themselves have been updated. - case *channeldb.ChannelEdgeInfo: + case *models.ChannelEdgeInfo: return nil // Any new ChannelUpdateAnnouncements will generate a corresponding // ChannelEdgeUpdate notification. - case *channeldb.ChannelEdgePolicy: + case *models.ChannelEdgePolicy: // We'll need to fetch the edge's information from the database // in order to get the information concerning which nodes are // being connected. diff --git a/routing/notifications_test.go b/routing/notifications_test.go index 00bc29f6b..5d6695010 100644 --- a/routing/notifications_test.go +++ b/routing/notifications_test.go @@ -16,6 +16,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/btcwallet" @@ -74,9 +75,9 @@ func createTestNode() (*channeldb.LightningNode, error) { } func randEdgePolicy(chanID *lnwire.ShortChannelID, - node *channeldb.LightningNode) *channeldb.ChannelEdgePolicy { + node *channeldb.LightningNode) *models.ChannelEdgePolicy { - return &channeldb.ChannelEdgePolicy{ + return &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: chanID.ToUint64(), LastUpdate: time.Unix(int64(prand.Int31()), 0), @@ -85,7 +86,7 @@ func randEdgePolicy(chanID *lnwire.ShortChannelID, MaxHTLC: lnwire.MilliSatoshi(prand.Int31()), FeeBaseMSat: lnwire.MilliSatoshi(prand.Int31()), FeeProportionalMillionths: lnwire.MilliSatoshi(prand.Int31()), - Node: node, + ToNode: node.PubKeyBytes, } } @@ -431,11 +432,11 @@ 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 := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -469,7 +470,8 @@ func TestEdgeUpdateNotification(t *testing.T) { } assertEdgeCorrect := func(t *testing.T, edgeUpdate *ChannelEdgeUpdate, - edgeAnn *channeldb.ChannelEdgePolicy) { + edgeAnn *models.ChannelEdgePolicy) { + if edgeUpdate.ChanID != edgeAnn.ChannelID { t.Fatalf("channel ID of edge doesn't match: "+ "expected %v, got %v", chanID.ToUint64(), edgeUpdate.ChanID) @@ -613,11 +615,11 @@ func TestNodeUpdateNotification(t *testing.T) { testFeaturesBuf := new(bytes.Buffer) require.NoError(t, testFeatures.Encode(testFeaturesBuf)) - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -799,11 +801,11 @@ func TestNotificationCancellation(t *testing.T) { // to the client. ntfnClient.Cancel() - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -870,11 +872,11 @@ 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 := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), diff --git a/routing/pathfind.go b/routing/pathfind.go index d007be05e..091c18d92 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/btcutil" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/feature" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" @@ -49,7 +50,7 @@ const ( type pathFinder = func(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, source, target route.Vertex, amt lnwire.MilliSatoshi, timePref float64, finalHtlcExpiry int32) ( - []*channeldb.CachedEdgePolicy, float64, error) + []*models.CachedEdgePolicy, float64, error) var ( // DefaultEstimator is the default estimator used for computing @@ -87,7 +88,7 @@ var ( // of the edge. type edgePolicyWithSource struct { sourceNode route.Vertex - edge *channeldb.CachedEdgePolicy + edge *models.CachedEdgePolicy } // finalHopParams encapsulates various parameters for route construction that @@ -125,7 +126,7 @@ type finalHopParams struct { // NOTE: If a non-nil blinded path is provided it is assumed to have been // validated by the caller. func newRoute(sourceVertex route.Vertex, - pathEdges []*channeldb.CachedEdgePolicy, currentHeight uint32, + pathEdges []*models.CachedEdgePolicy, currentHeight uint32, finalHop finalHopParams, blindedPath *sphinx.BlindedPath) ( *route.Route, error) { @@ -355,7 +356,7 @@ type graphParams struct { // additionalEdges is an optional set of edges that should be // considered during path finding, that is not already found in the // channel graph. - additionalEdges map[route.Vertex][]*channeldb.CachedEdgePolicy + additionalEdges map[route.Vertex][]*models.CachedEdgePolicy // bandwidthHints is an interface that provides bandwidth hints that // can provide a better estimate of the current channel bandwidth than @@ -493,7 +494,7 @@ func getOutgoingBalance(node route.Vertex, outgoingChans map[uint64]struct{}, // available bandwidth. func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, source, target route.Vertex, amt lnwire.MilliSatoshi, timePref float64, - finalHtlcExpiry int32) ([]*channeldb.CachedEdgePolicy, float64, error) { + finalHtlcExpiry int32) ([]*models.CachedEdgePolicy, float64, error) { // Pathfinding can be a significant portion of the total payment // latency, especially on low-powered devices. Log several metrics to @@ -994,7 +995,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // Use the distance map to unravel the forward path from source to // target. - var pathEdges []*channeldb.CachedEdgePolicy + var pathEdges []*models.CachedEdgePolicy currentNode := source for { // Determine the next hop forward using the next map. diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index c016451bd..a0dd1fa66 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -23,6 +23,7 @@ import ( "github.com/btcsuite/btcd/wire" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" @@ -96,7 +97,7 @@ var ( _ = testSScalar.SetByteSlice(testSBytes) testSig = ecdsa.NewSignature(testRScalar, testSScalar) - testAuthProof = channeldb.ChannelAuthProof{ + testAuthProof = models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -303,16 +304,6 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( } } - aliasForNode := func(node route.Vertex) string { - for alias, pubKey := range aliasMap { - if pubKey == node { - return alias - } - } - - return "" - } - // With all the vertexes inserted, we can now insert the edges into the // test graph. for _, edge := range g.Edges { @@ -345,7 +336,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( // We first insert the existence of the edge between the two // nodes. - edgeInfo := channeldb.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo{ ChannelID: edge.ChannelID, AuthProof: &testAuthProof, ChannelPoint: fundingPoint, @@ -376,7 +367,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( targetNode = edgeInfo.NodeKey2Bytes } - edgePolicy := &channeldb.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), MessageFlags: lnwire.ChanUpdateMsgFlags(edge.MessageFlags), ChannelFlags: channelFlags, @@ -387,10 +378,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( MaxHTLC: lnwire.MilliSatoshi(edge.MaxHTLC), FeeBaseMSat: lnwire.MilliSatoshi(edge.FeeBaseMsat), FeeProportionalMillionths: lnwire.MilliSatoshi(edge.FeeRate), - Node: &channeldb.LightningNode{ - Alias: aliasForNode(targetNode), - PubKeyBytes: targetNode, - }, + ToNode: targetNode, } if err := graph.UpdateEdgePolicy(edgePolicy); err != nil { return nil, err @@ -657,7 +645,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, // We first insert the existence of the edge between the two // nodes. - edgeInfo := channeldb.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo{ ChannelID: channelID, AuthProof: &testAuthProof, ChannelPoint: *fundingPoint, @@ -684,12 +672,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, channelFlags |= lnwire.ChanUpdateDisabled } - node2Features := lnwire.EmptyFeatureVector() - if node2.testChannelPolicy != nil { - node2Features = node2.Features - } - - edgePolicy := &channeldb.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), MessageFlags: msgFlags, ChannelFlags: channelFlags, @@ -700,11 +683,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, MaxHTLC: node1.MaxHTLC, FeeBaseMSat: node1.FeeBaseMsat, FeeProportionalMillionths: node1.FeeRate, - Node: &channeldb.LightningNode{ - Alias: node2.Alias, - PubKeyBytes: node2Vertex, - Features: node2Features, - }, + ToNode: node2Vertex, } if err := graph.UpdateEdgePolicy(edgePolicy); err != nil { return nil, err @@ -722,12 +701,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, } channelFlags |= lnwire.ChanUpdateDirection - node1Features := lnwire.EmptyFeatureVector() - if node1.testChannelPolicy != nil { - node1Features = node1.Features - } - - edgePolicy := &channeldb.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), MessageFlags: msgFlags, ChannelFlags: channelFlags, @@ -738,11 +712,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, MaxHTLC: node2.MaxHTLC, FeeBaseMSat: node2.FeeBaseMsat, FeeProportionalMillionths: node2.FeeRate, - Node: &channeldb.LightningNode{ - Alias: node1.Alias, - PubKeyBytes: node1Vertex, - Features: node1Features, - }, + ToNode: node1Vertex, } if err := graph.UpdateEdgePolicy(edgePolicy); err != nil { return nil, err @@ -1234,7 +1204,7 @@ func runPathFindingWithAdditionalEdges(t *testing.T, useCache bool) { // Create the channel edge going from songoku to doge and include it in // our map of additional edges. - songokuToDoge := &channeldb.CachedEdgePolicy{ + songokuToDoge := &models.CachedEdgePolicy{ ToNodePubKey: func() route.Vertex { return doge.PubKeyBytes }, @@ -1245,12 +1215,12 @@ func runPathFindingWithAdditionalEdges(t *testing.T, useCache bool) { TimeLockDelta: 9, } - additionalEdges := map[route.Vertex][]*channeldb.CachedEdgePolicy{ + additionalEdges := map[route.Vertex][]*models.CachedEdgePolicy{ graph.aliasMap["songoku"]: {songokuToDoge}, } find := func(r *RestrictParams) ( - []*channeldb.CachedEdgePolicy, error) { + []*models.CachedEdgePolicy, error) { return dbFindPath( graph.graph, additionalEdges, &mockBandwidthHints{}, @@ -1320,7 +1290,7 @@ func runPathFindingWithRedundantAdditionalEdges(t *testing.T, useCache bool) { // Create the channel edge going from alice to bob and include it in // our map of additional edges. - aliceToBob := &channeldb.CachedEdgePolicy{ + aliceToBob := &models.CachedEdgePolicy{ ToNodePubKey: func() route.Vertex { return target }, @@ -1331,7 +1301,7 @@ func runPathFindingWithRedundantAdditionalEdges(t *testing.T, useCache bool) { TimeLockDelta: 9, } - additionalEdges := map[route.Vertex][]*channeldb.CachedEdgePolicy{ + additionalEdges := map[route.Vertex][]*models.CachedEdgePolicy{ ctx.source: {aliceToBob}, } @@ -1365,9 +1335,9 @@ func TestNewRoute(t *testing.T) { createHop := func(baseFee lnwire.MilliSatoshi, feeRate lnwire.MilliSatoshi, bandwidth lnwire.MilliSatoshi, - timeLockDelta uint16) *channeldb.CachedEdgePolicy { + timeLockDelta uint16) *models.CachedEdgePolicy { - return &channeldb.CachedEdgePolicy{ + return &models.CachedEdgePolicy{ ToNodePubKey: func() route.Vertex { return route.Vertex{} }, @@ -1384,7 +1354,7 @@ func TestNewRoute(t *testing.T) { // hops is the list of hops (the route) that gets passed into // the call to newRoute. - hops []*channeldb.CachedEdgePolicy + hops []*models.CachedEdgePolicy // paymentAmount is the amount that is send into the route // indicated by hops. @@ -1436,7 +1406,7 @@ func TestNewRoute(t *testing.T) { // For a single hop payment, no fees are expected to be paid. name: "single hop", paymentAmount: 100000, - hops: []*channeldb.CachedEdgePolicy{ + hops: []*models.CachedEdgePolicy{ createHop(100, 1000, 1000000, 10), }, metadata: []byte{1, 2, 3}, @@ -1450,7 +1420,7 @@ func TestNewRoute(t *testing.T) { // a fee to receive the payment. name: "two hop", paymentAmount: 100000, - hops: []*channeldb.CachedEdgePolicy{ + hops: []*models.CachedEdgePolicy{ createHop(0, 1000, 1000000, 10), createHop(30, 1000, 1000000, 5), }, @@ -1465,7 +1435,7 @@ func TestNewRoute(t *testing.T) { name: "two hop tlv onion feature", destFeatures: tlvFeatures, paymentAmount: 100000, - hops: []*channeldb.CachedEdgePolicy{ + hops: []*models.CachedEdgePolicy{ createHop(0, 1000, 1000000, 10), createHop(30, 1000, 1000000, 5), }, @@ -1482,7 +1452,7 @@ func TestNewRoute(t *testing.T) { destFeatures: tlvPayAddrFeatures, paymentAddr: &testPaymentAddr, paymentAmount: 100000, - hops: []*channeldb.CachedEdgePolicy{ + hops: []*models.CachedEdgePolicy{ createHop(0, 1000, 1000000, 10), createHop(30, 1000, 1000000, 5), }, @@ -1502,7 +1472,7 @@ func TestNewRoute(t *testing.T) { // gets rounded down to 1. name: "three hop", paymentAmount: 100000, - hops: []*channeldb.CachedEdgePolicy{ + hops: []*models.CachedEdgePolicy{ createHop(0, 10, 1000000, 10), createHop(0, 10, 1000000, 5), createHop(0, 10, 1000000, 3), @@ -1517,7 +1487,7 @@ func TestNewRoute(t *testing.T) { // because of the increase amount to forward. name: "three hop with fee carry over", paymentAmount: 100000, - hops: []*channeldb.CachedEdgePolicy{ + hops: []*models.CachedEdgePolicy{ createHop(0, 10000, 1000000, 10), createHop(0, 10000, 1000000, 5), createHop(0, 10000, 1000000, 3), @@ -1532,7 +1502,7 @@ func TestNewRoute(t *testing.T) { // effect. name: "three hop with minimal fees for carry over", paymentAmount: 100000, - hops: []*channeldb.CachedEdgePolicy{ + hops: []*models.CachedEdgePolicy{ createHop(0, 10000, 1000000, 10), // First hop charges 0.1% so the second hop fee @@ -1771,7 +1741,7 @@ func runDestTLVGraphFallback(t *testing.T, useCache bool) { require.NoError(t, err, "unable to fetch source node") find := func(r *RestrictParams, - target route.Vertex) ([]*channeldb.CachedEdgePolicy, error) { + target route.Vertex) ([]*models.CachedEdgePolicy, error) { return dbFindPath( ctx.graph, nil, &mockBandwidthHints{}, @@ -2283,7 +2253,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(bob) + bobNode, err := ctx.graph.FetchLightningNode(nil, bob) require.NoError(t, err, "unable to find bob") if err := ctx.graph.SetSourceNode(bobNode); err != nil { t.Fatalf("unable to set source node: %v", err) @@ -2332,7 +2302,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(alice) + aliceNode, err := ctx.graph.FetchLightningNode(nil, alice) require.NoError(t, err, "unable to find alice") if err := ctx.graph.SetSourceNode(aliceNode); err != nil { t.Fatalf("unable to set source node: %v", err) @@ -2429,7 +2399,7 @@ func TestPathFindSpecExample(t *testing.T) { } func assertExpectedPath(t *testing.T, aliasMap map[string]route.Vertex, - path []*channeldb.CachedEdgePolicy, nodeAliases ...string) { + path []*models.CachedEdgePolicy, nodeAliases ...string) { if len(path) != len(nodeAliases) { t.Fatal("number of hops and number of aliases do not match") @@ -3074,7 +3044,7 @@ func (c *pathFindingTestContext) aliasFromKey(pubKey route.Vertex) string { } func (c *pathFindingTestContext) findPath(target route.Vertex, - amt lnwire.MilliSatoshi) ([]*channeldb.CachedEdgePolicy, + amt lnwire.MilliSatoshi) ([]*models.CachedEdgePolicy, error) { return dbFindPath( @@ -3083,7 +3053,7 @@ func (c *pathFindingTestContext) findPath(target route.Vertex, ) } -func (c *pathFindingTestContext) assertPath(path []*channeldb.CachedEdgePolicy, +func (c *pathFindingTestContext) assertPath(path []*models.CachedEdgePolicy, expected []uint64) { if len(path) != len(expected) { @@ -3102,11 +3072,11 @@ func (c *pathFindingTestContext) assertPath(path []*channeldb.CachedEdgePolicy, // dbFindPath calls findPath after getting a db transaction from the database // graph. func dbFindPath(graph *channeldb.ChannelGraph, - additionalEdges map[route.Vertex][]*channeldb.CachedEdgePolicy, + additionalEdges map[route.Vertex][]*models.CachedEdgePolicy, bandwidthHints bandwidthHints, r *RestrictParams, cfg *PathFindingConfig, source, target route.Vertex, amt lnwire.MilliSatoshi, timePref float64, - finalHtlcExpiry int32) ([]*channeldb.CachedEdgePolicy, error) { + finalHtlcExpiry int32) ([]*models.CachedEdgePolicy, error) { sourceNode, err := graph.SourceNode() if err != nil { @@ -3210,7 +3180,7 @@ func TestBlindedRouteConstruction(t *testing.T) { // route. Proportional fees are omitted for easy test // calculations, but non-zero base fees ensure our fee is // still accounted for. - aliceBobEdge = &channeldb.CachedEdgePolicy{ + aliceBobEdge = &models.CachedEdgePolicy{ ChannelID: 1, // We won't actually use this timelock / fee (since // it's the sender's outbound channel), but we include @@ -3224,7 +3194,7 @@ func TestBlindedRouteConstruction(t *testing.T) { ToNodeFeatures: tlvFeatures, } - bobCarolEdge = &channeldb.CachedEdgePolicy{ + bobCarolEdge = &models.CachedEdgePolicy{ ChannelID: 2, TimeLockDelta: 15, FeeBaseMSat: 20, @@ -3257,7 +3227,7 @@ func TestBlindedRouteConstruction(t *testing.T) { carolDaveEdge := blindedEdges[carolVertex][0] daveEveEdge := blindedEdges[daveBlindedVertex][0] - edges := []*channeldb.CachedEdgePolicy{ + edges := []*models.CachedEdgePolicy{ aliceBobEdge, bobCarolEdge, carolDaveEdge, diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index d84c264c2..b2c3834f2 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -9,6 +9,7 @@ import ( "github.com/go-errors/errors" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -874,7 +875,7 @@ func (p *shardHandler) handleFailureMessage(rt *route.Route, var ( isAdditionalEdge bool - policy *channeldb.CachedEdgePolicy + policy *models.CachedEdgePolicy ) // Before we apply the channel update, we need to decide whether the diff --git a/routing/payment_session.go b/routing/payment_session.go index 0a9078502..a04a4de55 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -8,6 +8,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -144,13 +145,13 @@ type PaymentSession interface { // a boolean to indicate whether the update has been applied without // error. UpdateAdditionalEdge(msg *lnwire.ChannelUpdate, pubKey *btcec.PublicKey, - policy *channeldb.CachedEdgePolicy) bool + policy *models.CachedEdgePolicy) bool // GetAdditionalEdgePolicy uses the public key and channel ID to query // the ephemeral channel edge policy for additional edges. Returns a nil // if nothing found. GetAdditionalEdgePolicy(pubKey *btcec.PublicKey, - channelID uint64) *channeldb.CachedEdgePolicy + channelID uint64) *models.CachedEdgePolicy } // paymentSession is used during an HTLC routings session to prune the local @@ -162,7 +163,7 @@ type PaymentSession interface { // loop if payment attempts take long enough. An additional set of edges can // also be provided to assist in reaching the payment's destination. type paymentSession struct { - additionalEdges map[route.Vertex][]*channeldb.CachedEdgePolicy + additionalEdges map[route.Vertex][]*models.CachedEdgePolicy getBandwidthHints func(routingGraph) (bandwidthHints, error) @@ -405,7 +406,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, // updates to the supplied policy. It returns a boolean to indicate whether // there's an error when applying the updates. func (p *paymentSession) UpdateAdditionalEdge(msg *lnwire.ChannelUpdate, - pubKey *btcec.PublicKey, policy *channeldb.CachedEdgePolicy) bool { + pubKey *btcec.PublicKey, policy *models.CachedEdgePolicy) bool { // Validate the message signature. if err := VerifyChannelUpdateSignature(msg, pubKey); err != nil { @@ -430,7 +431,7 @@ func (p *paymentSession) UpdateAdditionalEdge(msg *lnwire.ChannelUpdate, // ephemeral channel edge policy for additional edges. Returns a nil if nothing // found. func (p *paymentSession) GetAdditionalEdgePolicy(pubKey *btcec.PublicKey, - channelID uint64) *channeldb.CachedEdgePolicy { + channelID uint64) *models.CachedEdgePolicy { target := route.NewVertex(pubKey) diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go index 9527e4e13..229c932f3 100644 --- a/routing/payment_session_source.go +++ b/routing/payment_session_source.go @@ -3,6 +3,7 @@ package routing import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/zpay32" @@ -94,9 +95,9 @@ func (m *SessionSource) NewPaymentSessionEmpty() PaymentSession { // RouteHintsToEdges converts a list of invoice route hints to an edge map that // can be passed into pathfinding. func RouteHintsToEdges(routeHints [][]zpay32.HopHint, target route.Vertex) ( - map[route.Vertex][]*channeldb.CachedEdgePolicy, error) { + map[route.Vertex][]*models.CachedEdgePolicy, error) { - edges := make(map[route.Vertex][]*channeldb.CachedEdgePolicy) + edges := make(map[route.Vertex][]*models.CachedEdgePolicy) // Traverse through all of the available hop hints and include them in // our edges map, indexed by the public key of the channel's starting @@ -126,7 +127,7 @@ func RouteHintsToEdges(routeHints [][]zpay32.HopHint, target route.Vertex) ( // Finally, create the channel edge from the hop hint // and add it to list of edges corresponding to the node // at the start of the channel. - edge := &channeldb.CachedEdgePolicy{ + edge := &models.CachedEdgePolicy{ ToNodePubKey: func() route.Vertex { return endNode.PubKeyBytes }, diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go index 18858f1f9..1c199ff40 100644 --- a/routing/payment_session_test.go +++ b/routing/payment_session_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -211,7 +212,7 @@ func TestRequestRoute(t *testing.T) { // Override pathfinder with a mock. session.pathFinder = func(_ *graphParams, r *RestrictParams, _ *PathFindingConfig, _, _ route.Vertex, _ lnwire.MilliSatoshi, - _ float64, _ int32) ([]*channeldb.CachedEdgePolicy, float64, + _ float64, _ int32) ([]*models.CachedEdgePolicy, float64, error) { // We expect find path to receive a cltv limit excluding the @@ -220,7 +221,7 @@ func TestRequestRoute(t *testing.T) { t.Fatal("wrong cltv limit") } - path := []*channeldb.CachedEdgePolicy{ + path := []*models.CachedEdgePolicy{ { ToNodePubKey: func() route.Vertex { return route.Vertex{} diff --git a/routing/router.go b/routing/router.go index 827e21864..fa255544c 100644 --- a/routing/router.go +++ b/routing/router.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/batch" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" @@ -135,17 +136,17 @@ type ChannelGraphSource interface { // AddEdge is used to add edge/channel to the topology of the router, // after all information about channel will be gathered this // edge/channel might be used in construction of payment path. - AddEdge(edge *channeldb.ChannelEdgeInfo, + AddEdge(edge *models.ChannelEdgeInfo, op ...batch.SchedulerOption) error // AddProof updates the channel edge info with proof which is needed to // properly announce the edge to the rest of the network. AddProof(chanID lnwire.ShortChannelID, - proof *channeldb.ChannelAuthProof) error + proof *models.ChannelAuthProof) error // UpdateEdge is used to update edge information, without this message // edge considered as not fully constructed. - UpdateEdge(policy *channeldb.ChannelEdgePolicy, + UpdateEdge(policy *models.ChannelEdgePolicy, op ...batch.SchedulerOption) error // IsStaleNode returns true if the graph source has a node announcement @@ -176,8 +177,8 @@ type ChannelGraphSource interface { // emanating from the "source" node which is the center of the // star-graph. ForAllOutgoingChannels(cb func(tx kvdb.RTx, - c *channeldb.ChannelEdgeInfo, - e *channeldb.ChannelEdgePolicy) error) error + c *models.ChannelEdgeInfo, + e *models.ChannelEdgePolicy) error) error // CurrentBlockHeight returns the block height from POV of the router // subsystem. @@ -185,8 +186,8 @@ type ChannelGraphSource interface { // GetChannelByID return the channel by the channel id. GetChannelByID(chanID lnwire.ShortChannelID) ( - *channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy, - *channeldb.ChannelEdgePolicy, error) + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) // FetchLightningNode attempts to look up a target node by its identity // public key. channeldb.ErrGraphNodeNotFound is returned if the node @@ -897,15 +898,15 @@ func (r *ChannelRouter) pruneZombieChans() error { log.Infof("Examining channel graph for zombie channels") // A helper method to detect if the channel belongs to this node - isSelfChannelEdge := func(info *channeldb.ChannelEdgeInfo) bool { + isSelfChannelEdge := func(info *models.ChannelEdgeInfo) bool { return info.NodeKey1Bytes == r.selfNode.PubKeyBytes || info.NodeKey2Bytes == r.selfNode.PubKeyBytes } // First, we'll collect all the channels which are eligible for garbage // collection due to being zombies. - filterPruneChans := func(info *channeldb.ChannelEdgeInfo, - e1, e2 *channeldb.ChannelEdgePolicy) error { + filterPruneChans := func(info *models.ChannelEdgeInfo, + e1, e2 *models.ChannelEdgePolicy) error { // Exit early in case this channel is already marked to be pruned if _, markedToPrune := chansToPrune[info.ChannelID]; markedToPrune { @@ -1539,7 +1540,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}, log.Tracef("Updated vertex data for node=%x", msg.PubKeyBytes) r.stats.incNumNodeUpdates() - case *channeldb.ChannelEdgeInfo: + case *models.ChannelEdgeInfo: log.Debugf("Received ChannelEdgeInfo for channel %v", msg.ChannelID) @@ -1706,7 +1707,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}, "view: %v", err) } - case *channeldb.ChannelEdgePolicy: + case *models.ChannelEdgePolicy: log.Debugf("Received ChannelEdgePolicy for channel %v", msg.ChannelID) @@ -1883,7 +1884,7 @@ type RouteRequest struct { // RouteHints is an alias type for a set of route hints, with the source node // as the map's key and the details of the hint(s) in the edge policy. -type RouteHints map[route.Vertex][]*channeldb.CachedEdgePolicy +type RouteHints map[route.Vertex][]*models.CachedEdgePolicy // NewRouteRequest produces a new route request for a regular payment or one // to a blinded route, validating that the target, routeHints and finalExpiry @@ -2668,7 +2669,7 @@ func (r *ChannelRouter) applyChannelUpdate(msg *lnwire.ChannelUpdate) bool { return false } - err = r.UpdateEdge(&channeldb.ChannelEdgePolicy{ + err = r.UpdateEdge(&models.ChannelEdgePolicy{ SigBytes: msg.Signature.ToSignatureBytes(), ChannelID: msg.ShortChannelID.ToUint64(), LastUpdate: time.Unix(int64(msg.Timestamp), 0), @@ -2720,7 +2721,7 @@ func (r *ChannelRouter) AddNode(node *channeldb.LightningNode, // in construction of payment path. // // NOTE: This method is part of the ChannelGraphSource interface. -func (r *ChannelRouter) AddEdge(edge *channeldb.ChannelEdgeInfo, +func (r *ChannelRouter) AddEdge(edge *models.ChannelEdgeInfo, op ...batch.SchedulerOption) error { rMsg := &routingMsg{ @@ -2746,7 +2747,7 @@ func (r *ChannelRouter) AddEdge(edge *channeldb.ChannelEdgeInfo, // considered as not fully constructed. // // NOTE: This method is part of the ChannelGraphSource interface. -func (r *ChannelRouter) UpdateEdge(update *channeldb.ChannelEdgePolicy, +func (r *ChannelRouter) UpdateEdge(update *models.ChannelEdgePolicy, op ...batch.SchedulerOption) error { rMsg := &routingMsg{ @@ -2787,9 +2788,9 @@ func (r *ChannelRouter) SyncedHeight() uint32 { // // NOTE: This method is part of the ChannelGraphSource interface. func (r *ChannelRouter) GetChannelByID(chanID lnwire.ShortChannelID) ( - *channeldb.ChannelEdgeInfo, - *channeldb.ChannelEdgePolicy, - *channeldb.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) { return r.cfg.Graph.FetchChannelEdgesByID(chanID.ToUint64()) } @@ -2802,7 +2803,7 @@ func (r *ChannelRouter) GetChannelByID(chanID lnwire.ShortChannelID) ( func (r *ChannelRouter) FetchLightningNode( node route.Vertex) (*channeldb.LightningNode, error) { - return r.cfg.Graph.FetchLightningNode(node) + return r.cfg.Graph.FetchLightningNode(nil, node) } // ForEachNode is used to iterate over every node in router topology. @@ -2822,18 +2823,21 @@ func (r *ChannelRouter) ForEachNode( // // NOTE: This method is part of the ChannelGraphSource interface. func (r *ChannelRouter) ForAllOutgoingChannels(cb func(kvdb.RTx, - *channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy) error) error { + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy) error) error { - return r.selfNode.ForEachChannel(nil, func(tx kvdb.RTx, - c *channeldb.ChannelEdgeInfo, - e, _ *channeldb.ChannelEdgePolicy) error { + return r.cfg.Graph.ForEachNodeChannel(nil, r.selfNode.PubKeyBytes, + func(tx kvdb.RTx, c *models.ChannelEdgeInfo, + e *models.ChannelEdgePolicy, + _ *models.ChannelEdgePolicy) error { - if e == nil { - return fmt.Errorf("channel from self node has no policy") - } + if e == nil { + return fmt.Errorf("channel from self node " + + "has no policy") + } - return cb(tx, c, e) - }) + return cb(tx, c, e) + }, + ) } // AddProof updates the channel edge info with proof which is needed to @@ -2841,7 +2845,7 @@ func (r *ChannelRouter) ForAllOutgoingChannels(cb func(kvdb.RTx, // // NOTE: This method is part of the ChannelGraphSource interface. func (r *ChannelRouter) AddProof(chanID lnwire.ShortChannelID, - proof *channeldb.ChannelAuthProof) error { + proof *models.ChannelAuthProof) error { info, _, _, err := r.cfg.Graph.FetchChannelEdgesByID(chanID.ToUint64()) if err != nil { @@ -3126,14 +3130,14 @@ func getRouteUnifiers(source route.Vertex, hops []route.Vertex, // including fees, to send the payment. func getPathEdges(source route.Vertex, receiverAmt lnwire.MilliSatoshi, unifiers []*edgeUnifier, bandwidthHints *bandwidthManager, - hops []route.Vertex) ([]*channeldb.CachedEdgePolicy, + hops []route.Vertex) ([]*models.CachedEdgePolicy, lnwire.MilliSatoshi, error) { // Now that we arrived at the start of the route and found out the route // total amount, we make a forward pass. Because the amount may have // been increased in the backward pass, fees need to be recalculated and // amount ranges re-checked. - var pathEdges []*channeldb.CachedEdgePolicy + var pathEdges []*models.CachedEdgePolicy for i, unifier := range unifiers { edge := unifier.getEdge(receiverAmt, bandwidthHints) if edge == nil { diff --git a/routing/router_test.go b/routing/router_test.go index ea1fec287..14e2ae839 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -19,6 +19,7 @@ import ( sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/htlcswitch" lnmock "github.com/lightningnetwork/lnd/lntest/mock" @@ -1241,7 +1242,7 @@ func TestAddProof(t *testing.T) { ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) // After utxo was recreated adding the edge without the proof. - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, @@ -1330,7 +1331,7 @@ func TestIgnoreChannelEdgePolicyForUnknownChannel(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -1338,7 +1339,7 @@ func TestIgnoreChannelEdgePolicyForUnknownChannel(t *testing.T) { BitcoinKey2Bytes: pub2, AuthProof: nil, } - edgePolicy := &channeldb.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -1408,7 +1409,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -1423,7 +1424,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { // We must add the edge policy to be able to use the edge for route // finding. - edgePolicy := &channeldb.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -1431,9 +1432,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { MinHTLC: 1, FeeBaseMSat: 10, FeeProportionalMillionths: 10000, - Node: &channeldb.LightningNode{ - PubKeyBytes: edge.NodeKey2Bytes, - }, + ToNode: edge.NodeKey2Bytes, } edgePolicy.ChannelFlags = 0 @@ -1442,7 +1441,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { } // Create edge in the other direction as well. - edgePolicy = &channeldb.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -1450,9 +1449,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { MinHTLC: 1, FeeBaseMSat: 10, FeeProportionalMillionths: 10000, - Node: &channeldb.LightningNode{ - PubKeyBytes: edge.NodeKey1Bytes, - }, + ToNode: edge.NodeKey1Bytes, } edgePolicy.ChannelFlags = 1 @@ -1507,7 +1504,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge = &channeldb.ChannelEdgeInfo{ + edge = &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), AuthProof: nil, } @@ -1520,7 +1517,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { t.Fatalf("unable to add edge to the channel graph: %v.", err) } - edgePolicy = &channeldb.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -1528,9 +1525,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { MinHTLC: 1, FeeBaseMSat: 10, FeeProportionalMillionths: 10000, - Node: &channeldb.LightningNode{ - PubKeyBytes: edge.NodeKey2Bytes, - }, + ToNode: edge.NodeKey2Bytes, } edgePolicy.ChannelFlags = 0 @@ -1538,7 +1533,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { t.Fatalf("unable to update edge policy: %v", err) } - edgePolicy = &channeldb.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -1546,9 +1541,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { MinHTLC: 1, FeeBaseMSat: 10, FeeProportionalMillionths: 10000, - Node: &channeldb.LightningNode{ - PubKeyBytes: edge.NodeKey1Bytes, - }, + ToNode: edge.NodeKey1Bytes, } edgePolicy.ChannelFlags = 1 @@ -1613,14 +1606,14 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { _, _, err = ctx.router.FindRoute(req) require.NoError(t, err, "unable to find any routes") - copy1, err := ctx.graph.FetchLightningNode(pub1) + copy1, err := ctx.graph.FetchLightningNode(nil, pub1) require.NoError(t, err, "unable to fetch node") if copy1.Alias != n1.Alias { t.Fatalf("fetched node not equal to original") } - copy2, err := ctx.graph.FetchLightningNode(pub2) + copy2, err := ctx.graph.FetchLightningNode(nil, pub2) require.NoError(t, err, "unable to fetch node") if copy2.Alias != n2.Alias { @@ -1710,11 +1703,11 @@ func TestWakeUpOnStaleBranch(t *testing.T) { node2, err := createTestNode() require.NoError(t, err, "unable to create test node") - edge1 := &channeldb.ChannelEdgeInfo{ + edge1 := &models.ChannelEdgeInfo{ ChannelID: chanID1, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -1728,11 +1721,11 @@ func TestWakeUpOnStaleBranch(t *testing.T) { t.Fatalf("unable to add edge: %v", err) } - edge2 := &channeldb.ChannelEdgeInfo{ + edge2 := &models.ChannelEdgeInfo{ ChannelID: chanID2, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -1918,13 +1911,13 @@ func TestDisconnectedBlocks(t *testing.T) { node2, err := createTestNode() require.NoError(t, err, "unable to create test node") - edge1 := &channeldb.ChannelEdgeInfo{ + edge1 := &models.ChannelEdgeInfo{ ChannelID: chanID1, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, BitcoinKey1Bytes: node1.PubKeyBytes, BitcoinKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -1938,13 +1931,13 @@ func TestDisconnectedBlocks(t *testing.T) { t.Fatalf("unable to add edge: %v", err) } - edge2 := &channeldb.ChannelEdgeInfo{ + edge2 := &models.ChannelEdgeInfo{ ChannelID: chanID2, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, BitcoinKey1Bytes: node1.PubKeyBytes, BitcoinKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -2069,11 +2062,11 @@ func TestRouterChansClosedOfflinePruneGraph(t *testing.T) { require.NoError(t, err, "unable to create test node") node2, err := createTestNode() require.NoError(t, err, "unable to create test node") - edge1 := &channeldb.ChannelEdgeInfo{ + edge1 := &models.ChannelEdgeInfo{ ChannelID: chanID1.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &channeldb.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -2508,7 +2501,7 @@ func TestIsStaleNode(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -2584,7 +2577,7 @@ func TestIsKnownEdge(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -2640,7 +2633,7 @@ func TestIsStaleEdgePolicy(t *testing.T) { t.Fatalf("router failed to detect fresh edge policy") } - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -2653,7 +2646,7 @@ func TestIsStaleEdgePolicy(t *testing.T) { } // We'll also add two edge policies, one for each direction. - edgePolicy := &channeldb.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: updateTimeStamp, @@ -2667,7 +2660,7 @@ func TestIsStaleEdgePolicy(t *testing.T) { t.Fatalf("unable to update edge policy: %v", err) } - edgePolicy = &channeldb.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: updateTimeStamp, @@ -3210,7 +3203,7 @@ func TestGetPathEdges(t *testing.T) { bandwidthHints *bandwidthManager hops []route.Vertex - expectedEdges []*channeldb.CachedEdgePolicy + expectedEdges []*models.CachedEdgePolicy expectedAmt lnwire.MilliSatoshi expectedErr string }{{ @@ -3265,7 +3258,7 @@ const ( // newChannelEdgeInfo is a helper function used to create a new channel edge, // possibly skipping adding it to parts of the chain/state as well. func newChannelEdgeInfo(ctx *testCtx, fundingHeight uint32, - ecm edgeCreationModifier) (*channeldb.ChannelEdgeInfo, error) { + ecm edgeCreationModifier) (*models.ChannelEdgeInfo, error) { node1, err := createTestNode() if err != nil { @@ -3284,7 +3277,7 @@ func newChannelEdgeInfo(ctx *testCtx, fundingHeight uint32, return nil, fmt.Errorf("unable to create edge: %w", err) } - edge := &channeldb.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, @@ -3315,7 +3308,7 @@ func newChannelEdgeInfo(ctx *testCtx, fundingHeight uint32, } func assertChanChainRejection(t *testing.T, ctx *testCtx, - edge *channeldb.ChannelEdgeInfo, failCode errorCode) { + edge *models.ChannelEdgeInfo, failCode errorCode) { t.Helper() @@ -4723,7 +4716,7 @@ func TestNewRouteRequest(t *testing.T) { name: "hints and blinded", blindedPayment: blindedMultiHop, routeHints: make( - map[route.Vertex][]*channeldb.CachedEdgePolicy, + map[route.Vertex][]*models.CachedEdgePolicy, ), err: ErrHintsAndBlinded, }, diff --git a/routing/unified_edges.go b/routing/unified_edges.go index e8c2a9270..aee168348 100644 --- a/routing/unified_edges.go +++ b/routing/unified_edges.go @@ -3,6 +3,7 @@ package routing import ( "github.com/btcsuite/btcd/btcutil" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -41,7 +42,7 @@ func newNodeEdgeUnifier(sourceNode, toNode route.Vertex, // addPolicy adds a single channel policy. Capacity may be zero if unknown // (light clients). func (u *nodeEdgeUnifier) addPolicy(fromNode route.Vertex, - edge *channeldb.CachedEdgePolicy, capacity btcutil.Amount) { + edge *models.CachedEdgePolicy, capacity btcutil.Amount) { localChan := fromNode == u.sourceNode @@ -93,7 +94,7 @@ func (u *nodeEdgeUnifier) addGraphPolicies(g routingGraph) error { // unifiedEdge is the individual channel data that is kept inside an edgeUnifier // object. type unifiedEdge struct { - policy *channeldb.CachedEdgePolicy + policy *models.CachedEdgePolicy capacity btcutil.Amount } @@ -233,7 +234,7 @@ func (u *edgeUnifier) getEdgeLocal(amt lnwire.MilliSatoshi, // forwarding context. func (u *edgeUnifier) getEdgeNetwork(amt lnwire.MilliSatoshi) *unifiedEdge { var ( - bestPolicy *channeldb.CachedEdgePolicy + bestPolicy *models.CachedEdgePolicy maxFee lnwire.MilliSatoshi maxTimelock uint16 maxCapMsat lnwire.MilliSatoshi diff --git a/routing/unified_edges_test.go b/routing/unified_edges_test.go index 752a79718..9b603d78c 100644 --- a/routing/unified_edges_test.go +++ b/routing/unified_edges_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/btcsuite/btcd/btcutil" - "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" "github.com/stretchr/testify/require" @@ -21,7 +21,7 @@ func TestNodeEdgeUnifier(t *testing.T) { bandwidthHints := &mockBandwidthHints{} // Add two channels between the pair of nodes. - p1 := channeldb.CachedEdgePolicy{ + p1 := models.CachedEdgePolicy{ FeeProportionalMillionths: 100000, FeeBaseMSat: 30, TimeLockDelta: 60, @@ -29,7 +29,7 @@ func TestNodeEdgeUnifier(t *testing.T) { MaxHTLC: 5000, MinHTLC: 100, } - p2 := channeldb.CachedEdgePolicy{ + p2 := models.CachedEdgePolicy{ FeeProportionalMillionths: 190000, FeeBaseMSat: 10, TimeLockDelta: 40, @@ -49,7 +49,7 @@ func TestNodeEdgeUnifier(t *testing.T) { unifierNoCapacity.addPolicy(fromNode, &p2, 0) unifierNoInfo := newNodeEdgeUnifier(source, toNode, nil) - unifierNoInfo.addPolicy(fromNode, &channeldb.CachedEdgePolicy{}, 0) + unifierNoInfo.addPolicy(fromNode, &models.CachedEdgePolicy{}, 0) tests := []struct { name string diff --git a/routing/validation_barrier.go b/routing/validation_barrier.go index a7c6561ac..aeef3d4b8 100644 --- a/routing/validation_barrier.go +++ b/routing/validation_barrier.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -125,7 +126,7 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) { v.nodeAnnDependencies[route.Vertex(msg.NodeID1)] = signals v.nodeAnnDependencies[route.Vertex(msg.NodeID2)] = signals } - case *channeldb.ChannelEdgeInfo: + case *models.ChannelEdgeInfo: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) if _, ok := v.chanAnnFinSignal[shortID]; !ok { @@ -143,7 +144,7 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) { // These other types don't have any dependants, so no further // initialization needs to be done beyond just occupying a job slot. - case *channeldb.ChannelEdgePolicy: + case *models.ChannelEdgePolicy: return case *lnwire.ChannelUpdate: return @@ -187,7 +188,7 @@ func (v *ValidationBarrier) WaitForDependants(job interface{}) error { switch msg := job.(type) { // Any ChannelUpdate or NodeAnnouncement jobs will need to wait on the // completion of any active ChannelAnnouncement jobs related to them. - case *channeldb.ChannelEdgePolicy: + case *models.ChannelEdgePolicy: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) signals, ok = v.chanEdgeDependencies[shortID] @@ -217,7 +218,7 @@ func (v *ValidationBarrier) WaitForDependants(job interface{}) error { // return directly. case *lnwire.AnnounceSignatures: // TODO(roasbeef): need to wait on chan ann? - case *channeldb.ChannelEdgeInfo: + case *models.ChannelEdgeInfo: case *lnwire.ChannelAnnouncement: } @@ -263,7 +264,7 @@ func (v *ValidationBarrier) SignalDependants(job interface{}, allow bool) { // If we've just finished executing a ChannelAnnouncement, then we'll // close out the signal, and remove the signal from the map of active // ones. This will allow/deny any dependent jobs to continue execution. - case *channeldb.ChannelEdgeInfo: + case *models.ChannelEdgeInfo: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) finSignals, ok := v.chanAnnFinSignal[shortID] if ok { @@ -296,7 +297,7 @@ func (v *ValidationBarrier) SignalDependants(job interface{}, allow bool) { delete(v.nodeAnnDependencies, route.Vertex(msg.NodeID)) case *lnwire.ChannelUpdate: delete(v.chanEdgeDependencies, msg.ShortChannelID) - case *channeldb.ChannelEdgePolicy: + case *models.ChannelEdgePolicy: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) delete(v.chanEdgeDependencies, shortID) diff --git a/rpcserver.go b/rpcserver.go index 85a156cf9..fa23f0485 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -38,6 +38,7 @@ import ( "github.com/lightningnetwork/lnd/chanbackup" "github.com/lightningnetwork/lnd/chanfitness" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/discovery" @@ -5921,8 +5922,8 @@ func (r *rpcServer) DescribeGraph(ctx context.Context, // Next, for each active channel we know of within the graph, create a // similar response which details both the edge information as well as // the routing policies of th nodes connecting the two edges. - err = graph.ForEachChannel(func(edgeInfo *channeldb.ChannelEdgeInfo, - c1, c2 *channeldb.ChannelEdgePolicy) error { + err = graph.ForEachChannel(func(edgeInfo *models.ChannelEdgeInfo, + c1, c2 *models.ChannelEdgePolicy) error { // Do not include unannounced channels unless specifically // requested. Unannounced channels include both private channels as @@ -5932,7 +5933,7 @@ func (r *rpcServer) DescribeGraph(ctx context.Context, return nil } - edge := marshalDbEdge(edgeInfo, c1, c2) + edge := marshalDBEdge(edgeInfo, c1, c2) resp.Edges = append(resp.Edges, edge) return nil @@ -5977,8 +5978,8 @@ func marshalExtraOpaqueData(data []byte) map[uint64][]byte { return records } -func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo, - c1, c2 *channeldb.ChannelEdgePolicy) *lnrpc.ChannelEdge { +func marshalDBEdge(edgeInfo *models.ChannelEdgeInfo, + c1, c2 *models.ChannelEdgePolicy) *lnrpc.ChannelEdge { // Make sure the policies match the node they belong to. c1 should point // to the policy for NodeKey1, and c2 for NodeKey2. @@ -6021,7 +6022,7 @@ func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo, } func marshalDBRoutingPolicy( - policy *channeldb.ChannelEdgePolicy) *lnrpc.RoutingPolicy { + policy *models.ChannelEdgePolicy) *lnrpc.RoutingPolicy { disabled := policy.ChannelFlags&lnwire.ChanUpdateDisabled != 0 @@ -6113,7 +6114,7 @@ func (r *rpcServer) GetChanInfo(ctx context.Context, // Convert the database's edge format into the network/RPC edge format // which couples the edge itself along with the directional node // routing policies of each node involved within the channel. - channelEdge := marshalDbEdge(edgeInfo, edge1, edge2) + channelEdge := marshalDBEdge(edgeInfo, edge1, edge2) return channelEdge, nil } @@ -6135,7 +6136,7 @@ func (r *rpcServer) GetNodeInfo(ctx context.Context, // With the public key decoded, attempt to fetch the node corresponding // to this public key. If the node cannot be found, then an error will // be returned. - node, err := graph.FetchLightningNode(pubKey) + node, err := graph.FetchLightningNode(nil, pubKey) switch { case err == channeldb.ErrGraphNodeNotFound: return nil, status.Error(codes.NotFound, err.Error()) @@ -6151,30 +6152,33 @@ func (r *rpcServer) GetNodeInfo(ctx context.Context, channels []*lnrpc.ChannelEdge ) - if err := node.ForEachChannel(nil, func(_ kvdb.RTx, - edge *channeldb.ChannelEdgeInfo, - c1, c2 *channeldb.ChannelEdgePolicy) error { + err = graph.ForEachNodeChannel(nil, node.PubKeyBytes, + func(_ kvdb.RTx, edge *models.ChannelEdgeInfo, + c1, c2 *models.ChannelEdgePolicy) error { - numChannels++ - totalCapacity += edge.Capacity + numChannels++ + totalCapacity += edge.Capacity - // Only populate the node's channels if the user requested them. - if in.IncludeChannels { - // Do not include unannounced channels - private - // channels or public channels whose authentication - // proof were not confirmed yet. - if edge.AuthProof == nil { - return nil + // Only populate the node's channels if the user + // requested them. + if in.IncludeChannels { + // Do not include unannounced channels - private + // channels or public channels whose + // authentication proof were not confirmed yet. + if edge.AuthProof == nil { + return nil + } + + // Convert the database's edge format into the + // network/RPC edge format. + channelEdge := marshalDBEdge(edge, c1, c2) + channels = append(channels, channelEdge) } - // Convert the database's edge format into the - // network/RPC edge format. - channelEdge := marshalDbEdge(edge, c1, c2) - channels = append(channels, channelEdge) - } - - return nil - }); err != nil { + return nil + }, + ) + if err != nil { return nil, err } @@ -6763,34 +6767,39 @@ func (r *rpcServer) FeeReport(ctx context.Context, } var feeReports []*lnrpc.ChannelFeeReport - err = selfNode.ForEachChannel(nil, func(_ kvdb.RTx, chanInfo *channeldb.ChannelEdgeInfo, - edgePolicy, _ *channeldb.ChannelEdgePolicy) error { + err = channelGraph.ForEachNodeChannel(nil, selfNode.PubKeyBytes, + func(_ kvdb.RTx, chanInfo *models.ChannelEdgeInfo, + edgePolicy, _ *models.ChannelEdgePolicy) error { - // Self node should always have policies for its channels. - if edgePolicy == nil { - return fmt.Errorf("no policy for outgoing channel %v ", - chanInfo.ChannelID) - } + // Self node should always have policies for its + // channels. + if edgePolicy == nil { + return fmt.Errorf("no policy for outgoing "+ + "channel %v ", chanInfo.ChannelID) + } - // We'll compute the effective fee rate by converting from a - // fixed point fee rate to a floating point fee rate. The fee - // rate field in the database the amount of mSAT charged per - // 1mil mSAT sent, so will divide by this to get the proper fee - // rate. - feeRateFixedPoint := edgePolicy.FeeProportionalMillionths - feeRate := float64(feeRateFixedPoint) / feeBase + // We'll compute the effective fee rate by converting + // from a fixed point fee rate to a floating point fee + // rate. The fee rate field in the database the amount + // of mSAT charged per 1mil mSAT sent, so will divide by + // this to get the proper fee rate. + feeRateFixedPoint := + edgePolicy.FeeProportionalMillionths + feeRate := float64(feeRateFixedPoint) / feeBase - // TODO(roasbeef): also add stats for revenue for each channel - feeReports = append(feeReports, &lnrpc.ChannelFeeReport{ - ChanId: chanInfo.ChannelID, - ChannelPoint: chanInfo.ChannelPoint.String(), - BaseFeeMsat: int64(edgePolicy.FeeBaseMSat), - FeePerMil: int64(feeRateFixedPoint), - FeeRate: feeRate, - }) + // TODO(roasbeef): also add stats for revenue for each + // channel + feeReports = append(feeReports, &lnrpc.ChannelFeeReport{ + ChanId: chanInfo.ChannelID, + ChannelPoint: chanInfo.ChannelPoint.String(), + BaseFeeMsat: int64(edgePolicy.FeeBaseMSat), + FeePerMil: int64(feeRateFixedPoint), + FeeRate: feeRate, + }) - return nil - }) + return nil + }, + ) if err != nil { return nil, err } @@ -7099,7 +7108,7 @@ func (r *rpcServer) ForwardingHistory(ctx context.Context, return "", err } - peer, err := r.server.graphDB.FetchLightningNode(vertex) + peer, err := r.server.graphDB.FetchLightningNode(nil, vertex) if err != nil { return "", err } diff --git a/server.go b/server.go index f3419a446..fcc489435 100644 --- a/server.go +++ b/server.go @@ -32,6 +32,7 @@ import ( "github.com/lightningnetwork/lnd/chanbackup" "github.com/lightningnetwork/lnd/chanfitness" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/contractcourt" @@ -1232,7 +1233,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, // Wrap the DeleteChannelEdges method so that the funding manager can // use it without depending on several layers of indirection. deleteAliasEdge := func(scid lnwire.ShortChannelID) ( - *channeldb.ChannelEdgePolicy, error) { + *models.ChannelEdgePolicy, error) { info, e1, e2, err := s.graphDB.FetchChannelEdgesByID( scid.ToUint64(), @@ -1251,7 +1252,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, var ourKey [33]byte copy(ourKey[:], nodeKeyDesc.PubKey.SerializeCompressed()) - var ourPolicy *channeldb.ChannelEdgePolicy + var ourPolicy *models.ChannelEdgePolicy if info != nil && info.NodeKey1Bytes == ourKey { ourPolicy = e1 } else { @@ -3092,10 +3093,10 @@ func (s *server) establishPersistentConnections() error { // TODO(roasbeef): instead iterate over link nodes and query graph for // each of the nodes. selfPub := s.identityECDH.PubKey().SerializeCompressed() - err = sourceNode.ForEachChannel(nil, func( + err = s.graphDB.ForEachNodeChannel(nil, sourceNode.PubKeyBytes, func( tx kvdb.RTx, - chanInfo *channeldb.ChannelEdgeInfo, - policy, _ *channeldb.ChannelEdgePolicy) error { + chanInfo *models.ChannelEdgeInfo, + policy, _ *models.ChannelEdgePolicy) error { // If the remote party has announced the channel to us, but we // haven't yet, then we won't have a policy. However, we don't @@ -3107,7 +3108,9 @@ func (s *server) establishPersistentConnections() error { // We'll now fetch the peer opposite from us within this // channel so we can queue up a direct connection to them. - channelPeer, err := chanInfo.FetchOtherNode(tx, selfPub) + channelPeer, err := s.graphDB.FetchOtherNode( + tx, chanInfo, selfPub, + ) if err != nil { return fmt.Errorf("unable to fetch channel peer for "+ "ChannelPoint(%v): %v", chanInfo.ChannelPoint, @@ -4594,7 +4597,7 @@ func (s *server) fetchNodeAdvertisedAddrs(pub *btcec.PublicKey) ([]net.Addr, err return nil, err } - node, err := s.graphDB.FetchLightningNode(vertex) + node, err := s.graphDB.FetchLightningNode(nil, vertex) if err != nil { return nil, err }