From 118e0a99c1c9119890600884c70ddaca78ad08f5 Mon Sep 17 00:00:00 2001 From: Erick Cestari Date: Tue, 10 Jun 2025 11:42:37 -0300 Subject: [PATCH] routerrpc: reject invoices missing secret/path Ensure that a payment is only sent if the invoice includes either a payment address (payment secret) or at least one blinded path. --- lnrpc/routerrpc/router_backend.go | 11 ++++++++++- lnrpc/routerrpc/router_backend_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 6c0fe8294..ab53b4ba9 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -990,6 +990,15 @@ func (r *RouterBackend) extractIntentFromSendRequest( return nil, err } + // An invoice must include either a payment address or + // blinded paths. + if payReq.PaymentAddr.IsNone() && + len(payReq.BlindedPaymentPaths) == 0 { + + return nil, errors.New("payment request must contain " + + "either a payment address or blinded paths") + } + // If the amount was not included in the invoice, then we let // the payer specify the amount of satoshis they wish to send. // We override the amount to pay with the amount provided from @@ -1006,7 +1015,7 @@ func (r *RouterBackend) extractIntentFromSendRequest( if reqAmt != 0 { return nil, errors.New("amount must not be " + "specified when paying a non-zero " + - " amount invoice") + "amount invoice") } payIntent.Amount = *payReq.MilliSat diff --git a/lnrpc/routerrpc/router_backend_test.go b/lnrpc/routerrpc/router_backend_test.go index 962ea05b9..608f734bb 100644 --- a/lnrpc/routerrpc/router_backend_test.go +++ b/lnrpc/routerrpc/router_backend_test.go @@ -505,6 +505,13 @@ func TestExtractIntentFromSendRequest(t *testing.T) { "g6aykds4ydvf2x9lpngqcfux3hv8qlraan9v3s9296r5w5eh959yzadgh5ck" + "gjydgyfxdpumxtuk3p3caugmlqpz5necs" + const paymentReqMissingAddr = "lnbcrt100p1p70xwfzpp5qqqsyqcyq5rqwzqfq" + + "qqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kge" + + "tjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaqnp4q0n326hr8v9zprg8" + + "gsvezcch06gfaqqhde2aj730yg0durunfhv669qypqqqz3uu8wnr7883qzxr" + + "566nuhled49fx6e6q0jn06w6gpgyznwzxwf8xdmye87kpx0y8lqtcgwywsau" + + "0jkm66evelkw7cggwlegp4anv3cq62wusm" + destNodeBytes, err := hex.DecodeString(destKey) require.NoError(t, err) @@ -720,6 +727,23 @@ func TestExtractIntentFromSendRequest(t *testing.T) { valid: false, expectedErrorMsg: "invoice expired.", }, + { + name: "Invoice missing payment address", + backend: &RouterBackend{ + ShouldSetExpEndorsement: func() bool { + return false + }, + ActiveNetParams: &chaincfg.RegressionNetParams, + MaxTotalTimelock: 1000, + Clock: mockClock, + }, + sendReq: &SendPaymentRequest{ + PaymentRequest: paymentReqMissingAddr, + }, + valid: false, + expectedErrorMsg: "payment request must contain " + + "either a payment address or blinded paths", + }, { name: "Invalid dest vertex length", backend: &RouterBackend{