diff --git a/cmd/lncli/arg_parse.go b/cmd/lncli/arg_parse.go index a97e0e2ed..49d165d55 100644 --- a/cmd/lncli/arg_parse.go +++ b/cmd/lncli/arg_parse.go @@ -3,6 +3,7 @@ package main import ( "regexp" "strconv" + "strings" "time" ) @@ -38,3 +39,10 @@ func parseTime(s string, base time.Time) (uint64, error) { return strconv.ParseUint(s, 10, 64) } + +var lightningPrefix = "lightning:" + +// stripPrefix removes accidentally copied 'lightning:' prefix. +func stripPrefix(s string) string { + return strings.TrimSpace(strings.TrimPrefix(s, lightningPrefix)) +} diff --git a/cmd/lncli/arg_parse_test.go b/cmd/lncli/arg_parse_test.go index 9de6f895a..571292d2c 100644 --- a/cmd/lncli/arg_parse_test.go +++ b/cmd/lncli/arg_parse_test.go @@ -3,6 +3,8 @@ package main import ( "testing" "time" + + "github.com/stretchr/testify/require" ) var now = time.Date(2017, 11, 10, 7, 8, 9, 1234, time.UTC) @@ -86,3 +88,30 @@ func TestParseTime(t *testing.T) { } } } + +var stripPrefixTests = []struct { + in string + expected string +}{ + { + "lightning:ln123", + "ln123", + }, + { + "lightning: ln123", + "ln123", + }, + { + "ln123", + "ln123", + }, +} + +func TestStripPrefix(t *testing.T) { + t.Parallel() + + for _, test := range stripPrefixTests { + actual := stripPrefix(test.in) + require.Equal(t, test.expected, actual) + } +} diff --git a/cmd/lncli/cmd_invoice.go b/cmd/lncli/cmd_invoice.go index 4053a8d7d..b66457d0d 100644 --- a/cmd/lncli/cmd_invoice.go +++ b/cmd/lncli/cmd_invoice.go @@ -292,7 +292,7 @@ func decodePayReq(ctx *cli.Context) error { } resp, err := client.DecodePayReq(ctxc, &lnrpc.PayReqString{ - PayReq: payreq, + PayReq: stripPrefix(payreq), }) if err != nil { return err diff --git a/cmd/lncli/cmd_payments.go b/cmd/lncli/cmd_payments.go index 0cf5e9e96..725870c9f 100644 --- a/cmd/lncli/cmd_payments.go +++ b/cmd/lncli/cmd_payments.go @@ -284,7 +284,7 @@ func sendPayment(ctx *cli.Context) error { // details of the payment are encoded within the request. if ctx.IsSet("pay_req") { req := &routerrpc.SendPaymentRequest{ - PaymentRequest: ctx.String("pay_req"), + PaymentRequest: stripPrefix(ctx.String("pay_req")), Amt: ctx.Int64("amt"), DestCustomRecords: make(map[uint64][]byte), } @@ -832,7 +832,7 @@ func payInvoice(ctx *cli.Context) error { } req := &routerrpc.SendPaymentRequest{ - PaymentRequest: payReq, + PaymentRequest: stripPrefix(payReq), Amt: ctx.Int64("amt"), DestCustomRecords: make(map[uint64][]byte), } diff --git a/docs/release-notes/release-notes-0.16.0.md b/docs/release-notes/release-notes-0.16.0.md index 499129d80..c7b23e25e 100644 --- a/docs/release-notes/release-notes-0.16.0.md +++ b/docs/release-notes/release-notes-0.16.0.md @@ -174,6 +174,13 @@ certain large transactions](https://github.com/lightningnetwork/lnd/pull/7100). * [Label the openchannel tx first before notifying the channel open event.](https://github.com/lightningnetwork/lnd/pull/7158) +* [Add check for `pay_req` argument in `sendpayment` and `decodepayreq` + commands to trim "lightning:" prefix before processing the request]( + https://github.com/lightningnetwork/lnd/pull/7150). Invoices may be prefixed + with "lightning:" on mobile and web apps and it's likely for users to copy + the invoice payment request together with the prefix, which throws checksum + error when pasting it to the CLI. + ## Code Health * [test: use `T.TempDir` to create temporary test