/// # Limitations
///
/// Requires a direct connection to an introduction node in [`Offer::paths`] or to
- /// [`Offer::signing_pubkey`], if empty. A similar restriction applies to the responding
+ /// [`Offer::issuer_signing_pubkey`], if empty. A similar restriction applies to the responding
/// [`Bolt12Invoice::payment_paths`].
///
/// # Errors
let message = OffersMessage::InvoiceRequest(invoice_request.clone());
pending_offers_messages.push((message, instructions));
});
- } else if let Some(signing_pubkey) = invoice_request.signing_pubkey() {
+ } else if let Some(node_id) = invoice_request.issuer_signing_pubkey() {
for reply_path in reply_paths {
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
- destination: Destination::Node(signing_pubkey),
+ destination: Destination::Node(node_id),
reply_path,
};
let message = OffersMessage::InvoiceRequest(invoice_request.clone());
}
} else {
debug_assert!(false);
- return Err(Bolt12SemanticError::MissingSigningPubkey);
+ return Err(Bolt12SemanticError::MissingIssuerSigningPubkey);
}
Ok(())
.create_offer_builder(None).unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(bob_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
let introduction_node_id = resolve_introduction_node(david, &path);
.create_offer_builder(None).unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(bob_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
let introduction_node_id = resolve_introduction_node(david, &path);
.create_offer_builder(None).unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(bob_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
let introduction_node_id = resolve_introduction_node(david, &path);
.unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(alice_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
.create_offer_builder(None).unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(alice_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id));
.clear_paths()
.amount_msats(10_000_000)
.build().unwrap();
- assert_eq!(offer.signing_pubkey(), Some(alice_id));
+ assert_eq!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(offer.paths().is_empty());
let payment_id = PaymentId([1; 32]);
.unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(alice_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
.create_offer_builder(None).unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(alice_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id));
.create_offer_builder(None).unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(alice_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
.amount_msats(10_000_000)
.build().unwrap();
assert_eq!(offer.metadata(), None);
- assert_ne!(offer.signing_pubkey(), Some(alice_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
.unwrap()
.amount_msats(10_000_000)
.build().unwrap();
- assert_ne!(offer.signing_pubkey(), Some(alice_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
assert!(!offer.paths().is_empty());
for path in offer.paths() {
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id));
check_invoice_signing_pubkey(&fields.signing_pubkey, &offer_tlv_stream)?;
- if offer_tlv_stream.node_id.is_none() && offer_tlv_stream.paths.is_none() {
+ if offer_tlv_stream.issuer_id.is_none() && offer_tlv_stream.paths.is_none() {
let refund = RefundContents::try_from(
(payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream)
)?;
pub(super) fn check_invoice_signing_pubkey(
invoice_signing_pubkey: &PublicKey, offer_tlv_stream: &OfferTlvStream
) -> Result<(), Bolt12SemanticError> {
- match (&offer_tlv_stream.node_id, &offer_tlv_stream.paths) {
- (Some(expected_signing_pubkey), _) => {
- if invoice_signing_pubkey != expected_signing_pubkey {
+ match (&offer_tlv_stream.issuer_id, &offer_tlv_stream.paths) {
+ (Some(issuer_signing_pubkey), _) => {
+ if invoice_signing_pubkey != issuer_signing_pubkey {
return Err(Bolt12SemanticError::InvalidSigningPubkey);
}
},
paths: None,
issuer: None,
quantity_max: None,
- node_id: Some(&recipient_pubkey()),
+ issuer_id: Some(&recipient_pubkey()),
},
InvoiceRequestTlvStreamRef {
chain: None,
paths: None,
issuer: None,
quantity_max: None,
- node_id: None,
+ issuer_id: None,
},
InvoiceRequestTlvStreamRef {
chain: None,
let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
.amount_msats(1000)
- // Omit the path so that node_id is used for the signing pubkey instead of deriving
+ // Omit the path so that node_id is used for the signing pubkey instead of deriving it
.build().unwrap();
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
};
let invoice = OfferBuilder::new(recipient_pubkey())
- .clear_signing_pubkey()
+ .clear_issuer_signing_pubkey()
.amount_msats(1000)
.path(paths[0].clone())
.path(paths[1].clone())
}
let invoice = OfferBuilder::new(recipient_pubkey())
- .clear_signing_pubkey()
+ .clear_issuer_signing_pubkey()
.amount_msats(1000)
.path(paths[0].clone())
.path(paths[1].clone())
/// The `payment_paths` parameter is useful for maintaining the payment recipient's privacy. It
/// must contain one or more elements ordered from most-preferred to least-preferred, if there's
/// a preference. Note, however, that any privacy is lost if a public node id was used for
- /// [`Offer::signing_pubkey`].
+ /// [`Offer::issuer_signing_pubkey`].
///
/// Errors if the request contains unknown required features.
///
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
}
- let signing_pubkey = match $contents.contents.inner.offer.signing_pubkey() {
+ let signing_pubkey = match $contents.contents.inner.offer.issuer_signing_pubkey() {
Some(signing_pubkey) => signing_pubkey,
- None => return Err(Bolt12SemanticError::MissingSigningPubkey),
+ None => return Err(Bolt12SemanticError::MissingIssuerSigningPubkey),
};
<$builder>::for_offer(&$contents, payment_paths, created_at, payment_hash, signing_pubkey)
&$self, payment_paths: Vec<BlindedPaymentPath>, payment_hash: PaymentHash,
created_at: core::time::Duration, signing_pubkey: PublicKey
) -> Result<$builder, Bolt12SemanticError> {
- debug_assert!($contents.contents.inner.offer.signing_pubkey().is_none());
+ debug_assert!($contents.contents.inner.offer.issuer_signing_pubkey().is_none());
if $contents.invoice_request_features().requires_unknown_bits() {
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
Some(keys) => keys,
};
- match $contents.contents.inner.offer.signing_pubkey() {
+ match $contents.contents.inner.offer.issuer_signing_pubkey() {
Some(signing_pubkey) => debug_assert_eq!(signing_pubkey, keys.public_key()),
- None => return Err(Bolt12SemanticError::MissingSigningPubkey),
+ None => return Err(Bolt12SemanticError::MissingIssuerSigningPubkey),
}
<$builder>::for_offer_using_keys(
assert_eq!(unsigned_invoice_request.paths(), &[]);
assert_eq!(unsigned_invoice_request.issuer(), None);
assert_eq!(unsigned_invoice_request.supported_quantity(), Quantity::One);
- assert_eq!(unsigned_invoice_request.signing_pubkey(), Some(recipient_pubkey()));
+ assert_eq!(unsigned_invoice_request.issuer_signing_pubkey(), Some(recipient_pubkey()));
assert_eq!(unsigned_invoice_request.chain(), ChainHash::using_genesis_block(Network::Bitcoin));
assert_eq!(unsigned_invoice_request.amount_msats(), None);
assert_eq!(unsigned_invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty());
assert_eq!(invoice_request.paths(), &[]);
assert_eq!(invoice_request.issuer(), None);
assert_eq!(invoice_request.supported_quantity(), Quantity::One);
- assert_eq!(invoice_request.signing_pubkey(), Some(recipient_pubkey()));
+ assert_eq!(invoice_request.issuer_signing_pubkey(), Some(recipient_pubkey()));
assert_eq!(invoice_request.chain(), ChainHash::using_genesis_block(Network::Bitcoin));
assert_eq!(invoice_request.amount_msats(), None);
assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty());
paths: None,
issuer: None,
quantity_max: None,
- node_id: Some(&recipient_pubkey()),
+ issuer_id: Some(&recipient_pubkey()),
},
InvoiceRequestTlvStreamRef {
chain: None,
}
#[test]
- fn fails_parsing_invoice_request_without_node_id() {
+ fn fails_parsing_invoice_request_without_issuer_id() {
let offer = OfferBuilder::new(recipient_pubkey())
.amount_msats(1000)
.build().unwrap();
let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap();
let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream();
- tlv_stream.1.node_id = None;
+ tlv_stream.1.issuer_id = None;
let mut buffer = Vec::new();
tlv_stream.write(&mut buffer).unwrap();
match InvoiceRequest::try_from(buffer) {
Ok(_) => panic!("expected error"),
Err(e) => {
- assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey));
+ assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey));
},
}
}
.amount_msats(1000)
.supported_quantity(Quantity::Unbounded)
.build().unwrap();
- assert_eq!(offer.signing_pubkey(), Some(node_id));
+ assert_eq!(offer.issuer_signing_pubkey(), Some(node_id));
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.chain(Network::Testnet).unwrap()
/// A 128-bit number used only once.
///
-/// Needed when constructing [`Offer::metadata`] and deriving [`Offer::signing_pubkey`] from
+/// Needed when constructing [`Offer::metadata`] and deriving [`Offer::issuer_signing_pubkey`] from
/// [`ExpandedKey`]. Must not be reused for any other derivation without first hashing.
///
/// [`Offer::metadata`]: crate::offers::offer::Offer::metadata
-/// [`Offer::signing_pubkey`]: crate::offers::offer::Offer::signing_pubkey
+/// [`Offer::issuer_signing_pubkey`]: crate::offers::offer::Offer::issuer_signing_pubkey
/// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Nonce(pub(crate) [u8; Self::LENGTH]);
macro_rules! offer_explicit_metadata_builder_methods { (
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
) => {
- /// Creates a new builder for an offer using the [`Offer::signing_pubkey`] for signing invoices.
- /// The associated secret key must be remembered while the offer is valid.
+ /// Creates a new builder for an offer using the `signing_pubkey` for signing invoices. The
+ /// associated secret key must be remembered while the offer is valid.
///
/// Use a different pubkey per offer to avoid correlating offers.
///
offer: OfferContents {
chains: None, metadata: None, amount: None, description: None,
features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None,
- supported_quantity: Quantity::One, signing_pubkey: Some(signing_pubkey),
+ supported_quantity: Quantity::One, issuer_signing_pubkey: Some(signing_pubkey),
},
metadata_strategy: core::marker::PhantomData,
secp_ctx: None,
/// Similar to [`OfferBuilder::new`] except, if [`OfferBuilder::path`] is called, the signing
/// pubkey is derived from the given [`ExpandedKey`] and [`Nonce`]. This provides recipient
/// privacy by using a different signing pubkey for each offer. Otherwise, the provided
- /// `node_id` is used for the signing pubkey.
+ /// `node_id` is used for [`Offer::issuer_signing_pubkey`].
///
/// Also, sets the metadata when [`OfferBuilder::build`] is called such that it can be used by
/// [`InvoiceRequest::verify_using_metadata`] to determine if the request was produced for the
offer: OfferContents {
chains: None, metadata: Some(metadata), amount: None, description: None,
features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None,
- supported_quantity: Quantity::One, signing_pubkey: Some(node_id),
+ supported_quantity: Quantity::One, issuer_signing_pubkey: Some(node_id),
},
metadata_strategy: core::marker::PhantomData,
secp_ctx: Some(secp_ctx),
}
/// Adds a blinded path to [`Offer::paths`]. Must include at least one path if only connected by
- /// private channels or if [`Offer::signing_pubkey`] is not a public node id.
+ /// private channels or if [`Offer::issuer_signing_pubkey`] is not a public node id.
///
/// Successive calls to this method will add another blinded path. Caller is responsible for not
/// adding duplicate paths.
debug_assert_eq!(tlv_stream.metadata, None);
tlv_stream.metadata = None;
if metadata.derives_recipient_keys() {
- tlv_stream.node_id = None;
+ tlv_stream.issuer_id = None;
}
// Either replace the signing pubkey with the derived pubkey or include the metadata
let (derived_metadata, keys) =
metadata.derive_from(iv_bytes, tlv_stream, $self.secp_ctx);
match keys {
- Some(keys) => $self.offer.signing_pubkey = Some(keys.public_key()),
+ Some(keys) => $self.offer.issuer_signing_pubkey = Some(keys.public_key()),
None => $self.offer.metadata = Some(derived_metadata),
}
} else {
}
#[cfg_attr(c_bindings, allow(dead_code))]
- pub(crate) fn clear_signing_pubkey($($self_mut)* $self: $self_type) -> $return_type {
- $self.offer.signing_pubkey = None;
+ pub(crate) fn clear_issuer_signing_pubkey($($self_mut)* $self: $self_type) -> $return_type {
+ $self.offer.issuer_signing_pubkey = None;
$return_value
}
issuer: Option<String>,
paths: Option<Vec<BlindedMessagePath>>,
supported_quantity: Quantity,
- signing_pubkey: Option<PublicKey>,
+ issuer_signing_pubkey: Option<PublicKey>,
}
macro_rules! offer_accessors { ($self: ident, $contents: expr) => {
}
/// The public key used by the recipient to sign invoices.
- pub fn signing_pubkey(&$self) -> Option<bitcoin::secp256k1::PublicKey> {
- $contents.signing_pubkey()
+ pub fn issuer_signing_pubkey(&$self) -> Option<bitcoin::secp256k1::PublicKey> {
+ $contents.issuer_signing_pubkey()
}
} }
}
}
- pub(super) fn signing_pubkey(&self) -> Option<PublicKey> {
- self.signing_pubkey
+ pub(super) fn issuer_signing_pubkey(&self) -> Option<PublicKey> {
+ self.issuer_signing_pubkey
}
pub(super) fn verify_using_metadata<T: secp256k1::Signing>(
let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| {
match record.r#type {
OFFER_METADATA_TYPE => false,
- OFFER_NODE_ID_TYPE => !metadata.derives_recipient_keys(),
+ OFFER_ISSUER_ID_TYPE => !metadata.derives_recipient_keys(),
_ => true,
}
});
- let signing_pubkey = match self.signing_pubkey() {
+ let signing_pubkey = match self.issuer_signing_pubkey() {
Some(signing_pubkey) => signing_pubkey,
None => return Err(()),
};
paths: self.paths.as_ref(),
issuer: self.issuer.as_ref(),
quantity_max: self.supported_quantity.to_tlv_record(),
- node_id: self.signing_pubkey.as_ref(),
+ issuer_id: self.issuer_signing_pubkey.as_ref(),
}
}
}
/// TLV record type for [`Offer::metadata`].
const OFFER_METADATA_TYPE: u64 = 4;
-/// TLV record type for [`Offer::signing_pubkey`].
-const OFFER_NODE_ID_TYPE: u64 = 22;
+/// TLV record type for [`Offer::issuer_signing_pubkey`].
+const OFFER_ISSUER_ID_TYPE: u64 = 22;
tlv_stream!(OfferTlvStream, OfferTlvStreamRef, OFFER_TYPES, {
(2, chains: (Vec<ChainHash>, WithoutLength)),
(16, paths: (Vec<BlindedMessagePath>, WithoutLength)),
(18, issuer: (String, WithoutLength)),
(20, quantity_max: (u64, HighZeroBytesDroppedBigSize)),
- (OFFER_NODE_ID_TYPE, node_id: PublicKey),
+ (OFFER_ISSUER_ID_TYPE, issuer_id: PublicKey),
});
impl Bech32Encode for Offer {
fn try_from(tlv_stream: OfferTlvStream) -> Result<Self, Self::Error> {
let OfferTlvStream {
chains, metadata, currency, amount, description, features, absolute_expiry, paths,
- issuer, quantity_max, node_id,
+ issuer, quantity_max, issuer_id,
} = tlv_stream;
let metadata = metadata.map(|metadata| Metadata::Bytes(metadata));
Some(n) => Quantity::Bounded(NonZeroU64::new(n).unwrap()),
};
- let (signing_pubkey, paths) = match (node_id, paths) {
- (None, None) => return Err(Bolt12SemanticError::MissingSigningPubkey),
+ let (issuer_signing_pubkey, paths) = match (issuer_id, paths) {
+ (None, None) => return Err(Bolt12SemanticError::MissingIssuerSigningPubkey),
(_, Some(paths)) if paths.is_empty() => return Err(Bolt12SemanticError::MissingPaths),
- (node_id, paths) => (node_id, paths),
+ (issuer_id, paths) => (issuer_id, paths),
};
Ok(OfferContents {
chains, metadata, amount, description, features, absolute_expiry, issuer, paths,
- supported_quantity, signing_pubkey,
+ supported_quantity, issuer_signing_pubkey,
})
}
}
assert_eq!(offer.issuer(), None);
assert_eq!(offer.supported_quantity(), Quantity::One);
assert!(!offer.expects_quantity());
- assert_eq!(offer.signing_pubkey(), Some(pubkey(42)));
+ assert_eq!(offer.issuer_signing_pubkey(), Some(pubkey(42)));
assert_eq!(
offer.as_tlv_stream(),
paths: None,
issuer: None,
quantity_max: None,
- node_id: Some(&pubkey(42)),
+ issuer_id: Some(&pubkey(42)),
},
);
.amount_msats(1000)
.build().unwrap();
assert!(offer.metadata().is_some());
- assert_eq!(offer.signing_pubkey(), Some(node_id));
+ assert_eq!(offer.issuer_signing_pubkey(), Some(node_id));
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
.path(blinded_path)
.build().unwrap();
assert!(offer.metadata().is_none());
- assert_ne!(offer.signing_pubkey(), Some(node_id));
+ assert_ne!(offer.issuer_signing_pubkey(), Some(node_id));
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
// Fails verification with altered signing pubkey
let mut tlv_stream = offer.as_tlv_stream();
- let signing_pubkey = pubkey(1);
- tlv_stream.node_id = Some(&signing_pubkey);
+ let issuer_id = pubkey(1);
+ tlv_stream.issuer_id = Some(&issuer_id);
let mut encoded_offer = Vec::new();
tlv_stream.write(&mut encoded_offer).unwrap();
.unwrap();
let tlv_stream = offer.as_tlv_stream();
assert_eq!(offer.paths(), paths.as_slice());
- assert_eq!(offer.signing_pubkey(), Some(pubkey(42)));
+ assert_eq!(offer.issuer_signing_pubkey(), Some(pubkey(42)));
assert_ne!(pubkey(42), pubkey(44));
assert_eq!(tlv_stream.paths, Some(&paths));
- assert_eq!(tlv_stream.node_id, Some(&pubkey(42)));
+ assert_eq!(tlv_stream.issuer_id, Some(&pubkey(42)));
}
#[test]
BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] },
]
))
- .clear_signing_pubkey()
+ .clear_issuer_signing_pubkey()
.build()
.unwrap();
if let Err(e) = offer.to_string().parse::<Offer>() {
}
#[test]
- fn parses_offer_with_node_id() {
+ fn parses_offer_with_issuer_id() {
let offer = OfferBuilder::new(pubkey(42)).build().unwrap();
if let Err(e) = offer.to_string().parse::<Offer>() {
panic!("error parsing offer: {:?}", e);
}
let mut tlv_stream = offer.as_tlv_stream();
- tlv_stream.node_id = None;
+ tlv_stream.issuer_id = None;
let mut encoded_offer = Vec::new();
tlv_stream.write(&mut encoded_offer).unwrap();
match Offer::try_from(encoded_offer) {
Ok(_) => panic!("expected error"),
Err(e) => {
- assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey));
+ assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey));
},
}
}
// Malformed: empty
assert_eq!(
"lno1".parse::<Offer>(),
- Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)),
+ Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)),
);
// Malformed: truncated at type
Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)),
);
- // Malformed: invalid offer_node_id
+ // Malformed: invalid offer_issuer_id
assert_eq!(
"lno1pgz5znzfgdz3vggzqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvps".parse::<Offer>(),
Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)),
Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription)),
);
- // Missing offer_node_id"
+ // Missing offer_issuer_id
assert_eq!(
"lno1pgx9getnwss8vetrw3hhyuc".parse::<Offer>(),
- Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)),
+ Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)),
);
}
}
UnexpectedFeatures,
/// A required description was not provided.
MissingDescription,
- /// A signing pubkey was not provided.
- MissingSigningPubkey,
- /// A signing pubkey was provided but a different one was expected.
- InvalidSigningPubkey,
- /// A signing pubkey was provided but was not expected.
- UnexpectedSigningPubkey,
+ /// An issuer's signing pubkey was not provided.
+ MissingIssuerSigningPubkey,
+ /// An issuer's signing pubkey was provided but was not expected.
+ UnexpectedIssuerSigningPubkey,
/// A quantity was expected but was missing.
MissingQuantity,
/// An unsupported quantity was provided.
MissingPaymentHash,
/// An invoice payment hash was provided but was not expected.
UnexpectedPaymentHash,
+ /// A signing pubkey was not provided.
+ MissingSigningPubkey,
+ /// A signing pubkey was provided but a different one was expected.
+ InvalidSigningPubkey,
/// A signature was expected but was missing.
MissingSignature,
}
paths: None,
issuer: self.issuer.as_ref(),
quantity_max: None,
- node_id: None,
+ issuer_id: None,
};
let features = {
OfferTlvStream {
chains, metadata, currency, amount: offer_amount, description,
features: offer_features, absolute_expiry, paths: offer_paths, issuer, quantity_max,
- node_id,
+ issuer_id,
},
InvoiceRequestTlvStream {
chain, amount, features, quantity, payer_id, payer_note, paths
return Err(Bolt12SemanticError::UnexpectedQuantity);
}
- if node_id.is_some() {
- return Err(Bolt12SemanticError::UnexpectedSigningPubkey);
+ if issuer_id.is_some() {
+ return Err(Bolt12SemanticError::UnexpectedIssuerSigningPubkey);
}
let amount_msats = match amount {
paths: None,
issuer: None,
quantity_max: None,
- node_id: None,
+ issuer_id: None,
},
InvoiceRequestTlvStreamRef {
chain: None,
},
}
- let node_id = payer_pubkey();
+ let issuer_id = payer_pubkey();
let mut tlv_stream = refund.as_tlv_stream();
- tlv_stream.1.node_id = Some(&node_id);
+ tlv_stream.1.issuer_id = Some(&issuer_id);
match Refund::try_from(tlv_stream.to_bytes()) {
Ok(_) => panic!("expected error"),
Err(e) => {
- assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedSigningPubkey));
+ assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedIssuerSigningPubkey));
},
}
}
return Err(Bolt12SemanticError::MissingPaths);
}
- let offer_signing_pubkey =
- offer.signing_pubkey().ok_or(Bolt12SemanticError::MissingSigningPubkey)?;
+ let issuer_signing_pubkey =
+ offer.issuer_signing_pubkey().ok_or(Bolt12SemanticError::MissingIssuerSigningPubkey)?;
let keys = offer
.verify(nonce, &expanded_key, &secp_ctx)
.ok_or(Bolt12SemanticError::MissingSigningPubkey)?;
let signing_pubkey = keys.public_key();
- if signing_pubkey != offer_signing_pubkey {
+ if signing_pubkey != issuer_signing_pubkey {
return Err(Bolt12SemanticError::InvalidSigningPubkey);
}
assert!(invoice.fallbacks().is_empty());
assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
- let offer_signing_pubkey = offer.signing_pubkey().unwrap();
+ let signing_pubkey = offer.issuer_signing_pubkey().unwrap();
let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice.bytes);
- assert!(
- merkle::verify_signature(&invoice.signature, &message, offer_signing_pubkey).is_ok()
- );
+ assert!(merkle::verify_signature(&invoice.signature, &message, signing_pubkey).is_ok());
let paths = vec![blinded_path()];
assert_eq!(
paths: Some(&paths),
issuer: None,
quantity_max: None,
- node_id: Some(&offer_signing_pubkey),
+ issuer_id: Some(&signing_pubkey),
},
InvoiceTlvStreamRef {
paths: Some(Iterable(
amount: None,
fallbacks: None,
features: None,
- node_id: Some(&offer_signing_pubkey),
+ node_id: Some(&signing_pubkey),
message_paths: Some(&paths),
},
SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
}
#[test]
- fn fails_build_offer_signing_pubkey() {
+ fn fails_building_with_missing_issuer_signing_pubkey() {
let node_id = recipient_pubkey();
let now = now();
let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
.build()
.unwrap();
- // Error if offer signing pubkey is missing.
- let mut offer_missing_signing_pubkey = valid_offer.clone();
- let mut offer_tlv_stream = offer_missing_signing_pubkey.as_tlv_stream();
- offer_tlv_stream.node_id.take();
+ let mut offer_missing_issuer_id = valid_offer.clone();
+ let mut offer_tlv_stream = offer_missing_issuer_id.as_tlv_stream();
+ offer_tlv_stream.issuer_id.take();
let mut buffer = Vec::new();
offer_tlv_stream.write(&mut buffer).unwrap();
- offer_missing_signing_pubkey = Offer::try_from(buffer).unwrap();
+ offer_missing_issuer_id = Offer::try_from(buffer).unwrap();
if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
- &offer_missing_signing_pubkey,
+ &offer_missing_issuer_id,
payment_paths(),
vec![blinded_path()],
now,
nonce,
&secp_ctx,
) {
- assert_eq!(e, Bolt12SemanticError::MissingSigningPubkey);
+ assert_eq!(e, Bolt12SemanticError::MissingIssuerSigningPubkey);
} else {
panic!("expected error")
}
+ }
+
+ #[test]
+ fn fails_building_with_invalid_metadata() {
+ let now = now();
+ let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
+ let entropy = FixedEntropy {};
+ let nonce = Nonce::from_entropy_source(&entropy);
+ let secp_ctx = Secp256k1::new();
- // Error if the offer's metadata cannot be verified.
let offer = OfferBuilder::new(recipient_pubkey())
.path(blinded_path())
.metadata(vec![42; 32])