Skip to content

Commit 4c4f167

Browse files
committed
Move reasonable-default arguments out of pay_for_offer.
`ChannelManager::pay_for_offer` and `ChannelManager::pay_for_offer_from_human_readable_name` have accumulated a handful of arguments, most of which we expect users to never actually set. Instead, here, we move `quantity` and `payer_note` (which we expect users to never set) as well as `route_params_config` and `retry_strategy` (which we expect users to generally stick with the defaults on) into a new struct, which implements `Default`. This cleans up a good bit of cruft on payment calls.
1 parent 6771d84 commit 4c4f167

File tree

5 files changed

+115
-102
lines changed

5 files changed

+115
-102
lines changed

lightning-dns-resolver/src/lib.rs

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ mod test {
162162
use lightning::blinded_path::message::{BlindedMessagePath, MessageContext};
163163
use lightning::blinded_path::NodeIdLookUp;
164164
use lightning::events::{Event, PaymentPurpose};
165-
use lightning::ln::channelmanager::{PaymentId, Retry};
165+
use lightning::ln::channelmanager::{OptionalOfferPaymentInfo, PaymentId};
166166
use lightning::ln::functional_test_utils::*;
167167
use lightning::ln::msgs::{
168168
BaseMessageHandler, ChannelMessageHandler, Init, OnionMessageHandler,
@@ -173,7 +173,6 @@ mod test {
173173
use lightning::onion_message::messenger::{
174174
AOnionMessenger, Destination, MessageRouter, OnionMessagePath, OnionMessenger,
175175
};
176-
use lightning::routing::router::RouteParametersConfig;
177176
use lightning::sign::{KeysManager, NodeSigner, Recipient};
178177
use lightning::types::features::InitFeatures;
179178
use lightning::types::payment::PaymentHash;
@@ -369,23 +368,18 @@ mod test {
369368
async fn pay_offer_flow<'a, 'b, 'c>(
370369
nodes: &[Node<'a, 'b, 'c>], resolver_messenger: &impl AOnionMessenger,
371370
resolver_id: PublicKey, payer_id: PublicKey, payee_id: PublicKey, offer: Offer,
372-
name: HumanReadableName, amt: u64, payment_id: PaymentId, payer_note: Option<String>,
373-
retry: Retry, params: RouteParametersConfig, resolvers: Vec<Destination>,
371+
name: HumanReadableName, payment_id: PaymentId, payer_note: Option<String>,
372+
resolvers: Vec<Destination>,
374373
) {
375374
// Override contents to offer provided
376375
let proof_override = &nodes[0].node.testing_dnssec_proof_offer_resolution_override;
377376
proof_override.lock().unwrap().insert(name.clone(), offer);
377+
let amt = 42_000;
378+
let mut opts = OptionalOfferPaymentInfo::default();
379+
opts.payer_note = payer_note.clone();
378380
nodes[0]
379381
.node
380-
.pay_for_offer_from_human_readable_name(
381-
name,
382-
amt,
383-
payment_id,
384-
payer_note.clone(),
385-
retry,
386-
params,
387-
resolvers,
388-
)
382+
.pay_for_offer_from_human_readable_name(name, amt, payment_id, opts, resolvers)
389383
.unwrap();
390384

391385
let query = nodes[0].onion_messenger.next_onion_message_for_peer(resolver_id).unwrap();
@@ -482,9 +476,6 @@ mod test {
482476

483477
let bs_offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
484478
let resolvers = vec![Destination::Node(resolver_id)];
485-
let retry = Retry::Attempts(0);
486-
let amt = 42_000;
487-
let params = RouteParametersConfig::default();
488479

489480
pay_offer_flow(
490481
&nodes,
@@ -494,11 +485,8 @@ mod test {
494485
payee_id,
495486
bs_offer.clone(),
496487
name.clone(),
497-
amt,
498488
PaymentId([42; 32]),
499489
None,
500-
retry,
501-
params,
502490
resolvers.clone(),
503491
)
504492
.await;
@@ -512,11 +500,8 @@ mod test {
512500
payee_id,
513501
bs_offer,
514502
name,
515-
amt,
516503
PaymentId([21; 32]),
517504
Some("foo".into()),
518-
retry,
519-
params,
520505
resolvers,
521506
)
522507
.await;

lightning/src/ln/async_payments_tests.rs

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentTlvs};
1313
use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
1414
use crate::events::{Event, HTLCHandlingFailureType, PaidBolt12Invoice, PaymentFailureReason};
1515
use crate::ln::blinded_payment_tests::{fail_blinded_htlc_backwards, get_blinded_route_parameters};
16-
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
16+
use crate::ln::channelmanager::{OptionalOfferPaymentInfo, PaymentId, RecipientOnionFields};
1717
use crate::ln::functional_test_utils::*;
1818
use crate::ln::msgs;
1919
use crate::ln::msgs::{
@@ -32,7 +32,7 @@ use crate::onion_message::messenger::{Destination, MessageRouter, MessageSendIns
3232
use crate::onion_message::offers::OffersMessage;
3333
use crate::onion_message::packet::ParsedOnionMessageContents;
3434
use crate::prelude::*;
35-
use crate::routing::router::{Payee, PaymentParameters, RouteParametersConfig};
35+
use crate::routing::router::{Payee, PaymentParameters};
3636
use crate::sign::NodeSigner;
3737
use crate::sync::Mutex;
3838
use crate::types::features::Bolt12InvoiceFeatures;
@@ -239,10 +239,9 @@ fn static_invoice_unknown_required_features() {
239239

240240
let amt_msat = 5000;
241241
let payment_id = PaymentId([1; 32]);
242-
let params = RouteParametersConfig::default();
243242
nodes[0]
244243
.node
245-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params)
244+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
246245
.unwrap();
247246

248247
// 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() {
300299
create_static_invoice(&nodes[1], &nodes[2], None, &secp_ctx);
301300
let amt_msat = 5000;
302301
let payment_id = PaymentId([1; 32]);
303-
let params = RouteParametersConfig::default();
304302
nodes[0]
305303
.node
306-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params)
304+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
307305
.unwrap();
308306

309307
// 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() {
418416

419417
let amt_msat = 5000;
420418
let payment_id = PaymentId([1; 32]);
421-
let params = RouteParametersConfig::default();
422419
nodes[0]
423420
.node
424-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params)
421+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
425422
.unwrap();
426423
let release_held_htlc_om =
427424
pass_async_payments_oms(static_invoice.clone(), &nodes[0], &nodes[1], &nodes[2]).1;
@@ -470,10 +467,9 @@ fn expired_static_invoice_fail() {
470467

471468
let amt_msat = 5000;
472469
let payment_id = PaymentId([1; 32]);
473-
let params = RouteParametersConfig::default();
474470
nodes[0]
475471
.node
476-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params)
472+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
477473
.unwrap();
478474

479475
let invreq_om = nodes[0]
@@ -561,10 +557,9 @@ fn async_receive_mpp() {
561557
// the different MPP parts to not be unique.
562558
let amt_msat = 15_000_000;
563559
let payment_id = PaymentId([1; 32]);
564-
let params = RouteParametersConfig::default();
565560
nodes[0]
566561
.node
567-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), params)
562+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
568563
.unwrap();
569564
let release_held_htlc_om_3_0 =
570565
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[3]).1;
@@ -652,10 +647,9 @@ fn amount_doesnt_match_invreq() {
652647

653648
let amt_msat = 5000;
654649
let payment_id = PaymentId([1; 32]);
655-
let params = RouteParametersConfig::default();
656650
nodes[0]
657651
.node
658-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), params)
652+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
659653
.unwrap();
660654
let release_held_htlc_om_3_0 =
661655
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[3]).1;
@@ -888,10 +882,9 @@ fn invalid_async_receive_with_retry<F1, F2>(
888882
let payment_hash: PaymentHash = keysend_preimage.into();
889883
*nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some(hardcoded_random_bytes);
890884

891-
let params = RouteParametersConfig::default();
892885
nodes[0]
893886
.node
894-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(2), params)
887+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
895888
.unwrap();
896889
let release_held_htlc_om_2_0 =
897890
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1;
@@ -978,10 +971,9 @@ fn expired_static_invoice_message_path() {
978971

979972
let amt_msat = 5000;
980973
let payment_id = PaymentId([1; 32]);
981-
let params = RouteParametersConfig::default();
982974
nodes[0]
983975
.node
984-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), params)
976+
.pay_for_offer(&offer, Some(amt_msat), payment_id, Default::default())
985977
.unwrap();
986978

987979
// While the invoice is unexpired, respond with release_held_htlc.
@@ -1083,11 +1075,9 @@ fn expired_static_invoice_payment_path() {
10831075
let (offer, static_invoice) = create_static_invoice(&nodes[1], &nodes[2], None, &secp_ctx);
10841076
let amt_msat = 5000;
10851077
let payment_id = PaymentId([1; 32]);
1086-
let params = RouteParametersConfig::default();
1087-
nodes[0]
1088-
.node
1089-
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params)
1090-
.unwrap();
1078+
let mut params: OptionalOfferPaymentInfo = Default::default();
1079+
params.retry_strategy = Retry::Attempts(0);
1080+
nodes[0].node.pay_for_offer(&offer, Some(amt_msat), payment_id, params).unwrap();
10911081
let release_held_htlc_om =
10921082
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1;
10931083
nodes[0]

lightning/src/ln/channelmanager.rs

Lines changed: 70 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,53 @@ impl Readable for InterceptId {
687687
}
688688
}
689689

