Skip to content

Commit eaa5916

Browse files
committed
Introduce send_invoice_request_response
1 parent 37f7bec commit eaa5916

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4463,6 +4463,91 @@ where
44634463
}
44644464
}
44654465

4466+
/// Sends a response for a received [`InvoiceRequest`].
4467+
///
4468+
/// The received [`InvoiceRequest`] is first verified to ensure it was created for an
4469+
/// offer corresponding to the given expanded key. After authentication, the appropriate
4470+
/// builders are called to generate the response.
4471+
///
4472+
/// Response generation may result in errors in a few cases:
4473+
///
4474+
/// - If there are semantic issues with the received messages, a
4475+
/// [`Bolt12ResponseError::SemanticError`] is generated, for which a corresponding
4476+
/// [`InvoiceError`] is created.
4477+
///
4478+
/// - If verification of the received [`InvoiceRequest`] fails, a
4479+
/// [`Bolt12ResponseError::VerificationError`] is generated. In this case, no
4480+
/// [`InvoiceError`] is created to prevent probing attacks by potential attackers.
4481+
///
4482+
/// ## Custom Amount:
4483+
/// The received [`InvoiceRequest`] might not contain the corresponding amount.
4484+
/// In such cases, the user may provide their custom amount in millisatoshis (msats).
4485+
/// If the user chooses not to, the builder defaults to using the amount specified in the Offers.
4486+
///
4487+
/// However, if the received [`InvoiceRequest`] does contain an amount, a custom amount must
4488+
/// not be provided. Doing so will result in a [`Bolt12ResponseError::UnexpectedAmount`].
4489+
///
4490+
/// ## Currency:
4491+
/// The corresponding [`Offer`] for the received [`InvoiceRequest`] might be denominated
4492+
/// in [`Amount::Currency`].
4493+
/// If that is the case, the user must ensure the following:
4494+
///
4495+
/// - If the `InvoiceRequest` contains an amount (denominated in [`Amount::Bitcoin`]),
4496+
/// it should be checked that it appropriately pays for the amount and quantity specified
4497+
/// within the corresponding [`Offer`].
4498+
///
4499+
/// - If the `InvoiceRequest` does not contain an amount, an appropriate custom amount
4500+
/// should be provided to create the corresponding [`Bolt12Invoice`] for the response.
4501+
///
4502+
/// To retry, the user can reuse the same [`InvoiceRequest`] to generate the appropriate
4503+
/// response.
4504+
///
4505+
/// [`Amount::Bitcoin`]: crate::offers::offer::Amount::Bitcoin
4506+
/// [`Amount::Currency`]: crate::offers::offer::Amount::Currency
4507+
pub fn send_invoice_request_response(
4508+
&self, invoice_request: InvoiceRequest, context: Option<OffersContext>,
4509+
custom_amount_msat: Option<u64>, responder: Responder
4510+
) -> Result<(), Bolt12ResponseError> {
4511+
let result = self.get_response_for_invoice_request(invoice_request, context, custom_amount_msat);
4512+
let mut pending_offers_message = self.pending_offers_messages.lock().unwrap();
4513+
4514+
match result {
4515+
Ok((response, payment_hash)) => {
4516+
match response {
4517+
OffersMessage::Invoice(invoice) => {
4518+
let nonce = Nonce::from_entropy_source(&*self.entropy_source);
4519+
let hmac = payment_hash.hmac_for_offer_payment(nonce, &self.inbound_payment_key);
4520+
let context = MessageContext::Offers(OffersContext::InboundPayment { payment_hash: invoice.payment_hash(), nonce, hmac });
4521+
let instructions = responder.respond_with_reply_path(context).into_instructions();
4522+
let message = OffersMessage::Invoice(invoice);
4523+
4524+
pending_offers_message.push((message, instructions))
4525+
},
4526+
_ => {
4527+
let instructions = responder.respond().into_instructions();
4528+
4529+
pending_offers_message.push((response, instructions))
4530+
}
4531+
}
4532+
}
4533+
Err(error) => {
4534+
match error {
4535+
Bolt12ResponseError::SemanticError(error) => {
4536+
let invoice_error = InvoiceError::from(error);
4537+
let message = OffersMessage::InvoiceError(invoice_error);
4538+
4539+
let instructions = responder.respond().into_instructions();
4540+
4541+
pending_offers_message.push((message, instructions))
4542+
}
4543+
_ => return Err(error),
4544+
}
4545+
}
4546+
};
4547+
4548+
Ok(())
4549+
}
4550+
44664551
#[cfg(async_payments)]
44674552
fn initiate_async_payment(
44684553
&self, invoice: &StaticInvoice, payment_id: PaymentId

lightning/src/onion_message/messenger.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ pub struct ResponseInstruction {
394394
}
395395

396396
impl ResponseInstruction {
397-
fn into_instructions(self) -> MessageSendInstructions {
397+
pub(crate) fn into_instructions(self) -> MessageSendInstructions {
398398
MessageSendInstructions::ForReply { instructions: self }
399399
}
400400
}

0 commit comments

Comments
 (0)