lnd.xprv/routing/heap.go

182 lines
5.7 KiB
Go
Raw Normal View History

package routing
2018-06-04 23:10:05 +03:00
import (
"container/heap"
2018-06-04 23:10:05 +03:00
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
2018-06-04 23:10:05 +03:00
)
// nodeWithDist is a helper struct that couples the distance from the current
// source to a node with a pointer to the node itself.
type nodeWithDist struct {
// dist is the distance to this node from the source node in our
// current context.
dist int64
// node is the vertex itself. This can be used to explore all the
// outgoing edges (channels) emanating from a node.
node route.Vertex
2018-06-04 23:10:05 +03:00
// amountToReceive is the amount that should be received by this node.
// Either as final payment to the final node or as an intermediate
// amount that includes also the fees for subsequent hops.
amountToReceive lnwire.MilliSatoshi
// incomingCltv is the expected cltv value for the incoming htlc of this
// node. This value does not include the final cltv.
incomingCltv uint32
// probability is the probability that from this node onward the route
// is successful.
probability float64
// weight is the cost of the route from this node to the destination.
// Includes the routing fees and a virtual cost factor to account for
// time locks.
weight int64
}
// distanceHeap is a min-distance heap that's used within our path finding
// algorithm to keep track of the "closest" node to our source node.
type distanceHeap struct {
nodes []nodeWithDist
// pubkeyIndices maps public keys of nodes to their respective index in
// the heap. This is used as a way to avoid db lookups by using heap.Fix
// instead of having duplicate entries on the heap.
pubkeyIndices map[route.Vertex]int
}
// newDistanceHeap initializes a new distance heap. This is required because
// we must initialize the pubkeyIndices map for path-finding optimizations.
func newDistanceHeap() distanceHeap {
distHeap := distanceHeap{
pubkeyIndices: make(map[route.Vertex]int),
}
return distHeap
}
// Len returns the number of nodes in the priority queue.
//
// NOTE: This is part of the heap.Interface implementation.
func (d *distanceHeap) Len() int { return len(d.nodes) }
// Less returns whether the item in the priority queue with index i should sort
// before the item with index j.
//
// NOTE: This is part of the heap.Interface implementation.
func (d *distanceHeap) Less(i, j int) bool {
return d.nodes[i].dist < d.nodes[j].dist
}
// Swap swaps the nodes at the passed indices in the priority queue.
//
// NOTE: This is part of the heap.Interface implementation.
func (d *distanceHeap) Swap(i, j int) {
d.nodes[i], d.nodes[j] = d.nodes[j], d.nodes[i]
d.pubkeyIndices[d.nodes[i].node] = i
d.pubkeyIndices[d.nodes[j].node] = j
}
// Push pushes the passed item onto the priority queue.
//
// NOTE: This is part of the heap.Interface implementation.
func (d *distanceHeap) Push(x interface{}) {
n := x.(nodeWithDist)
d.nodes = append(d.nodes, n)
d.pubkeyIndices[n.node] = len(d.nodes) - 1
}
// Pop removes the highest priority item (according to Less) from the priority
// queue and returns it.
//
// NOTE: This is part of the heap.Interface implementation.
func (d *distanceHeap) Pop() interface{} {
n := len(d.nodes)
x := d.nodes[n-1]
d.nodes = d.nodes[0 : n-1]
delete(d.pubkeyIndices, x.node)
return x
}
// PushOrFix attempts to adjust the position of a given node in the heap.
// If the vertex already exists in the heap, then we must call heap.Fix to
// modify its position and reorder the heap. If the vertex does not already
// exist in the heap, then it is pushed onto the heap. Otherwise, we will end
// up performing more db lookups on the same node in the pathfinding algorithm.
func (d *distanceHeap) PushOrFix(dist nodeWithDist) {
index, ok := d.pubkeyIndices[dist.node]
if !ok {
heap.Push(d, dist)
return
}
// Change the value at the specified index.
d.nodes[index] = dist
// Call heap.Fix to reorder the heap.
heap.Fix(d, index)
}
// path represents an ordered set of edges which forms an available path from a
// given source node to our destination. During the process of computing the
// KSP's from a source to destination, several path swill be considered in the
// process.
type path struct {
// dist is the distance from the source node to the destination node
// that the path requires.
dist int
// hops is an ordered list of edges that comprises a potential payment
// path.
hops []*channeldb.ChannelEdgePolicy
}
// pathHeap is a min-heap that stores potential paths to be considered within
// our KSP implementation. The heap sorts paths according to their cumulative
// distance from a given source.
type pathHeap struct {
paths []path
}
// Len returns the number of nodes in the priority queue.
//
// NOTE: This is part of the heap.Interface implementation.
func (p *pathHeap) Len() int { return len(p.paths) }
// Less returns whether the item in the priority queue with index i should sort
// before the item with index j.
//
// NOTE: This is part of the heap.Interface implementation.
func (p *pathHeap) Less(i, j int) bool {
return p.paths[i].dist < p.paths[j].dist
}
// Swap swaps the nodes at the passed indices in the priority queue.
//
// NOTE: This is part of the heap.Interface implementation.
func (p *pathHeap) Swap(i, j int) {
p.paths[i], p.paths[j] = p.paths[j], p.paths[i]
}
// Push pushes the passed item onto the priority queue.
//
// NOTE: This is part of the heap.Interface implementation.
func (p *pathHeap) Push(x interface{}) {
p.paths = append(p.paths, x.(path))
}
// Pop removes the highest priority item (according to Less) from the priority
// queue and returns it.
//
// NOTE: This is part of the heap.Interface implementation.
func (p *pathHeap) Pop() interface{} {
n := len(p.paths)
x := p.paths[n-1]
p.paths = p.paths[0 : n-1]
return x
}