lnrpc: ensure parsing of the Amp flag for payments is consistent

In this commit, we fix an inconsistent in the API related to AMP
payments. When a payment request isn't specified, we require the `--amp`
flag on the CLI to make an AMP payment. However, for payment requests,
we don't require this flag. To fix this inconsistency, we now require
the `--amp` flag to _also_ be set for payment requests.
This commit is contained in:
Olaoluwa Osuntokun 2024-04-23 18:33:39 -07:00
parent ab2f34e13b
commit e8031fdccf
No known key found for this signature in database
GPG key ID: 3BBD59E99B280306
4 changed files with 52 additions and 3 deletions

View file

@ -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 whether through gRPC or the REST API, due to the destructive nature of the
operation. 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 ## lncli Updates
* [Documented all available `lncli` * [Documented all available `lncli`
@ -532,6 +536,7 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor
* Marcos Fernandez Perez * Marcos Fernandez Perez
* Matt Morehouse * Matt Morehouse
* Mohamed Awnallah * Mohamed Awnallah
* Olaoluwa Osuntokun
* Ononiwu Maureen Chiamaka * Ononiwu Maureen Chiamaka
* Slyghtning * Slyghtning
* Tee8z * Tee8z

View file

@ -129,6 +129,7 @@ func testSendPaymentAMPInvoiceCase(ht *lntest.HarnessTest,
PaymentAddr: externalPayAddr, PaymentAddr: externalPayAddr,
TimeoutSeconds: 60, TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat, FeeLimitMsat: noFeeLimitMsat,
Amp: true,
} }
payment := ht.SendPaymentAssertSettled(mts.alice, sendReq) 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. // Now we'll use Carol to pay the invoice that Dave created.
ht.CompletePaymentRequests( ht.CompletePaymentRequests(
carol, []string{addInvoiceResp.PaymentRequest}, carol, []string{addInvoiceResp.PaymentRequest},
lntest.WithAMP(),
) )
// Dave should get a notification that the invoice has been settled. // Dave should get a notification that the invoice has been settled.
@ -274,6 +276,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntest.HarnessTest) {
// has received another payment. // has received another payment.
ht.CompletePaymentRequests( ht.CompletePaymentRequests(
carol, []string{addInvoiceResp.PaymentRequest}, carol, []string{addInvoiceResp.PaymentRequest},
lntest.WithAMP(),
) )
// Dave should get another notification. // Dave should get another notification.

View file

@ -940,6 +940,14 @@ func (r *RouterBackend) extractIntentFromSendRequest(
payAddr := payReq.PaymentAddr payAddr := payReq.PaymentAddr
if payReq.Features.HasFeature(lnwire.AMPOptional) { 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. // Generate random SetID and root share.
var setID [32]byte var setID [32]byte
_, err = rand.Read(setID[:]) _, err = rand.Read(setID[:])

View file

@ -105,6 +105,32 @@ type HarnessTest struct {
cleaned bool 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 // NewHarnessTest creates a new instance of a harnessTest from a regular
// testing.T instance. // testing.T instance.
func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService, 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 // all payment requests. This function does not return until all payments
// have reached the specified status. // have reached the specified status.
func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode, 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. // Create a buffered chan to signal the results.
results := make(chan rpc.PaymentClient, len(paymentRequests)) results := make(chan rpc.PaymentClient, len(paymentRequests))
@ -1449,6 +1481,7 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode,
PaymentRequest: payReq, PaymentRequest: payReq,
TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()), TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()),
FeeLimitMsat: noFeeLimitMsat, FeeLimitMsat: noFeeLimitMsat,
Amp: payOpts.useAMP,
} }
stream := hn.RPC.SendPayment(req) 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 // requests. This function does not return until all payments successfully
// complete without errors. // complete without errors.
func (h *HarnessTest) CompletePaymentRequests(hn *node.HarnessNode, func (h *HarnessTest) CompletePaymentRequests(hn *node.HarnessNode,
paymentRequests []string) { paymentRequests []string, opts ...HarnessOpt) {
h.completePaymentRequestsAssertStatus( h.completePaymentRequestsAssertStatus(
hn, paymentRequests, lnrpc.Payment_SUCCEEDED, hn, paymentRequests, lnrpc.Payment_SUCCEEDED, opts...,
) )
} }