Skip to content

Commit e4619af

Browse files
committed
multi: add node omission list for blinded paths
1 parent b490dee commit e4619af

File tree

10 files changed

+1254
-1142
lines changed

10 files changed

+1254
-1142
lines changed

cmd/lncli/cmd_invoice.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ var addInvoiceCommand = cli.Command{
110110
"to an invoice. This option will only be " +
111111
"used if `--blind` has also been set.",
112112
},
113+
cli.StringSliceFlag{
114+
Name: "blinded_path_omit_node",
115+
Usage: "The pub key (in hex) of a node not to " +
116+
"use on a blinded path. The flag may be " +
117+
"specified multiple times.",
118+
},
113119
},
114120
Action: actionDecorator(addInvoice),
115121
}
@@ -221,6 +227,17 @@ func parseBlindedPathCfg(ctx *cli.Context) (*lnrpc.BlindedPathConfig, error) {
221227
blindCfg.MaxNumPaths = &maxPaths
222228
}
223229

230+
for _, pubKey := range ctx.StringSlice("blinded_path_omit_node") {
231+
pubKeyBytes, err := hex.DecodeString(pubKey)
232+
if err != nil {
233+
return nil, err
234+
}
235+
236+
blindCfg.NodeOmissionList = append(
237+
blindCfg.NodeOmissionList, pubKeyBytes,
238+
)
239+
}
240+
224241
return &blindCfg, nil
225242
}
226243

lnrpc/invoicesrpc/invoices.swagger.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,14 @@
412412
"type": "integer",
413413
"format": "int64",
414414
"description": "The maximum number of blinded paths to select and add to an invoice."
415+
},
416+
"node_omission_list": {
417+
"type": "array",
418+
"items": {
419+
"type": "string",
420+
"format": "byte"
421+
},
422+
"description": "A list of node IDs of nodes that should not be used in any of our generated\nblinded paths."
415423
}
416424
}
417425
},

lnrpc/lightning.pb.go

Lines changed: 1152 additions & 1139 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lnrpc/lightning.proto

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3867,6 +3867,12 @@ message BlindedPathConfig {
38673867
The maximum number of blinded paths to select and add to an invoice.
38683868
*/
38693869
optional uint32 max_num_paths = 3;
3870+
3871+
/*
3872+
A list of node IDs of nodes that should not be used in any of our generated
3873+
blinded paths.
3874+
*/
3875+
repeated bytes node_omission_list = 4;
38703876
}
38713877

38723878
enum InvoiceHTLCState {

lnrpc/lightning.swagger.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3561,6 +3561,14 @@
35613561
"type": "integer",
35623562
"format": "int64",
35633563
"description": "The maximum number of blinded paths to select and add to an invoice."
3564+
},
3565+
"node_omission_list": {
3566+
"type": "array",
3567+
"items": {
3568+
"type": "string",
3569+
"format": "byte"
3570+
},
3571+
"description": "A list of node IDs of nodes that should not be used in any of our generated\nblinded paths."
35643572
}
35653573
}
35663574
},

routing/pathfind.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/lightningnetwork/lnd/channeldb"
1515
"github.com/lightningnetwork/lnd/channeldb/models"
1616
"github.com/lightningnetwork/lnd/feature"
17+
"github.com/lightningnetwork/lnd/fn"
1718
"github.com/lightningnetwork/lnd/lnutils"
1819
"github.com/lightningnetwork/lnd/lnwire"
1920
"github.com/lightningnetwork/lnd/record"
@@ -1150,6 +1151,10 @@ type blindedPathRestrictions struct {
11501151
// path. This doesn't include our node, so if the maximum is 1, then
11511152
// the path will contain our node along with an introduction node hop.
11521153
maxNumHops uint8
1154+
1155+
// nodeOmissionSet holds a set of node IDs of nodes that we should
1156+
// ignore during blinded path selection.
1157+
nodeOmissionSet fn.Set[route.Vertex]
11531158
}
11541159

11551160
// blindedHop holds the information about a hop we have selected for a blinded
@@ -1253,6 +1258,12 @@ func processNodeForBlindedPath(g Graph, node route.Vertex,
12531258
return nil, false, nil
12541259
}
12551260

