lnd/graph/interfaces.go
Elle Mouton be84d6974e
channeldb: add a graph.DB interface
..which describes the database methods that are required for graph
maintaining and building.
2024-07-15 15:13:58 +02:00

281 lines
13 KiB
Go

package graph
import (
"time"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/batch"
"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"
)
// ChannelGraphSource represents the source of information about the topology
// of the lightning network. It's responsible for the addition of nodes, edges,
// applying edge updates, and returning the current block height with which the
// topology is synchronized.
//
//nolint:interfacebloat
type ChannelGraphSource interface {
// AddNode is used to add information about a node to the router
// database. If the node with this pubkey is not present in an existing
// channel, it will be ignored.
AddNode(node *channeldb.LightningNode,
op ...batch.SchedulerOption) error
// 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 *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 *models.ChannelAuthProof) error
// UpdateEdge is used to update edge information, without this message
// edge considered as not fully constructed.
UpdateEdge(policy *models.ChannelEdgePolicy,
op ...batch.SchedulerOption) error
// IsStaleNode returns true if the graph source has a node announcement
// for the target node with a more recent timestamp. This method will
// also return true if we don't have an active channel announcement for
// the target node.
IsStaleNode(node route.Vertex, timestamp time.Time) bool
// IsPublicNode determines whether the given vertex is seen as a public
// node in the graph from the graph's source node's point of view.
IsPublicNode(node route.Vertex) (bool, error)
// IsKnownEdge returns true if the graph source already knows of the
// passed channel ID either as a live or zombie edge.
IsKnownEdge(chanID lnwire.ShortChannelID) bool
// IsStaleEdgePolicy returns true if the graph source has a channel
// edge for the passed channel ID (and flags) that have a more recent
// timestamp.
IsStaleEdgePolicy(chanID lnwire.ShortChannelID, timestamp time.Time,
flags lnwire.ChanUpdateChanFlags) bool
// MarkEdgeLive clears an edge from our zombie index, deeming it as
// live.
MarkEdgeLive(chanID lnwire.ShortChannelID) error
// ForAllOutgoingChannels is used to iterate over all channels
// emanating from the "source" node which is the center of the
// star-graph.
ForAllOutgoingChannels(cb func(tx kvdb.RTx,
c *models.ChannelEdgeInfo,
e *models.ChannelEdgePolicy) error) error
// CurrentBlockHeight returns the block height from POV of the router
// subsystem.
CurrentBlockHeight() (uint32, error)
// GetChannelByID return the channel by the channel id.
GetChannelByID(chanID lnwire.ShortChannelID) (
*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
// doesn't exist within the graph.
FetchLightningNode(route.Vertex) (*channeldb.LightningNode, error)
// ForEachNode is used to iterate over every node in the known graph.
ForEachNode(func(node *channeldb.LightningNode) error) error
}
// DB is an interface describing a persisted Lightning Network graph.
//
//nolint:interfacebloat
type DB interface {
// 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() (*chainhash.Hash, uint32, 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 the 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 are
// returned if the function succeeds without error.
PruneGraph(spentOutputs []*wire.OutPoint, blockHash *chainhash.Hash,
blockHeight uint32) ([]*models.ChannelEdgeInfo, error)
// ChannelView returns the verifiable edge information for each active
// channel within the known channel graph. 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() ([]channeldb.EdgePoint, error)
// PruneGraphNodes is a garbage collection method which attempts to
// prune out any nodes from the channel graph that are currently
// unconnected. This ensure 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() 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() (*channeldb.LightningNode, 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() ([]uint64, 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(chanIDs []uint64) ([]channeldb.ChannelEdge, error)
// ChanUpdatesInHorizon returns all the known channel edges which have
// at least one edge that has an update timestamp within the specified
// horizon.
ChanUpdatesInHorizon(startTime, endTime time.Time) (
[]channeldb.ChannelEdge, 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(strictZombiePruning, markZombie bool,
chanIDs ...uint64) 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(height uint32) ([]*models.ChannelEdgeInfo,
error)
// HasChannelEdge 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.
HasChannelEdge(chanID uint64) (time.Time, time.Time, bool, bool, 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 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.
FetchChannelEdgesByID(chanID uint64) (*models.ChannelEdgeInfo,
*models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error)
// AddLightningNode 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.
AddLightningNode(node *channeldb.LightningNode,
op ...batch.SchedulerOption) 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(edge *models.ChannelEdgeInfo,
op ...batch.SchedulerOption) error
// 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.
MarkEdgeZombie(chanID uint64, pubKey1, pubKey2 [33]byte) 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(edge *models.ChannelEdgePolicy,
op ...batch.SchedulerOption) error
// HasLightningNode determines if the graph has a vertex identified by
// the target node identity public key. 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.
HasLightningNode(nodePub [33]byte) (time.Time, 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.
FetchLightningNode(nodePub route.Vertex) (*channeldb.LightningNode,
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(cb func(kvdb.RTx, *channeldb.LightningNode) error) 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(nodePub route.Vertex, cb func(kvdb.RTx,
*models.ChannelEdgeInfo,
*models.ChannelEdgePolicy,
*models.ChannelEdgePolicy) error) error
// UpdateChannelEdge retrieves and update edge of the graph database.
// Method only reserved for updating an edge info after its already been
// created. 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.
UpdateChannelEdge(edge *models.ChannelEdgeInfo) 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(pubKey [33]byte) (bool, error)
// MarkEdgeLive clears an edge from our zombie index, deeming it as
// live.
MarkEdgeLive(chanID uint64) error
}