Skip to content

Commit 37f7bec

Browse files
committed
Introduce get_response_for_invoice_request
1. Introduce a set of private functions that handles the creation of response for a received Invoice Request. 2. This helps refactor the the logic of response creation in a single function. 3. This will be used in the following commit to send response for invoice_request asynchronously.
1 parent 20eeb2a commit 37f7bec

File tree

1 file changed

+126
-81
lines changed

1 file changed

+126
-81
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 126 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutb
6565
use crate::ln::wire::Encode;
6666
use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
6767
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};
6969
use crate::offers::nonce::Nonce;
7070
use crate::offers::offer::{Offer, OfferBuilder};
7171
use crate::offers::parse::Bolt12SemanticError;
@@ -4358,6 +4358,111 @@ where
43584358
)
43594359
}
43604360

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+
43614466
#[cfg(async_payments)]
43624467
fn initiate_async_payment(
43634468
&self, invoice: &StaticInvoice, payment_id: PaymentId
@@ -11081,86 +11186,26 @@ where
1108111186
},
1108211187
};
1108311188

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,
1116411209
}
1116511210
},
1116611211
OffersMessage::Invoice(invoice) => {

0 commit comments

Comments
 (0)