Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[abandoned]route: Add onion blob to sendtoroute #6750

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions cmd/lncli/cmd_payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -975,10 +975,21 @@ func sendToRoute(ctx *cli.Context) error {
route = routes.Route
}

var onionBlob []byte

if ctx.IsSet("onion_blob") {
onionBlob, err = hex.DecodeString(ctx.String("onion_blob"))

if err != nil {
return err
}
}

req := &routerrpc.SendToRouteRequest{
PaymentHash: rHash,
Route: route,
SkipTempErr: ctx.Bool("skip_temp_err"),
OnionBlob: onionBlob,
}

return sendToRouteRequest(ctx, req)
Expand Down
3 changes: 3 additions & 0 deletions docs/release-notes/release-notes-0.16.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
that were signed by our wallet. Prior to this change `SignPsbt` didn't
indicate whether the Psbt held any inputs for our wallet to sign.

* Allowing users to parse a [custom onion blob though the
sendtoroute interface](https://github.com/lightningnetwork/lnd/pull/6750).

* [Add list addresses RPC](https://github.com/lightningnetwork/lnd/pull/6596).

* Add [TrackPayments](https://github.com/lightningnetwork/lnd/pull/6335)
Expand Down
30 changes: 21 additions & 9 deletions lnrpc/routerrpc/router.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions lnrpc/routerrpc/router.proto
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,12 @@ message SendToRouteRequest {
routes, incorrect payment details, or insufficient funds.
*/
bool skip_temp_err = 3;

/*
Custom onion blob. Limited to 1366 bytes. This will be used instead of the
standard generated sphinx package.
*/
bytes onion_blob = 4;
}

message SendToRouteResponse {
Expand Down
5 changes: 5 additions & 0 deletions lnrpc/routerrpc/router.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,11 @@
"skip_temp_err": {
"type": "boolean",
"description": "Whether the payment should be marked as failed when a temporary error is\nreturned from the given route. Set it to true so the payment won't be\nfailed unless a terminal error is occurred, such as payment timeout, no\nroutes, incorrect payment details, or insufficient funds."
},
"onion_blob": {
"type": "string",
"format": "byte",
"description": "Custom onion blob. Limited to 1366 bytes. This will be used instead of the\nstandard generated sphinx package."
}
}
},
Expand Down
12 changes: 10 additions & 2 deletions lnrpc/routerrpc/router_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,10 @@ func (s *Server) SendToRouteV2(ctx context.Context,
if req.Route == nil {
return nil, fmt.Errorf("unable to send, no routes provided")
}
if len(req.OnionBlob) > lnwire.OnionPacketSize {
return nil, fmt.Errorf("the provided onion blob is to large, "+
"size is limited to %d bytes", lnwire.OnionPacketSize)
}

route, err := s.cfg.RouterBackend.UnmarshallRoute(req.Route)
if err != nil {
Expand All @@ -412,9 +416,13 @@ func (s *Server) SendToRouteV2(ctx context.Context,
// case, we give precedence to the attempt information as stored in the
// db.
if req.SkipTempErr {
attempt, err = s.cfg.Router.SendToRouteSkipTempErr(hash, route)
attempt, err = s.cfg.Router.SendToRouteSkipTempErr(
hash, route, req.OnionBlob,
)
} else {
attempt, err = s.cfg.Router.SendToRoute(hash, route)
attempt, err = s.cfg.Router.SendToRoute(
hash, route, req.OnionBlob,
)
}
if attempt != nil {
rpcAttempt, err := s.cfg.RouterBackend.MarshalHTLCAttempt(
Expand Down
35 changes: 23 additions & 12 deletions routing/payment_lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,9 @@ lifecycle:
lastShard := rt.ReceiverAmt() == currentState.remainingAmt

// We found a route to try, launch a new shard.
attempt, outcome, err := shardHandler.launchShard(rt, lastShard)
attempt, outcome, err := shardHandler.launchShard(
rt, lastShard, nil,
)
switch {
// We may get a terminal error if we've processed a shard with
// a terminal state (settled or permanent failure), while we
Expand Down Expand Up @@ -426,12 +428,13 @@ type launchOutcome struct {
// non-nil error, it means that the attempt was not sent onto the network, so
// no result will be available in the future for it.
func (p *shardHandler) launchShard(rt *route.Route,
lastShard bool) (*channeldb.HTLCAttemptInfo, *launchOutcome, error) {
lastShard bool, customOnionBlob []byte) (*channeldb.HTLCAttemptInfo,
*launchOutcome, error) {

// Using the route received from the payment session, create a new
// shard to send.
firstHop, htlcAdd, attempt, err := p.createNewPaymentAttempt(
rt, lastShard,
rt, lastShard, customOnionBlob,
)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -658,7 +661,8 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
}

// createNewPaymentAttempt creates a new payment attempt from the given route.
func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool) (
func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool,
customOninonBlob []byte) (
lnwire.ShortChannelID, *lnwire.UpdateAddHTLC,
*channeldb.HTLCAttemptInfo, error) {

Expand Down Expand Up @@ -696,14 +700,7 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool)
hop.AMP = shard.AMP()
}

// Generate the raw encoded sphinx packet to be included along
// with the htlcAdd message that we send directly to the
// switch.
hash := shard.Hash()
onionBlob, _, err := generateSphinxPacket(rt, hash[:], sessionKey)
if err != nil {
return lnwire.ShortChannelID{}, nil, nil, err
}

// Craft an HTLC packet to send to the layer 2 switch. The
// metadata within this packet will be used to route the
Expand All @@ -713,7 +710,21 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool)
Expiry: rt.TotalTimeLock,
PaymentHash: hash,
}
copy(htlcAdd.OnionBlob[:], onionBlob)

// Use the custom onion blob if it is provided. Otherwise, we will
// generate the raw encoded sphinx packet to be included along
// with the htlcAdd message that we send directly to the
// switch.
if customOninonBlob != nil {
copy(htlcAdd.OnionBlob[:], customOninonBlob)
} else {
onionBlob, _, err := generateSphinxPacket(rt, hash[:],
sessionKey)
if err != nil {
return lnwire.ShortChannelID{}, nil, nil, err
}
copy(htlcAdd.OnionBlob[:], onionBlob)
}

// Attempt to send this payment through the network to complete
// the payment. If this attempt fails, then we'll continue on
Expand Down
16 changes: 9 additions & 7 deletions routing/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -2157,18 +2157,19 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) (

// SendToRoute sends a payment using the provided route and fails the payment
// when an error is returned from the attempt.
func (r *ChannelRouter) SendToRoute(htlcHash lntypes.Hash,
rt *route.Route) (*channeldb.HTLCAttempt, error) {
func (r *ChannelRouter) SendToRoute(htlcHash lntypes.Hash, rt *route.Route,
customOnionBlob []byte) (*channeldb.HTLCAttempt, error) {

return r.sendToRoute(htlcHash, rt, false)
return r.sendToRoute(htlcHash, rt, false, customOnionBlob)
}

// SendToRouteSkipTempErr sends a payment using the provided route and fails
// the payment ONLY when a terminal error is returned from the attempt.
func (r *ChannelRouter) SendToRouteSkipTempErr(htlcHash lntypes.Hash,
rt *route.Route) (*channeldb.HTLCAttempt, error) {
rt *route.Route, customOnionBlob []byte) (*channeldb.HTLCAttempt,
error) {

return r.sendToRoute(htlcHash, rt, true)
return r.sendToRoute(htlcHash, rt, true, customOnionBlob)
}

// sendToRoute attempts to send a payment with the given hash through the
Expand All @@ -2178,7 +2179,8 @@ func (r *ChannelRouter) SendToRouteSkipTempErr(htlcHash lntypes.Hash,
// was initiated, both return values will be non-nil. If skipTempErr is true,
// the payment won't be failed unless a terminal error has occurred.
func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
skipTempErr bool) (*channeldb.HTLCAttempt, error) {
skipTempErr bool, customOnionBlob []byte) (*channeldb.HTLCAttempt,
error) {

// Calculate amount paid to receiver.
amt := rt.ReceiverAmt()
Expand Down Expand Up @@ -2243,7 +2245,7 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
}

var shardError error
attempt, outcome, err := sh.launchShard(rt, false)
attempt, outcome, err := sh.launchShard(rt, false, customOnionBlob)

// With SendToRoute, it can happen that the route exceeds protocol
// constraints. Mark the payment as failed with an internal error.
Expand Down
16 changes: 8 additions & 8 deletions routing/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ func TestChannelUpdateValidation(t *testing.T) {
// Send off the payment request to the router. The specified route
// should be attempted and the channel update should be received by
// router and ignored because it is missing a valid signature.
_, err = ctx.router.SendToRoute(payment, rt)
_, err = ctx.router.SendToRoute(payment, rt, nil)
require.Error(t, err, "expected route to fail with channel update")

_, e1, e2, err = ctx.router.GetChannelByID(
Expand All @@ -478,7 +478,7 @@ func TestChannelUpdateValidation(t *testing.T) {
signErrChanUpdate(t, testGraph.privKeyMap["b"], &errChanUpdate)

// Retry the payment using the same route as before.
_, err = ctx.router.SendToRoute(payment, rt)
_, err = ctx.router.SendToRoute(payment, rt, nil)
require.Error(t, err, "expected route to fail with channel update")

// This time a valid signature was supplied and the policy change should
Expand Down Expand Up @@ -2870,7 +2870,7 @@ func TestSendToRouteStructuredError(t *testing.T) {
// update should be received by router and ignored
// because it is missing a valid
// signature.
_, err = ctx.router.SendToRoute(payment, rt)
_, err = ctx.router.SendToRoute(payment, rt, nil)

fErr, ok := err.(*htlcswitch.ForwardingError)
require.True(
Expand Down Expand Up @@ -2951,7 +2951,7 @@ func TestSendToRouteMaxHops(t *testing.T) {
// Send off the payment request to the router. We expect an error back
// indicating that the route is too long.
var payment lntypes.Hash
_, err = ctx.router.SendToRoute(payment, rt)
_, err = ctx.router.SendToRoute(payment, rt, nil)
if err != route.ErrMaxRouteHopsExceeded {
t.Fatalf("expected ErrMaxRouteHopsExceeded, but got %v", err)
}
Expand Down Expand Up @@ -4197,7 +4197,7 @@ func TestSendToRouteSkipTempErrSuccess(t *testing.T) {
).Return(nil)

// Expect a successful send to route.
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
attempt, err := router.SendToRouteSkipTempErr(payHash, rt, nil)
require.NoError(t, err)
require.Equal(t, testAttempt, attempt)

Expand Down Expand Up @@ -4283,7 +4283,7 @@ func TestSendToRouteSkipTempErrTempFailure(t *testing.T) {
).Return(nil, nil)

// Expect a failed send to route.
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
attempt, err := router.SendToRouteSkipTempErr(payHash, rt, nil)
require.Equal(t, tempErr, err)
require.Equal(t, testAttempt, attempt)

Expand Down Expand Up @@ -4372,7 +4372,7 @@ func TestSendToRouteSkipTempErrPermanentFailure(t *testing.T) {
).Return(&failureReason, nil)

// Expect a failed send to route.
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
attempt, err := router.SendToRouteSkipTempErr(payHash, rt, nil)
require.Equal(t, permErr, err)
require.Equal(t, testAttempt, attempt)

Expand Down Expand Up @@ -4461,7 +4461,7 @@ func TestSendToRouteTempFailure(t *testing.T) {
).Return(nil, nil)

// Expect a failed send to route.
attempt, err := router.SendToRoute(payHash, rt)
attempt, err := router.SendToRoute(payHash, rt, nil)
require.Equal(t, tempErr, err)
require.Equal(t, testAttempt, attempt)

Expand Down
2 changes: 1 addition & 1 deletion rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5057,7 +5057,7 @@ func (r *rpcServer) dispatchPaymentIntent(
} else {
var attempt *channeldb.HTLCAttempt
attempt, routerErr = r.server.chanRouter.SendToRoute(
payIntent.rHash, payIntent.route,
payIntent.rHash, payIntent.route, nil,
)

if routerErr == nil {
Expand Down