Skip to content

Commit 004b885

Browse files
committed
Include InvoiceRequest fields to PaymentContext
When receiving a payment, it's useful to know information about the InvoiceRequest. Include this data in PaymentContext::Bolt12Offer so users can display information about an inbound payment (e.g., the payer note).
1 parent 092632a commit 004b885

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

lightning/src/blinded_path/payment.rs

+8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::ln::channelmanager::CounterpartyForwardingInfo;
1212
use crate::ln::features::BlindedHopFeatures;
1313
use crate::ln::msgs::DecodeError;
1414
use crate::offers::invoice::BlindedPayInfo;
15+
use crate::offers::invoice_request::InvoiceRequestFields;
1516
use crate::offers::offer::OfferId;
1617
use crate::prelude::*;
1718
use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, Writeable, Writer};
@@ -115,6 +116,12 @@ pub enum PaymentContext {
115116
///
116117
/// [`Offer`]: crate::offers::offer::Offer
117118
offer_id: OfferId,
119+
120+
/// Fields from an [`InvoiceRequest`] sent for a [`Bolt12Invoice`].
121+
///
122+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
123+
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
124+
invoice_request: InvoiceRequestFields,
118125
},
119126
/// The payment was made for invoice sent for a BOLT 12 [`Refund`].
120127
///
@@ -342,6 +349,7 @@ impl Readable for PaymentConstraints {
342349
impl_writeable_tlv_based_enum_upgradable!(PaymentContext,
343350
(0, Bolt12Offer) => {
344351
(0, offer_id, required),
352+
(2, invoice_request, required),
345353
},
346354
(2, Bolt12Refund) => {},
347355
);

lightning/src/ln/channelmanager.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9499,6 +9499,7 @@ where
94999499

95009500
let payment_context = PaymentContext::Bolt12Offer {
95019501
offer_id: invoice_request.offer_id,
9502+
invoice_request: invoice_request.fields(),
95029503
};
95039504
let payment_paths = match self.create_blinded_payment_paths(
95049505
amount_msats, payment_secret, Some(payment_context)

lightning/src/offers/invoice_request.rs

+80-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ use crate::offers::offer::{Offer, OfferContents, OfferId, OfferTlvStream, OfferT
7777
use crate::offers::parse::{Bolt12ParseError, ParsedMessage, Bolt12SemanticError};
7878
use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef};
7979
use crate::offers::signer::{Metadata, MetadataMaterial};
80-
use crate::util::ser::{HighZeroBytesDroppedBigSize, SeekReadable, WithoutLength, Writeable, Writer};
81-
use crate::util::string::PrintableString;
80+
use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, SeekReadable, WithoutLength, Writeable, Writer};
81+
use crate::util::string::{PrintableString, UntrustedString};
8282

8383
#[cfg(not(c_bindings))]
8484
use {
@@ -872,6 +872,24 @@ impl VerifiedInvoiceRequest {
872872
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<DerivedSigningPubkey>);
873873
#[cfg(c_bindings)]
874874
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceWithDerivedSigningPubkeyBuilder);
875+
876+
pub(crate) fn fields(&self) -> InvoiceRequestFields {
877+
let InvoiceRequestContents {
878+
payer_id,
879+
inner: InvoiceRequestContentsWithoutPayerId {
880+
payer: _, offer: _, chain, amount_msats, features, quantity, payer_note
881+
},
882+
} = &self.inner.contents;
883+
884+
InvoiceRequestFields {
885+
payer_id: *payer_id,
886+
chain: *chain,
887+
amount_msats: *amount_msats,
888+
features: features.clone(),
889+
quantity: *quantity,
890+
payer_note: payer_note.clone().map(|mut s| { s.truncate(512); UntrustedString(s) }),
891+
}
892+
}
875893
}
876894

877895
impl InvoiceRequestContents {
@@ -1100,6 +1118,66 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
11001118
}
11011119
}
11021120

1121+
/// Fields sent in an [`InvoiceRequest`] message to include in [`PaymentContext::Bolt12Offer`].
1122+
///
1123+
/// [`PaymentContext::Bolt12Offer`]: crate::blinded_path::payment::PaymentContext::Bolt12Offer
1124+
#[derive(Clone, Debug, Eq, PartialEq)]
1125+
pub struct InvoiceRequestFields {
1126+
/// A possibly transient pubkey used to sign the invoice request.
1127+
pub payer_id: PublicKey,
1128+
1129+
/// A chain from [`Offer::chains`] that the offer is valid for.
1130+
pub chain: Option<ChainHash>,
1131+
1132+
/// The amount to pay in msats (i.e., the minimum lightning-payable unit for [`chain`]), which
1133+
/// must be greater than or equal to [`Offer::amount`], converted if necessary.
1134+
///
1135+
/// [`chain`]: Self::chain
1136+
pub amount_msats: Option<u64>,
1137+
1138+
/// Features pertaining to requesting an invoice.
1139+
pub features: InvoiceRequestFeatures,
1140+
1141+
/// The quantity of the offer's item conforming to [`Offer::is_valid_quantity`].
1142+
pub quantity: Option<u64>,
1143+
1144+
/// A payer-provided note which will be seen by the recipient and reflected back in the invoice
1145+
/// response.
1146+
pub payer_note: Option<UntrustedString>,
1147+
}
1148+
1149+
impl Writeable for InvoiceRequestFields {
1150+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
1151+
write_tlv_fields!(writer, {
1152+
(0, self.payer_id, required),
1153+
(2, self.chain, option),
1154+
(4, self.amount_msats, option),
1155+
(6, WithoutLength(&self.features), required),
1156+
(8, self.quantity, option),
1157+
(10, self.payer_note, option),
1158+
});
1159+
Ok(())
1160+
}
1161+
}
1162+
1163+
impl Readable for InvoiceRequestFields {
1164+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
1165+
_init_and_read_len_prefixed_tlv_fields!(reader, {
1166+
(0, payer_id, required),
1167+
(2, chain, option),
1168+
(4, amount_msats, option),
1169+
(6, features, (option, encoding: (InvoiceRequestFeatures, WithoutLength))),
1170+
(8, quantity, option),
1171+
(10, payer_note, option),
1172+
});
1173+
let features = features.unwrap_or(InvoiceRequestFeatures::empty());
1174+
1175+
Ok(InvoiceRequestFields {
1176+
payer_id: payer_id.0.unwrap(), chain, amount_msats, features, quantity, payer_note
1177+
})
1178+
}
1179+
}
1180+
11031181
#[cfg(test)]
11041182
mod tests {
11051183
use super::{InvoiceRequest, InvoiceRequestTlvStreamRef, SIGNATURE_TAG, UnsignedInvoiceRequest};

0 commit comments

Comments
 (0)