routing: rewrite package to conform to BOLT07 and factor in fees+timelocks
This commit overhauls the routing package significantly to simplify the
code, conform to the rest of the coding style within the package, and
observe the new authenticated gossiping scheme outlined in BOLT07.
As a major step towards a more realistic path finding algorithm, fees
are properly calculated and observed during path finding. If a path has
sufficient capacity _before_ fees are applied, but afterwards the
finalized route would exceed the capacity of a single link, the route
is marked as invalid.
Currently a naive weighting algorithm is used which only factors in the
time-lock delta at each hop, thereby optimizing for the lowest time
lock. Fee calculation also isn’t finalized since we aren’t yet using
milli-satoshi throughout the daemon. The final TODO item within the PR
is to properly perform a multi-path search and rank the results based
on a summation heuristic rather than just return the first (out of
many) route found.
On the server side, once nodes are initially connected to the daemon,
our routing table will be synced with the peer’s using a naive “just
send everything scheme” to hold us over until I spec out some a
efficient graph reconciliation protocol. Additionally, the routing
table is now pruned by the channel router itself once new blocks arrive
rather than depending on peers to tell us when a channel flaps or is
closed.
Finally, the validation of peer announcements aren’t yet fully
implemented as they’ll be implemented within the pending discovery
package that was blocking on the completion of this package. Most off
the routing message processing will be moved out of this package and
into the discovery package where full validation will be carried out.
2016-12-27 06:20:26 +01:00
|
|
|
package routing
|
|
|
|
|
2020-01-27 12:33:53 +01:00
|
|
|
import (
|
|
|
|
"github.com/lightningnetwork/lnd/channeldb"
|
2021-10-21 13:55:22 +02:00
|
|
|
"github.com/lightningnetwork/lnd/kvdb"
|
2020-01-27 12:33:53 +01:00
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
"github.com/lightningnetwork/lnd/routing/route"
|
|
|
|
)
|
|
|
|
|
|
|
|
// routingGraph is an abstract interface that provides information about nodes
|
|
|
|
// and edges to pathfinding.
|
|
|
|
type routingGraph interface {
|
2021-09-21 19:18:24 +02:00
|
|
|
// forEachNodeChannel calls the callback for every channel of the given
|
|
|
|
// node.
|
2020-01-27 12:33:53 +01:00
|
|
|
forEachNodeChannel(nodePub route.Vertex,
|
2021-09-21 19:18:20 +02:00
|
|
|
cb func(channel *channeldb.DirectedChannel) error) error
|
2020-01-27 12:33:53 +01:00
|
|
|
|
|
|
|
// sourceNode returns the source node of the graph.
|
|
|
|
sourceNode() route.Vertex
|
|
|
|
|
|
|
|
// fetchNodeFeatures returns the features of the given node.
|
|
|
|
fetchNodeFeatures(nodePub route.Vertex) (*lnwire.FeatureVector, error)
|
|
|
|
}
|
|
|
|
|
2021-09-21 19:18:24 +02:00
|
|
|
// CachedGraph is a routingGraph implementation that retrieves from the
|
2020-01-27 12:33:53 +01:00
|
|
|
// database.
|
2021-09-21 19:18:24 +02:00
|
|
|
type CachedGraph struct {
|
2020-01-27 12:33:53 +01:00
|
|
|
graph *channeldb.ChannelGraph
|
2021-10-21 13:55:22 +02:00
|
|
|
tx kvdb.RTx
|
2020-01-27 12:33:53 +01:00
|
|
|
source route.Vertex
|
|
|
|
}
|
|
|
|
|
2021-09-21 19:18:24 +02:00
|
|
|
// A compile time assertion to make sure CachedGraph implements the routingGraph
|
|
|
|
// interface.
|
|
|
|
var _ routingGraph = (*CachedGraph)(nil)
|
|
|
|
|
2021-10-21 13:55:22 +02:00
|
|
|
// NewCachedGraph instantiates a new db-connected routing graph. It implicitly
|
2020-01-27 12:33:53 +01:00
|
|
|
// instantiates a new read transaction.
|
2021-10-21 13:55:22 +02:00
|
|
|
func NewCachedGraph(sourceNode *channeldb.LightningNode,
|
|
|
|
graph *channeldb.ChannelGraph) (*CachedGraph, error) {
|
|
|
|
|
|
|
|
tx, err := graph.NewPathFindTx()
|
2020-01-27 12:33:53 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-09-21 19:18:24 +02:00
|
|
|
return &CachedGraph{
|
2020-01-27 12:33:53 +01:00
|
|
|
graph: graph,
|
2021-10-21 13:55:22 +02:00
|
|
|
tx: tx,
|
2020-01-27 12:33:53 +01:00
|
|
|
source: sourceNode.PubKeyBytes,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2021-10-21 13:55:22 +02:00
|
|
|
// close attempts to close the underlying db transaction. This is a no-op in
|
|
|
|
// case the underlying graph uses an in-memory cache.
|
|
|
|
func (g *CachedGraph) close() error {
|
|
|
|
if g.tx == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return g.tx.Rollback()
|
|
|
|
}
|
|
|
|
|
2020-01-27 12:33:53 +01:00
|
|
|
// forEachNodeChannel calls the callback for every channel of the given node.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the routingGraph interface.
|
2021-09-21 19:18:24 +02:00
|
|
|
func (g *CachedGraph) forEachNodeChannel(nodePub route.Vertex,
|
2021-09-21 19:18:20 +02:00
|
|
|
cb func(channel *channeldb.DirectedChannel) error) error {
|
2020-01-27 12:33:53 +01:00
|
|
|
|
2021-10-21 13:55:22 +02:00
|
|
|
return g.graph.ForEachNodeChannel(g.tx, nodePub, cb)
|
2020-01-27 12:33:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// sourceNode returns the source node of the graph.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the routingGraph interface.
|
2021-09-21 19:18:24 +02:00
|
|
|
func (g *CachedGraph) sourceNode() route.Vertex {
|
2020-01-27 12:33:53 +01:00
|
|
|
return g.source
|
|
|
|
}
|
|
|
|
|
|
|
|
// fetchNodeFeatures returns the features of the given node. If the node is
|
|
|
|
// unknown, assume no additional features are supported.
|
|
|
|
//
|
|
|
|
// NOTE: Part of the routingGraph interface.
|
2021-09-21 19:18:24 +02:00
|
|
|
func (g *CachedGraph) fetchNodeFeatures(nodePub route.Vertex) (
|
2020-01-27 12:33:53 +01:00
|
|
|
*lnwire.FeatureVector, error) {
|
|
|
|
|
2021-09-21 19:18:20 +02:00
|
|
|
return g.graph.FetchNodeFeatures(nodePub)
|
2020-01-27 12:33:53 +01:00
|
|
|
}
|