Skip to content

Commit df32198

Browse files
committed
Update InvoiceBuilder's amount_msats
1. The amount_msats function first checks if any amount is given with the invoice requests, and defaults to using offer's amount if it's absent. 2. This can be a problem if the amount in offer was represent as a Currency. 3. Update amount_msats to take in an optional custom amount which can be used in case amount if absent in Invoice Request. 4. This update will be utilised in the following commits to set custom amount_msats when responding to Invoice Request Asychronously.
1 parent fdf8a3e commit df32198

File tree

5 files changed

+36
-25
lines changed

5 files changed

+36
-25
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11082,7 +11082,7 @@ where
1108211082
};
1108311083

1108411084
let amount_msats = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(
11085-
&invoice_request.inner
11085+
&invoice_request.inner, None
1108611086
) {
1108711087
Ok(amount_msats) => amount_msats,
1108811088
Err(error) => return Some((OffersMessage::InvoiceError(error.into()), responder.respond())),
@@ -11121,11 +11121,11 @@ where
1112111121
let response = if invoice_request.keys.is_some() {
1112211122
#[cfg(feature = "std")]
1112311123
let builder = invoice_request.respond_using_derived_keys(
11124-
payment_paths, payment_hash
11124+
payment_paths, payment_hash, None
1112511125
);
1112611126
#[cfg(not(feature = "std"))]
1112711127
let builder = invoice_request.respond_using_derived_keys_no_std(
11128-
payment_paths, payment_hash, created_at
11128+
payment_paths, payment_hash, created_at, None
1112911129
);
1113011130
builder
1113111131
.map(InvoiceBuilder::<DerivedSigningPubkey>::from)

lightning/src/ln/offers_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2223,7 +2223,7 @@ fn fails_paying_invoice_with_unknown_required_features() {
22232223
let created_at = alice.node.duration_since_epoch();
22242224
let invoice = invoice_request
22252225
.verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).unwrap()
2226-
.respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at).unwrap()
2226+
.respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at, None).unwrap()
22272227
.features_unchecked(Bolt12InvoiceFeatures::unknown())
22282228
.build_and_sign(&secp_ctx).unwrap();
22292229

