Skip to content

Commit

Permalink
Merge pull request #8752 from ellemouton/rb-receives-setup
Browse files Browse the repository at this point in the history
[1/4] Route Blinding Receives: Groundwork
  • Loading branch information
Roasbeef authored Jul 11, 2024
2 parents f2759dc + 85ddffb commit f464dac
Show file tree
Hide file tree
Showing 27 changed files with 1,267 additions and 459 deletions.
16 changes: 14 additions & 2 deletions cmd/lncli/cmd_payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -1099,8 +1099,13 @@ var queryRoutesCommand = cli.Command{
},
cli.Int64Flag{
Name: "final_cltv_delta",
Usage: "(optional) number of blocks the last hop has to reveal " +
"the preimage",
Usage: "(optional) number of blocks the last hop has " +
"to reveal the preimage. Note that this " +
"should not be set in the case where the " +
"path includes a blinded path since in " +
"that case, the receiver will already have " +
"accounted for this value in the " +
"blinded_cltv value",
},
cli.BoolFlag{
Name: "use_mc",
Expand Down Expand Up @@ -1238,6 +1243,13 @@ func parseBlindedPaymentParameters(ctx *cli.Context) (
return nil, nil
}

// If a blinded path has been provided, then the final_cltv_delta flag
// should not be provided since this value will be ignored.
if ctx.IsSet("final_cltv_delta") {
return nil, fmt.Errorf("`final_cltv_delta` should not be " +
"provided if a blinded path is provided")
}

// If any one of our blinding related flags is set, we expect the
// full set to be set and we'll error out accordingly.
introNode, err := route.NewVertexFromStr(
Expand Down
3 changes: 3 additions & 0 deletions docs/release-notes/release-notes-0.18.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
channel. We will still wait for the channel to have at least one confirmation
and so the main change here is that we don't error out for such a case.

* [Groundwork](https://github.com/lightningnetwork/lnd/pull/8752) in preparation
for implementing route blinding receives.

## Testing
## Database

Expand Down
31 changes: 27 additions & 4 deletions htlcswitch/hop/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
if err != nil {
return nil, err
}

// Validate the data in the blinded route against our incoming htlc's
// information.
if err := ValidateBlindedRouteData(
Expand All @@ -368,9 +369,31 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
return nil, err
}

// Exit early if this onion is for the exit hop of the route since
// route blinding receives are not yet supported.
if isFinalHop {
return nil, fmt.Errorf("being the final hop in a blinded " +
"path is not yet supported")
}

// At this point, we know we are a forwarding node for this onion
// and so we expect the relay info and next SCID fields to be set.
relayInfo, err := routeData.RelayInfo.UnwrapOrErr(
fmt.Errorf("relay info not set for non-final blinded hop"),
)
if err != nil {
return nil, err
}

nextSCID, err := routeData.ShortChannelID.UnwrapOrErr(
fmt.Errorf("next SCID not set for non-final blinded hop"),
)
if err != nil {
return nil, err
}

fwdAmt, err := calculateForwardingAmount(
b.IncomingAmount, routeData.RelayInfo.Val.BaseFee,
routeData.RelayInfo.Val.FeeRate,
b.IncomingAmount, relayInfo.Val.BaseFee, relayInfo.Val.FeeRate,
)
if err != nil {
return nil, err
Expand Down Expand Up @@ -400,10 +423,10 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
}

return &ForwardingInfo{
NextHop: routeData.ShortChannelID.Val,
NextHop: nextSCID.Val,
AmountToForward: fwdAmt,
OutgoingCTLV: b.IncomingCltv - uint32(
routeData.RelayInfo.Val.CltvExpiryDelta,
relayInfo.Val.CltvExpiryDelta,
),
// Remap from blinding override type to blinding point type.
NextBlinding: tlv.SomeRecordT(
Expand Down
2 changes: 1 addition & 1 deletion htlcswitch/hop/iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func TestDecryptAndValidateFwdInfo(t *testing.T) {

// Encode valid blinding data that we'll fake decrypting for our test.
maxCltv := 1000
blindedData := record.NewBlindedRouteData(
blindedData := record.NewNonFinalBlindedRouteData(
lnwire.NewShortChanIDFromInt(1500), nil,
record.PaymentRelayInfo{
CltvExpiryDelta: 10,
Expand Down
12 changes: 6 additions & 6 deletions htlcswitch/hop/payload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
}{
{
name: "max cltv expired",
data: record.NewBlindedRouteData(
data: record.NewNonFinalBlindedRouteData(
scid,
nil,
record.PaymentRelayInfo{},
Expand All @@ -663,7 +663,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
},
{
name: "zero max cltv",
data: record.NewBlindedRouteData(
data: record.NewNonFinalBlindedRouteData(
scid,
nil,
record.PaymentRelayInfo{},
Expand All @@ -682,7 +682,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
},
{
name: "amount below minimum",
data: record.NewBlindedRouteData(
data: record.NewNonFinalBlindedRouteData(
scid,
nil,
record.PaymentRelayInfo{},
Expand All @@ -699,7 +699,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
},
{
name: "valid, no features",
data: record.NewBlindedRouteData(
data: record.NewNonFinalBlindedRouteData(
scid,
nil,
record.PaymentRelayInfo{},
Expand All @@ -714,7 +714,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
},
{
name: "unknown features",
data: record.NewBlindedRouteData(
data: record.NewNonFinalBlindedRouteData(
scid,
nil,
record.PaymentRelayInfo{},
Expand All @@ -738,7 +738,7 @@ func TestValidateBlindedRouteData(t *testing.T) {
},
{
name: "valid data",
data: record.NewBlindedRouteData(
data: record.NewNonFinalBlindedRouteData(
scid,
nil,
record.PaymentRelayInfo{
Expand Down
4 changes: 2 additions & 2 deletions itest/lnd_route_blinding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ func (b *blindedForwardTest) createBlindedRoute(hops []*forwardingEdge,

// Encode the route's blinded data and include it in the
// blinded hop.
payload := record.NewBlindedRouteData(
payload := record.NewNonFinalBlindedRouteData(
scid, nil, *relayInfo, constraints, nil,
)
payloadBytes, err := record.EncodeBlindedRouteData(payload)
Expand Down Expand Up @@ -739,7 +739,7 @@ func (b *blindedForwardTest) createBlindedRoute(hops []*forwardingEdge,
// node ID here so that it _looks like_ a valid
// forwarding hop (though in reality it's the last
// hop).
record.NewBlindedRouteData(
record.NewNonFinalBlindedRouteData(
lnwire.NewShortChanIDFromInt(100), nil,
record.PaymentRelayInfo{}, nil, nil,
),
Expand Down
54 changes: 54 additions & 0 deletions lnrpc/invoicesrpc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,60 @@ func CreateRPCRouteHints(routeHints [][]zpay32.HopHint) []*lnrpc.RouteHint {
return res
}

// CreateRPCBlindedPayments takes a set of zpay32.BlindedPaymentPath and
// converts them into a set of lnrpc.BlindedPaymentPaths.
func CreateRPCBlindedPayments(blindedPaths []*zpay32.BlindedPaymentPath) (
[]*lnrpc.BlindedPaymentPath, error) {

var res []*lnrpc.BlindedPaymentPath
for _, path := range blindedPaths {
features := path.Features.Features()
var featuresSlice []lnrpc.FeatureBit
for feature := range features {
featuresSlice = append(
featuresSlice, lnrpc.FeatureBit(feature),
)
}

if len(path.Hops) == 0 {
return nil, fmt.Errorf("each blinded path must " +
"contain at least one hop")
}

var hops []*lnrpc.BlindedHop
for _, hop := range path.Hops {
blindedNodeID := hop.BlindedNodePub.
SerializeCompressed()
hops = append(hops, &lnrpc.BlindedHop{
BlindedNode: blindedNodeID,
EncryptedData: hop.CipherText,
})
}

introNode := path.Hops[0].BlindedNodePub
firstBlindingPoint := path.FirstEphemeralBlindingPoint

blindedPath := &lnrpc.BlindedPath{
IntroductionNode: introNode.SerializeCompressed(),
BlindingPoint: firstBlindingPoint.
SerializeCompressed(),
BlindedHops: hops,
}

res = append(res, &lnrpc.BlindedPaymentPath{
BlindedPath: blindedPath,
BaseFeeMsat: uint64(path.FeeBaseMsat),
ProportionalFeeRate: path.FeeRate,
TotalCltvDelta: uint32(path.CltvExpiryDelta),
HtlcMinMsat: path.HTLCMinMsat,
HtlcMaxMsat: path.HTLCMaxMsat,
Features: featuresSlice,
})
}

return res, nil
}

// CreateZpay32HopHints takes in the lnrpc form of route hints and converts them
// into an invoice decoded form.
func CreateZpay32HopHints(routeHints []*lnrpc.RouteHint) ([][]zpay32.HopHint, error) {
Expand Down
Loading

0 comments on commit f464dac

Please sign in to comment.