diff --git a/lightning-dns-resolver/src/lib.rs b/lightning-dns-resolver/src/lib.rs index 73dccdadd23..f0451b6cc26 100644 --- a/lightning-dns-resolver/src/lib.rs +++ b/lightning-dns-resolver/src/lib.rs @@ -162,7 +162,7 @@ mod test { use lightning::blinded_path::message::{BlindedMessagePath, MessageContext}; use lightning::blinded_path::NodeIdLookUp; use lightning::events::{Event, PaymentPurpose}; - use lightning::ln::channelmanager::{PaymentId, Retry}; + use lightning::ln::channelmanager::{OptionalOfferPaymentInfo, PaymentId}; use lightning::ln::functional_test_utils::*; use lightning::ln::msgs::{ BaseMessageHandler, ChannelMessageHandler, Init, OnionMessageHandler, @@ -173,7 +173,6 @@ mod test { use lightning::onion_message::messenger::{ AOnionMessenger, Destination, MessageRouter, OnionMessagePath, OnionMessenger, }; - use lightning::routing::router::RouteParametersConfig; use lightning::sign::{KeysManager, NodeSigner, Recipient}; use lightning::types::features::InitFeatures; use lightning::types::payment::PaymentHash; @@ -369,23 +368,18 @@ mod test { async fn pay_offer_flow<'a, 'b, 'c>( nodes: &[Node<'a, 'b, 'c>], resolver_messenger: &impl AOnionMessenger, resolver_id: PublicKey, payer_id: PublicKey, payee_id: PublicKey, offer: Offer, - name: HumanReadableName, amt: u64, payment_id: PaymentId, payer_note: Option, - retry: Retry, params: RouteParametersConfig, resolvers: Vec, + name: HumanReadableName, payment_id: PaymentId, payer_note: Option, + resolvers: Vec, ) { // Override contents to offer provided let proof_override = &nodes[0].node.testing_dnssec_proof_offer_resolution_override; proof_override.lock().unwrap().insert(name.clone(), offer); + let amt = 42_000; + let mut opts = OptionalOfferPaymentInfo::default(); + opts.payer_note = payer_note.clone(); nodes[0] .node - .pay_for_offer_from_human_readable_name( - name, - amt, - payment_id, - payer_note.clone(), - retry, - params, - resolvers, - ) + .pay_for_offer_from_human_readable_name(name, amt, payment_id, opts, resolvers) .unwrap(); let query = nodes[0].onion_messenger.next_onion_message_for_peer(resolver_id).unwrap(); @@ -482,9 +476,6 @@ mod test { let bs_offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap(); let resolvers = vec![Destination::Node(resolver_id)]; - let retry = Retry::Attempts(0); - let amt = 42_000; - let params = RouteParametersConfig::default(); pay_offer_flow( &nodes, @@ -494,11 +485,8 @@ mod test { payee_id, bs_offer.clone(), name.clone(), - amt, PaymentId([42; 32]), None, - retry, - params, resolvers.clone(), ) .await; @@ -512,11 +500,8 @@ mod test { payee_id, bs_offer, name, - amt, PaymentId([21; 32]), Some("foo".into()), - retry, - params, resolvers, ) .await; diff --git a/lightning/src/ln/async_payments_tests.rs b/lightning/src/ln/async_payments_tests.rs index a956f2ebae2..4f36b708e5a 100644 --- a/lightning/src/ln/async_payments_tests.rs +++ b/lightning/src/ln/async_payments_tests.rs @@ -13,7 +13,7 @@ use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentTlvs}; use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS}; use crate::events::{Event, HTLCHandlingFailureType, PaidBolt12Invoice, PaymentFailureReason}; use crate::ln::blinded_payment_tests::{fail_blinded_htlc_backwards, get_blinded_route_parameters}; -use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; +use crate::ln::channelmanager::{OptionalOfferPaymentInfo, PaymentId, RecipientOnionFields}; use crate::ln::functional_test_utils::*; use crate::ln::msgs; use crate::ln::msgs::{ @@ -32,7 +32,7 @@ use crate::onion_message::messenger::{Destination, MessageRouter, MessageSendIns use crate::onion_message::offers::OffersMessage; use crate::onion_message::packet::ParsedOnionMessageContents; use crate::prelude::*; -use crate::routing::router::{Payee, PaymentParameters, RouteParametersConfig}; +use crate::routing::router::{Payee, PaymentParameters}; use crate::sign::NodeSigner; use crate::sync::Mutex; use crate::types::features::Bolt12InvoiceFeatures; @@ -239,10 +239,9 @@ fn static_invoice_unknown_required_features() { let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); // Don't forward the invreq since we don't support retrieving the static invoice from the @@ -300,10 +299,9 @@ fn ignore_unexpected_static_invoice() { create_static_invoice(&nodes[1], &nodes[2], None, &secp_ctx); let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); // Don't forward the invreq since we don't support retrieving the static invoice from the @@ -418,10 +416,9 @@ fn async_receive_flow_success() { let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); let release_held_htlc_om = pass_async_payments_oms(static_invoice.clone(), &nodes[0], &nodes[1], &nodes[2]).1; @@ -470,10 +467,9 @@ fn expired_static_invoice_fail() { let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); let invreq_om = nodes[0] @@ -561,10 +557,9 @@ fn async_receive_mpp() { // the different MPP parts to not be unique. let amt_msat = 15_000_000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); let release_held_htlc_om_3_0 = pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[3]).1; @@ -652,10 +647,9 @@ fn amount_doesnt_match_invreq() { let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); let release_held_htlc_om_3_0 = pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[3]).1; @@ -888,10 +882,9 @@ fn invalid_async_receive_with_retry( let payment_hash: PaymentHash = keysend_preimage.into(); *nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some(hardcoded_random_bytes); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(2), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); let release_held_htlc_om_2_0 = pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1; @@ -978,10 +971,9 @@ fn expired_static_invoice_message_path() { let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), params) + .pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default(), None) .unwrap(); // While the invoice is unexpired, respond with release_held_htlc. @@ -1083,11 +1075,9 @@ fn expired_static_invoice_payment_path() { let (offer, static_invoice) = create_static_invoice(&nodes[1], &nodes[2], None, &secp_ctx); let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - let params = RouteParametersConfig::default(); - nodes[0] - .node - .pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params) - .unwrap(); + let mut params: OptionalOfferPaymentInfo = Default::default(); + params.retry_strategy = Retry::Attempts(0); + nodes[0].node.pay_for_offer(&offer, Some(amt_msat), payment_id, params, None).unwrap(); let release_held_htlc_om = pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1; nodes[0] diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 8a904a90e64..7169de37195 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -687,6 +687,53 @@ impl Readable for InterceptId { } } +/// Optional arguments to [`ChannelManager::pay_for_offer`] +#[cfg_attr( + feature = "dnssec", + doc = "and [`ChannelManager::pay_for_offer_from_human_readable_name`]" +)] +/// . +/// +/// These fields will often not need to be set, and the provided [`Self::default`] can be used. +pub struct OptionalOfferPaymentInfo { + /// The quantity of the offer which we wish to pay for. This is communicated to the recipient + /// and determines the minimum value which we must pay. + /// + /// This must be set if we're paying for an offer that has [`Offer::expects_quantity`]. + /// + #[cfg_attr( + feature = "dnssec", + doc = "Note that setting this will cause [`ChannelManager::pay_for_offer_from_human_readable_name`] to fail." + )] + pub quantity: Option, + /// A note which is communicated to the recipient about this payment via + /// [`InvoiceRequest::payer_note`]. + pub payer_note: Option, + /// Pathfinding options which tweak how the path is constructed to the recipient. + pub route_params_config: RouteParametersConfig, + /// The number of tries or time during which we'll retry this payment if some paths to the + /// recipient fail. + /// + /// Once the retry limit is reached, further path failures will not be retried and the payment + /// will ultimately fail once all pending paths have failed (generating an + /// [`Event::PaymentFailed`]). + pub retry_strategy: Retry, +} + +impl Default for OptionalOfferPaymentInfo { + fn default() -> Self { + Self { + quantity: None, + payer_note: None, + route_params_config: Default::default(), + #[cfg(feature = "std")] + retry_strategy: Retry::Timeout(core::time::Duration::from_secs(2)), + #[cfg(not(feature = "std"))] + retry_strategy: Retry::Attempts(3), + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] /// Uniquely describes an HTLC by its source. Just the guaranteed-unique subset of [`HTLCSource`]. pub(crate) enum SentHTLCId { @@ -2256,18 +2303,16 @@ where /// /// ``` /// # use lightning::events::{Event, EventsProvider}; -/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry}; +/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails}; /// # use lightning::offers::offer::Offer; -/// # use lightning::routing::router::RouteParametersConfig; /// # /// # fn example( -/// # channel_manager: T, offer: &Offer, quantity: Option, amount_msats: Option, -/// # payer_note: Option, retry: Retry, route_params_config: RouteParametersConfig +/// # channel_manager: T, offer: &Offer, amount_msats: Option, /// # ) { /// # let channel_manager = channel_manager.get_cm(); /// let payment_id = PaymentId([42; 32]); /// match channel_manager.pay_for_offer( -/// offer, quantity, amount_msats, payer_note, payment_id, retry, route_params_config +/// offer, amount_msats, payment_id, Default::default(), None, /// ) { /// Ok(()) => println!("Requesting invoice for offer"), /// Err(e) => println!("Unable to request invoice for offer: {:?}", e), @@ -5024,6 +5069,9 @@ where /// Sends a payment to the route found using the provided [`RouteParameters`], retrying failed /// payment paths based on the provided `Retry`. /// + /// You should likely prefer [`Self::pay_for_bolt11_invoice`] or [`Self::pay_for_offer`] in + /// general, however this method may allow for slightly more customization. + /// /// May generate [`UpdateHTLCs`] message(s) event on success, which should be relayed (e.g. via /// [`PeerManager::process_events`]). /// @@ -11128,16 +11176,12 @@ where /// /// Uses [`InvoiceRequestBuilder`] such that the [`InvoiceRequest`] it builds is recognized by /// the [`ChannelManager`] when handling a [`Bolt12Invoice`] message in response to the request. - /// The optional parameters are used in the builder, if `Some`: - /// - `quantity` for [`InvoiceRequest::quantity`] which must be set if - /// [`Offer::expects_quantity`] is `true`. - /// - `amount_msats` if overpaying what is required for the given `quantity` is desired, and - /// - `payer_note` for [`InvoiceRequest::payer_note`]. /// - /// # Custom Routing Parameters + /// `amount_msats` allows you to overpay what is required to satisfy the offer, or may be + /// required if the offer does not require a specific amount. /// - /// Users can customize routing parameters via [`RouteParametersConfig`]. - /// To use default settings, call the function with [`RouteParametersConfig::default`]. + /// If the [`Offer`] was built from a human readable name resolved using BIP 353, + /// `derived_from_hrn` must be set to `Some` to include the name. /// /// # Payment /// @@ -11155,12 +11199,6 @@ where /// to construct a [`BlindedMessagePath`] for the reply path. For further privacy implications, see the /// docs of the parameterized [`Router`], which implements [`MessageRouter`]. /// - /// # Limitations - /// - /// Requires a direct connection to an introduction node in [`Offer::paths`] or to - /// [`Offer::issuer_signing_pubkey`], if empty. A similar restriction applies to the responding - /// [`Bolt12Invoice::payment_paths`]. - /// /// # Errors /// /// Errors if: @@ -11179,9 +11217,8 @@ where /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments pub fn pay_for_offer( - &self, offer: &Offer, quantity: Option, amount_msats: Option, - payer_note: Option, payment_id: PaymentId, retry_strategy: Retry, - route_params_config: RouteParametersConfig, + &self, offer: &Offer, amount_msats: Option, payment_id: PaymentId, + optional_info: OptionalOfferPaymentInfo, derived_from_hrn: Option, ) -> Result<(), Bolt12SemanticError> { let create_pending_payment_fn = |invoice_request: &InvoiceRequest, nonce| { let expiration = StaleExpiration::TimerTicks(1); @@ -11194,8 +11231,8 @@ where .add_new_awaiting_invoice( payment_id, expiration, - retry_strategy, - route_params_config, + optional_info.retry_strategy, + optional_info.route_params_config, Some(retryable_invoice_request), ) .map_err(|_| Bolt12SemanticError::DuplicatePaymentId) @@ -11203,11 +11240,11 @@ where self.pay_for_offer_intern( offer, - quantity, + optional_info.quantity, amount_msats, - payer_note, + optional_info.payer_note, payment_id, - None, + derived_from_hrn, create_pending_payment_fn, ) } @@ -11311,12 +11348,8 @@ where /// If the wallet supports paying on-chain schemes, you should instead use /// [`OMNameResolver::resolve_name`] and [`OMNameResolver::handle_dnssec_proof_for_uri`] (by /// implementing [`DNSResolverMessageHandler`]) directly to look up a URI and then delegate to - /// your normal URI handling. - /// - /// # Custom Routing Parameters - /// - /// Users can customize routing parameters via [`RouteParametersConfig`]. - /// To use default settings, call the function with [`RouteParametersConfig::default`]. + /// your normal URI handling. The `bitcoin-payment-instructions` crate provides an + /// implementation of much of this logic. /// /// # Payment /// @@ -11335,16 +11368,11 @@ where /// to construct a [`BlindedMessagePath`] for the reply path. For further privacy implications, see the /// docs of the parameterized [`Router`], which implements [`MessageRouter`]. /// - /// # Limitations - /// - /// Requires a direct connection to the given [`Destination`] as well as an introduction node in - /// [`Offer::paths`] or to [`Offer::issuer_signing_pubkey`], if empty. A similar restriction applies to - /// the responding [`Bolt12Invoice::payment_paths`]. - /// /// # Errors /// /// Errors if: /// - a duplicate `payment_id` is provided given the caveats in the aforementioned link, + /// - [`OptionalOfferPaymentInfo.quantity`] is set. /// /// [BIP 353]: https://github.com/bitcoin/bips/blob/master/bip-0353.mediawiki /// [bLIP 32]: https://github.com/lightning/blips/blob/master/blip-0032.md @@ -11358,9 +11386,12 @@ where #[cfg(feature = "dnssec")] pub fn pay_for_offer_from_human_readable_name( &self, name: HumanReadableName, amount_msats: u64, payment_id: PaymentId, - payer_note: Option, retry_strategy: Retry, - route_params_config: RouteParametersConfig, dns_resolvers: Vec, + optional_info: OptionalOfferPaymentInfo, dns_resolvers: Vec, ) -> Result<(), ()> { + if optional_info.quantity.is_some() { + return Err(()); + } + let (onion_message, context) = self.flow.hrn_resolver.resolve_name(payment_id, name, &*self.entropy_source)?; @@ -11368,10 +11399,10 @@ where self.pending_outbound_payments.add_new_awaiting_offer( payment_id, expiration, - retry_strategy, - route_params_config, + optional_info.retry_strategy, + optional_info.route_params_config, amount_msats, - payer_note, + optional_info.payer_note, )?; self.flow diff --git a/lightning/src/ln/max_payment_path_len_tests.rs b/lightning/src/ln/max_payment_path_len_tests.rs index ff5053644d8..02631761998 100644 --- a/lightning/src/ln/max_payment_path_len_tests.rs +++ b/lightning/src/ln/max_payment_path_len_tests.rs @@ -17,7 +17,7 @@ use crate::blinded_path::payment::{ use crate::blinded_path::BlindedHop; use crate::events::Event; use crate::ln::blinded_payment_tests::get_blinded_route_parameters; -use crate::ln::channelmanager::PaymentId; +use crate::ln::channelmanager::{OptionalOfferPaymentInfo, PaymentId}; use crate::ln::functional_test_utils::*; use crate::ln::msgs; use crate::ln::msgs::{BaseMessageHandler, OnionMessageHandler}; @@ -27,7 +27,7 @@ use crate::ln::outbound_payment::{RecipientOnionFields, Retry, RetryableSendFail use crate::offers::nonce::Nonce; use crate::prelude::*; use crate::routing::router::{ - PaymentParameters, RouteParameters, RouteParametersConfig, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, + PaymentParameters, RouteParameters, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, }; use crate::sign::NodeSigner; use crate::types::features::BlindedHopFeatures; @@ -519,10 +519,9 @@ fn bolt12_invoice_too_large_blinded_paths() { let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap(); let payment_id = PaymentId([1; 32]); - let route_config = RouteParametersConfig::default(); nodes[0] .node - .pay_for_offer(&offer, None, Some(5000), None, payment_id, Retry::Attempts(0), route_config) + .pay_for_offer(&offer, Some(5000), payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); let invreq_om = nodes[0] .onion_messenger diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index ad0a8eea2aa..ba40d757166 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -50,7 +50,7 @@ use crate::blinded_path::message::BlindedMessagePath; use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext}; use crate::blinded_path::message::OffersContext; use crate::events::{ClosureReason, Event, HTLCHandlingFailureType, PaidBolt12Invoice, PaymentFailureReason, PaymentPurpose}; -use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry, self}; +use crate::ln::channelmanager::{Bolt12PaymentError, OptionalOfferPaymentInfo, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry, self}; use crate::types::features::Bolt12InvoiceFeatures; use crate::ln::functional_test_utils::*; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement}; @@ -543,7 +543,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { } let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -712,7 +712,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { } let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None).unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -833,7 +833,7 @@ fn pays_for_offer_without_blinded_paths() { assert!(offer.paths().is_empty()); let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None).unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -960,7 +960,7 @@ fn send_invoice_requests_with_distinct_reply_path() { } let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); connect_peers(david, bob); @@ -1094,7 +1094,7 @@ fn creates_and_pays_for_offer_with_retry() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); } let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None).unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let _lost_onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -1166,7 +1166,7 @@ fn pays_bolt12_invoice_asynchronously() { .build().unwrap(); let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None).unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -1263,7 +1263,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { } let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None).unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -1404,7 +1404,7 @@ fn fails_authentication_when_handling_invoice_request() { // Send the invoice request directly to Alice instead of using a blinded path. let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -1430,7 +1430,7 @@ fn fails_authentication_when_handling_invoice_request() { // Send the invoice request to Alice using an invalid blinded path. let payment_id = PaymentId([2; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -1507,7 +1507,7 @@ fn fails_authentication_when_handling_invoice_for_offer() { // Initiate an invoice request, but abandon tracking it. let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); david.node.abandon_payment(payment_id); get_event!(david, Event::PaymentFailed); @@ -1524,7 +1524,7 @@ fn fails_authentication_when_handling_invoice_for_offer() { }; let payment_id = PaymentId([2; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -1708,7 +1708,7 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() { let payment_id = PaymentId([1; 32]); - match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths), } @@ -1721,7 +1721,7 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() { assert!( david.node.pay_for_offer( - &offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default() + &offer, None, payment_id, OptionalOfferPaymentInfo::default(), None ).is_ok() ); @@ -1812,7 +1812,7 @@ fn fails_creating_invoice_request_for_unsupported_chain() { .build().unwrap(); let payment_id = PaymentId([1; 32]); - match bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match bob.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain), } @@ -1871,7 +1871,7 @@ fn fails_creating_invoice_request_without_blinded_reply_path() { let payment_id = PaymentId([1; 32]); - match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths), } @@ -1906,12 +1906,12 @@ fn fails_creating_invoice_request_with_duplicate_payment_id() { let payment_id = PaymentId([1; 32]); assert!( david.node.pay_for_offer( - &offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default() + &offer, None, payment_id, OptionalOfferPaymentInfo::default(), None ).is_ok() ); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); - match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId), } @@ -1990,7 +1990,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() { .build().unwrap(); let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); connect_peers(david, bob); @@ -2199,7 +2199,7 @@ fn fails_paying_invoice_with_unknown_required_features() { .build().unwrap(); let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david.node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None) .unwrap(); connect_peers(david, bob); @@ -2276,7 +2276,7 @@ fn rejects_keysend_to_non_static_invoice_path() { let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap(); let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), RouteParametersConfig::default()).unwrap(); + nodes[0].node.pay_for_offer(&offer, Some(amt_msat), payment_id, OptionalOfferPaymentInfo::default(), None).unwrap(); let invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap(); nodes[1].onion_messenger.handle_onion_message(nodes[0].node.get_our_node_id(), &invreq_om); let invoice_om = nodes[1].onion_messenger.next_onion_message_for_peer(nodes[0].node.get_our_node_id()).unwrap(); @@ -2361,7 +2361,7 @@ fn no_double_pay_with_stale_channelmanager() { assert!(offer.paths().is_empty()); let payment_id = PaymentId([1; 32]); - nodes[0].node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + nodes[0].node.pay_for_offer(&offer, None, payment_id, OptionalOfferPaymentInfo::default(), None).unwrap(); expect_recent_payment!(nodes[0], RecentPaymentDetails::AwaitingInvoice, payment_id); let invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(bob_id).unwrap();