Skip to content

Rename BOLT 12 message paths fields and methods #3118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions lightning/src/offers/invoice.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is Copyright its original authors, visible in version control
// This file is Copyright its original authors, visible in version control
// history.
//
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
Expand Down Expand Up @@ -690,8 +690,8 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
/// From [`Offer::paths`] or [`Refund::paths`].
///
/// [`Offer::paths`]: crate::offers::offer::Offer::paths
pub fn message_paths(&$self) -> &[BlindedPath] {
$contents.message_paths()
pub fn offer_request_paths(&$self) -> &[BlindedPath] {
$contents.offer_request_paths()
}

/// The quantity of items supported.
Expand Down Expand Up @@ -726,9 +726,9 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
}

/// A possibly transient pubkey used to sign the invoice request or to send an invoice for a
/// refund in case there are no [`message_paths`].
/// refund in case there are no [`offer_request_paths`].
///
/// [`message_paths`]: Self::message_paths
/// [`offer_request_paths`]: Self::offer_request_paths
pub fn payer_id(&$self) -> PublicKey {
$contents.payer_id()
}
Expand Down Expand Up @@ -891,7 +891,7 @@ impl InvoiceContents {
}
}

fn message_paths(&self) -> &[BlindedPath] {
fn offer_request_paths(&self) -> &[BlindedPath] {
match self {
InvoiceContents::ForOffer { invoice_request, .. } => {
invoice_request.inner.offer.paths()
Expand Down Expand Up @@ -1102,7 +1102,7 @@ impl InvoiceFields {
fallbacks: self.fallbacks.as_ref(),
features,
node_id: Some(&self.signing_pubkey),
message_paths: None,
invoice_message_paths: None,
}
}
}
Expand Down Expand Up @@ -1171,7 +1171,7 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
(174, features: (Bolt12InvoiceFeatures, WithoutLength)),
(176, node_id: PublicKey),
// Only present in `StaticInvoice`s.
(238, message_paths: (Vec<BlindedPath>, WithoutLength)),
(238, invoice_message_paths: (Vec<BlindedPath>, WithoutLength)),
});

pub(super) type BlindedPathIter<'a> = core::iter::Map<
Expand Down Expand Up @@ -1309,11 +1309,11 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
invoice_request_tlv_stream,
InvoiceTlvStream {
paths, blindedpay, created_at, relative_expiry, payment_hash, amount, fallbacks,
features, node_id, message_paths,
features, node_id, invoice_message_paths,
},
) = tlv_stream;

if message_paths.is_some() { return Err(Bolt12SemanticError::UnexpectedPaths) }
if invoice_message_paths.is_some() { return Err(Bolt12SemanticError::UnexpectedPaths) }

let payment_paths = construct_payment_paths(blindedpay, paths)?;

