diff --git a/go.mod b/go.mod index ab2f80e..22942e8 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/lightninglabs/loop require ( github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d + github.com/btcsuite/btcutil v1.0.2 github.com/coreos/bbolt v1.3.3 github.com/fortytw2/leaktest v1.3.0 github.com/golang/protobuf v1.3.2 @@ -11,10 +11,9 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.12.2 github.com/jessevdk/go-flags v1.4.0 github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d - github.com/lightningnetwork/lnd v0.9.0-beta-rc3.0.20200121213302-a2977c4438b5 - github.com/lightningnetwork/lnd/queue v1.0.2 + github.com/lightningnetwork/lnd v0.10.0-beta.rc1 + github.com/lightningnetwork/lnd/queue v1.0.3 github.com/urfave/cli v1.20.0 - golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 golang.org/x/text v0.3.2 // indirect google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c diff --git a/go.sum b/go.sum index 27737b5..afc06cf 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,12 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.11.0 h1:XhwqdhEchy5a0q6R+y3F82roD2hYycPCHovgNyJS08w= -github.com/btcsuite/btcwallet v0.11.0/go.mod h1:qtPAohN1ioo0pvJt/j7bZM8ANBWlYWVCVFL0kkijs7s= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil/psbt v1.0.2 h1:gCVY3KxdoEVU7Q6TjusPO+GANIwVgr9yTLqM+a6CZr8= +github.com/btcsuite/btcutil/psbt v1.0.2/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= +github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb h1:kkq2SSCy+OrC7GVZLIqutoHVR2yW4SJQdX70jtmuLDI= +github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb/go.mod h1:9fJNm1aXi4q9P5Nk23mmqppCy1Le3f2/JMWj9UXKkCc= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= @@ -36,8 +40,9 @@ github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZw github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0 h1:6DxkcoMnCPY4E9cUDPB5tbuuf40SmmMkSQkoE8vCT+s= github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= github.com/btcsuite/btcwallet/walletdb v1.0.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= -github.com/btcsuite/btcwallet/walletdb v1.1.0 h1:JHAL7wZ8pX4SULabeAv/wPO9sseRWMGzE80lfVmRw6Y= -github.com/btcsuite/btcwallet/walletdb v1.1.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= +github.com/btcsuite/btcwallet/walletdb v1.2.0/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= +github.com/btcsuite/btcwallet/walletdb v1.3.1 h1:lW1Ac3F1jJY4K11P+YQtRNcP5jFk27ASfrV7C6mvRU0= +github.com/btcsuite/btcwallet/walletdb v1.3.1/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= github.com/btcsuite/btcwallet/wtxmgr v1.0.0 h1:aIHgViEmZmZfe0tQQqF1xyd2qBqFWxX5vZXkkbjtbeA= github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY= github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 h1:kij1x2aL7VE6gtx8KMIt8PGPgI5GV9LgtHFG5KaEMPY= @@ -137,18 +142,20 @@ github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= github.com/lightninglabs/neutrino v0.11.0 h1:lPpYFCtsfJX2W5zI4pWycPmbbBdr7zU+BafYdLoD6k0= github.com/lightninglabs/neutrino v0.11.0/go.mod h1:CuhF0iuzg9Sp2HO6ZgXgayviFTn1QHdSTJlMncK80wg= +github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200 h1:j4iZ1XlUAPQmW6oSzMcJGILYsRHNs+4O3Gk+2Ms5Dww= +github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200/go.mod h1:MlZmoKa7CJP3eR1s5yB7Rm5aSyadpKkxqAwLQmog7N0= github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d h1:QWD/5MPnaZfUVP7P8wLa4M8Td2DI7XXHXt2vhVtUgGI= github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d/go.mod h1:KDb67YMzoh4eudnzClmvs2FbiLG9vxISmLApUkCa4uI= github.com/lightningnetwork/lightning-onion v1.0.1 h1:qChGgS5+aPxFeR6JiUsGvanei1bn6WJpYbvosw/1604= github.com/lightningnetwork/lightning-onion v1.0.1/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4= -github.com/lightningnetwork/lnd v0.9.0-beta-rc3.0.20200121213302-a2977c4438b5 h1:qLO+I/7EggqegY8uu6k9TuE/5Tc5zV2L8gQGfgEV9LY= -github.com/lightningnetwork/lnd v0.9.0-beta-rc3.0.20200121213302-a2977c4438b5/go.mod h1:sxMH8WLTqgERzBCrTrBCuDkT6SqAjZhnOWiAQSNzJ8A= -github.com/lightningnetwork/lnd/cert v1.0.0 h1:J0gtf2UNQX2U+/j5cXnX2wIMSTuJuwrXv7m9qJr2wtw= -github.com/lightningnetwork/lnd/cert v1.0.0/go.mod h1:fmtemlSMf5t4hsQmcprSoOykypAPp+9c+0d0iqTScMo= +github.com/lightningnetwork/lnd v0.10.0-beta.rc1 h1:eCLOYu+Erw+GIxMJHbkTRn23eBVN3s7u188iyw3747Y= +github.com/lightningnetwork/lnd v0.10.0-beta.rc1/go.mod h1:UNd+jGvZbtHFAR4syN6ab2euqh5DNzbVjjomZZFlCEY= +github.com/lightningnetwork/lnd/cert v1.0.1 h1:D+FOL2J/MzoolaWSEZJZc5Qb7vqy6P8IX1HGzqHWnQM= +github.com/lightningnetwork/lnd/cert v1.0.1/go.mod h1:fmtemlSMf5t4hsQmcprSoOykypAPp+9c+0d0iqTScMo= github.com/lightningnetwork/lnd/queue v1.0.1 h1:jzJKcTy3Nj5lQrooJ3aaw9Lau3I0IwvQR5sqtjdv2R0= github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms= -github.com/lightningnetwork/lnd/queue v1.0.2 h1:Hx43fmTz2pDH4fIYDr57P/M5cB+GEMLzN+eif8576Xo= -github.com/lightningnetwork/lnd/queue v1.0.2/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= +github.com/lightningnetwork/lnd/queue v1.0.3 h1:5ufYVE7lh9GJnL1wOoeO3bZ3aAHWNnkNFHP7W1+NiJ8= +github.com/lightningnetwork/lnd/queue v1.0.3/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= github.com/lightningnetwork/lnd/ticker v1.0.0 h1:S1b60TEGoTtCe2A0yeB+ecoj/kkS4qpwh6l+AkQEZwU= github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= @@ -200,8 +207,8 @@ golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d h1:2+ZP7EfsZV7Vvmx3TIqSlSzATMkTAKqM14YGFPoSKjI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -225,6 +232,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/lndclient/router_client.go b/lndclient/router_client.go index 91109ee..a7b722b 100644 --- a/lndclient/router_client.go +++ b/lndclient/router_client.go @@ -34,10 +34,22 @@ type RouterClient interface { // PaymentStatus describe the state of a payment. type PaymentStatus struct { - State routerrpc.PaymentState - Preimage lntypes.Preimage - Fee lnwire.MilliSatoshi - Route *route.Route + State lnrpc.Payment_PaymentStatus + Preimage lntypes.Preimage + Fee lnwire.MilliSatoshi + Value lnwire.MilliSatoshi + InFlightAmt lnwire.MilliSatoshi + InFlightHtlcs int +} + +func (p PaymentStatus) String() string { + text := fmt.Sprintf("state=%v", p.State) + if p.State == lnrpc.Payment_IN_FLIGHT { + text += fmt.Sprintf(", inflight_htlcs=%v, inflight_amt=%v", + p.InFlightHtlcs, p.InFlightAmt) + } + + return text } // SendPaymentRequest defines the payment parameters for a new payment. @@ -81,6 +93,10 @@ type SendPaymentRequest struct { // LastHopPubkey is the pubkey of the last hop of the route taken // for this payment. If empty, any hop may be used. LastHopPubkey *route.Vertex + + // The maximum number of partial payments that may be used to complete + // the full amount. + MaxShards uint32 } // routerClient is a wrapper around the generated routerrpc proxy. @@ -108,6 +124,7 @@ func (r *routerClient) SendPayment(ctx context.Context, FeeLimitSat: int64(request.MaxFee), PaymentRequest: request.Invoice, TimeoutSeconds: int32(request.Timeout.Seconds()), + MaxShards: request.MaxShards, } if request.MaxCltv != nil { rpcReq.CltvLimit = *request.MaxCltv @@ -170,7 +187,7 @@ func (r *routerClient) trackPayment(ctx context.Context, errorChan := make(chan error, 1) go func() { for { - rpcStatus, err := stream.Recv() + payment, err := stream.Recv() if err != nil { switch status.Convert(err).Code() { @@ -189,7 +206,7 @@ func (r *routerClient) trackPayment(ctx context.Context, return } - status, err := unmarshallPaymentStatus(rpcStatus) + status, err := unmarshallPaymentStatus(payment) if err != nil { errorChan <- err return @@ -208,33 +225,36 @@ func (r *routerClient) trackPayment(ctx context.Context, // unmarshallPaymentStatus converts an rpc status update to the PaymentStatus // type that is used throughout the application. -func unmarshallPaymentStatus(rpcStatus *routerrpc.PaymentStatus) ( +func unmarshallPaymentStatus(rpcPayment *lnrpc.Payment) ( *PaymentStatus, error) { status := PaymentStatus{ - State: rpcStatus.State, + State: rpcPayment.Status, } - if status.State == routerrpc.PaymentState_SUCCEEDED { - preimage, err := lntypes.MakePreimage( - rpcStatus.Preimage, + if status.State == lnrpc.Payment_SUCCEEDED { + preimage, err := lntypes.MakePreimageFromStr( + rpcPayment.PaymentPreimage, ) if err != nil { return nil, err } status.Preimage = preimage + status.Fee = lnwire.MilliSatoshi(rpcPayment.FeeMsat) + status.Value = lnwire.MilliSatoshi(rpcPayment.ValueMsat) + } - status.Fee = lnwire.MilliSatoshi( - rpcStatus.Route.TotalFeesMsat, - ) - - if rpcStatus.Route != nil { - route, err := unmarshallRoute(rpcStatus.Route) - if err != nil { - return nil, err - } - status.Route = route + for _, htlc := range rpcPayment.Htlcs { + if htlc.Status != lnrpc.HTLCAttempt_IN_FLIGHT { + continue } + + status.InFlightHtlcs++ + + lastHop := htlc.Route.Hops[len(htlc.Route.Hops)-1] + status.InFlightAmt += lnwire.MilliSatoshi( + lastHop.AmtToForwardMsat, + ) } return &status, nil diff --git a/loopout.go b/loopout.go index 883ca8d..a9ea174 100644 --- a/loopout.go +++ b/loopout.go @@ -4,6 +4,7 @@ import ( "context" "crypto/rand" "crypto/sha256" + "errors" "fmt" "time" @@ -14,6 +15,8 @@ import ( "github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/sweep" "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" ) @@ -36,6 +39,16 @@ var ( // // TODO(wilmer): tune? DefaultSweepConfTargetDelta = DefaultSweepConfTarget * 2 + + // paymentTimeout is the timeout for the loop out payment loop as + // communicated to lnd. + paymentTimeout = time.Minute +) + +const ( + // loopOutMaxShards defines that maximum number of shards that may be + // used for a loop out swap. + loopOutMaxShards = 5 ) // loopOutSwap contains all the in-memory state related to a pending loop out @@ -388,19 +401,120 @@ func (s *loopOutSwap) persistState(ctx context.Context) error { func (s *loopOutSwap) payInvoices(ctx context.Context) { // Pay the swap invoice. s.log.Infof("Sending swap payment %v", s.SwapInvoice) - s.swapPaymentChan = s.lnd.Client.PayInvoice( + s.swapPaymentChan = s.payInvoice( ctx, s.SwapInvoice, s.MaxSwapRoutingFee, s.LoopOutContract.UnchargeChannel, ) // Pay the prepay invoice. s.log.Infof("Sending prepayment %v", s.PrepayInvoice) - s.prePaymentChan = s.lnd.Client.PayInvoice( + s.prePaymentChan = s.payInvoice( ctx, s.PrepayInvoice, s.MaxPrepayRoutingFee, nil, ) } +// payInvoice pays a single invoice. +func (s *loopOutSwap) payInvoice(ctx context.Context, invoice string, + maxFee btcutil.Amount, + outgoingChannel *uint64) chan lndclient.PaymentResult { + + resultChan := make(chan lndclient.PaymentResult) + + go func() { + var result lndclient.PaymentResult + + status, err := s.payInvoiceAsync( + ctx, invoice, maxFee, outgoingChannel, + ) + if err != nil { + result.Err = err + } else { + result.Preimage = status.Preimage + result.PaidFee = status.Fee.ToSatoshis() + result.PaidAmt = status.Value.ToSatoshis() + } + + select { + case resultChan <- result: + case <-ctx.Done(): + } + }() + + return resultChan +} + +// payInvoiceAsync is the asynchronously executed part of paying an invoice. +func (s *loopOutSwap) payInvoiceAsync(ctx context.Context, + invoice string, maxFee btcutil.Amount, outgoingChannel *uint64) ( + *lndclient.PaymentStatus, error) { + + // Extract hash from payment request. Unfortunately the request + // components aren't available directly. + chainParams := s.lnd.ChainParams + hash, _, err := swap.DecodeInvoice(chainParams, invoice) + if err != nil { + return nil, err + } + + req := lndclient.SendPaymentRequest{ + MaxFee: maxFee, + Invoice: invoice, + OutgoingChannel: outgoingChannel, + Timeout: paymentTimeout, + MaxShards: loopOutMaxShards, + } + + // Lookup state of the swap payment. + paymentStateCtx, cancel := context.WithCancel(ctx) + defer cancel() + + payStatusChan, payErrChan, err := s.lnd.Router.SendPayment( + paymentStateCtx, req, + ) + if err != nil { + return nil, err + } + + for { + select { + // Payment advanced to the next state. + case payState := <-payStatusChan: + s.log.Infof("Payment %v: %v", hash, payState) + + switch payState.State { + case lnrpc.Payment_SUCCEEDED: + return &payState, nil + + case lnrpc.Payment_FAILED: + return nil, errors.New("payment failed") + + case lnrpc.Payment_IN_FLIGHT: + // Continue waiting for final state. + + default: + return nil, errors.New("unknown payment state") + } + + // Abort the swap in case of an error. An unknown payment error + // from TrackPayment is no longer expected here. + case err := <-payErrChan: + if err != channeldb.ErrAlreadyPaid { + return nil, err + } + + payStatusChan, payErrChan, err = + s.lnd.Router.TrackPayment(paymentStateCtx, hash) + if err != nil { + return nil, err + } + + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} + // waitForConfirmedHtlc waits for a confirmed htlc to appear on the chain. In // case we haven't revealed the preimage yet, it also monitors block height and // off-chain payment failure. diff --git a/lsat/interceptor.go b/lsat/interceptor.go index d0adc15..c121211 100644 --- a/lsat/interceptor.go +++ b/lsat/interceptor.go @@ -10,7 +10,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightninglabs/loop/lndclient" - "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/macaroons" "github.com/lightningnetwork/lnd/zpay32" @@ -399,13 +399,13 @@ func (i *Interceptor) trackPayment(ctx context.Context, token *Token) error { // If the payment was successful, we have all the // information we need and we can return the fully paid // token. - case routerrpc.PaymentState_SUCCEEDED: + case lnrpc.Payment_SUCCEEDED: extractPaymentDetails(token, result) return i.store.StoreToken(token) // The payment is still in transit, we'll give it more // time to complete. - case routerrpc.PaymentState_IN_FLIGHT: + case lnrpc.Payment_IN_FLIGHT: // Any other state means either error or timeout. default: @@ -440,8 +440,6 @@ func isPaymentRequired(err error) bool { // from the payment status and stores them in the token. func extractPaymentDetails(token *Token, status lndclient.PaymentStatus) { token.Preimage = status.Preimage - total := status.Route.TotalAmount - fees := status.Route.TotalFees() - token.AmountPaid = total - fees - token.RoutingFeePaid = fees + token.AmountPaid = status.Value + token.RoutingFeePaid = status.Fee } diff --git a/lsat/interceptor_test.go b/lsat/interceptor_test.go index cf7bac2..24764d8 100644 --- a/lsat/interceptor_test.go +++ b/lsat/interceptor_test.go @@ -11,9 +11,8 @@ import ( "github.com/lightninglabs/loop/lndclient" "github.com/lightninglabs/loop/test" - "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" - "github.com/lightningnetwork/lnd/routing/route" "google.golang.org/grpc" "google.golang.org/grpc/status" "gopkg.in/macaroon.v2" @@ -160,9 +159,8 @@ var ( // return an error. resetBackend(nil, "") msg.Updates <- lndclient.PaymentStatus{ - State: routerrpc.PaymentState_SUCCEEDED, + State: lnrpc.Payment_SUCCEEDED, Preimage: paidPreimage, - Route: &route.Route{}, } }, expectToken: true, diff --git a/test/context.go b/test/context.go index 96f7d2b..2ee09f9 100644 --- a/test/context.go +++ b/test/context.go @@ -9,6 +9,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/loop/lndclient" "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/zpay32" ) @@ -124,15 +125,15 @@ func (ctx *Context) AssertPaid( // Assert that client pays swap invoice. for { - var swapPayment PaymentChannelMessage + var swapPayment RouterPaymentChannelMessage select { - case swapPayment = <-ctx.Lnd.SendPaymentChannel: + case swapPayment = <-ctx.Lnd.RouterSendPaymentChannel: case <-time.After(Timeout): ctx.T.Fatalf("no payment sent for invoice: %v", expectedMemo) } - payReq := ctx.DecodeInvoice(swapPayment.PaymentRequest) + payReq := ctx.DecodeInvoice(swapPayment.Invoice) if _, ok := ctx.PaidInvoices[*payReq.Description]; ok { ctx.T.Fatalf("duplicate invoice paid: %v", @@ -140,12 +141,12 @@ func (ctx *Context) AssertPaid( } done := func(result error) { - select { - case swapPayment.Done <- lndclient.PaymentResult{ - Err: result, - }: - case <-time.After(Timeout): - ctx.T.Fatalf("payment result not consumed") + if result != nil { + swapPayment.Errors <- result + return + } + swapPayment.Updates <- lndclient.PaymentStatus{ + State: lnrpc.Payment_SUCCEEDED, } }