//! use lightning::offers::parse::ParseError;
//! use lightning::util::ser::{Readable, Writeable};
//!
-//! # use lightning::onion_message::BlindedPath;
+//! # use lightning::blinded_path::BlindedPath;
//! # #[cfg(feature = "std")]
//! # use std::time::SystemTime;
//! #
use bitcoin::blockdata::constants::ChainHash;
use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::{PublicKey, Secp256k1, self};
+use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
use core::convert::TryFrom;
use core::num::NonZeroU64;
use core::ops::Deref;
use core::time::Duration;
use crate::chain::keysinterface::EntropySource;
use crate::io;
+use crate::blinded_path::BlindedPath;
use crate::ln::features::OfferFeatures;
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
use crate::ln::msgs::MAX_VALUE_MSAT;
use crate::offers::merkle::TlvStream;
use crate::offers::parse::{Bech32Encode, ParseError, ParsedMessage, SemanticError};
use crate::offers::signer::{Metadata, MetadataMaterial, self};
-use crate::onion_message::BlindedPath;
use crate::util::ser::{HighZeroBytesDroppedBigSize, WithoutLength, Writeable, Writer};
use crate::util::string::PrintableString;
#[cfg(feature = "std")]
use std::time::SystemTime;
-const IV_BYTES: &[u8; IV_LEN] = b"LDK Offer ~~~~~~";
+pub(super) const IV_BYTES: &[u8; IV_LEN] = b"LDK Offer ~~~~~~";
/// Builds an [`Offer`] for the "offer to be paid" flow.
///
/// See [module-level documentation] for usage.
///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+///
/// [module-level documentation]: self
pub struct OfferBuilder<'a, M: MetadataStrategy, T: secp256k1::Signing> {
offer: OfferContents,
}
/// Indicates how [`Offer::metadata`] may be set.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub trait MetadataStrategy {}
/// [`Offer::metadata`] may be explicitly set or left empty.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct ExplicitMetadata {}
/// [`Offer::metadata`] will be derived.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct DerivedMetadata {}
impl MetadataStrategy for ExplicitMetadata {}
/// A complete description of the purpose of the payment. Intended to be displayed to the user
/// but with the caveat that it has not been verified in any way.
pub fn description(&self) -> PrintableString {
- PrintableString(&self.contents.description)
+ self.contents.description()
}
/// Features pertaining to the offer.
/// - derives the [`InvoiceRequest::payer_id`] such that a different key can be used for each
/// request, and
/// - sets the [`InvoiceRequest::metadata`] when [`InvoiceRequestBuilder::build`] is called such
- /// that it can be used to determine if the invoice was requested using a base [`ExpandedKey`]
- /// from which the payer id was derived.
+ /// that it can be used by [`Invoice::verify`] to determine if the invoice was requested using
+ /// a base [`ExpandedKey`] from which the payer id was derived.
///
/// Useful to protect the sender's privacy.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
/// [`InvoiceRequest::metadata`]: crate::offers::invoice_request::InvoiceRequest::metadata
/// [`Invoice::verify`]: crate::offers::invoice::Invoice::verify
///
/// Useful for recurring payments using the same `payer_id` with different invoices.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
pub fn request_invoice_deriving_metadata<ES: Deref>(
&self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES
Ok(InvoiceRequestBuilder::deriving_metadata(self, payer_id, expanded_key, entropy_source))
}
- /// Creates an [`InvoiceRequest`] for the offer with the given `metadata` and `payer_id`, which
- /// will be reflected in the `Invoice` response.
+ /// Creates an [`InvoiceRequestBuilder`] for the offer with the given `metadata` and `payer_id`,
+ /// which will be reflected in the `Invoice` response.
///
/// The `metadata` is useful for including information about the derivation of `payer_id` such
/// that invoice response handling can be stateless. Also serves as payer-provided entropy while
///
/// Errors if the offer contains unknown required features.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
pub fn request_invoice(
&self, metadata: Vec<u8>, payer_id: PublicKey
self.metadata.as_ref().and_then(|metadata| metadata.as_bytes())
}
+ pub fn description(&self) -> PrintableString {
+ PrintableString(&self.description)
+ }
+
#[cfg(feature = "std")]
pub(super) fn is_expired(&self) -> bool {
match self.absolute_expiry {
/// Verifies that the offer metadata was produced from the offer in the TLV stream.
pub(super) fn verify<T: secp256k1::Signing>(
- &self, tlv_stream: TlvStream<'_>, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
- ) -> bool {
+ &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1<T>
+ ) -> Result<Option<KeyPair>, ()> {
match self.metadata() {
Some(metadata) => {
- let tlv_stream = tlv_stream.range(OFFER_TYPES).filter(|record| {
+ let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| {
match record.r#type {
OFFER_METADATA_TYPE => false,
OFFER_NODE_ID_TYPE => !self.metadata.as_ref().unwrap().derives_keys(),
metadata, key, IV_BYTES, self.signing_pubkey(), tlv_stream, secp_ctx
)
},
- None => false,
+ None => Err(()),
}
}
}
/// Valid type range for offer TLV records.
-const OFFER_TYPES: core::ops::Range<u64> = 1..80;
+pub(super) const OFFER_TYPES: core::ops::Range<u64> = 1..80;
/// TLV record type for [`Offer::metadata`].
const OFFER_METADATA_TYPE: u64 = 4;
use core::convert::TryFrom;
use core::num::NonZeroU64;
use core::time::Duration;
+ use crate::blinded_path::{BlindedHop, BlindedPath};
use crate::chain::keysinterface::KeyMaterial;
use crate::ln::features::OfferFeatures;
use crate::ln::inbound_payment::ExpandedKey;
use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
use crate::offers::parse::{ParseError, SemanticError};
use crate::offers::test_utils::*;
- use crate::onion_message::{BlindedHop, BlindedPath};
use crate::util::ser::{BigSize, Writeable};
use crate::util::string::PrintableString;
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
.sign(payer_sign).unwrap();
- assert!(invoice_request.verify(&expanded_key, &secp_ctx));
+ assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok());
// Fails verification with altered offer field
let mut tlv_stream = offer.as_tlv_stream();
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
.sign(payer_sign).unwrap();
- assert!(!invoice_request.verify(&expanded_key, &secp_ctx));
+ assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
// Fails verification with altered metadata
let mut tlv_stream = offer.as_tlv_stream();
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
.sign(payer_sign).unwrap();
- assert!(!invoice_request.verify(&expanded_key, &secp_ctx));
+ assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
}
#[test]
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
.sign(payer_sign).unwrap();
- assert!(invoice_request.verify(&expanded_key, &secp_ctx));
+ assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok());
// Fails verification with altered offer field
let mut tlv_stream = offer.as_tlv_stream();
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
.sign(payer_sign).unwrap();
- assert!(!invoice_request.verify(&expanded_key, &secp_ctx));
+ assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
// Fails verification with altered signing pubkey
let mut tlv_stream = offer.as_tlv_stream();
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
.sign(payer_sign).unwrap();
- assert!(!invoice_request.verify(&expanded_key, &secp_ctx));
+ assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
}
#[test]