690+
/// Optional arguments to [`ChannelManager::pay_for_offer`]
691+
#[cfg_attr(
692+
feature = "dnssec",
693+
doc = "and [`ChannelManager::pay_for_offer_from_human_readable_name`]"
694+
)]
695+
/// .
696+
///
697+
/// These fields will often not need to be set, and the provided [`Self::default`] can be used.
698+
pub struct OptionalOfferPaymentInfo {
699+
/// The quantity of the offer which we wish to pay for. This is communicated to the recipient
700+
/// and determines the minimum value which we must pay.
701+
///
702+
/// This must be set if we're paying for an offer that has [`Offer::expects_quantity`].
703+
///
704+
#[cfg_attr(
705+
feature = "dnssec",
706+
doc = "Note that setting this will cause [`ChannelManager::pay_for_offer_from_human_readable_name`] to fail."
707+
)]
708+
pub quantity: Option<u64>,
709+
/// A note which is communicated to the recipient about this payment via
710+
/// [`InvoiceRequest::payer_note`].
711+
pub payer_note: Option<String>,
712+
/// Pathfinding options which tweak how the path is constructed to the recipient.
713+
pub route_params_config: RouteParametersConfig,
714+
/// The number of tries or time during which we'll retry this payment if some paths to the
715+
/// recipient fail.
716+
///
717+
/// Once the retry limit is reached, further path failures will not be retried and the payment
718+
/// will ultimately fail once all pending paths have failed (generating an
719+
/// [`Event::PaymentFailed`]).
720+
pub retry_strategy: Retry,
721+
}
722+
723+
impl Default for OptionalOfferPaymentInfo {
724+
fn default() -> Self {
725+
Self {
726+
quantity: None,
727+
payer_note: None,
728+
route_params_config: Default::default(),
729+
#[cfg(feature = "std")]
730+
retry_strategy: Retry::Timeout(core::time::Duration::from_secs(2)),
731+
#[cfg(not(feature = "std"))]
732+
retry_strategy: Retry::Attempts(3),
733+
}
734+
}
735+
}
736+
690737
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
691738
/// Uniquely describes an HTLC by its source. Just the guaranteed-unique subset of [`HTLCSource`].
692739
pub(crate) enum SentHTLCId {
@@ -2256,18 +2303,16 @@ where
22562303
///
22572304
/// ```
22582305
/// # use lightning::events::{Event, EventsProvider};
2259-
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry};
2306+
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails};
22602307
/// # use lightning::offers::offer::Offer;
2261-
/// # use lightning::routing::router::RouteParametersConfig;
22622308
/// #
22632309
/// # fn example<T: AChannelManager>(
2264-
/// # channel_manager: T, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
2265-
/// # payer_note: Option<String>, retry: Retry, route_params_config: RouteParametersConfig
2310+
/// # channel_manager: T, offer: &Offer, amount_msats: Option<u64>,
22662311
/// # ) {
22672312
/// # let channel_manager = channel_manager.get_cm();
22682313
/// let payment_id = PaymentId([42; 32]);
22692314
/// match channel_manager.pay_for_offer(
2270-
/// offer, quantity, amount_msats, payer_note, payment_id, retry, route_params_config
2315+
/// offer, amount_msats, payment_id, Default::default(),
22712316
/// ) {
22722317
/// Ok(()) => println!("Requesting invoice for offer"),
22732318
/// Err(e) => println!("Unable to request invoice for offer: {:?}", e),
@@ -5024,6 +5069,9 @@ where
50245069
/// Sends a payment to the route found using the provided [`RouteParameters`], retrying failed
50255070
/// payment paths based on the provided `Retry`.
50265071
///
5072+
/// You should likely prefer [`Self::pay_for_bolt11_invoice`] or [`Self::pay_for_offer`] in
5073+
/// general, however this method may allow for slightly more customization.
5074+
///
50275075
/// May generate [`UpdateHTLCs`] message(s) event on success, which should be relayed (e.g. via
50285076
/// [`PeerManager::process_events`]).
50295077
///
@@ -11128,16 +11176,9 @@ where
1112811176
///
1112911177
/// Uses [`InvoiceRequestBuilder`] such that the [`InvoiceRequest`] it builds is recognized by
1113011178
/// the [`ChannelManager`] when handling a [`Bolt12Invoice`] message in response to the request.
11131-
/// The optional parameters are used in the builder, if `Some`:
11132-
/// - `quantity` for [`InvoiceRequest::quantity`] which must be set if
11133-
/// [`Offer::expects_quantity`] is `true`.
11134-
/// - `amount_msats` if overpaying what is required for the given `quantity` is desired, and
11135-
/// - `payer_note` for [`InvoiceRequest::payer_note`].
1113611179
///
11137-
/// # Custom Routing Parameters
11138-
///
11139-
/// Users can customize routing parameters via [`RouteParametersConfig`].
11140-
/// To use default settings, call the function with [`RouteParametersConfig::default`].
11180+
/// `amount_msats` allows you to overpay what is required to satisfy the offer, or may be
11181+
/// required if the offer does not require a specific amount.
1114111182
///
1114211183
/// # Payment
1114311184
///
@@ -11179,9 +11220,8 @@ where
1117911220
/// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
1118011221
/// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
1118111222
pub fn pay_for_offer(
11182-
&self, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
11183-
payer_note: Option<String>, payment_id: PaymentId, retry_strategy: Retry,
11184-
route_params_config: RouteParametersConfig,
11223+
&self, offer: &Offer, amount_msats: Option<u64>, payment_id: PaymentId,
11224+
optional_info: OptionalOfferPaymentInfo,
1118511225
) -> Result<(), Bolt12SemanticError> {
1118611226
let create_pending_payment_fn = |invoice_request: &InvoiceRequest, nonce| {
1118711227
let expiration = StaleExpiration::TimerTicks(1);
@@ -11194,18 +11234,18 @@ where
1119411234
.add_new_awaiting_invoice(
1119511235
payment_id,
1119611236
expiration,
11197-
retry_strategy,
11198-
route_params_config,
11237+
optional_info.retry_strategy,
11238+
optional_info.route_params_config,
1119911239
Some(retryable_invoice_request),
1120011240
)
1120111241
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)
1120211242
};
1120311243

