diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index cb638c0ee..01a821db6 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -368,6 +368,10 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor whether through gRPC or the REST API, due to the destructive nature of the operation. +* When paying an AMP payment request, [the `--amp` flag is now + required](https://github.com/lightningnetwork/lnd/pull/8681) to be consistent + w/ the flow when a payment request isn't used. + ## lncli Updates * [Documented all available `lncli` @@ -532,6 +536,7 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * Marcos Fernandez Perez * Matt Morehouse * Mohamed Awnallah +* Olaoluwa Osuntokun * Ononiwu Maureen Chiamaka * Slyghtning * Tee8z diff --git a/itest/lnd_amp_test.go b/itest/lnd_amp_test.go index a96911319..23bfd8654 100644 --- a/itest/lnd_amp_test.go +++ b/itest/lnd_amp_test.go @@ -129,6 +129,7 @@ func testSendPaymentAMPInvoiceCase(ht *lntest.HarnessTest, PaymentAddr: externalPayAddr, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, + Amp: true, } payment := ht.SendPaymentAssertSettled(mts.alice, sendReq) @@ -252,6 +253,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntest.HarnessTest) { // Now we'll use Carol to pay the invoice that Dave created. ht.CompletePaymentRequests( carol, []string{addInvoiceResp.PaymentRequest}, + lntest.WithAMP(), ) // Dave should get a notification that the invoice has been settled. @@ -274,6 +276,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntest.HarnessTest) { // has received another payment. ht.CompletePaymentRequests( carol, []string{addInvoiceResp.PaymentRequest}, + lntest.WithAMP(), ) // Dave should get another notification. diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 18233991d..9fde63411 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -940,6 +940,14 @@ func (r *RouterBackend) extractIntentFromSendRequest( payAddr := payReq.PaymentAddr if payReq.Features.HasFeature(lnwire.AMPOptional) { + // The opt-in AMP flag is required to pay an AMP + // invoice. + if !rpcPayReq.Amp { + return nil, fmt.Errorf("the AMP flag (--amp " + + "or SendPaymentRequest.Amp) must be " + + "set to pay an AMP invoice") + } + // Generate random SetID and root share. var setID [32]byte _, err = rand.Read(setID[:]) diff --git a/lntest/harness.go b/lntest/harness.go index 5c2bef488..889bb156e 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -105,6 +105,32 @@ type HarnessTest struct { cleaned bool } +// harnessOpts contains functional option to modify the behavior of the various +// harness calls. +type harnessOpts struct { + useAMP bool +} + +// defaultHarnessOpts returns a new instance of the harnessOpts with default +// values specified. +func defaultHarnessOpts() harnessOpts { + return harnessOpts{ + useAMP: false, + } +} + +// HarnessOpt is a functional option that can be used to modify the behavior of +// harness functionality. +type HarnessOpt func(*harnessOpts) + +// WithAMP is a functional option that can be used to enable the AMP feature +// for sending payments. +func WithAMP() HarnessOpt { + return func(h *harnessOpts) { + h.useAMP = true + } +} + // NewHarnessTest creates a new instance of a harnessTest from a regular // testing.T instance. func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService, @@ -1438,7 +1464,13 @@ func (h *HarnessTest) FundCoinsP2TR(amt btcutil.Amount, // all payment requests. This function does not return until all payments // have reached the specified status. func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode, - paymentRequests []string, status lnrpc.Payment_PaymentStatus) { + paymentRequests []string, status lnrpc.Payment_PaymentStatus, + opts ...HarnessOpt) { + + payOpts := defaultHarnessOpts() + for _, opt := range opts { + opt(&payOpts) + } // Create a buffered chan to signal the results. results := make(chan rpc.PaymentClient, len(paymentRequests)) @@ -1449,6 +1481,7 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode, PaymentRequest: payReq, TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()), FeeLimitMsat: noFeeLimitMsat, + Amp: payOpts.useAMP, } stream := hn.RPC.SendPayment(req) @@ -1477,10 +1510,10 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode, // requests. This function does not return until all payments successfully // complete without errors. func (h *HarnessTest) CompletePaymentRequests(hn *node.HarnessNode, - paymentRequests []string) { + paymentRequests []string, opts ...HarnessOpt) { h.completePaymentRequestsAssertStatus( - hn, paymentRequests, lnrpc.Payment_SUCCEEDED, + hn, paymentRequests, lnrpc.Payment_SUCCEEDED, opts..., ) }