routing: add comments and clean-up to findBlindedPaths

Here we add some more comments and a bit of code clean up to the
`findBlindedPaths` function. No logic is changed here.
This commit is contained in:
Elle Mouton committed 2025-06-25 12:33:00 +02:00
1 parent 33e6f28542
commit da37fe20fc
1 file changed
+50 -27
+50 -27
View File
@@ -1227,24 +1227,46 @@ func findBlindedPaths(g Graph, target route.Vertex,
} }
var ( var (
// The target node is always the last hop in the path. // The target node is always the last hop in the path, and so
incomingPath = []blindedHop{{vertex: target}} // we add it to the incoming path from the get-go. Any additions
whiteListedNodes = map[route.Vertex]bool{target: true} // to the slice should be prepended.
incomingPath = []blindedHop{{
vertex: target,
}}
// supportsRouteBlinding is a list of nodes that we can assume
// support route blinding without needing to rely on the feature
// bits announced in their node announcement. Since we are
// finding a path to the target node, we can assume it supports
// route blinding.
supportsRouteBlinding = map[route.Vertex]bool{
target: true,
}
visited = make(map[route.Vertex]bool) visited = make(map[route.Vertex]bool)
errChanFound = errors.New("found incoming channel")
nextTarget = target nextTarget = target
haveIncomingPath = len(restrictions.incomingChainedChannels) > 0
// errChanFound is an error variable we return from the DB
// iteration call below when we have found the channel we are
// looking for. This lets us exit the iteration early.
errChanFound = errors.New("found incoming channel")
) )
for _, chanID := range restrictions.incomingChainedChannels { for _, chanID := range restrictions.incomingChainedChannels {
// Mark that we have visited this node so that we don't revisit
// it later on when we call "processNodeForBlindedPath".
visited[nextTarget] = true visited[nextTarget] = true
err := g.ForEachNodeDirectedChannel(nextTarget, err := g.ForEachNodeDirectedChannel(nextTarget,
func(channel *graphdb.DirectedChannel) error { func(channel *graphdb.DirectedChannel) error {
// Not the right channel, continue to the node's // This is not the right channel, continue to
// other channels. // the node's other channels.
if channel.ChannelID != chanID { if channel.ChannelID != chanID {
return nil return nil
} }
// We found the channel in question. Prepend it
// to the incoming path.
incomingPath = append([]blindedHop{ incomingPath = append([]blindedHop{
{ {
vertex: channel.OtherNode, vertex: channel.OtherNode,
@@ -1259,39 +1281,37 @@ func findBlindedPaths(g Graph, target route.Vertex,
return errChanFound return errChanFound
}, },
) )
if err == nil { // We expect errChanFound to be returned if the channel in
// question was found.
if !errors.Is(err, errChanFound) && err != nil {
return nil, err
} else if err == nil {
return nil, fmt.Errorf("incoming channel %d is not "+ return nil, fmt.Errorf("incoming channel %d is not "+
"seen as owned by node %v", chanID, nextTarget) "seen as owned by node %v", chanID, nextTarget)
} }
if !errors.Is(err, errChanFound) {
return nil, err
}
// Check that the user didn't accidentally add a channel that // Check that the user didn't accidentally add a channel that
// is owned by a node in the node omission set // is owned by a node in the node omission set.
if restrictions.nodeOmissionSet.Contains(nextTarget) { if restrictions.nodeOmissionSet.Contains(nextTarget) {
return nil, fmt.Errorf("node %v cannot simultaneously "+ return nil, fmt.Errorf("node %v cannot simultaneously "+
"be included in the omission set and in the "+ "be included in the omission set and in the "+
"partially specified path", nextTarget) "partially specified path", nextTarget)
} }
if whiteListedNodes[nextTarget] { // Check that we have not already visited the next target node
// since this would mean a circular incoming path.
if visited[nextTarget] {
return nil, fmt.Errorf("a circular route cannot be " + return nil, fmt.Errorf("a circular route cannot be " +
"specified for the incoming blinded path") "specified for the incoming blinded path")
} }
whiteListedNodes[nextTarget] = true
supportsRouteBlinding[nextTarget] = true
} }
// If the node is not the destination node, then it is required that the // A helper closure which checks if the node in question has advertised
// node advertise the route blinding feature-bit in order for it to be // that it supports route blinding.
// chosen as a node on the blinded path. nodeSupportsRouteBlinding := func(node route.Vertex) (bool, error) {
// We skip checking the target node, as accepting blinded payments if supportsRouteBlinding[node] {
// (via invoice) doesn't imply support for routing them (via node
// announcement).
// We skip checking incomingChainedChannels nodes, as we might not yet
// have an updated node announcement for them.
supportsRouteBlinding := func(node route.Vertex) (bool, error) {
if whiteListedNodes[node] {
return true, nil return true, nil
} }
@@ -1308,8 +1328,12 @@ func findBlindedPaths(g Graph, target route.Vertex,
// conditions such as: The maxHops number being reached or reaching // conditions such as: The maxHops number being reached or reaching
// a node that doesn't have any other edges - in that final case, the // a node that doesn't have any other edges - in that final case, the
// whole path should be ignored. // whole path should be ignored.
//
// NOTE: any paths returned will end at the "nextTarget" node meaning
// that if we have a fixed list of incoming chained channels, then this
// fixed list must be appended to any of the returned paths.
paths, _, err := processNodeForBlindedPath( paths, _, err := processNodeForBlindedPath(
g, nextTarget, supportsRouteBlinding, visited, restrictions, g, nextTarget, nodeSupportsRouteBlinding, visited, restrictions,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -1319,8 +1343,7 @@ func findBlindedPaths(g Graph, target route.Vertex,
// When there is no path to add, but incomingChainedChannels can be // When there is no path to add, but incomingChainedChannels can be
// used. // used.
lenChainedChannels := int8(len(restrictions.incomingChainedChannels)) if len(paths) == 0 && haveIncomingPath {
if len(paths) == 0 && lenChainedChannels > 0 {
orderedPaths = [][]blindedHop{incomingPath} orderedPaths = [][]blindedHop{incomingPath}
} else { } else {
// Reverse each path so that the order is correct (from // Reverse each path so that the order is correct (from
@@ -1337,7 +1360,7 @@ func findBlindedPaths(g Graph, target route.Vertex,
// Handle the special case that allows a blinded path with the // Handle the special case that allows a blinded path with the
// introduction node as the destination node. // introduction node as the destination node.
if restrictions.minNumHops == 0 && lenChainedChannels == 0 { if restrictions.minNumHops == 0 && !haveIncomingPath {
singleHopPath := [][]blindedHop{{{vertex: target}}} singleHopPath := [][]blindedHop{{{vertex: target}}}
//nolint:makezero //nolint:makezero