]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Authenticate Bolt12Invoice using BlindedPath data
authorJeffrey Czyz <jkczyz@gmail.com>
Fri, 12 Jul 2024 23:16:44 +0000 (18:16 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Mon, 22 Jul 2024 16:34:05 +0000 (11:34 -0500)
When a Bolt12Invoice is handled with an OfferContext, use both the
containing payment_id and nonce to verify that it is for a pending
outbound payment. Previously, the nonce the payment_id were taken from
the payer_metadata and the latter was compared against the payment_id
in the OfferContext. The payer_metadata thus no longer needs to include
either when a blinded path is used. However, some payer_metadata will
still be needed as per the spec.

lightning/src/ln/channelmanager.rs

index 9aa80348eac1c80f634caee02a84cfda25a6d061..20bcbdc308cc8714d85222d8d74fdd756c45c0bb 100644 (file)
@@ -10807,36 +10807,41 @@ where
                                }
                        },
                        OffersMessage::Invoice(invoice) => {
-                               let expected_payment_id = match context {
+                               let payer_data = match context {
                                        OffersContext::Unknown {} if invoice.is_for_refund_without_paths() => None,
-                                       OffersContext::OutboundPayment { payment_id, .. } => Some(payment_id),
+                                       OffersContext::OutboundPayment { payment_id, nonce } => Some((payment_id, nonce)),
                                        _ => return ResponseInstruction::NoResponse,
                                };
 
-                               let result = match invoice.verify(expanded_key, secp_ctx) {
-                                       Ok(payment_id) => {
-                                               if let Some(expected_payment_id) = expected_payment_id {
-                                                       if payment_id != expected_payment_id {
-                                                               return ResponseInstruction::NoResponse;
-                                                       }
-                                               }
-
-                                               let features = self.bolt12_invoice_features();
-                                               if invoice.invoice_features().requires_unknown_bits_from(&features) {
-                                                       Err(InvoiceError::from(Bolt12SemanticError::UnknownRequiredFeatures))
-                                               } else if self.default_configuration.manually_handle_bolt12_invoices {
-                                                       let event = Event::InvoiceReceived { payment_id, invoice, responder };
-                                                       self.pending_events.lock().unwrap().push_back((event, None));
-                                                       return ResponseInstruction::NoResponse;
+                               let payment_id = match payer_data {
+                                       Some((payment_id, nonce)) => {
+                                               if invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx) {
+                                                       payment_id
                                                } else {
-                                                       self.send_payment_for_verified_bolt12_invoice(&invoice, payment_id)
-                                                               .map_err(|e| {
-                                                                       log_trace!(self.logger, "Failed paying invoice: {:?}", e);
-                                                                       InvoiceError::from_string(format!("{:?}", e))
-                                                               })
+                                                       return ResponseInstruction::NoResponse;
                                                }
                                        },
-                                       Err(()) => return ResponseInstruction::NoResponse,
+                                       None => match invoice.verify(expanded_key, secp_ctx) {
+                                               Ok(payment_id) => payment_id,
+                                               Err(()) => return ResponseInstruction::NoResponse,
+                                       },
+                               };
+
+                               let result = {
+                                       let features = self.bolt12_invoice_features();
+                                       if invoice.invoice_features().requires_unknown_bits_from(&features) {
+                                               Err(InvoiceError::from(Bolt12SemanticError::UnknownRequiredFeatures))
+                                       } else if self.default_configuration.manually_handle_bolt12_invoices {
+                                               let event = Event::InvoiceReceived { payment_id, invoice, responder };
+                                               self.pending_events.lock().unwrap().push_back((event, None));
+                                               return ResponseInstruction::NoResponse;
+                                       } else {
+                                               self.send_payment_for_verified_bolt12_invoice(&invoice, payment_id)
+                                                       .map_err(|e| {
+                                                               log_trace!(self.logger, "Failed paying invoice: {:?}", e);
+                                                               InvoiceError::from_string(format!("{:?}", e))
+                                                       })
+                                       }
                                };
 
                                match result {