github.com/decred/dcrlnd@v0.7.6/routing/heap.go (about) 1 package routing 2 3 import ( 4 "container/heap" 5 6 "github.com/decred/dcrlnd/channeldb" 7 "github.com/decred/dcrlnd/lnwire" 8 "github.com/decred/dcrlnd/routing/route" 9 ) 10 11 // nodeWithDist is a helper struct that couples the distance from the current 12 // source to a node with a pointer to the node itself. 13 type nodeWithDist struct { 14 // dist is the distance to this node from the source node in our 15 // current context. 16 dist int64 17 18 // node is the vertex itself. This can be used to explore all the 19 // outgoing edges (channels) emanating from a node. 20 node route.Vertex 21 22 // amountToReceive is the amount that should be received by this node. 23 // Either as final payment to the final node or as an intermediate 24 // amount that includes also the fees for subsequent hops. 25 amountToReceive lnwire.MilliAtom 26 27 // incomingCltv is the expected absolute expiry height for the incoming 28 // htlc of this node. This value should already include the final cltv 29 // delta. 30 incomingCltv int32 31 32 // probability is the probability that from this node onward the route 33 // is successful. 34 probability float64 35 36 // weight is the cost of the route from this node to the destination. 37 // Includes the routing fees and a virtual cost factor to account for 38 // time locks. 39 weight int64 40 41 // nextHop is the edge this route comes from. 42 nextHop *channeldb.CachedEdgePolicy 43 44 // routingInfoSize is the total size requirement for the payloads field 45 // in the onion packet from this hop towards the final destination. 46 routingInfoSize uint64 47 } 48 49 // distanceHeap is a min-distance heap that's used within our path finding 50 // algorithm to keep track of the "closest" node to our source node. 51 type distanceHeap struct { 52 nodes []*nodeWithDist 53 54 // pubkeyIndices maps public keys of nodes to their respective index in 55 // the heap. This is used as a way to avoid db lookups by using heap.Fix 56 // instead of having duplicate entries on the heap. 57 pubkeyIndices map[route.Vertex]int 58 } 59 60 // newDistanceHeap initializes a new distance heap. This is required because 61 // we must initialize the pubkeyIndices map for path-finding optimizations. 62 func newDistanceHeap(numNodes int) distanceHeap { 63 distHeap := distanceHeap{ 64 pubkeyIndices: make(map[route.Vertex]int, numNodes), 65 nodes: make([]*nodeWithDist, 0, numNodes), 66 } 67 68 return distHeap 69 } 70 71 // Len returns the number of nodes in the priority queue. 72 // 73 // NOTE: This is part of the heap.Interface implementation. 74 func (d *distanceHeap) Len() int { return len(d.nodes) } 75 76 // Less returns whether the item in the priority queue with index i should sort 77 // before the item with index j. 78 // 79 // NOTE: This is part of the heap.Interface implementation. 80 func (d *distanceHeap) Less(i, j int) bool { 81 // If distances are equal, tie break on probability. 82 if d.nodes[i].dist == d.nodes[j].dist { 83 return d.nodes[i].probability > d.nodes[j].probability 84 } 85 86 return d.nodes[i].dist < d.nodes[j].dist 87 } 88 89 // Swap swaps the nodes at the passed indices in the priority queue. 90 // 91 // NOTE: This is part of the heap.Interface implementation. 92 func (d *distanceHeap) Swap(i, j int) { 93 d.nodes[i], d.nodes[j] = d.nodes[j], d.nodes[i] 94 d.pubkeyIndices[d.nodes[i].node] = i 95 d.pubkeyIndices[d.nodes[j].node] = j 96 } 97 98 // Push pushes the passed item onto the priority queue. 99 // 100 // NOTE: This is part of the heap.Interface implementation. 101 func (d *distanceHeap) Push(x interface{}) { 102 n := x.(*nodeWithDist) 103 d.nodes = append(d.nodes, n) 104 d.pubkeyIndices[n.node] = len(d.nodes) - 1 105 } 106 107 // Pop removes the highest priority item (according to Less) from the priority 108 // queue and returns it. 109 // 110 // NOTE: This is part of the heap.Interface implementation. 111 func (d *distanceHeap) Pop() interface{} { 112 n := len(d.nodes) 113 x := d.nodes[n-1] 114 d.nodes[n-1] = nil 115 d.nodes = d.nodes[0 : n-1] 116 delete(d.pubkeyIndices, x.node) 117 return x 118 } 119 120 // PushOrFix attempts to adjust the position of a given node in the heap. 121 // If the vertex already exists in the heap, then we must call heap.Fix to 122 // modify its position and reorder the heap. If the vertex does not already 123 // exist in the heap, then it is pushed onto the heap. Otherwise, we will end 124 // up performing more db lookups on the same node in the pathfinding algorithm. 125 func (d *distanceHeap) PushOrFix(dist *nodeWithDist) { 126 index, ok := d.pubkeyIndices[dist.node] 127 if !ok { 128 heap.Push(d, dist) 129 return 130 } 131 132 // Change the value at the specified index. 133 d.nodes[index] = dist 134 135 // Call heap.Fix to reorder the heap. 136 heap.Fix(d, index) 137 }