lnd/routing/graph.go

66 lines
2.1 KiB
Go
Raw Normal View History

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 (
"fmt"
"github.com/btcsuite/btcd/btcutil"
2020-01-27 12:33:53 +01:00
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)
// Graph is an abstract interface that provides information about nodes and
// edges to pathfinding.
type Graph interface {
// ForEachNodeChannel calls the callback for every channel of the given
// node.
ForEachNodeChannel(nodePub route.Vertex,
cb func(channel *channeldb.DirectedChannel) error) error
2020-01-27 12:33:53 +01:00
// FetchNodeFeatures returns the features of the given node.
FetchNodeFeatures(nodePub route.Vertex) (*lnwire.FeatureVector, error)
2020-01-27 12:33:53 +01:00
}
// GraphSessionFactory can be used to produce a new Graph instance which can
// then be used for a path-finding session. Depending on the implementation,
// the Graph session will represent a DB connection where a read-lock is being
// held across calls to the backing Graph.
type GraphSessionFactory interface {
// NewGraphSession will produce a new Graph to use for a path-finding
// session. It returns the Graph along with a call-back that must be
// called once Graph access is complete. This call-back will close any
// read-only transaction that was created at Graph construction time.
NewGraphSession() (Graph, func() error, error)
2020-01-27 12:33:53 +01:00
}
// FetchAmountPairCapacity determines the maximal public capacity between two
// nodes depending on the amount we try to send.
func FetchAmountPairCapacity(graph Graph, source, nodeFrom, nodeTo route.Vertex,
amount lnwire.MilliSatoshi) (btcutil.Amount, error) {
// Create unified edges for all incoming connections.
//
// Note: Inbound fees are not used here because this method is only used
// by a deprecated router rpc.
u := newNodeEdgeUnifier(source, nodeTo, false, nil)
err := u.addGraphPolicies(graph)
if err != nil {
return 0, err
}
edgeUnifier, ok := u.edgeUnifiers[nodeFrom]
if !ok {
return 0, fmt.Errorf("no edge info for node pair %v -> %v",
nodeFrom, nodeTo)
}
edge := edgeUnifier.getEdgeNetwork(amount, 0)
if edge == nil {
return 0, fmt.Errorf("no edge for node pair %v -> %v "+
"(amount %v)", nodeFrom, nodeTo, amount)
}
return edge.capacity, nil
}