1120411244
self.pay_for_offer_intern(
1120511245
offer,
11206-
quantity,
11246+
optional_info.quantity,
1120711247
amount_msats,
11208-
payer_note,
11248+
optional_info.payer_note,
1120911249
payment_id,
1121011250
None,
1121111251
create_pending_payment_fn,
@@ -11313,11 +11353,6 @@ where
1131311353
/// implementing [`DNSResolverMessageHandler`]) directly to look up a URI and then delegate to
1131411354
/// your normal URI handling.
1131511355
///
11316-
/// # Custom Routing Parameters
11317-
///
11318-
/// Users can customize routing parameters via [`RouteParametersConfig`].
11319-
/// To use default settings, call the function with [`RouteParametersConfig::default`].
11320-
///
1132111356
/// # Payment
1132211357
///
1132311358
/// The provided `payment_id` is used to ensure that only one invoice is paid for the request
@@ -11345,6 +11380,7 @@ where
1134511380
///
1134611381
/// Errors if:
1134711382
/// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
11383+
/// - [`OptionalOfferPaymentInfo.quantity`] is set.
1134811384
///
1134911385
/// [BIP 353]: https://github.com/bitcoin/bips/blob/master/bip-0353.mediawiki
1135011386
/// [bLIP 32]: https://github.com/lightning/blips/blob/master/blip-0032.md
@@ -11358,20 +11394,23 @@ where
1135811394
#[cfg(feature = "dnssec")]
1135911395
pub fn pay_for_offer_from_human_readable_name(
1136011396
&self, name: HumanReadableName, amount_msats: u64, payment_id: PaymentId,
11361-
payer_note: Option<String>, retry_strategy: Retry,
11362-
route_params_config: RouteParametersConfig, dns_resolvers: Vec<Destination>,
11397+
optional_info: OptionalOfferPaymentInfo, dns_resolvers: Vec<Destination>,
1136311398
) -> Result<(), ()> {
11399+
if optional_info.quantity.is_some() {
11400+
return Err(());
11401+
}
11402+
1136411403
let (onion_message, context) =
1136511404
self.flow.hrn_resolver.resolve_name(payment_id, name, &*self.entropy_source)?;
1136611405

1136711406
let expiration = StaleExpiration::TimerTicks(1);
1136811407
self.pending_outbound_payments.add_new_awaiting_offer(
1136911408
payment_id,
1137011409
expiration,
11371-
retry_strategy,
11372-
route_params_config,
11410+
optional_info.retry_strategy,
11411+
optional_info.route_params_config,
1137311412
amount_msats,
11374-
payer_note,
11413+
optional_info.payer_note,
1137511414
)?;
1137611415

1137711416
self.flow

0 commit comments

Comments
 (0)