Skip to content

Commit

Permalink
Authenticate Bolt12Invoice using BlindedPath data
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jkczyz committed Jul 12, 2024
1 parent b379209 commit 46bee8c
Showing 1 changed file with 28 additions and 23 deletions.
51 changes: 28 additions & 23 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10623,40 +10623,45 @@ 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 logger = WithContext::from(
&self.logger, None, None, Some(invoice.payment_hash()),
);

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 (invoice, payment_id) = match payer_data {
Some((payment_id, nonce)) => {
if invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx) {
(invoice, payment_id)
} else {
self.send_payment_for_verified_bolt12_invoice(&invoice, payment_id)
.map_err(|e| {
log_trace!(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) => (invoice, 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!(logger, "Failed paying invoice: {:?}", e);
InvoiceError::from_string(format!("{:?}", e))
})
}
};

match result {
Expand Down

0 comments on commit 46bee8c

Please sign in to comment.