Skip to content

Commit 46bee8c

Browse files
committed
Authenticate Bolt12Invoice using BlindedPath data
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.
1 parent b379209 commit 46bee8c

File tree

1 file changed

+28
-23
lines changed

1 file changed

+28
-23
lines changed

lightning/src/ln/channelmanager.rs

+28-23
Original file line numberDiff line numberDiff line change
@@ -10623,40 +10623,45 @@ where
1062310623
}
1062410624
},
1062510625
OffersMessage::Invoice(invoice) => {
10626-
let expected_payment_id = match context {
10626+
let payer_data = match context {
1062710627
OffersContext::Unknown {} if invoice.is_for_refund_without_paths() => None,
10628-
OffersContext::OutboundPayment { payment_id, .. } => Some(payment_id),
10628+
OffersContext::OutboundPayment { payment_id, nonce } => Some((payment_id, nonce)),
1062910629
_ => return ResponseInstruction::NoResponse,
1063010630
};
1063110631

1063210632
let logger = WithContext::from(
1063310633
&self.logger, None, None, Some(invoice.payment_hash()),
1063410634
);
1063510635

10636-
let result = match invoice.verify(expanded_key, secp_ctx) {
10637-
Ok(payment_id) => {
10638-
if let Some(expected_payment_id) = expected_payment_id {
10639-
if payment_id != expected_payment_id {
10640-
return ResponseInstruction::NoResponse;
10641-
}
10642-
}
10643-
10644-
let features = self.bolt12_invoice_features();
10645-
if invoice.invoice_features().requires_unknown_bits_from(&features) {
10646-
Err(InvoiceError::from(Bolt12SemanticError::UnknownRequiredFeatures))
10647-
} else if self.default_configuration.manually_handle_bolt12_invoices {
10648-
let event = Event::InvoiceReceived { payment_id, invoice, responder };
10649-
self.pending_events.lock().unwrap().push_back((event, None));
10650-
return ResponseInstruction::NoResponse;
10636+
let (invoice, payment_id) = match payer_data {
10637+
Some((payment_id, nonce)) => {
10638+
if invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx) {
10639+
(invoice, payment_id)
1065110640
} else {
10652-
self.send_payment_for_verified_bolt12_invoice(&invoice, payment_id)
10653-
.map_err(|e| {
10654-
log_trace!(logger, "Failed paying invoice: {:?}", e);
10655-
InvoiceError::from_string(format!("{:?}", e))
10656-
})
10641+
return ResponseInstruction::NoResponse;
1065710642
}
1065810643
},
10659-
Err(()) => return ResponseInstruction::NoResponse,
10644+
None => match invoice.verify(expanded_key, secp_ctx) {
10645+
Ok(payment_id) => (invoice, payment_id),
10646+
Err(()) => return ResponseInstruction::NoResponse,
10647+
},
10648+
};
10649+
10650+
let result = {
10651+
let features = self.bolt12_invoice_features();
10652+
if invoice.invoice_features().requires_unknown_bits_from(&features) {
10653+
Err(InvoiceError::from(Bolt12SemanticError::UnknownRequiredFeatures))
10654+
} else if self.default_configuration.manually_handle_bolt12_invoices {
10655+
let event = Event::InvoiceReceived { payment_id, invoice, responder };
10656+
self.pending_events.lock().unwrap().push_back((event, None));
10657+
return ResponseInstruction::NoResponse;
10658+
} else {
10659+
self.send_payment_for_verified_bolt12_invoice(&invoice, payment_id)
10660+
.map_err(|e| {
10661+
log_trace!(logger, "Failed paying invoice: {:?}", e);
10662+
InvoiceError::from_string(format!("{:?}", e))
10663+
})
10664+
}
1066010665
};
1066110666

1066210667
match result {

0 commit comments

Comments
 (0)