@@ -68,7 +68,7 @@ use crate::ln::outbound_payment::{OutboundPayments, PendingOutboundPayment, Retr
6868use crate::offers::invoice::{Bolt12Invoice, DerivedSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice, DEFAULT_RELATIVE_EXPIRY};
6969use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestBuilder};
7070use crate::offers::nonce::Nonce;
71- use crate::offers::offer::{ Offer, OfferBuilder} ;
71+ use crate::offers::offer::Offer;
7272use crate::offers::parse::Bolt12SemanticError;
7373use crate::offers::refund::{Refund, RefundBuilder};
7474use crate::offers::signer;
@@ -88,7 +88,7 @@ use crate::util::logger::{Level, Logger, WithContext};
8888use crate::util::errors::APIError;
8989#[cfg(async_payments)] use {
9090 crate::blinded_path::payment::AsyncBolt12OfferContext,
91- crate::offers::offer::Amount,
91+ crate::offers::offer::{ Amount, DerivedMetadata, OfferBuilder} ,
9292 crate::offers::static_invoice::{DEFAULT_RELATIVE_EXPIRY as STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY, StaticInvoice, StaticInvoiceBuilder},
9393};
9494
@@ -99,18 +99,14 @@ use crate::onion_message::dns_resolution::{DNSResolverMessage, DNSResolverMessag
9999
100100#[cfg(not(c_bindings))]
101101use {
102- crate::offers::offer::DerivedMetadata,
103102 crate::onion_message::messenger::DefaultMessageRouter,
104103 crate::routing::router::DefaultRouter,
105104 crate::routing::gossip::NetworkGraph,
106105 crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters},
107106 crate::sign::KeysManager,
108107};
109108#[cfg(c_bindings)]
110- use {
111- crate::offers::offer::OfferWithDerivedMetadataBuilder,
112- crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder,
113- };
109+ use crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder;
114110
115111use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, CreationError, Currency, Description, InvoiceBuilder as Bolt11InvoiceBuilder, SignOrCreationError, DEFAULT_EXPIRY_TIME};
116112
@@ -1957,6 +1953,7 @@ where
19571953/// ```
19581954/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
19591955/// # use lightning::ln::channelmanager::{AChannelManager, Bolt11InvoiceParameters};
1956+ /// # use lightning::offers::flow::OffersMessageCommons;
19601957/// #
19611958/// # fn example<T: AChannelManager>(channel_manager: T) {
19621959/// # let channel_manager = channel_manager.get_cm();
@@ -2057,56 +2054,8 @@ where
20572054/// ```
20582055///
20592056/// ## BOLT 12 Offers
2060- ///
2061- /// The [`offers`] module is useful for creating BOLT 12 offers. An [`Offer`] is a precursor to a
2062- /// [`Bolt12Invoice`], which must first be requested by the payer. The interchange of these messages
2063- /// as defined in the specification is handled by [`ChannelManager`]. However, this only works with
2064- /// an [`Offer`] created using a builder returned by [`create_offer_builder`]. With this approach,
2065- /// BOLT 12 offers and invoices are stateless just as BOLT 11 invoices are.
2066- ///
2067- /// ```
2068- /// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
2069- /// # use lightning::ln::channelmanager::AChannelManager;
2070- /// # use lightning::offers::parse::Bolt12SemanticError;
2071- /// #
2072- /// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
2073- /// # let channel_manager = channel_manager.get_cm();
2074- /// # let absolute_expiry = None;
2075- /// let offer = channel_manager
2076- /// .create_offer_builder(absolute_expiry)?
2077- /// # ;
2078- /// # // Needed for compiling for c_bindings
2079- /// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into();
2080- /// # let offer = builder
2081- /// .description("coffee".to_string())
2082- /// .amount_msats(10_000_000)
2083- /// .build()?;
2084- /// let bech32_offer = offer.to_string();
2085- ///
2086- /// // On the event processing thread
2087- /// channel_manager.process_pending_events(&|event| {
2088- /// match event {
2089- /// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
2090- /// PaymentPurpose::Bolt12OfferPayment { payment_preimage: Some(payment_preimage), .. } => {
2091- /// println!("Claiming payment {}", payment_hash);
2092- /// channel_manager.claim_funds(payment_preimage);
2093- /// },
2094- /// PaymentPurpose::Bolt12OfferPayment { payment_preimage: None, .. } => {
2095- /// println!("Unknown payment hash: {}", payment_hash);
2096- /// }
2097- /// # _ => {},
2098- /// },
2099- /// Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
2100- /// println!("Claimed {} msats", amount_msat);
2101- /// },
2102- /// // ...
2103- /// # _ => {},
2104- /// }
2105- /// Ok(())
2106- /// });
2107- /// # Ok(())
2108- /// # }
2109- /// ```
2057+ ///
2058+ /// For more information on creating offers, see [`create_offer_builder`].
21102059///
21112060/// Use [`pay_for_offer`] to initiated payment, which sends an [`InvoiceRequest`] for an [`Offer`]
21122061/// and pays the [`Bolt12Invoice`] response.
@@ -2228,6 +2177,7 @@ where
22282177/// ```
22292178/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
22302179/// # use lightning::ln::channelmanager::AChannelManager;
2180+ /// # use lightning::offers::flow::OffersMessageCommons;
22312181/// # use lightning::offers::refund::Refund;
22322182/// #
22332183/// # fn example<T: AChannelManager>(channel_manager: T, refund: &Refund) {
@@ -2346,7 +2296,6 @@ where
23462296/// [`claim_funds`]: Self::claim_funds
23472297/// [`send_payment`]: Self::send_payment
23482298/// [`offers`]: crate::offers
2349- /// [`create_offer_builder`]: Self::create_offer_builder
23502299/// [`pay_for_offer`]: Self::pay_for_offer
23512300/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
23522301/// [`create_refund_builder`]: Self::create_refund_builder
@@ -2358,6 +2307,7 @@ where
23582307/// [`update_channel`]: chain::Watch::update_channel
23592308/// [`ChannelUpdate`]: msgs::ChannelUpdate
23602309/// [`read`]: ReadableArgs::read
2310+ /// [`create_offer_builder`]: crate::offers::flow::OffersMessageFlow::create_offer_builder
23612311//
23622312// Lock order:
23632313// The tree structure below illustrates the lock order requirements for the different locks of the
@@ -2853,11 +2803,13 @@ const MAX_NO_CHANNEL_PEERS: usize = 250;
28532803/// The maximum expiration from the current time where an [`Offer`] or [`Refund`] is considered
28542804/// short-lived, while anything with a greater expiration is considered long-lived.
28552805///
2856- /// Using [`ChannelManager ::create_offer_builder`] or [`ChannelManager::create_refund_builder`],
2806+ /// Using [`OffersMessageFlow ::create_offer_builder`] or [`ChannelManager::create_refund_builder`],
28572807/// will included a [`BlindedMessagePath`] created using:
28582808/// - [`MessageRouter::create_compact_blinded_paths`] when short-lived, and
28592809/// - [`MessageRouter::create_blinded_paths`] when long-lived.
28602810///
2811+ /// [`OffersMessageFlow::create_offer_builder`]: crate::offers::flow::OffersMessageFlow::create_offer_builder
2812+ ///
28612813/// Using compact [`BlindedMessagePath`]s may provide better privacy as the [`MessageRouter`] could select
28622814/// more hops. However, since they use short channel ids instead of pubkeys, they are more likely to
28632815/// become invalid over time as channels are closed. Thus, they are only suitable for short-term use.
@@ -6853,7 +6805,7 @@ where
68536805 /// [`Event::PaymentClaimable::claim_deadline`]: crate::events::Event::PaymentClaimable::claim_deadline
68546806 /// [`Event::PaymentClaimed`]: crate::events::Event::PaymentClaimed
68556807 /// [`process_pending_events`]: EventsProvider::process_pending_events
6856- /// [`create_inbound_payment`]: Self ::create_inbound_payment
6808+ /// [`create_inbound_payment`]: ChannelManager ::create_inbound_payment
68576809 /// [`create_inbound_payment_for_hash`]: ChannelManager::create_inbound_payment_for_hash
68586810 /// [`claim_funds_with_known_custom_tlvs`]: ChannelManager::claim_funds_with_known_custom_tlvs
68596811 pub fn claim_funds(&self, payment_preimage: PaymentPreimage) {
@@ -9682,57 +9634,6 @@ impl Default for Bolt11InvoiceParameters {
96829634 }
96839635}
96849636
9685- macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
9686- /// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
9687- /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer's
9688- /// expiration will be `absolute_expiry` if `Some`, otherwise it will not expire.
9689- ///
9690- /// # Privacy
9691- ///
9692- /// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the offer based on the given
9693- /// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
9694- /// privacy implications as well as those of the parameterized [`Router`], which implements
9695- /// [`MessageRouter`].
9696- ///
9697- /// Also, uses a derived signing pubkey in the offer for recipient privacy.
9698- ///
9699- /// # Limitations
9700- ///
9701- /// Requires a direct connection to the introduction node in the responding [`InvoiceRequest`]'s
9702- /// reply path.
9703- ///
9704- /// # Errors
9705- ///
9706- /// Errors if the parameterized [`Router`] is unable to create a blinded path for the offer.
9707- ///
9708- /// [`Offer`]: crate::offers::offer::Offer
9709- /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
9710- pub fn create_offer_builder(
9711- &$self, absolute_expiry: Option<Duration>
9712- ) -> Result<$builder, Bolt12SemanticError> {
9713- let node_id = $self.get_our_node_id();
9714- let expanded_key = &$self.inbound_payment_key;
9715- let entropy = &*$self.entropy_source;
9716- let secp_ctx = &$self.secp_ctx;
9717-
9718- let nonce = Nonce::from_entropy_source(entropy);
9719- let context = OffersContext::InvoiceRequest { nonce };
9720- let path = $self.create_blinded_paths_using_absolute_expiry(context, absolute_expiry)
9721- .and_then(|paths| paths.into_iter().next().ok_or(()))
9722- .map_err(|_| Bolt12SemanticError::MissingPaths)?;
9723- let builder = OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx)
9724- .chain_hash($self.chain_hash)
9725- .path(path);
9726-
9727- let builder = match absolute_expiry {
9728- None => builder,
9729- Some(absolute_expiry) => builder.absolute_expiry(absolute_expiry),
9730- };
9731-
9732- Ok(builder.into())
9733- }
9734- } }
9735-
97369637macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
97379638 /// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
97389639 /// [`ChannelManager`] when handling [`Bolt12Invoice`] messages for the refund.
@@ -9877,6 +9778,16 @@ where
98779778 ) -> Result<(), Bolt12PaymentError> {
98789779 self.initiate_async_payment(invoice, payment_id)
98799780 }
9781+
9782+ fn create_blinded_paths_using_absolute_expiry(
9783+ &self, context: OffersContext, absolute_expiry: Option<Duration>,
9784+ ) -> Result<Vec<BlindedMessagePath>, ()> {
9785+ self.create_blinded_paths_using_absolute_expiry(context, absolute_expiry)
9786+ }
9787+
9788+ fn get_chain_hash(&self) -> ChainHash {
9789+ self.chain_hash
9790+ }
98809791}
98819792
98829793/// Defines the maximum number of [`OffersMessage`] including different reply paths to be sent
@@ -9898,13 +9809,9 @@ where
98989809 MR::Target: MessageRouter,
98999810 L::Target: Logger,
99009811{
9901- #[cfg(not(c_bindings))]
9902- create_offer_builder!(self, OfferBuilder<DerivedMetadata, secp256k1::All>);
99039812 #[cfg(not(c_bindings))]
99049813 create_refund_builder!(self, RefundBuilder<secp256k1::All>);
99059814
9906- #[cfg(c_bindings)]
9907- create_offer_builder!(self, OfferWithDerivedMetadataBuilder);
99089815 #[cfg(c_bindings)]
99099816 create_refund_builder!(self, RefundMaybeWithDerivedMetadataBuilder);
99109817
@@ -10416,12 +10323,11 @@ where
1041610323 /// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
1041710324 /// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
1041810325 /// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
10419- fn create_blinded_paths_using_absolute_expiry(
10326+ pub fn create_blinded_paths_using_absolute_expiry(
1042010327 &self, context: OffersContext, absolute_expiry: Option<Duration>,
1042110328 ) -> Result<Vec<BlindedMessagePath>, ()> {
1042210329 let now = self.duration_since_epoch();
1042310330 let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
10424-
1042510331 if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
1042610332 self.create_compact_blinded_paths(context)
1042710333 } else {
@@ -15540,6 +15446,7 @@ pub mod bench {
1554015446 use crate::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentId, RecipientOnionFields, Retry};
1554115447 use crate::ln::functional_test_utils::*;
1554215448 use crate::ln::msgs::{ChannelMessageHandler, Init};
15449+ use crate::offers::flow::OffersMessageCommons;
1554315450 use crate::routing::gossip::NetworkGraph;
1554415451 use crate::routing::router::{PaymentParameters, RouteParameters};
1554515452 use crate::util::test_utils;
0 commit comments