mirror of
https://github.com/lightningnetwork/lnd.git
synced 2026-08-13 12:32:48 +02:00
Migrate all btcd dependencies to the new per-package v2 modules (wire/v2, txscript/v2, chaincfg/v2, chainhash/v2, btcutil/v2, psbt/v2, btcec/v2) introduced by btcd v0.26.0, and pin the tagged ecosystem versions: btcwallet v0.17.0, neutrino v0.18.0 and lightning-onion v1.4.0. The bulk of the import rewrite was produced by the scripted diff from https://github.com/btcsuite/btcd/pull/2547 (followed by 'make rpc'). The address symbols that moved out of btcutil into the new address package are imported as btcaddr where a local "address" variable would otherwise shadow them. The go.mod/go.sum updates and the remaining manual compilation fixes are folded into this single commit so it builds on its own (the migration was previously split into a reproducible scripted-diff plus follow-ups, intended to be squashed on merge).
421 lines
20 KiB
Go
421 lines
20 KiB
Go
package graphdb
|
|
|
|
import (
|
|
"context"
|
|
"iter"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/btcsuite/btcd/chainhash/v2"
|
|
"github.com/btcsuite/btcd/wire/v2"
|
|
"github.com/lightningnetwork/lnd/batch"
|
|
"github.com/lightningnetwork/lnd/graph/db/models"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
"github.com/lightningnetwork/lnd/routing/route"
|
|
)
|
|
|
|
// NodeTraverser is an abstract read only interface that provides information
|
|
// about nodes and their edges. The interface is about providing fast read-only
|
|
// access to the graph and so if a cache is available, it should be used.
|
|
type NodeTraverser interface {
|
|
// ForEachNodeDirectedChannel calls the callback for every channel of
|
|
// the given node.
|
|
ForEachNodeDirectedChannel(ctx context.Context, nodePub route.Vertex,
|
|
cb func(channel *DirectedChannel) error, reset func()) error
|
|
|
|
// FetchNodeFeatures returns the features of the given node.
|
|
FetchNodeFeatures(ctx context.Context,
|
|
nodePub route.Vertex) (*lnwire.FeatureVector, error)
|
|
}
|
|
|
|
// Store represents the main interface for the channel graph database for all
|
|
// channels and nodes gossiped via the V1 gossip protocol as defined in BOLT 7.
|
|
type Store interface { //nolint:interfacebloat
|
|
// ForEachNodeDirectedChannel calls the callback for every channel of
|
|
// the given node.
|
|
ForEachNodeDirectedChannel(ctx context.Context, v lnwire.GossipVersion,
|
|
nodePub route.Vertex, cb func(channel *DirectedChannel) error,
|
|
reset func()) error
|
|
|
|
// FetchNodeFeatures returns the features of the given node.
|
|
FetchNodeFeatures(ctx context.Context, v lnwire.GossipVersion,
|
|
nodePub route.Vertex) (*lnwire.FeatureVector, error)
|
|
|
|
// AddNode adds a vertex/node to the graph database. If the
|
|
// node is not in the database from before, this will add a new,
|
|
// unconnected one to the graph. If it is present from before, this will
|
|
// update that node's information. Note that this method is expected to
|
|
// only be called to update an already present node from a node
|
|
// announcement, or to insert a node found in a channel update.
|
|
AddNode(ctx context.Context, node *models.Node,
|
|
op ...batch.SchedulerOption) error
|
|
|
|
// AddrsForNode returns all known addresses for the target node public
|
|
// key that the graph DB is aware of. The returned boolean indicates if
|
|
// the given node is unknown to the graph DB or not.
|
|
AddrsForNode(ctx context.Context, v lnwire.GossipVersion,
|
|
nodePub *btcec.PublicKey) (bool, []net.Addr, error)
|
|
|
|
// ForEachSourceNodeChannel iterates through all channels of the source
|
|
// node, executing the passed callback on each. The call-back is
|
|
// provided with the channel's outpoint, whether we have a policy for
|
|
// the channel and the channel peer's node information.
|
|
ForEachSourceNodeChannel(ctx context.Context, v lnwire.GossipVersion,
|
|
cb func(chanPoint wire.OutPoint, havePolicy bool,
|
|
otherNode *models.Node) error,
|
|
reset func()) error
|
|
|
|
// 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.
|
|
//
|
|
// Unknown policies are passed into the callback as nil values.
|
|
ForEachNodeChannel(ctx context.Context, v lnwire.GossipVersion,
|
|
nodePub route.Vertex, cb func(*models.ChannelEdgeInfo,
|
|
*models.ChannelEdgePolicy,
|
|
*models.ChannelEdgePolicy) error, reset func()) error
|
|
|
|
// ForEachNodeCached is similar to forEachNode, but it returns
|
|
// DirectedChannel data to the call-back.
|
|
//
|
|
// NOTE: The callback contents MUST not be modified.
|
|
ForEachNodeCached(ctx context.Context, v lnwire.GossipVersion,
|
|
cb func(ctx context.Context, node route.Vertex,
|
|
chans map[uint64]*DirectedChannel) error,
|
|
reset func()) error
|
|
|
|
// ForEachNode iterates through all the stored vertices/nodes in the
|
|
// graph, executing the passed callback with each node encountered. If
|
|
// the callback returns an error, then the transaction is aborted and
|
|
// the iteration stops early.
|
|
ForEachNode(ctx context.Context, v lnwire.GossipVersion,
|
|
cb func(*models.Node) error, reset func()) error
|
|
|
|
// ForEachNodeCacheable iterates through all the stored vertices/nodes
|
|
// in the graph, executing the passed callback with each node
|
|
// encountered. If the callback returns an error, then the transaction
|
|
// is aborted and the iteration stops early.
|
|
ForEachNodeCacheable(ctx context.Context, v lnwire.GossipVersion,
|
|
cb func(route.Vertex, *lnwire.FeatureVector) error,
|
|
reset func()) error
|
|
|
|
// LookupAlias attempts to return the alias as advertised by the target
|
|
// node.
|
|
LookupAlias(ctx context.Context, v lnwire.GossipVersion,
|
|
pub *btcec.PublicKey) (string, error)
|
|
|
|
// DeleteNode starts a new database transaction to remove a
|
|
// vertex/node from the database according to the node's public key.
|
|
DeleteNode(ctx context.Context, v lnwire.GossipVersion,
|
|
nodePub route.Vertex) error
|
|
|
|
// NodeUpdatesInHorizon returns all the known lightning nodes which have
|
|
// updates within the passed range for the given gossip version. For v1
|
|
// gossip, the range is time-based with [start, end) per BOLT 07. This
|
|
// method can be used by two nodes to quickly determine if they have
|
|
// the same set of up to date node announcements.
|
|
NodeUpdatesInHorizon(ctx context.Context, v lnwire.GossipVersion,
|
|
r NodeUpdateRange,
|
|
opts ...IteratorOption) iter.Seq2[*models.Node, error]
|
|
|
|
// FetchNode 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.
|
|
FetchNode(ctx context.Context, v lnwire.GossipVersion,
|
|
nodePub route.Vertex) (*models.Node, error)
|
|
|
|
// HasV1Node determines if the graph has a vertex identified by
|
|
// the target node identity public key in the V1 graph. If the node
|
|
// exists in the database, a timestamp of when the data for the node
|
|
// was lasted updated is returned along with a true boolean. Otherwise,
|
|
// an empty time.Time is returned with a false boolean.
|
|
// This is specific to the V1 graph since only V1 node announcements
|
|
// use timestamps for their latest update timestamp.
|
|
HasV1Node(ctx context.Context, nodePub [33]byte) (time.Time, bool,
|
|
error)
|
|
|
|
// HasNode determines if the graph has a vertex identified by
|
|
// the target node identity public key.
|
|
HasNode(ctx context.Context, v lnwire.GossipVersion,
|
|
nodePub [33]byte) (bool, error)
|
|
|
|
// IsPublicNode is a helper method that determines whether the node with
|
|
// the given public key is seen as a public node in the graph from the
|
|
// graph's source node's point of view.
|
|
IsPublicNode(ctx context.Context, v lnwire.GossipVersion,
|
|
pubKey [33]byte) (bool, error)
|
|
|
|
// GraphSession will provide the call-back with access to a
|
|
// NodeTraverser instance which can be used to perform queries against
|
|
// the channel graph.
|
|
GraphSession(ctx context.Context,
|
|
cb func(graph NodeTraverser) error, reset func()) error
|
|
|
|
// ForEachChannel iterates through all the channel edges stored within
|
|
// the graph and invokes the passed callback for each edge. The callback
|
|
// takes two edges as since this is a directed graph, both the in/out
|
|
// edges are visited. If the callback returns an error, then the
|
|
// transaction is aborted and the iteration stops early.
|
|
//
|
|
// 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.
|
|
//
|
|
// TODO(elle): add a cross-version iteration API and make this iterate
|
|
// over all versions.
|
|
ForEachChannel(ctx context.Context, v lnwire.GossipVersion,
|
|
cb func(*models.ChannelEdgeInfo, *models.ChannelEdgePolicy,
|
|
*models.ChannelEdgePolicy) error, reset func()) error
|
|
|
|
// ForEachChannelCacheable iterates through all the channel edges stored
|
|
// within the graph and invokes the passed callback for each edge. The
|
|
// callback takes two edges as since this is a directed graph, both the
|
|
// in/out edges are visited. If the callback returns an error, then the
|
|
// transaction is aborted and the iteration stops early.
|
|
//
|
|
// 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.
|
|
//
|
|
// NOTE: this method is like ForEachChannel but fetches only the data
|
|
// required for the graph cache.
|
|
ForEachChannelCacheable(ctx context.Context, v lnwire.GossipVersion,
|
|
cb func(*models.CachedEdgeInfo, *models.CachedEdgePolicy,
|
|
*models.CachedEdgePolicy) error, reset func()) error
|
|
|
|
// DisabledChannelIDs returns the channel ids of disabled channels.
|
|
// A channel is disabled when two of the associated ChanelEdgePolicies
|
|
// have their disabled bit on.
|
|
DisabledChannelIDs(ctx context.Context,
|
|
v lnwire.GossipVersion) ([]uint64, error)
|
|
|
|
// AddChannelEdge adds a new (undirected, blank) edge to the graph
|
|
// database. An undirected edge from the two target nodes are created.
|
|
// The information stored denotes the static attributes of the channel,
|
|
// such as the channelID, the keys 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.
|
|
AddChannelEdge(ctx context.Context, edge *models.ChannelEdgeInfo,
|
|
op ...batch.SchedulerOption) error
|
|
|
|
// HasV1ChannelEdge returns true if the database knows of a channel edge
|
|
// with the passed channel ID, and false otherwise. If an edge with that
|
|
// ID is found within the graph, then two time stamps representing the
|
|
// last time the edge was updated for both directed edges are returned
|
|
// along with the boolean. If it is not found, then the zombie index is
|
|
// checked and its result is returned as the second boolean.
|
|
HasV1ChannelEdge(ctx context.Context, chanID uint64) (
|
|
time.Time, time.Time, bool, bool, error)
|
|
|
|
// HasChannelEdge returns true if the database knows of a channel edge
|
|
// with the passed channel ID and gossip version, and false otherwise.
|
|
// If it is not found, then the zombie index is checked and its result
|
|
// is returned as the second boolean.
|
|
HasChannelEdge(ctx context.Context, v lnwire.GossipVersion,
|
|
chanID uint64) (bool, bool, error)
|
|
|
|
// DeleteChannelEdges removes edges with the given channel IDs from the
|
|
// database and marks them as zombies. This ensures that we're unable to
|
|
// re-add it to our database once again. If an edge does not exist
|
|
// within the database, then ErrEdgeNotFound will be returned. If
|
|
// strictZombiePruning is true, then when we mark these edges as
|
|
// zombies, we'll set up the keys such that we require the node that
|
|
// failed to send the fresh update to be the one that resurrects the
|
|
// channel from its zombie state. The markZombie bool denotes whether
|
|
// to mark the channel as a zombie.
|
|
DeleteChannelEdges(ctx context.Context, v lnwire.GossipVersion,
|
|
strictZombiePruning, markZombie bool, chanIDs ...uint64) (
|
|
[]*models.ChannelEdgeInfo, error)
|
|
|
|
// AddEdgeProof sets the proof of an existing edge in the graph
|
|
// database.
|
|
AddEdgeProof(ctx context.Context, chanID lnwire.ShortChannelID,
|
|
proof *models.ChannelAuthProof) error
|
|
|
|
// ChannelID attempt to lookup the 8-byte compact channel ID which maps
|
|
// to the passed channel point (outpoint). If the passed channel doesn't
|
|
// exist within the database, then ErrEdgeNotFound is returned.
|
|
ChannelID(ctx context.Context, v lnwire.GossipVersion,
|
|
chanPoint *wire.OutPoint) (uint64, error)
|
|
|
|
// HighestChanID returns the "highest" known channel ID in the channel
|
|
// graph. This represents the "newest" channel from the PoV of the
|
|
// chain. This method can be used by peers to quickly determine if
|
|
// they're graphs are in sync.
|
|
HighestChanID(ctx context.Context, v lnwire.GossipVersion) (
|
|
uint64, error)
|
|
|
|
// ChanUpdatesInHorizon returns all the known channel edges which have
|
|
// at least one edge update within the specified range for the given
|
|
// gossip version. For v1 gossip, the range is time-based with
|
|
// [start, end) per BOLT 07.
|
|
ChanUpdatesInHorizon(ctx context.Context, v lnwire.GossipVersion,
|
|
r ChanUpdateRange,
|
|
opts ...IteratorOption) iter.Seq2[ChannelEdge, error]
|
|
|
|
// FilterKnownChanIDs takes a set of channel IDs for a given gossip
|
|
// version and returns the subset of chan ID's that we don't know and
|
|
// are not known zombies of the passed set. In other words, we perform
|
|
// a set difference of our set of chan ID's and the ones passed in.
|
|
// This method can be used by callers to determine the set of channels
|
|
// another peer knows of that we don't. The ChannelUpdateInfos for the
|
|
// known zombies is also returned.
|
|
FilterKnownChanIDs(ctx context.Context, v lnwire.GossipVersion,
|
|
chansInfo []ChannelUpdateInfo) ([]uint64, []ChannelUpdateInfo,
|
|
error)
|
|
|
|
// FilterChannelRange returns the channel ID's of all known channels
|
|
// which were mined in a block height within the passed range for the
|
|
// given gossip version. The channel IDs are grouped by their common
|
|
// block height. This method can be used to quickly share with a peer
|
|
// the set of channels we know of within a particular range to catch
|
|
// them up after a period of time offline. If withTimestamps is true
|
|
// then the timestamp info of the latest received channel update
|
|
// messages of the channel will be included in the response.
|
|
FilterChannelRange(ctx context.Context, v lnwire.GossipVersion,
|
|
startHeight, endHeight uint32,
|
|
withTimestamps bool) ([]BlockChannelRange, error)
|
|
|
|
// FetchChanInfos returns the set of channel edges that correspond to
|
|
// the passed channel ID's. If an edge is the query is unknown to the
|
|
// database, it will skipped and the result will contain only those
|
|
// edges that exist at the time of the query. This can be used to
|
|
// respond to peer queries that are seeking to fill in gaps in their
|
|
// view of the channel graph.
|
|
FetchChanInfos(ctx context.Context, v lnwire.GossipVersion,
|
|
chanIDs []uint64) ([]ChannelEdge, error)
|
|
|
|
// 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.
|
|
FetchChannelEdgesByOutpoint(ctx context.Context,
|
|
v lnwire.GossipVersion, op *wire.OutPoint) (
|
|
*models.ChannelEdgeInfo, *models.ChannelEdgePolicy,
|
|
*models.ChannelEdgePolicy, error)
|
|
|
|
// FetchChannelEdgesByID attempts to lookup the two directed edges for
|
|
// the channel identified by the channel ID. 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.
|
|
//
|
|
// ErrZombieEdge can 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.
|
|
FetchChannelEdgesByID(ctx context.Context, v lnwire.GossipVersion,
|
|
chanID uint64) (
|
|
*models.ChannelEdgeInfo, *models.ChannelEdgePolicy,
|
|
*models.ChannelEdgePolicy, error)
|
|
|
|
// ChannelView returns the verifiable edge information for each active
|
|
// channel within the known channel graph for the given gossip version.
|
|
// The set of UTXO's (along with their scripts) returned are the ones
|
|
// that need to be watched on chain to detect channel closes on the
|
|
// resident blockchain.
|
|
ChannelView(ctx context.Context, v lnwire.GossipVersion) ([]EdgePoint,
|
|
error)
|
|
|
|
// MarkEdgeZombie attempts to mark a channel identified by its channel
|
|
// ID as a zombie for the given gossip version. This method is used on
|
|
// an ad-hoc basis, when channels need to be marked as zombies outside
|
|
// the normal pruning cycle.
|
|
MarkEdgeZombie(ctx context.Context, v lnwire.GossipVersion,
|
|
chanID uint64, pubKey1, pubKey2 [33]byte) error
|
|
|
|
// MarkEdgeLive clears an edge from our zombie index for the given
|
|
// gossip version, deeming it as live.
|
|
MarkEdgeLive(ctx context.Context, v lnwire.GossipVersion,
|
|
chanID uint64) error
|
|
|
|
// IsZombieEdge returns whether the edge is considered zombie. If it is
|
|
// a zombie, then the two node public keys corresponding to this edge
|
|
// are also returned.
|
|
IsZombieEdge(ctx context.Context, v lnwire.GossipVersion,
|
|
chanID uint64) (bool, [33]byte, [33]byte, error)
|
|
|
|
// NumZombies returns the current number of zombie channels in the
|
|
// graph.
|
|
NumZombies(ctx context.Context, v lnwire.GossipVersion) (uint64, error)
|
|
|
|
// PutClosedScid stores a SCID for a closed channel in the database.
|
|
// This is so that we can ignore channel announcements that we know to
|
|
// be closed without having to validate them and fetch a block.
|
|
PutClosedScid(ctx context.Context, scid lnwire.ShortChannelID) error
|
|
|
|
// IsClosedScid checks whether a channel identified by the passed in
|
|
// scid is closed. This helps avoid having to perform expensive
|
|
// validation checks.
|
|
IsClosedScid(ctx context.Context,
|
|
scid lnwire.ShortChannelID) (bool, error)
|
|
|
|
// UpdateEdgePolicy updates the edge routing policy for a single
|
|
// directed edge within the database for the referenced channel. The
|
|
// `flags` attribute within the ChannelEdgePolicy determines which of
|
|
// the directed edges are being updated. If the flag is 1, then the
|
|
// first node's information is being 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.
|
|
UpdateEdgePolicy(ctx context.Context, edge *models.ChannelEdgePolicy,
|
|
op ...batch.SchedulerOption) (route.Vertex, route.Vertex, error)
|
|
|
|
// SourceNode returns the source node of the graph. The source node is
|
|
// treated as the center node within a star-graph. This method may be
|
|
// used to kick off a path finding algorithm in order to explore the
|
|
// reachability of another node based off the source node.
|
|
SourceNode(ctx context.Context, v lnwire.GossipVersion) (*models.Node,
|
|
error)
|
|
|
|
// SetSourceNode sets the source node within the graph database. The
|
|
// source node is to be used as the center of a star-graph within path
|
|
// finding algorithms.
|
|
SetSourceNode(ctx context.Context,
|
|
node *models.Node) error
|
|
|
|
// PruneTip returns the block height and hash of the latest block that
|
|
// has been used to prune channels in the graph. Knowing the "prune tip"
|
|
// allows callers to tell if the graph is currently in sync with the
|
|
// current best known UTXO state.
|
|
PruneTip(ctx context.Context) (*chainhash.Hash, uint32, error)
|
|
|
|
// PruneGraphNodes is a garbage collection method which attempts to
|
|
// prune out any nodes from the channel graph that are currently
|
|
// unconnected. This ensures that we only maintain a graph of reachable
|
|
// nodes. In the event that a pruned node gains more channels, it will
|
|
// be re-added back to the graph.
|
|
PruneGraphNodes(ctx context.Context) ([]route.Vertex, error)
|
|
|
|
// PruneGraph prunes newly closed channels from the channel graph in
|
|
// response to a new block being solved on the network. Any transactions
|
|
// which spend the funding output of any known channels within he graph
|
|
// will be deleted. Additionally, the "prune tip", or the last block
|
|
// which has been used to prune the graph is stored so callers can
|
|
// ensure the graph is fully in sync with the current UTXO state. A
|
|
// slice of channels that have been closed by the target block along
|
|
// with any pruned nodes are returned if the function succeeds without
|
|
// error.
|
|
PruneGraph(ctx context.Context, spentOutputs []*wire.OutPoint,
|
|
blockHash *chainhash.Hash, blockHeight uint32) (
|
|
[]*models.ChannelEdgeInfo, []route.Vertex, error)
|
|
|
|
// DisconnectBlockAtHeight is used to indicate that the block specified
|
|
// by the passed height has been disconnected from the main chain. This
|
|
// will "rewind" the graph back to the height below, deleting channels
|
|
// that are no longer confirmed from the graph. The prune log will be
|
|
// 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.
|
|
DisconnectBlockAtHeight(ctx context.Context,
|
|
height uint32) ([]*models.ChannelEdgeInfo, error)
|
|
}
|