From 4640507c5fee41398573a676d64d8ea750291f55 Mon Sep 17 00:00:00 2001 From: Jesse de Wit Date: Tue, 17 Oct 2023 16:55:55 +0200 Subject: [PATCH] add option for new onion format for lnd lsp --- config/config.go | 5 +++++ interceptor/intercept.go | 34 ++++++++++++++++++-------------- lnd/interceptor.go | 42 ++++++++++++++++++++++++---------------- 3 files changed, 49 insertions(+), 32 deletions(-) diff --git a/config/config.go b/config/config.go index dd287e5..12c773a 100644 --- a/config/config.go +++ b/config/config.go @@ -15,6 +15,11 @@ type NodeConfig struct { // configured node, so it's obvious which node an rpc call is meant for. Tokens []string `json:"tokens"` + // If the used token is in the LegacyOnionTokens array, the forwarded htlc + // will have the legacy onion format. As per the time of writing breezmobile + // requires the legacy onion format. + LegacyOnionTokens []string `json:"legacyOnionTokens"` + // The network location of the lightning node, e.g. `12.34.56.78:9012` or // `localhost:10011` Host string `json:"host"` diff --git a/interceptor/intercept.go b/interceptor/intercept.go index 9bbb0cd..af3b7da 100644 --- a/interceptor/intercept.go +++ b/interceptor/intercept.go @@ -15,6 +15,7 @@ import ( "github.com/breez/lspd/lightning" "github.com/breez/lspd/notifications" "github.com/btcsuite/btcd/wire" + "golang.org/x/exp/slices" "golang.org/x/sync/singleflight" ) @@ -35,14 +36,15 @@ var ( ) type InterceptResult struct { - Action InterceptAction - FailureCode InterceptFailureCode - Destination []byte - AmountMsat uint64 - TotalAmountMsat uint64 - ChannelPoint *wire.OutPoint - ChannelId uint64 - PaymentSecret []byte + Action InterceptAction + FailureCode InterceptFailureCode + Destination []byte + AmountMsat uint64 + TotalAmountMsat uint64 + ChannelPoint *wire.OutPoint + ChannelId uint64 + PaymentSecret []byte + UseLegacyOnionBlob bool } type Interceptor struct { @@ -257,14 +259,16 @@ func (i *Interceptor) Intercept(scid *basetypes.ShortChannelID, reqPaymentHash [ channelID = uint64(chanResult.InitialChannelID) } + useLegacyOnionBlob := slices.Contains(i.config.LegacyOnionTokens, token) return InterceptResult{ - Action: INTERCEPT_RESUME_WITH_ONION, - Destination: destination, - ChannelPoint: channelPoint, - ChannelId: channelID, - PaymentSecret: paymentSecret, - AmountMsat: uint64(amt), - TotalAmountMsat: uint64(outgoingAmountMsat), + Action: INTERCEPT_RESUME_WITH_ONION, + Destination: destination, + ChannelPoint: channelPoint, + ChannelId: channelID, + PaymentSecret: paymentSecret, + AmountMsat: uint64(amt), + TotalAmountMsat: uint64(outgoingAmountMsat), + UseLegacyOnionBlob: useLegacyOnionBlob, }, nil } diff --git a/lnd/interceptor.go b/lnd/interceptor.go index 8d1574f..2d4ecb1 100644 --- a/lnd/interceptor.go +++ b/lnd/interceptor.go @@ -139,23 +139,7 @@ func (i *LndHtlcInterceptor) intercept() error { interceptResult := i.interceptor.Intercept(&scid, request.PaymentHash, request.OutgoingAmountMsat, request.OutgoingExpiry, request.IncomingExpiry) switch interceptResult.Action { case interceptor.INTERCEPT_RESUME_WITH_ONION: - onion, err := i.constructOnion(interceptResult, request.OutgoingExpiry, request.PaymentHash) - if err == nil { - interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{ - IncomingCircuitKey: request.IncomingCircuitKey, - Action: routerrpc.ResolveHoldForwardAction_RESUME, - OutgoingAmountMsat: interceptResult.AmountMsat, - OutgoingRequestedChanId: uint64(interceptResult.ChannelId), - OnionBlob: onion, - }) - } else { - interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{ - IncomingCircuitKey: request.IncomingCircuitKey, - Action: routerrpc.ResolveHoldForwardAction_FAIL, - FailureCode: lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, - }) - } - + interceptorClient.Send(i.createOnionResponse(interceptResult, request)) case interceptor.INTERCEPT_FAIL_HTLC_WITH_CODE: interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{ IncomingCircuitKey: request.IncomingCircuitKey, @@ -257,3 +241,27 @@ func (i *LndHtlcInterceptor) constructOnion( return onionBlob.Bytes(), nil } + +func (i *LndHtlcInterceptor) createOnionResponse(interceptResult interceptor.InterceptResult, request *routerrpc.ForwardHtlcInterceptRequest) *routerrpc.ForwardHtlcInterceptResponse { + onionBlob := request.OnionBlob + + if interceptResult.UseLegacyOnionBlob { + var err error + onionBlob, err = i.constructOnion(interceptResult, request.OutgoingExpiry, request.PaymentHash) + if err != nil { + return &routerrpc.ForwardHtlcInterceptResponse{ + IncomingCircuitKey: request.IncomingCircuitKey, + Action: routerrpc.ResolveHoldForwardAction_FAIL, + FailureCode: lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, + } + } + } + + return &routerrpc.ForwardHtlcInterceptResponse{ + IncomingCircuitKey: request.IncomingCircuitKey, + Action: routerrpc.ResolveHoldForwardAction_RESUME, + OutgoingAmountMsat: interceptResult.AmountMsat, + OutgoingRequestedChanId: uint64(interceptResult.ChannelId), + OnionBlob: onionBlob, + } +}