Skip to content

Commit cc50f8d

Browse files
committed
Add InvoiceRequestTlvStream::paths
Instead of reusing OfferTlvStream::paths, add a dedicated paths TLV to InvoiceRequestTlvStream such that it can be used in Refund. This allows for an Offer without a signing_pubkey and still be able to differentiate whether an invoice is for an offer or a refund.
1 parent d2b1fb1 commit cc50f8d

File tree

4 files changed

+36
-14
lines changed

4 files changed

+36
-14
lines changed

lightning/src/offers/invoice.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,7 @@ mod tests {
16321632
quantity: None,
16331633
payer_id: Some(&payer_pubkey()),
16341634
payer_note: None,
1635+
paths: None,
16351636
},
16361637
InvoiceTlvStreamRef {
16371638
paths: Some(Iterable(payment_paths.iter().map(|(_, path)| path))),
@@ -1724,6 +1725,7 @@ mod tests {
17241725
quantity: None,
17251726
payer_id: Some(&payer_pubkey()),
17261727
payer_note: None,
1728+
paths: None,
17271729
},
17281730
InvoiceTlvStreamRef {
17291731
paths: Some(Iterable(payment_paths.iter().map(|(_, path)| path))),

lightning/src/offers/invoice_request.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,7 @@ impl InvoiceRequestContentsWithoutPayerId {
977977
quantity: self.quantity,
978978
payer_id: None,
979979
payer_note: self.payer_note.as_ref(),
980+
paths: None,
980981
};
981982

982983
(payer, offer, invoice_request)
@@ -1016,6 +1017,7 @@ tlv_stream!(InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef, INVOICE_REQUEST
10161017
(86, quantity: (u64, HighZeroBytesDroppedBigSize)),
10171018
(INVOICE_REQUEST_PAYER_ID_TYPE, payer_id: PublicKey),
10181019
(89, payer_note: (String, WithoutLength)),
1020+
(90, paths: (Vec<BlindedPath>, WithoutLength)),
10191021
});
10201022

10211023
type FullInvoiceRequestTlvStream =
@@ -1098,7 +1100,9 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
10981100
let (
10991101
PayerTlvStream { metadata },
11001102
offer_tlv_stream,
1101-
InvoiceRequestTlvStream { chain, amount, features, quantity, payer_id, payer_note },
1103+
InvoiceRequestTlvStream {
1104+
chain, amount, features, quantity, payer_id, payer_note, paths,
1105+
},
11021106
) = tlv_stream;
11031107

11041108
let payer = match metadata {
@@ -1125,6 +1129,10 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
11251129
Some(payer_id) => payer_id,
11261130
};
11271131

1132+
if paths.is_some() {
1133+
return Err(Bolt12SemanticError::UnexpectedPaths);
1134+
}
1135+
11281136
Ok(InvoiceRequestContents {
11291137
inner: InvoiceRequestContentsWithoutPayerId {
11301138
payer, offer, chain, amount_msats: amount, features, quantity, payer_note,
@@ -1316,6 +1324,7 @@ mod tests {
13161324
quantity: None,
13171325
payer_id: Some(&payer_pubkey()),
13181326
payer_note: None,
1327+
paths: None,
13191328
},
13201329
SignatureTlvStreamRef { signature: Some(&invoice_request.signature()) },
13211330
),

lightning/src/offers/parse.rs

+2
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ pub enum Bolt12SemanticError {
183183
DuplicatePaymentId,
184184
/// Blinded paths were expected but were missing.
185185
MissingPaths,
186+
/// Blinded paths were provided but were not expected.
187+
UnexpectedPaths,
186188
/// The blinded payinfo given does not match the number of blinded path hops.
187189
InvalidPayInfo,
188190
/// An invoice creation time was expected but was missing.

lightning/src/offers/refund.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ macro_rules! refund_explicit_metadata_builder_methods { () => {
170170
Ok(Self {
171171
refund: RefundContents {
172172
payer: PayerContents(metadata), description, absolute_expiry: None, issuer: None,
173-
paths: None, chain: None, amount_msats, features: InvoiceRequestFeatures::empty(),
174-
quantity: None, payer_id, payer_note: None,
173+
chain: None, amount_msats, features: InvoiceRequestFeatures::empty(),
174+
quantity: None, payer_id, payer_note: None, paths: None,
175175
},
176176
secp_ctx: None,
177177
})
@@ -209,8 +209,8 @@ macro_rules! refund_builder_methods { (
209209
Ok(Self {
210210
refund: RefundContents {
211211
payer: PayerContents(metadata), description, absolute_expiry: None, issuer: None,
212-
paths: None, chain: None, amount_msats, features: InvoiceRequestFeatures::empty(),
213-
quantity: None, payer_id: node_id, payer_note: None,
212+
chain: None, amount_msats, features: InvoiceRequestFeatures::empty(),
213+
quantity: None, payer_id: node_id, payer_note: None, paths: None,
214214
},
215215
secp_ctx: Some(secp_ctx),
216216
})
@@ -410,14 +410,14 @@ pub(super) struct RefundContents {
410410
description: String,
411411
absolute_expiry: Option<Duration>,
412412
issuer: Option<String>,
413-
paths: Option<Vec<BlindedPath>>,
414413
// invoice_request fields
415414
chain: Option<ChainHash>,
416415
amount_msats: u64,
417416
features: InvoiceRequestFeatures,
418417
quantity: Option<u64>,
419418
payer_id: PublicKey,
420419
payer_note: Option<String>,
420+
paths: Option<Vec<BlindedPath>>,
421421
}
422422

423423
impl Refund {
@@ -734,7 +734,7 @@ impl RefundContents {
734734
description: Some(&self.description),
735735
features: None,
736736
absolute_expiry: self.absolute_expiry.map(|duration| duration.as_secs()),
737-
paths: self.paths.as_ref(),
737+
paths: None,
738738
issuer: self.issuer.as_ref(),
739739
quantity_max: None,
740740
node_id: None,
@@ -752,6 +752,7 @@ impl RefundContents {
752752
quantity: self.quantity,
753753
payer_id: Some(&self.payer_id),
754754
payer_note: self.payer_note.as_ref(),
755+
paths: self.paths.as_ref(),
755756
};
756757

757758
(payer, offer, invoice_request)
@@ -820,9 +821,12 @@ impl TryFrom<RefundTlvStream> for RefundContents {
820821
PayerTlvStream { metadata: payer_metadata },
821822
OfferTlvStream {
822823
chains, metadata, currency, amount: offer_amount, description,
823-
features: offer_features, absolute_expiry, paths, issuer, quantity_max, node_id,
824+
features: offer_features, absolute_expiry, paths: offer_paths, issuer, quantity_max,
825+
node_id,
826+
},
827+
InvoiceRequestTlvStream {
828+
chain, amount, features, quantity, payer_id, payer_note, paths
824829
},
825-
InvoiceRequestTlvStream { chain, amount, features, quantity, payer_id, payer_note },
826830
) = tlv_stream;
827831

828832
let payer = match payer_metadata {
@@ -853,6 +857,10 @@ impl TryFrom<RefundTlvStream> for RefundContents {
853857

854858
let absolute_expiry = absolute_expiry.map(Duration::from_secs);
855859

860+
if offer_paths.is_some() {
861+
return Err(Bolt12SemanticError::UnexpectedPaths);
862+
}
863+
856864
if quantity_max.is_some() {
857865
return Err(Bolt12SemanticError::UnexpectedQuantity);
858866
}
@@ -877,8 +885,8 @@ impl TryFrom<RefundTlvStream> for RefundContents {
877885
};
878886

879887
Ok(RefundContents {
880-
payer, description, absolute_expiry, issuer, paths, chain, amount_msats, features,
881-
quantity, payer_id, payer_note,
888+
payer, description, absolute_expiry, issuer, chain, amount_msats, features, quantity,
889+
payer_id, payer_note, paths,
882890
})
883891
}
884892
}
@@ -980,6 +988,7 @@ mod tests {
980988
quantity: None,
981989
payer_id: Some(&payer_pubkey()),
982990
payer_note: None,
991+
paths: None,
983992
},
984993
),
985994
);
@@ -1173,12 +1182,12 @@ mod tests {
11731182
.path(paths[1].clone())
11741183
.build()
11751184
.unwrap();
1176-
let (_, offer_tlv_stream, invoice_request_tlv_stream) = refund.as_tlv_stream();
1177-
assert_eq!(refund.paths(), paths.as_slice());
1185+
let (_, _, invoice_request_tlv_stream) = refund.as_tlv_stream();
11781186
assert_eq!(refund.payer_id(), pubkey(42));
1187+
assert_eq!(refund.paths(), paths.as_slice());
11791188
assert_ne!(pubkey(42), pubkey(44));
1180-
assert_eq!(offer_tlv_stream.paths, Some(&paths));
11811189
assert_eq!(invoice_request_tlv_stream.payer_id, Some(&pubkey(42)));
1190+
assert_eq!(invoice_request_tlv_stream.paths, Some(&paths));
11821191
}
11831192

11841193
#[test]

0 commit comments

Comments
 (0)