Skip to content

Commit f464dac

Browse files
authored
Merge pull request #8752 from ellemouton/rb-receives-setup
[1/4] Route Blinding Receives: Groundwork
2 parents f2759dc + 85ddffb commit f464dac

27 files changed

+1267
-459
lines changed

cmd/lncli/cmd_payments.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,8 +1099,13 @@ var queryRoutesCommand = cli.Command{
10991099
},
11001100
cli.Int64Flag{
11011101
Name: "final_cltv_delta",
1102-
Usage: "(optional) number of blocks the last hop has to reveal " +
1103-
"the preimage",
1102+
Usage: "(optional) number of blocks the last hop has " +
1103+
"to reveal the preimage. Note that this " +
1104+
"should not be set in the case where the " +
1105+
"path includes a blinded path since in " +
1106+
"that case, the receiver will already have " +
1107+
"accounted for this value in the " +
1108+
"blinded_cltv value",
11041109
},
11051110
cli.BoolFlag{
11061111
Name: "use_mc",
@@ -1238,6 +1243,13 @@ func parseBlindedPaymentParameters(ctx *cli.Context) (
12381243
return nil, nil
12391244
}
12401245

1246+
// If a blinded path has been provided, then the final_cltv_delta flag
1247+
// should not be provided since this value will be ignored.
1248+
if ctx.IsSet("final_cltv_delta") {
1249+
return nil, fmt.Errorf("`final_cltv_delta` should not be " +
1250+
"provided if a blinded path is provided")
1251+
}
1252+
12411253
// If any one of our blinding related flags is set, we expect the
12421254
// full set to be set and we'll error out accordingly.
12431255
introNode, err := route.NewVertexFromStr(

docs/release-notes/release-notes-0.18.3.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@
8989
channel. We will still wait for the channel to have at least one confirmation
9090
and so the main change here is that we don't error out for such a case.
9191

92+
* [Groundwork](https://github.com/lightningnetwork/lnd/pull/8752) in preparation
93+
for implementing route blinding receives.
94+
9295
## Testing
9396
## Database
9497

htlcswitch/hop/iterator.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
360360
if err != nil {
361361
return nil, err
362362
}
363+
363364
// Validate the data in the blinded route against our incoming htlc's
364365
// information.
365366
if err := ValidateBlindedRouteData(
@@ -368,9 +369,31 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
368369
return nil, err
369370
}
370371

372+
// Exit early if this onion is for the exit hop of the route since
373+
// route blinding receives are not yet supported.
374+
if isFinalHop {
375+
return nil, fmt.Errorf("being the final hop in a blinded " +
376+
"path is not yet supported")
377+
}
378+
379+
// At this point, we know we are a forwarding node for this onion
380+
// and so we expect the relay info and next SCID fields to be set.
381+
relayInfo, err := routeData.RelayInfo.UnwrapOrErr(
382+
fmt.Errorf("relay info not set for non-final blinded hop"),
383+
)
384+
if err != nil {
385+
return nil, err
386+
}
387+
388+
nextSCID, err := routeData.ShortChannelID.UnwrapOrErr(
389+
fmt.Errorf("next SCID not set for non-final blinded hop"),
390+
)
391+
if err != nil {
392+
return nil, err
393+
}
394+
371395
fwdAmt, err := calculateForwardingAmount(
372-
b.IncomingAmount, routeData.RelayInfo.Val.BaseFee,
373-
routeData.RelayInfo.Val.FeeRate,
396+
b.IncomingAmount, relayInfo.Val.BaseFee, relayInfo.Val.FeeRate,
374397
)
375398
if err != nil {
376399
return nil, err
@@ -400,10 +423,10 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
400423
}
401424

402425
return &ForwardingInfo{
403-
NextHop: routeData.ShortChannelID.Val,
426+
NextHop: nextSCID.Val,
404427
AmountToForward: fwdAmt,
405428
OutgoingCTLV: b.IncomingCltv - uint32(
406-
routeData.RelayInfo.Val.CltvExpiryDelta,
429+
relayInfo.Val.CltvExpiryDelta,
407430
),
408431
// Remap from blinding override type to blinding point type.
409432
NextBlinding: tlv.SomeRecordT(

htlcswitch/hop/iterator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func TestDecryptAndValidateFwdInfo(t *testing.T) {
186186

187187
// Encode valid blinding data that we'll fake decrypting for our test.
188188
maxCltv := 1000
189-
blindedData := record.NewBlindedRouteData(
189+
blindedData := record.NewNonFinalBlindedRouteData(
190190
lnwire.NewShortChanIDFromInt(1500), nil,
191191
record.PaymentRelayInfo{
192192
CltvExpiryDelta: 10,

htlcswitch/hop/payload_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
646646
}{
647647
{
648648
name: "max cltv expired",
649-
data: record.NewBlindedRouteData(
649+
data: record.NewNonFinalBlindedRouteData(
650650
scid,
651651
nil,
652652
record.PaymentRelayInfo{},
@@ -663,7 +663,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
663663
},
664664
{
665665
name: "zero max cltv",
666-
data: record.NewBlindedRouteData(
666+
data: record.NewNonFinalBlindedRouteData(
667667
scid,
668668
nil,
669669
record.PaymentRelayInfo{},
@@ -682,7 +682,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
682682
},
683683
{
684684
name: "amount below minimum",
685-
data: record.NewBlindedRouteData(
685+
data: record.NewNonFinalBlindedRouteData(
686686
scid,
687687
nil,
688688
record.PaymentRelayInfo{},
@@ -699,7 +699,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
699699
},
700700
{
701701
name: "valid, no features",
702-
data: record.NewBlindedRouteData(
702+
data: record.NewNonFinalBlindedRouteData(
703703
scid,
704704
nil,
705705
record.PaymentRelayInfo{},
@@ -714,7 +714,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
714714
},
715715
{
716716
name: "unknown features",
717-
data: record.NewBlindedRouteData(
717+
data: record.NewNonFinalBlindedRouteData(
718718
scid,
719719
nil,
720720
record.PaymentRelayInfo{},
@@ -738,7 +738,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
738738
},
739739
{
740740
name: "valid data",
741-
data: record.NewBlindedRouteData(
741+
data: record.NewNonFinalBlindedRouteData(
742742
scid,
743743
nil,
744744
record.PaymentRelayInfo{

itest/lnd_route_blinding_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ func (b *blindedForwardTest) createBlindedRoute(hops []*forwardingEdge,
676676

677677
// Encode the route's blinded data and include it in the
678678
// blinded hop.
679-
payload := record.NewBlindedRouteData(
679+
payload := record.NewNonFinalBlindedRouteData(
680680
scid, nil, *relayInfo, constraints, nil,
681681
)
682682
payloadBytes, err := record.EncodeBlindedRouteData(payload)
@@ -739,7 +739,7 @@ func (b *blindedForwardTest) createBlindedRoute(hops []*forwardingEdge,
739739
// node ID here so that it _looks like_ a valid
740740
// forwarding hop (though in reality it's the last
741741
// hop).
742-
record.NewBlindedRouteData(
742+
record.NewNonFinalBlindedRouteData(
743743
lnwire.NewShortChanIDFromInt(100), nil,
744744
record.PaymentRelayInfo{}, nil, nil,
745745
),

lnrpc/invoicesrpc/utils.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,60 @@ func CreateRPCRouteHints(routeHints [][]zpay32.HopHint) []*lnrpc.RouteHint {
266266
return res
267267
}
268268

269+
// CreateRPCBlindedPayments takes a set of zpay32.BlindedPaymentPath and
270+
// converts them into a set of lnrpc.BlindedPaymentPaths.
271+
func CreateRPCBlindedPayments(blindedPaths []*zpay32.BlindedPaymentPath) (
272+
[]*lnrpc.BlindedPaymentPath, error) {
273+
274+
var res []*lnrpc.BlindedPaymentPath
275+
for _, path := range blindedPaths {
276+
features := path.Features.Features()
277+
var featuresSlice []lnrpc.FeatureBit
278+
for feature := range features {
279+
featuresSlice = append(
280+
featuresSlice, lnrpc.FeatureBit(feature),
281+
)
282+
}
283+
284+
if len(path.Hops) == 0 {
285+
return nil, fmt.Errorf("each blinded path must " +
286+
"contain at least one hop")
287+
}
288+
289+
var hops []*lnrpc.BlindedHop
290+
for _, hop := range path.Hops {
291+
blindedNodeID := hop.BlindedNodePub.
292+
SerializeCompressed()
293+
hops = append(hops, &lnrpc.BlindedHop{
294+
BlindedNode: blindedNodeID,
295+
EncryptedData: hop.CipherText,
296+
})
297+
}
298+
299+
introNode := path.Hops[0].BlindedNodePub
300+
firstBlindingPoint := path.FirstEphemeralBlindingPoint
301+
302+
blindedPath := &lnrpc.BlindedPath{
303+
IntroductionNode: introNode.SerializeCompressed(),
304+
BlindingPoint: firstBlindingPoint.
305+
SerializeCompressed(),
306+
BlindedHops: hops,
307+
}
308+
309+
res = append(res, &lnrpc.BlindedPaymentPath{
310+
BlindedPath: blindedPath,
311+
BaseFeeMsat: uint64(path.FeeBaseMsat),
312+
ProportionalFeeRate: path.FeeRate,
313+
TotalCltvDelta: uint32(path.CltvExpiryDelta),
314+
HtlcMinMsat: path.HTLCMinMsat,
315+
HtlcMaxMsat: path.HTLCMaxMsat,
316+
Features: featuresSlice,
317+
})
318+
}
319+
320+
return res, nil
321+
}
322+
269323
// CreateZpay32HopHints takes in the lnrpc form of route hints and converts them
270324
// into an invoice decoded form.
271325
func CreateZpay32HopHints(routeHints []*lnrpc.RouteHint) ([][]zpay32.HopHint, error) {

0 commit comments

Comments
 (0)