1261+
// If we have explicitly been told to ignore this node for blinded paths
1262+
// then we skip it too.
1263+
if restrictions.nodeOmissionSet.Contains(node) {
1264+
return nil, false, nil
1265+
}
1266+
12561267
supports, err := supportsRouteBlinding(node)
12571268
if err != nil {
12581269
return nil, false, err

routing/pathfind_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3705,7 +3705,26 @@ func TestFindBlindedPaths(t *testing.T) {
37053705
"charlie,eve,bob,dave",
37063706
})
37073707

3708-
// 4) Finally, we will test the special case where the destination node
3708+
// 4) Repeat the above test but instruct the function to never use
3709+
// charlie.
3710+
paths, err = ctx.findBlindedPaths(&blindedPathRestrictions{
3711+
minNumHops: 2,
3712+
maxNumHops: 3,
3713+
nodeOmissionSet: fn.NewSet[route.Vertex](
3714+
ctx.keyFromAlias("charlie"),
3715+
),
3716+
})
3717+
require.NoError(t, err)
3718+
3719+
// We expect the following paths:
3720+
// - F, B, D
3721+
// - E, B, D
3722+
assertPaths(paths, []string{
3723+
"frank,bob,dave",
3724+
"eve,bob,dave",
3725+
})
3726+
3727+
// 5) Finally, we will test the special case where the destination node
37093728
// is also the recipient.
37103729
paths, err = ctx.findBlindedPaths(&blindedPathRestrictions{
37113730
minNumHops: 0,

routing/router.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,10 @@ type BlindedPathRestrictions struct {
664664

665665
// MaxNumPaths is the maximum number of blinded paths to select.
666666
MaxNumPaths uint8
667+
668+
// NodeOmissionSet is a set of nodes that should not be used within any
669+
// of the blinded paths that we generate.
670+
NodeOmissionSet fn.Set[route.Vertex]
667671
}
668672

669673
// FindBlindedPaths finds a selection of paths to the destination node that can
@@ -676,8 +680,9 @@ func (r *ChannelRouter) FindBlindedPaths(destination route.Vertex,
676680
// path length restrictions.
677681
paths, err := findBlindedPaths(
678682
r.cfg.RoutingGraph, destination, &blindedPathRestrictions{
679-
minNumHops: restrictions.MinDistanceFromIntroNode,
680-
maxNumHops: restrictions.NumHops,
683+
minNumHops: restrictions.MinDistanceFromIntroNode,
684+
maxNumHops: restrictions.NumHops,
685+
nodeOmissionSet: restrictions.NodeOmissionSet,
681686
},
682687
)
683688
if err != nil {

routing/router_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,4 +3236,19 @@ func TestFindBlindedPathsWithMC(t *testing.T) {
32363236
"alice,bob,dave",
32373237
"alice,frank,dave",
32383238
})
3239+
3240+
// Test that if the user explicitly indicates that we should ignore
3241+
// the Frank node during path selection, then this is done.
3242+
routes, err = ctx.router.FindBlindedPaths(
3243+
dave, 1000, probabilitySrc, &BlindedPathRestrictions{
3244+
MinDistanceFromIntroNode: 2,
3245+
NumHops: 2,
3246+
MaxNumPaths: 3,
3247+
NodeOmissionSet: fn.NewSet(frank),
3248+
},
3249+
)
3250+
require.NoError(t, err)
3251+
assertPaths(routes, []string{
3252+
"alice,bob,dave",
3253+
})
32393254
}

rpcserver.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5788,6 +5788,7 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
57885788
MinDistanceFromIntroNode: globalBlindCfg.MinNumRealHops,
57895789
NumHops: globalBlindCfg.NumHops,
57905790
MaxNumPaths: globalBlindCfg.MaxNumPaths,
5791+
NodeOmissionSet: fn.NewSet[route.Vertex](),
57915792
}
57925793

57935794
if blind {
@@ -5802,6 +5803,15 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
58025803
blindingRestrictions.MaxNumPaths =
58035804
uint8(*blindCfg.MaxNumPaths)
58045805
}
5806+
5807+
for _, nodeIDBytes := range blindCfg.NodeOmissionList {
5808+
vertex, err := route.NewVertexFromBytes(nodeIDBytes)
5809+
if err != nil {
5810+
return nil, err
5811+
}
5812+
5813+
blindingRestrictions.NodeOmissionSet.Add(vertex)
5814+
}
58055815
}
58065816

58075817
if blindingRestrictions.MinDistanceFromIntroNode >

0 commit comments

Comments
 (0)