lightning/src/ln/outbound_payment.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ impl OutboundPayments {
10171017
abandon_with_entry!(entry, PaymentFailureReason::UnknownRequiredFeatures);
10181018
return Err(Bolt12PaymentError::UnknownRequiredFeatures)
10191019
}
1020-
let amount_msat = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(invreq) {
1020+
let amount_msat = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(invreq, None) {
10211021
Ok(amt) => amt,
10221022
Err(_) => {
10231023
// We check this during invoice request parsing, when constructing the invreq's

lightning/src/offers/invoice.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $s
216216
invoice_request: &'a InvoiceRequest, payment_paths: Vec<BlindedPaymentPath>,
217217
created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey
218218
) -> Result<Self, Bolt12SemanticError> {
219-
let amount_msats = Self::amount_msats(invoice_request)?;
219+
let amount_msats = Self::amount_msats(invoice_request, None)?;
220220
let contents = InvoiceContents::ForOffer {
221221
invoice_request: invoice_request.contents.clone(),
222222
fields: Self::fields(
@@ -272,9 +272,9 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $se
272272
#[cfg_attr(c_bindings, allow(dead_code))]
273273
pub(super) fn for_offer_using_keys(
274274
invoice_request: &'a InvoiceRequest, payment_paths: Vec<BlindedPaymentPath>,
275-
created_at: Duration, payment_hash: PaymentHash, keys: Keypair
275+
created_at: Duration, payment_hash: PaymentHash, keys: Keypair, custom_amount_msats: Option<u64>
276276
) -> Result<Self, Bolt12SemanticError> {
277-
let amount_msats = Self::amount_msats(invoice_request)?;
277+
let amount_msats = Self::amount_msats(invoice_request, custom_amount_msats)?;
278278
let signing_pubkey = keys.public_key();
279279
let contents = InvoiceContents::ForOffer {
280280
invoice_request: invoice_request.contents.clone(),
@@ -340,18 +340,29 @@ macro_rules! invoice_builder_methods { (
340340
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $type_param: ty $(, $self_mut: tt)?
341341
) => {
342342
pub(crate) fn amount_msats(
343-
invoice_request: &InvoiceRequest
343+
invoice_request: &InvoiceRequest, custom_amount_msats: Option<u64>
344344
) -> Result<u64, Bolt12SemanticError> {
345-
match invoice_request.amount_msats() {
346-
Some(amount_msats) => Ok(amount_msats),
347-
None => match invoice_request.contents.inner.offer.amount() {
348-
Some(Amount::Bitcoin { amount_msats }) => {
349-
amount_msats.checked_mul(invoice_request.quantity().unwrap_or(1))
350-
.ok_or(Bolt12SemanticError::InvalidAmount)
351-
},
352-
Some(Amount::Currency { .. }) => Err(Bolt12SemanticError::UnsupportedCurrency),
353-
None => Err(Bolt12SemanticError::MissingAmount),
354-
},
345+
if invoice_request.amount_msats().is_some() && custom_amount_msats.is_some() {
346+
return Err(Bolt12SemanticError::UnexpectedAmount);
347+
}
348+
349+
if let Some(amount_msats) = invoice_request.amount_msats() {
350+
return Ok(amount_msats);
351+
}
352+
353+
if let Some(custom_amount_msats) = custom_amount_msats {
354+
return Ok(custom_amount_msats);
355+
}
356+
357+
match invoice_request.contents.inner.offer.amount() {
358+
Some(Amount::Bitcoin { amount_msats }) => {
359+
let quantity = invoice_request.quantity().unwrap_or(1);
360+
amount_msats
361+
.checked_mul(quantity)
362+
.ok_or(Bolt12SemanticError::InvalidAmount)
363+
}
364+
Some(Amount::Currency { .. }) => Err(Bolt12SemanticError::UnsupportedCurrency),
365+
None => Err(Bolt12SemanticError::MissingAmount),
355366
}
356367
}
357368

@@ -1820,7 +1831,7 @@ mod tests {
18201831

18211832
if let Err(e) = invoice_request.clone()
18221833
.verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).unwrap()
1823-
.respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()).unwrap()
1834+
.respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now(), None).unwrap()
18241835
.build_and_sign(&secp_ctx)
18251836
{
18261837
panic!("error building invoice: {:?}", e);
@@ -1841,7 +1852,7 @@ mod tests {
18411852

18421853
match invoice_request
18431854
.verify_using_metadata(&expanded_key, &secp_ctx).unwrap()
1844-
.respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now())
1855+
.respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now(), None)
18451856
{
18461857
Ok(_) => panic!("expected error"),
18471858
Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidMetadata),

lightning/src/offers/invoice_request.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -883,13 +883,13 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
883883
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
884884
#[cfg(feature = "std")]
885885
pub fn respond_using_derived_keys(
886-
&$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash
886+
&$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash, custom_amount_msats: Option<u64>
887887
) -> Result<$builder, Bolt12SemanticError> {
888888
let created_at = std::time::SystemTime::now()
889889
.duration_since(std::time::SystemTime::UNIX_EPOCH)
890890
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
891891

892-
$self.respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at)
892+
$self.respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at, custom_amount_msats)
893893
}
894894

895895
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
@@ -901,7 +901,7 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
901901
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
902902
pub fn respond_using_derived_keys_no_std(
903903
&$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
904-
created_at: core::time::Duration
904+
created_at: core::time::Duration, custom_amount_msats: Option<u64>
905905
) -> Result<$builder, Bolt12SemanticError> {
906906
if $self.inner.invoice_request_features().requires_unknown_bits() {
907907
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
@@ -918,7 +918,7 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
918918
}
919919

920920
<$builder>::for_offer_using_keys(
921-
&$self.inner, payment_paths, created_at, payment_hash, keys
921+
&$self.inner, payment_paths, created_at, payment_hash, keys, custom_amount_msats
922922
)
923923
}
924924
} }

0 commit comments

Comments
 (0)