@@ -65,7 +65,7 @@ use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutb
65
65
use crate::ln::wire::Encode;
66
66
use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
67
67
use crate::offers::invoice_error::InvoiceError;
68
- use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequest, InvoiceRequestBuilder};
68
+ use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequest, InvoiceRequestBuilder, VerifiedInvoiceRequest };
69
69
use crate::offers::nonce::Nonce;
70
70
use crate::offers::offer::{Offer, OfferBuilder};
71
71
use crate::offers::parse::Bolt12SemanticError;
@@ -4358,6 +4358,111 @@ where
4358
4358
)
4359
4359
}
4360
4360
4361
+ fn get_response_for_invoice_request(&self, invoice_request: InvoiceRequest, context: Option<OffersContext>, custom_amount_msats: Option<u64>) -> Result<(OffersMessage, PaymentHash), Bolt12ResponseError> {
4362
+ let secp_ctx = &self.secp_ctx;
4363
+ let expanded_key = &self.inbound_payment_key;
4364
+
4365
+ // Make sure that invoice_request amount and custom amount are not present at the same time.
4366
+ if invoice_request.amount().is_some() && custom_amount_msats.is_some() {
4367
+ return Err(Bolt12ResponseError::UnexpectedAmount)
4368
+ }
4369
+
4370
+ let nonce = match context {
4371
+ None if invoice_request.metadata().is_some() => None,
4372
+ Some(OffersContext::InvoiceRequest { nonce }) => Some(nonce),
4373
+ _ => return Err(Bolt12ResponseError::VerificationError),
4374
+ };
4375
+
4376
+ let invoice_request = match nonce {
4377
+ Some(nonce) => match invoice_request.verify_using_recipient_data(
4378
+ nonce, expanded_key, secp_ctx,
4379
+ ) {
4380
+ Ok(invoice_request) => invoice_request,
4381
+ Err(()) => return Err(Bolt12ResponseError::VerificationError),
4382
+ },
4383
+ None => match invoice_request.verify_using_metadata(expanded_key, secp_ctx) {
4384
+ Ok(invoice_request) => invoice_request,
4385
+ Err(()) => return Err(Bolt12ResponseError::VerificationError),
4386
+ },
4387
+ };
4388
+
4389
+ self.get_response_for_verified_invoice_request(&invoice_request, custom_amount_msats)
4390
+ }
4391
+
4392
+ fn get_response_for_verified_invoice_request(&self, invoice_request: &VerifiedInvoiceRequest, custom_amount_msats: Option<u64>) -> Result<(OffersMessage, PaymentHash), Bolt12ResponseError> {
4393
+ let amount_msats = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(
4394
+ &invoice_request.inner, custom_amount_msats
4395
+ ) {
4396
+ Ok(amount_msats) => amount_msats,
4397
+ Err(error) => return Err(Bolt12ResponseError::SemanticError(error)),
4398
+ };
4399
+
4400
+ let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
4401
+
4402
+ let (payment_hash, payment_secret) = match self.create_inbound_payment(
4403
+ Some(amount_msats), relative_expiry, None
4404
+ ) {
4405
+ Ok((payment_hash, payment_secret)) => (payment_hash, payment_secret),
4406
+ Err(()) => return Err(Bolt12ResponseError::SemanticError(Bolt12SemanticError::InvalidAmount)),
4407
+ };
4408
+
4409
+ let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext {
4410
+ offer_id: invoice_request.offer_id,
4411
+ invoice_request: invoice_request.fields(),
4412
+ });
4413
+ let payment_paths = match self.create_blinded_payment_paths(
4414
+ amount_msats, payment_secret, payment_context
4415
+ ) {
4416
+ Ok(payment_paths) => payment_paths,
4417
+ Err(()) => return Err(Bolt12ResponseError::SemanticError(Bolt12SemanticError::MissingPaths)),
4418
+ };
4419
+
4420
+ #[cfg(not(feature = "std"))]
4421
+ let created_at = Duration::from_secs(
4422
+ self.highest_seen_timestamp.load(Ordering::Acquire) as u64
4423
+ );
4424
+
4425
+ let result = if invoice_request.keys.is_some() {
4426
+ #[cfg(feature = "std")]
4427
+ let builder = invoice_request.respond_using_derived_keys(
4428
+ payment_paths, payment_hash, custom_amount_msats
4429
+ );
4430
+ #[cfg(not(feature = "std"))]
4431
+ let builder = invoice_request.respond_using_derived_keys_no_std(
4432
+ payment_paths, payment_hash, created_at
4433
+ );
4434
+ builder
4435
+ .map(InvoiceBuilder::<DerivedSigningPubkey>::from)
4436
+ .and_then(|builder| builder.allow_mpp().build_and_sign(&self.secp_ctx))
4437
+ .map_err(InvoiceError::from)
4438
+ } else {
4439
+ #[cfg(feature = "std")]
4440
+ let builder = invoice_request.respond_with(payment_paths, payment_hash);
4441
+ #[cfg(not(feature = "std"))]
4442
+ let builder = invoice_request.respond_with_no_std(
4443
+ payment_paths, payment_hash, created_at
4444
+ );
4445
+ builder
4446
+ .map(InvoiceBuilder::<ExplicitSigningPubkey>::from)
4447
+ .and_then(|builder| builder.allow_mpp().build())
4448
+ .map_err(InvoiceError::from)
4449
+ .and_then(|invoice| {
4450
+ #[cfg(c_bindings)]
4451
+ let mut invoice = invoice;
4452
+ invoice
4453
+ .sign(|invoice: &UnsignedBolt12Invoice|
4454
+ self.node_signer.sign_bolt12_invoice(invoice)
4455
+ )
4456
+ .map_err(InvoiceError::from)
4457
+ })
4458
+ };
4459
+
4460
+ match result {
4461
+ Ok(invoice) => Ok((OffersMessage::Invoice(invoice), payment_hash)),
4462
+ Err(error) => Ok((OffersMessage::InvoiceError(error), payment_hash)),
4463
+ }
4464
+ }
4465
+
4361
4466
#[cfg(async_payments)]
4362
4467
fn initiate_async_payment(
4363
4468
&self, invoice: &StaticInvoice, payment_id: PaymentId
@@ -11081,86 +11186,26 @@ where
11081
11186
},
11082
11187
};
11083
11188
11084
- let amount_msats = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(
11085
- &invoice_request.inner, None
11086
- ) {
11087
- Ok(amount_msats) => amount_msats,
11088
- Err(error) => return Some((OffersMessage::InvoiceError(error.into()), responder.respond())),
11089
- };
11090
-
11091
- let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
11092
- let (payment_hash, payment_secret) = match self.create_inbound_payment(
11093
- Some(amount_msats), relative_expiry, None
11094
- ) {
11095
- Ok((payment_hash, payment_secret)) => (payment_hash, payment_secret),
11096
- Err(()) => {
11097
- let error = Bolt12SemanticError::InvalidAmount;
11098
- return Some((OffersMessage::InvoiceError(error.into()), responder.respond()));
11099
- },
11100
- };
11101
-
11102
- let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext {
11103
- offer_id: invoice_request.offer_id,
11104
- invoice_request: invoice_request.fields(),
11105
- });
11106
- let payment_paths = match self.create_blinded_payment_paths(
11107
- amount_msats, payment_secret, payment_context
11108
- ) {
11109
- Ok(payment_paths) => payment_paths,
11110
- Err(()) => {
11111
- let error = Bolt12SemanticError::MissingPaths;
11112
- return Some((OffersMessage::InvoiceError(error.into()), responder.respond()));
11113
- },
11114
- };
11115
-
11116
- #[cfg(not(feature = "std"))]
11117
- let created_at = Duration::from_secs(
11118
- self.highest_seen_timestamp.load(Ordering::Acquire) as u64
11119
- );
11120
-
11121
- let response = if invoice_request.keys.is_some() {
11122
- #[cfg(feature = "std")]
11123
- let builder = invoice_request.respond_using_derived_keys(
11124
- payment_paths, payment_hash, None
11125
- );
11126
- #[cfg(not(feature = "std"))]
11127
- let builder = invoice_request.respond_using_derived_keys_no_std(
11128
- payment_paths, payment_hash, created_at
11129
- );
11130
- builder
11131
- .map(InvoiceBuilder::<DerivedSigningPubkey>::from)
11132
- .and_then(|builder| builder.allow_mpp().build_and_sign(secp_ctx))
11133
- .map_err(InvoiceError::from)
11134
- } else {
11135
- #[cfg(feature = "std")]
11136
- let builder = invoice_request.respond_with(payment_paths, payment_hash);
11137
- #[cfg(not(feature = "std"))]
11138
- let builder = invoice_request.respond_with_no_std(
11139
- payment_paths, payment_hash, created_at
11140
- );
11141
- builder
11142
- .map(InvoiceBuilder::<ExplicitSigningPubkey>::from)
11143
- .and_then(|builder| builder.allow_mpp().build())
11144
- .map_err(InvoiceError::from)
11145
- .and_then(|invoice| {
11146
- #[cfg(c_bindings)]
11147
- let mut invoice = invoice;
11148
- invoice
11149
- .sign(|invoice: &UnsignedBolt12Invoice|
11150
- self.node_signer.sign_bolt12_invoice(invoice)
11151
- )
11152
- .map_err(InvoiceError::from)
11153
- })
11154
- };
11155
-
11156
- match response {
11157
- Ok(invoice) => {
11158
- let nonce = Nonce::from_entropy_source(&*self.entropy_source);
11159
- let hmac = payment_hash.hmac_for_offer_payment(nonce, expanded_key);
11160
- let context = MessageContext::Offers(OffersContext::InboundPayment { payment_hash, nonce, hmac });
11161
- Some((OffersMessage::Invoice(invoice), responder.respond_with_reply_path(context)))
11162
- },
11163
- Err(error) => Some((OffersMessage::InvoiceError(error.into()), responder.respond())),
11189
+ match self.get_response_for_verified_invoice_request(&invoice_request, None) {
11190
+ Ok((response, payment_hash)) => {
11191
+ match response {
11192
+ OffersMessage::Invoice(invoice) => {
11193
+ let nonce = Nonce::from_entropy_source(&*self.entropy_source);
11194
+ let hmac = payment_hash.hmac_for_offer_payment(nonce, expanded_key);
11195
+ let context = MessageContext::Offers(OffersContext::InboundPayment { payment_hash, nonce, hmac });
11196
+ Some((OffersMessage::Invoice(invoice), responder.respond_with_reply_path(context)))
11197
+ }
11198
+ OffersMessage::InvoiceError(error) => {
11199
+ Some((OffersMessage::InvoiceError(error), responder.respond()))
11200
+ }
11201
+ OffersMessage::InvoiceRequest(_) => {
11202
+ debug_assert!(false, "Shouldn't have received InvoiceRequest here.");
11203
+ None
11204
+ }
11205
+ }
11206
+ }
11207
+ Err(Bolt12ResponseError::SemanticError(error)) => Some((OffersMessage::InvoiceError(error.into()), responder.respond())),
11208
+ Err(_) => None,
11164
11209
}
11165
11210
},
11166
11211
OffersMessage::Invoice(invoice) => {
0 commit comments