Expand Down Expand Up @@ -1475,7 +1475,7 @@ mod tests {
assert_eq!(unsigned_invoice.description(), Some(PrintableString("")));
assert_eq!(unsigned_invoice.offer_features(), Some(&OfferFeatures::empty()));
assert_eq!(unsigned_invoice.absolute_expiry(), None);
assert_eq!(unsigned_invoice.message_paths(), &[]);
assert_eq!(unsigned_invoice.offer_request_paths(), &[]);
assert_eq!(unsigned_invoice.issuer(), None);
assert_eq!(unsigned_invoice.supported_quantity(), Some(Quantity::One));
assert_eq!(unsigned_invoice.signing_pubkey(), recipient_pubkey());
Expand Down Expand Up @@ -1517,7 +1517,7 @@ mod tests {
assert_eq!(invoice.description(), Some(PrintableString("")));
assert_eq!(invoice.offer_features(), Some(&OfferFeatures::empty()));
assert_eq!(invoice.absolute_expiry(), None);
assert_eq!(invoice.message_paths(), &[]);
assert_eq!(invoice.offer_request_paths(), &[]);
assert_eq!(invoice.issuer(), None);
assert_eq!(invoice.supported_quantity(), Some(Quantity::One));
assert_eq!(invoice.signing_pubkey(), recipient_pubkey());
Expand Down Expand Up @@ -1580,7 +1580,7 @@ mod tests {
fallbacks: None,
features: None,
node_id: Some(&recipient_pubkey()),
message_paths: None,
invoice_message_paths: None,
},
SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
),
Expand Down Expand Up @@ -1614,7 +1614,7 @@ mod tests {
assert_eq!(invoice.description(), Some(PrintableString("")));
assert_eq!(invoice.offer_features(), None);
assert_eq!(invoice.absolute_expiry(), None);
assert_eq!(invoice.message_paths(), &[]);
assert_eq!(invoice.offer_request_paths(), &[]);
assert_eq!(invoice.issuer(), None);
assert_eq!(invoice.supported_quantity(), None);
assert_eq!(invoice.signing_pubkey(), recipient_pubkey());
Expand Down Expand Up @@ -1672,7 +1672,7 @@ mod tests {
fallbacks: None,
features: None,
node_id: Some(&recipient_pubkey()),
message_paths: None,
invoice_message_paths: None,
},
SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
),
Expand Down Expand Up @@ -2445,7 +2445,7 @@ mod tests {
}

#[test]
fn fails_parsing_invoice_with_message_paths() {
fn fails_parsing_invoice_with_invoice_message_paths() {
let invoice = OfferBuilder::new(recipient_pubkey())
.amount_msats(1000)
.build().unwrap()
Expand All @@ -2466,8 +2466,8 @@ mod tests {
};

let mut tlv_stream = invoice.as_tlv_stream();
let message_paths = vec![blinded_path];
tlv_stream.3.message_paths = Some(&message_paths);
let invoice_message_paths = vec![blinded_path];
tlv_stream.3.invoice_message_paths = Some(&invoice_message_paths);

match Bolt12Invoice::try_from(tlv_stream.to_bytes()) {
Ok(_) => panic!("expected error"),
Expand Down
57 changes: 31 additions & 26 deletions lightning/src/offers/static_invoice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ struct InvoiceContents {
fallbacks: Option<Vec<FallbackAddress>>,
features: Bolt12InvoiceFeatures,
signing_pubkey: PublicKey,
message_paths: Vec<BlindedPath>,
async_receive_paths: Vec<BlindedPath>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused, async_receive_paths imply to me that these are payment paths, but the old name was message_paths, should it be like async_awoken_notify_message_paths or something more verbose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notify_online_message_paths? @jkczyz any thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remind me what message will be sent over this path and who is sending it?

It's in the static invoice that the mailbox sends back to the payer. So the path is to the recipient through their mailbox, IIUC? notify_online seems to align more with the reply path that would be used?

}

/// Builds a [`StaticInvoice`] from an [`Offer`].
Expand All @@ -98,14 +98,14 @@ impl<'a> StaticInvoiceBuilder<'a> {
/// after `created_at`.
pub fn for_offer_using_derived_keys<T: secp256k1::Signing>(
offer: &'a Offer, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
message_paths: Vec<BlindedPath>, created_at: Duration, expanded_key: &ExpandedKey,
async_receive_paths: Vec<BlindedPath>, created_at: Duration, expanded_key: &ExpandedKey,
secp_ctx: &Secp256k1<T>,
) -> Result<Self, Bolt12SemanticError> {
if offer.chains().len() > 1 {
return Err(Bolt12SemanticError::UnexpectedChain);
}

if payment_paths.is_empty() || message_paths.is_empty() || offer.paths().is_empty() {
if payment_paths.is_empty() || async_receive_paths.is_empty() || offer.paths().is_empty() {
return Err(Bolt12SemanticError::MissingPaths);
}

Expand All @@ -123,8 +123,13 @@ impl<'a> StaticInvoiceBuilder<'a> {
return Err(Bolt12SemanticError::InvalidSigningPubkey);
}

let invoice =
InvoiceContents::new(offer, payment_paths, message_paths, created_at, signing_pubkey);
let invoice = InvoiceContents::new(
offer,
payment_paths,
async_receive_paths,
created_at,
signing_pubkey,
);

Ok(Self { offer_bytes: &offer.bytes, invoice, keys })
}
Expand Down Expand Up @@ -224,14 +229,14 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
/// publicly reachable nodes. Taken from [`Offer::paths`].
///
/// [`Offer::paths`]: crate::offers::offer::Offer::paths
pub fn offer_message_paths(&$self) -> &[BlindedPath] {
$contents.offer_message_paths()
pub fn offer_request_paths(&$self) -> &[BlindedPath] {
$contents.offer_request_paths()
}

/// Paths to the recipient for indicating that a held HTLC is available to claim when they next
/// come online.
pub fn message_paths(&$self) -> &[BlindedPath] {
$contents.message_paths()
pub fn async_receive_paths(&$self) -> &[BlindedPath] {
$contents.async_receive_paths()
}

/// The quantity of items supported, from [`Offer::supported_quantity`].
Expand Down Expand Up @@ -327,12 +332,12 @@ impl InvoiceContents {

fn new(
offer: &Offer, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
message_paths: Vec<BlindedPath>, created_at: Duration, signing_pubkey: PublicKey,
async_receive_paths: Vec<BlindedPath>, created_at: Duration, signing_pubkey: PublicKey,
) -> Self {
Self {
offer: offer.contents.clone(),
payment_paths,
message_paths,
async_receive_paths,
created_at,
relative_expiry: None,
fallbacks: None,
Expand All @@ -352,7 +357,7 @@ impl InvoiceContents {

let invoice = InvoiceTlvStreamRef {
paths: Some(Iterable(self.payment_paths.iter().map(|(_, path)| path))),
message_paths: Some(self.message_paths.as_ref()),
invoice_message_paths: Some(self.async_receive_paths.as_ref()),
blindedpay: Some(Iterable(self.payment_paths.iter().map(|(payinfo, _)| payinfo))),
created_at: Some(self.created_at.as_secs()),
relative_expiry: self.relative_expiry.map(|duration| duration.as_secs() as u32),
Expand Down Expand Up @@ -395,12 +400,12 @@ impl InvoiceContents {
self.offer.issuer()
}

fn offer_message_paths(&self) -> &[BlindedPath] {
fn offer_request_paths(&self) -> &[BlindedPath] {
self.offer.paths()
}

fn message_paths(&self) -> &[BlindedPath] {
&self.message_paths[..]
fn async_receive_paths(&self) -> &[BlindedPath] {
&self.async_receive_paths[..]
}

fn supported_quantity(&self) -> Quantity {
Expand Down Expand Up @@ -510,7 +515,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
fallbacks,
features,
node_id,
message_paths,
invoice_message_paths,
payment_hash,
amount,
},
Expand All @@ -524,7 +529,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
}

let payment_paths = construct_payment_paths(blindedpay, paths)?;
let message_paths = message_paths.ok_or(Bolt12SemanticError::MissingPaths)?;
let async_receive_paths = invoice_message_paths.ok_or(Bolt12SemanticError::MissingPaths)?;

let created_at = match created_at {
None => return Err(Bolt12SemanticError::MissingCreationTime),
Expand All @@ -548,7 +553,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
Ok(InvoiceContents {
offer: OfferContents::try_from(offer_tlv_stream)?,
payment_paths,
message_paths,
async_receive_paths,
created_at,
relative_expiry,
fallbacks,
Expand Down Expand Up @@ -678,8 +683,8 @@ mod tests {
assert_eq!(invoice.description(), None);
assert_eq!(invoice.offer_features(), &OfferFeatures::empty());
assert_eq!(invoice.absolute_expiry(), None);
assert_eq!(invoice.offer_message_paths(), &[blinded_path()]);
assert_eq!(invoice.message_paths(), &[blinded_path()]);
assert_eq!(invoice.offer_request_paths(), &[blinded_path()]);
assert_eq!(invoice.async_receive_paths(), &[blinded_path()]);
assert_eq!(invoice.issuer(), None);
assert_eq!(invoice.supported_quantity(), Quantity::One);
assert_ne!(invoice.signing_pubkey(), recipient_pubkey());
Expand Down Expand Up @@ -726,7 +731,7 @@ mod tests {
fallbacks: None,
features: None,
node_id: Some(&offer_signing_pubkey),
message_paths: Some(&paths),
invoice_message_paths: Some(&paths),
},
SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
)
Expand Down Expand Up @@ -1055,9 +1060,9 @@ mod tests {
}

// Error if message paths are missing.
let missing_message_paths_invoice = invoice();
let mut tlv_stream = missing_message_paths_invoice.as_tlv_stream();
tlv_stream.1.message_paths = None;
let missing_async_receive_paths_invoice = invoice();
let mut tlv_stream = missing_async_receive_paths_invoice.as_tlv_stream();
tlv_stream.1.invoice_message_paths = None;
match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
Ok(_) => panic!("expected error"),
Err(e) => {
Expand Down Expand Up @@ -1137,8 +1142,8 @@ mod tests {
#[test]
fn fails_parsing_invoice_with_invalid_offer_fields() {
// Error if the offer is missing paths.
let missing_offer_paths_invoice = invoice();
let mut tlv_stream = missing_offer_paths_invoice.as_tlv_stream();
let missing_offer_request_paths_invoice = invoice();
let mut tlv_stream = missing_offer_request_paths_invoice.as_tlv_stream();
tlv_stream.0.paths = None;
match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
Ok(_) => panic!("expected error"),
Expand Down
Loading