From 34154802f3d1b590f1af92ca5db8d0a4f60902e3 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Tue, 10 Jun 2025 13:20:00 +0200 Subject: [PATCH] routing+itest: fix route blinding path selection bug Here we fix a bug which would not include the selected incoming blinded path chain from being included in the selected path set if it meets the minimum length requirement. The appropriate unit test and itest is updated to demonstrate the fix. --- itest/lnd_route_blinding_test.go | 7 +++--- routing/pathfind.go | 38 ++++++++++++++++++-------------- routing/pathfind_test.go | 2 ++ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 5e043f8a1..0e3c61f61 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -1589,9 +1589,10 @@ func testPartiallySpecifiedBlindedPath(ht *lntest.HarnessTest) { }, }) - // Assert that it contains one path with 3 hops, with eve as the - // introduction node. - assertPathDetails(invoice, 3, eve.PubKey[:]) + // Assert that it contains two paths: one 3 hop one starting at Eve and + // a 3 hop one starting at Dave (this one will be padded with a dummy + // hop) in order to keep all the paths equidistant. + assertPathDetails(invoice, 3, eve.PubKey[:], dave.PubKey[:]) // Check that Frank can pay the invoice. ht.CompletePaymentRequests(frank, []string{invoice.PaymentRequest}) diff --git a/routing/pathfind.go b/routing/pathfind.go index d2082f4e5..f489173f9 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -1339,31 +1339,35 @@ func findBlindedPaths(g Graph, target route.Vertex, return nil, err } - orderedPaths := make([][]blindedHop, len(paths)) + // Reverse each path so that the order is correct (from introduction + // node to last hop node) and then append the incoming path (if any was + // specified) to the end of the path. + orderedPaths := make([][]blindedHop, 0, len(paths)) + for _, path := range paths { + sort.Slice(path, func(i, j int) bool { + return j < i + }) - // When there is no path to add, but incomingChainedChannels can be - // used. - if len(paths) == 0 && haveIncomingPath { - orderedPaths = [][]blindedHop{incomingPath} - } else { - // Reverse each path so that the order is correct (from - // introduction node to last hop node) and then append this node - // on as the destination of each path. - for i, path := range paths { - sort.Slice(path, func(i, j int) bool { - return j < i - }) + orderedPaths = append( + orderedPaths, append(path, incomingPath...), + ) + } - orderedPaths[i] = append(path, incomingPath...) - } + // There is a chance we have an incoming path that by itself satisfies + // the minimum hop restriction. In that case, we add it as its own path. + if haveIncomingPath && + len(incomingPath) > int(restrictions.minNumHops) { + + orderedPaths = append(orderedPaths, incomingPath) } // Handle the special case that allows a blinded path with the - // introduction node as the destination node. + // introduction node as the destination node. This only applies if no + // incoming path was specified since in that case, by definition, the + // caller wants a non-zero length blinded path. if restrictions.minNumHops == 0 && !haveIncomingPath { singleHopPath := [][]blindedHop{{{vertex: target}}} - //nolint:makezero orderedPaths = append( orderedPaths, singleHopPath..., ) diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 5afb7bd14..36511f218 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -3941,9 +3941,11 @@ func TestFindBlindedPaths(t *testing.T) { require.NoError(t, err) // We expect the following paths: + // - B, D // - F, B, D // - E, B, D assertPaths(paths, []string{ + "bob,dave", "frank,bob,dave", "eve,bob,dave", })