Skip to content

Commit

Permalink
move lnd specific onion creation to lnd
Browse files Browse the repository at this point in the history
  • Loading branch information
JssDWt committed Jun 30, 2023
1 parent c37a745 commit 34646d5
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 97 deletions.
105 changes: 15 additions & 90 deletions interceptor/intercept.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ import (
"github.com/breez/lspd/config"
"github.com/breez/lspd/lightning"
"github.com/breez/lspd/notifications"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
sphinx "github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
"golang.org/x/sync/singleflight"
)

Expand All @@ -40,13 +35,14 @@ var (
)

type InterceptResult struct {
Action InterceptAction
FailureCode InterceptFailureCode
Destination []byte
AmountMsat uint64
ChannelPoint *wire.OutPoint
ChannelId uint64
OnionBlob []byte
Action InterceptAction
FailureCode InterceptFailureCode
Destination []byte
AmountMsat uint64
TotalAmountMsat uint64
ChannelPoint *wire.OutPoint
ChannelId uint64
PaymentSecret []byte
}

type Interceptor struct {
Expand Down Expand Up @@ -230,81 +226,9 @@ func (i *Interceptor) Intercept(scid *basetypes.ShortChannelID, reqPaymentHash [
}
}

pubKey, err := btcec.ParsePubKey(destination)
if err != nil {
log.Printf("btcec.ParsePubKey(%x): %v", destination, err)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}

sessionKey, err := btcec.NewPrivateKey()
if err != nil {
log.Printf("btcec.NewPrivateKey(): %v", err)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}

var bigProd, bigAmt big.Int
amt := (bigAmt.Div(bigProd.Mul(big.NewInt(outgoingAmountMsat), big.NewInt(int64(reqOutgoingAmountMsat))), big.NewInt(incomingAmountMsat))).Int64()

var addr [32]byte
copy(addr[:], paymentSecret)
hop := route.Hop{
AmtToForward: lnwire.MilliSatoshi(amt),
OutgoingTimeLock: reqOutgoingExpiry,
MPP: record.NewMPP(lnwire.MilliSatoshi(outgoingAmountMsat), addr),
CustomRecords: make(record.CustomSet),
}

var b bytes.Buffer
err = hop.PackHopPayload(&b, uint64(0))
if err != nil {
log.Printf("hop.PackHopPayload(): %v", err)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}

payload, err := sphinx.NewHopPayload(nil, b.Bytes())
if err != nil {
log.Printf("sphinx.NewHopPayload(): %v", err)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}

var sphinxPath sphinx.PaymentPath
sphinxPath[0] = sphinx.OnionHop{
NodePub: *pubKey,
HopPayload: payload,
}
sphinxPacket, err := sphinx.NewOnionPacket(
&sphinxPath, sessionKey, reqPaymentHash,
sphinx.DeterministicPacketFiller,
)
if err != nil {
log.Printf("sphinx.NewOnionPacket(): %v", err)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}
var onionBlob bytes.Buffer
err = sphinxPacket.Encode(&onionBlob)
if err != nil {
log.Printf("sphinxPacket.Encode(): %v", err)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}

deadline := time.Now().Add(60 * time.Second)

for {
Expand Down Expand Up @@ -334,12 +258,13 @@ func (i *Interceptor) Intercept(scid *basetypes.ShortChannelID, reqPaymentHash [
}

return InterceptResult{
Action: INTERCEPT_RESUME_WITH_ONION,
Destination: destination,
ChannelPoint: channelPoint,
ChannelId: channelID,
AmountMsat: uint64(amt),
OnionBlob: onionBlob.Bytes(),
Action: INTERCEPT_RESUME_WITH_ONION,
Destination: destination,
ChannelPoint: channelPoint,
ChannelId: channelID,
PaymentSecret: paymentSecret,
AmountMsat: uint64(amt),
TotalAmountMsat: uint64(outgoingAmountMsat),
}, nil
}

Expand Down
92 changes: 85 additions & 7 deletions lnd/interceptor.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lnd

import (
"bytes"
"context"
"log"
"sync"
Expand All @@ -9,8 +10,13 @@ import (
"github.com/breez/lspd/basetypes"
"github.com/breez/lspd/config"
"github.com/breez/lspd/interceptor"
"github.com/btcsuite/btcd/btcec/v2"
sphinx "github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand Down Expand Up @@ -133,13 +139,23 @@ 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:
interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{
IncomingCircuitKey: request.IncomingCircuitKey,
Action: routerrpc.ResolveHoldForwardAction_RESUME,
OutgoingAmountMsat: interceptResult.AmountMsat,
OutgoingRequestedChanId: uint64(interceptResult.ChannelId),
OnionBlob: interceptResult.OnionBlob,
})
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,
})
}

case interceptor.INTERCEPT_FAIL_HTLC_WITH_CODE:
interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{
IncomingCircuitKey: request.IncomingCircuitKey,
Expand Down Expand Up @@ -179,3 +195,65 @@ func (i *LndHtlcInterceptor) mapFailureCode(original interceptor.InterceptFailur
return lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE
}
}

func (i *LndHtlcInterceptor) constructOnion(
interceptResult interceptor.InterceptResult,
reqOutgoingExpiry uint32,
reqPaymentHash []byte,
) ([]byte, error) {
pubKey, err := btcec.ParsePubKey(interceptResult.Destination)
if err != nil {
log.Printf("btcec.ParsePubKey(%x): %v", interceptResult.Destination, err)
return nil, err
}

sessionKey, err := btcec.NewPrivateKey()
if err != nil {
log.Printf("btcec.NewPrivateKey(): %v", err)
return nil, err
}

var addr [32]byte
copy(addr[:], interceptResult.PaymentSecret)
hop := route.Hop{
AmtToForward: lnwire.MilliSatoshi(interceptResult.AmountMsat),
OutgoingTimeLock: reqOutgoingExpiry,
MPP: record.NewMPP(lnwire.MilliSatoshi(interceptResult.TotalAmountMsat), addr),
CustomRecords: make(record.CustomSet),
}

var b bytes.Buffer
err = hop.PackHopPayload(&b, uint64(0))
if err != nil {
log.Printf("hop.PackHopPayload(): %v", err)
return nil, err
}

payload, err := sphinx.NewHopPayload(nil, b.Bytes())
if err != nil {
log.Printf("sphinx.NewHopPayload(): %v", err)
return nil, err
}

var sphinxPath sphinx.PaymentPath
sphinxPath[0] = sphinx.OnionHop{
NodePub: *pubKey,
HopPayload: payload,
}
sphinxPacket, err := sphinx.NewOnionPacket(
&sphinxPath, sessionKey, reqPaymentHash,
sphinx.DeterministicPacketFiller,
)
if err != nil {
log.Printf("sphinx.NewOnionPacket(): %v", err)
return nil, err
}
var onionBlob bytes.Buffer
err = sphinxPacket.Encode(&onionBlob)
if err != nil {
log.Printf("sphinxPacket.Encode(): %v", err)
return nil, err
}

return onionBlob.Bytes(), nil
}

0 comments on commit 34646d5

Please sign in to comment.