mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-03-14 07:06:42 +01:00
Merge pull request #3342 from shaavan/i3262
Introduce RouteParametersConfig
This commit is contained in:
commit
ece4ab7cb7
8 changed files with 323 additions and 98 deletions
|
@ -170,6 +170,7 @@ 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;
|
||||
|
@ -405,7 +406,14 @@ mod test {
|
|||
let amt = 42_000;
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer_from_human_readable_name(name, amt, payment_id, retry, None, resolvers)
|
||||
.pay_for_offer_from_human_readable_name(
|
||||
name,
|
||||
amt,
|
||||
payment_id,
|
||||
retry,
|
||||
RouteParametersConfig::default(),
|
||||
resolvers,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let query = nodes[0].onion_messenger.next_onion_message_for_peer(resolver_id).unwrap();
|
||||
|
|
|
@ -33,7 +33,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};
|
||||
use crate::routing::router::{Payee, PaymentParameters, RouteParametersConfig};
|
||||
use crate::sign::NodeSigner;
|
||||
use crate::sync::Mutex;
|
||||
use crate::types::features::Bolt12InvoiceFeatures;
|
||||
|
@ -238,7 +238,15 @@ fn static_invoice_unknown_required_features() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(0),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Don't forward the invreq since we don't support retrieving the static invoice from the
|
||||
|
@ -298,7 +306,15 @@ fn ignore_unexpected_static_invoice() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(0),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Don't forward the invreq since we don't support retrieving the static invoice from the
|
||||
|
@ -415,7 +431,15 @@ fn async_receive_flow_success() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(0),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let release_held_htlc_om =
|
||||
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1;
|
||||
|
@ -463,7 +487,15 @@ fn expired_static_invoice_fail() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(0),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let invreq_om = nodes[0]
|
||||
|
@ -546,7 +578,15 @@ fn async_receive_mpp() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(1),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let release_held_htlc_om_3_0 =
|
||||
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[3]).1;
|
||||
|
@ -630,7 +670,15 @@ fn amount_doesnt_match_invreq() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(1),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let release_held_htlc_om_3_0 =
|
||||
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[3]).1;
|
||||
|
@ -859,7 +907,15 @@ fn invalid_async_receive_with_retry<F1, F2>(
|
|||
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(2), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(2),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let release_held_htlc_om_2_0 =
|
||||
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1;
|
||||
|
@ -948,7 +1004,15 @@ fn expired_static_invoice_message_path() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(1),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// While the invoice is unexpired, respond with release_held_htlc.
|
||||
|
@ -1052,7 +1116,15 @@ fn expired_static_invoice_payment_path() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
nodes[0]
|
||||
.node
|
||||
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), None)
|
||||
.pay_for_offer(
|
||||
&offer,
|
||||
None,
|
||||
Some(amt_msat),
|
||||
None,
|
||||
payment_id,
|
||||
Retry::Attempts(0),
|
||||
RouteParametersConfig::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let release_held_htlc_om =
|
||||
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1;
|
||||
|
|
|
@ -57,7 +57,7 @@ use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelType
|
|||
use crate::types::features::Bolt11InvoiceFeatures;
|
||||
#[cfg(trampoline)]
|
||||
use crate::routing::gossip::NodeId;
|
||||
use crate::routing::router::{BlindedTail, FixedRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteParameters, Router};
|
||||
use crate::routing::router::{BlindedTail, FixedRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteParameters, RouteParametersConfig, Router};
|
||||
use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, InboundHTLCErr, NextPacketDetails};
|
||||
use crate::ln::msgs;
|
||||
use crate::ln::onion_utils;
|
||||
|
@ -2105,6 +2105,7 @@ where
|
|||
/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
|
||||
/// # use lightning::ln::channelmanager::AChannelManager;
|
||||
/// # use lightning::offers::parse::Bolt12SemanticError;
|
||||
/// # use lightning::routing::router::RouteParametersConfig;
|
||||
/// #
|
||||
/// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
|
||||
/// # let channel_manager = channel_manager.get_cm();
|
||||
|
@ -2152,15 +2153,16 @@ where
|
|||
/// # use lightning::events::{Event, EventsProvider};
|
||||
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry};
|
||||
/// # use lightning::offers::offer::Offer;
|
||||
/// # use lightning::routing::router::RouteParametersConfig;
|
||||
/// #
|
||||
/// # fn example<T: AChannelManager>(
|
||||
/// # channel_manager: T, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
|
||||
/// # payer_note: Option<String>, retry: Retry, max_total_routing_fee_msat: Option<u64>
|
||||
/// # payer_note: Option<String>, retry: Retry, route_params_config: RouteParametersConfig
|
||||
/// # ) {
|
||||
/// # 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, max_total_routing_fee_msat
|
||||
/// offer, quantity, amount_msats, payer_note, payment_id, retry, route_params_config
|
||||
/// ) {
|
||||
/// Ok(()) => println!("Requesting invoice for offer"),
|
||||
/// Err(e) => println!("Unable to request invoice for offer: {:?}", e),
|
||||
|
@ -2208,16 +2210,17 @@ where
|
|||
/// # use lightning::events::{Event, EventsProvider};
|
||||
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry};
|
||||
/// # use lightning::offers::parse::Bolt12SemanticError;
|
||||
/// # use lightning::routing::router::RouteParametersConfig;
|
||||
/// #
|
||||
/// # fn example<T: AChannelManager>(
|
||||
/// # channel_manager: T, amount_msats: u64, absolute_expiry: Duration, retry: Retry,
|
||||
/// # max_total_routing_fee_msat: Option<u64>
|
||||
/// # route_params_config: RouteParametersConfig
|
||||
/// # ) -> Result<(), Bolt12SemanticError> {
|
||||
/// # let channel_manager = channel_manager.get_cm();
|
||||
/// let payment_id = PaymentId([42; 32]);
|
||||
/// let refund = channel_manager
|
||||
/// .create_refund_builder(
|
||||
/// amount_msats, absolute_expiry, payment_id, retry, max_total_routing_fee_msat
|
||||
/// amount_msats, absolute_expiry, payment_id, retry, route_params_config
|
||||
/// )?
|
||||
/// # ;
|
||||
/// # // Needed for compiling for c_bindings
|
||||
|
@ -10161,7 +10164,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
|
|||
/// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
|
||||
pub fn create_refund_builder(
|
||||
&$self, amount_msats: u64, absolute_expiry: Duration, payment_id: PaymentId,
|
||||
retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
|
||||
retry_strategy: Retry, route_params_config: RouteParametersConfig
|
||||
) -> Result<$builder, Bolt12SemanticError> {
|
||||
let node_id = $self.get_our_node_id();
|
||||
let expanded_key = &$self.inbound_payment_key;
|
||||
|
@ -10186,7 +10189,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
|
|||
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry);
|
||||
$self.pending_outbound_payments
|
||||
.add_new_awaiting_invoice(
|
||||
payment_id, expiration, retry_strategy, max_total_routing_fee_msat, None,
|
||||
payment_id, expiration, retry_strategy, route_params_config, None,
|
||||
)
|
||||
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
|
||||
|
||||
|
@ -10362,7 +10365,7 @@ where
|
|||
pub fn pay_for_offer(
|
||||
&self, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
|
||||
payer_note: Option<String>, payment_id: PaymentId, retry_strategy: Retry,
|
||||
max_total_routing_fee_msat: Option<u64>
|
||||
route_params_config: RouteParametersConfig
|
||||
) -> Result<(), Bolt12SemanticError> {
|
||||
self.pay_for_offer_intern(offer, quantity, amount_msats, payer_note, payment_id, None, |invoice_request, nonce| {
|
||||
let expiration = StaleExpiration::TimerTicks(1);
|
||||
|
@ -10373,7 +10376,7 @@ where
|
|||
};
|
||||
self.pending_outbound_payments
|
||||
.add_new_awaiting_invoice(
|
||||
payment_id, expiration, retry_strategy, max_total_routing_fee_msat,
|
||||
payment_id, expiration, retry_strategy, route_params_config,
|
||||
Some(retryable_invoice_request)
|
||||
)
|
||||
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)
|
||||
|
@ -10606,14 +10609,14 @@ where
|
|||
#[cfg(feature = "dnssec")]
|
||||
pub fn pay_for_offer_from_human_readable_name(
|
||||
&self, name: HumanReadableName, amount_msats: u64, payment_id: PaymentId,
|
||||
retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>,
|
||||
retry_strategy: Retry, route_params_config: RouteParametersConfig,
|
||||
dns_resolvers: Vec<Destination>,
|
||||
) -> Result<(), ()> {
|
||||
let (onion_message, context) =
|
||||
self.hrn_resolver.resolve_name(payment_id, name, &*self.entropy_source)?;
|
||||
let reply_paths = self.create_blinded_paths(MessageContext::DNSResolver(context))?;
|
||||
let expiration = StaleExpiration::TimerTicks(1);
|
||||
self.pending_outbound_payments.add_new_awaiting_offer(payment_id, expiration, retry_strategy, max_total_routing_fee_msat, amount_msats)?;
|
||||
self.pending_outbound_payments.add_new_awaiting_offer(payment_id, expiration, retry_strategy, route_params_config, amount_msats)?;
|
||||
let message_params = dns_resolvers
|
||||
.iter()
|
||||
.flat_map(|destination| reply_paths.iter().map(move |path| (path, destination)))
|
||||
|
|
|
@ -26,7 +26,7 @@ use crate::ln::onion_utils::MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY;
|
|||
use crate::ln::outbound_payment::{RecipientOnionFields, Retry, RetryableSendFailure};
|
||||
use crate::offers::nonce::Nonce;
|
||||
use crate::prelude::*;
|
||||
use crate::routing::router::{DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, PaymentParameters, RouteParameters};
|
||||
use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA};
|
||||
use crate::sign::NodeSigner;
|
||||
use crate::util::errors::APIError;
|
||||
use crate::util::ser::Writeable;
|
||||
|
@ -393,7 +393,7 @@ 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]);
|
||||
nodes[0].node.pay_for_offer(&offer, None, Some(5000), None, payment_id, Retry::Attempts(0), None).unwrap();
|
||||
nodes[0].node.pay_for_offer(&offer, None, Some(5000), None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).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);
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ use crate::onion_message::messenger::{Destination, PeeledOnion, MessageSendInstr
|
|||
use crate::onion_message::offers::OffersMessage;
|
||||
use crate::onion_message::packet::ParsedOnionMessageContents;
|
||||
use crate::routing::gossip::{NodeAlias, NodeId};
|
||||
use crate::routing::router::{PaymentParameters, RouteParameters};
|
||||
use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig};
|
||||
use crate::sign::{NodeSigner, Recipient};
|
||||
use crate::util::ser::Writeable;
|
||||
|
||||
|
@ -454,7 +454,7 @@ fn creates_short_lived_refund() {
|
|||
let absolute_expiry = bob.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = bob.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_eq!(refund.absolute_expiry(), Some(absolute_expiry));
|
||||
|
@ -483,7 +483,7 @@ fn creates_long_lived_refund() {
|
|||
+ Duration::from_secs(1);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = bob.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_eq!(refund.absolute_expiry(), Some(absolute_expiry));
|
||||
|
@ -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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
|
@ -642,7 +642,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = david.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_eq!(refund.amount_msats(), 10_000_000);
|
||||
|
@ -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), None).unwrap();
|
||||
bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap();
|
||||
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
|
||||
|
@ -771,7 +771,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = bob.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_eq!(refund.amount_msats(), 10_000_000);
|
||||
|
@ -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), None).unwrap();
|
||||
bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap();
|
||||
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
|
||||
|
@ -880,7 +880,7 @@ fn pays_for_refund_without_blinded_paths() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = bob.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.clear_paths()
|
||||
.build().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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
connect_peers(david, bob);
|
||||
|
@ -1035,7 +1035,7 @@ fn send_invoice_for_refund_with_distinct_reply_path() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = alice.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_ne!(refund.payer_signing_pubkey(), alice_id);
|
||||
|
@ -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), None).unwrap();
|
||||
bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).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), None).unwrap();
|
||||
bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap();
|
||||
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
|
||||
|
@ -1256,7 +1256,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), None).unwrap();
|
||||
bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap();
|
||||
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
|
||||
|
@ -1314,7 +1314,7 @@ fn creates_refund_with_blinded_path_using_unannounced_introduction_node() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = bob.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_ne!(refund.payer_signing_pubkey(), bob_id);
|
||||
|
@ -1397,7 +1397,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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
|
@ -1423,7 +1423,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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
|
@ -1500,7 +1500,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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
david.node.abandon_payment(payment_id);
|
||||
get_event!(david, Event::PaymentFailed);
|
||||
|
@ -1517,7 +1517,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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
|
@ -1597,7 +1597,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = david.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_ne!(refund.payer_signing_pubkey(), david_id);
|
||||
|
@ -1631,7 +1631,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {
|
|||
let invalid_path = refund.paths().first().unwrap().clone();
|
||||
let payment_id = PaymentId([2; 32]);
|
||||
let refund = david.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
assert_ne!(refund.payer_signing_pubkey(), david_id);
|
||||
|
@ -1701,7 +1701,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), None) {
|
||||
match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) {
|
||||
Ok(_) => panic!("Expected error"),
|
||||
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
|
||||
}
|
||||
|
@ -1714,7 +1714,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), None
|
||||
&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()
|
||||
).is_ok()
|
||||
);
|
||||
|
||||
|
@ -1758,7 +1758,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
|
|||
let absolute_expiry = david.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
match david.node.create_refund_builder(
|
||||
10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
|
||||
10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()
|
||||
) {
|
||||
Ok(_) => panic!("Expected error"),
|
||||
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
|
||||
|
@ -1769,7 +1769,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
|
|||
reconnect_nodes(args);
|
||||
|
||||
let refund = david.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
|
||||
|
@ -1805,7 +1805,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), None) {
|
||||
match bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) {
|
||||
Ok(_) => panic!("Expected error"),
|
||||
Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
|
||||
}
|
||||
|
@ -1827,7 +1827,7 @@ fn fails_sending_invoice_with_unsupported_chain_for_refund() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = bob.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.chain(Network::Signet)
|
||||
.build().unwrap();
|
||||
|
@ -1864,7 +1864,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), None) {
|
||||
match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) {
|
||||
Ok(_) => panic!("Expected error"),
|
||||
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
|
||||
}
|
||||
|
@ -1899,12 +1899,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), None
|
||||
&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()
|
||||
).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), None) {
|
||||
match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) {
|
||||
Ok(_) => panic!("Expected error"),
|
||||
Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId),
|
||||
}
|
||||
|
@ -1925,13 +1925,13 @@ fn fails_creating_refund_with_duplicate_payment_id() {
|
|||
let payment_id = PaymentId([1; 32]);
|
||||
assert!(
|
||||
nodes[0].node.create_refund_builder(
|
||||
10_000, absolute_expiry, payment_id, Retry::Attempts(0), None
|
||||
10_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()
|
||||
).is_ok()
|
||||
);
|
||||
expect_recent_payment!(nodes[0], RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
||||
match nodes[0].node.create_refund_builder(
|
||||
10_000, absolute_expiry, payment_id, Retry::Attempts(0), None
|
||||
10_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()
|
||||
) {
|
||||
Ok(_) => panic!("Expected error"),
|
||||
Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId),
|
||||
|
@ -1983,7 +1983,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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
|
||||
connect_peers(david, bob);
|
||||
|
@ -2051,7 +2051,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_refund() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = david.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
|
||||
|
@ -2100,7 +2100,7 @@ fn fails_paying_invoice_more_than_once() {
|
|||
let absolute_expiry = Duration::from_secs(u64::MAX);
|
||||
let payment_id = PaymentId([1; 32]);
|
||||
let refund = david.node
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None)
|
||||
.create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap()
|
||||
.build().unwrap();
|
||||
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
|
||||
|
@ -2192,7 +2192,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), None)
|
||||
david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default())
|
||||
.unwrap();
|
||||
|
||||
connect_peers(david, bob);
|
||||
|
@ -2269,7 +2269,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), None).unwrap();
|
||||
nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), RouteParametersConfig::default()).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();
|
||||
|
@ -2354,7 +2354,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), None).unwrap();
|
||||
nodes[0].node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).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();
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason};
|
|||
use crate::offers::invoice::Bolt12Invoice;
|
||||
use crate::offers::invoice_request::InvoiceRequest;
|
||||
use crate::offers::nonce::Nonce;
|
||||
use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router};
|
||||
use crate::routing::router::{BlindedTail, InFlightHtlcs, RouteParametersConfig, Path, PaymentParameters, Route, RouteParameters, Router};
|
||||
use crate::sign::{EntropySource, NodeSigner, Recipient};
|
||||
use crate::util::errors::APIError;
|
||||
use crate::util::logger::Logger;
|
||||
|
@ -62,7 +62,7 @@ pub(crate) enum PendingOutboundPayment {
|
|||
AwaitingOffer {
|
||||
expiration: StaleExpiration,
|
||||
retry_strategy: Retry,
|
||||
max_total_routing_fee_msat: Option<u64>,
|
||||
route_params_config: RouteParametersConfig,
|
||||
/// Human Readable Names-originated payments should always specify an explicit amount to
|
||||
/// send up-front, which we track here and enforce once we receive the offer.
|
||||
amount_msats: u64,
|
||||
|
@ -70,7 +70,7 @@ pub(crate) enum PendingOutboundPayment {
|
|||
AwaitingInvoice {
|
||||
expiration: StaleExpiration,
|
||||
retry_strategy: Retry,
|
||||
max_total_routing_fee_msat: Option<u64>,
|
||||
route_params_config: RouteParametersConfig,
|
||||
retryable_invoice_request: Option<RetryableInvoiceRequest>
|
||||
},
|
||||
// This state will never be persisted to disk because we transition from `AwaitingInvoice` to
|
||||
|
@ -79,9 +79,10 @@ pub(crate) enum PendingOutboundPayment {
|
|||
InvoiceReceived {
|
||||
payment_hash: PaymentHash,
|
||||
retry_strategy: Retry,
|
||||
// Note this field is currently just replicated from AwaitingInvoice but not actually
|
||||
// used anywhere.
|
||||
max_total_routing_fee_msat: Option<u64>,
|
||||
// Currently unused, but replicated from `AwaitingInvoice` to avoid potential
|
||||
// race conditions where this field might be missing upon reload. It may be required
|
||||
// for future retries.
|
||||
route_params_config: RouteParametersConfig,
|
||||
},
|
||||
// This state applies when we are paying an often-offline recipient and another node on the
|
||||
// network served us a static invoice on the recipient's behalf in response to our invoice
|
||||
|
@ -862,19 +863,19 @@ impl OutboundPayments {
|
|||
SP: Fn(SendAlongPathArgs) -> Result<(), APIError>,
|
||||
{
|
||||
let payment_hash = invoice.payment_hash();
|
||||
let max_total_routing_fee_msat;
|
||||
let params_config;
|
||||
let retry_strategy;
|
||||
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
|
||||
hash_map::Entry::Occupied(entry) => match entry.get() {
|
||||
PendingOutboundPayment::AwaitingInvoice {
|
||||
retry_strategy: retry, max_total_routing_fee_msat: max_total_fee, ..
|
||||
retry_strategy: retry, route_params_config, ..
|
||||
} => {
|
||||
retry_strategy = *retry;
|
||||
max_total_routing_fee_msat = *max_total_fee;
|
||||
params_config = *route_params_config;
|
||||
*entry.into_mut() = PendingOutboundPayment::InvoiceReceived {
|
||||
payment_hash,
|
||||
retry_strategy: *retry,
|
||||
max_total_routing_fee_msat,
|
||||
route_params_config: *route_params_config,
|
||||
};
|
||||
},
|
||||
_ => return Err(Bolt12PaymentError::DuplicateInvoice),
|
||||
|
@ -890,9 +891,10 @@ impl OutboundPayments {
|
|||
}
|
||||
|
||||
let mut route_params = RouteParameters::from_payment_params_and_value(
|
||||
PaymentParameters::from_bolt12_invoice(&invoice), invoice.amount_msats()
|
||||
PaymentParameters::from_bolt12_invoice(&invoice)
|
||||
.with_user_config_ignoring_fee_limit(params_config), invoice.amount_msats()
|
||||
);
|
||||
if let Some(max_fee_msat) = max_total_routing_fee_msat {
|
||||
if let Some(max_fee_msat) = params_config.max_total_routing_fee_msat {
|
||||
route_params.max_total_routing_fee_msat = Some(max_fee_msat);
|
||||
}
|
||||
self.send_payment_for_bolt12_invoice_internal(
|
||||
|
@ -1035,7 +1037,7 @@ impl OutboundPayments {
|
|||
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
|
||||
hash_map::Entry::Occupied(mut entry) => match entry.get_mut() {
|
||||
PendingOutboundPayment::AwaitingInvoice {
|
||||
retry_strategy, retryable_invoice_request, max_total_routing_fee_msat, ..
|
||||
retry_strategy, retryable_invoice_request, route_params_config, ..
|
||||
} => {
|
||||
let invreq = &retryable_invoice_request
|
||||
.as_ref()
|
||||
|
@ -1065,9 +1067,10 @@ impl OutboundPayments {
|
|||
};
|
||||
let keysend_preimage = PaymentPreimage(entropy_source.get_secure_random_bytes());
|
||||
let payment_hash = PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array());
|
||||
let pay_params = PaymentParameters::from_static_invoice(invoice);
|
||||
let pay_params = PaymentParameters::from_static_invoice(invoice)
|
||||
.with_user_config_ignoring_fee_limit(*route_params_config);
|
||||
let mut route_params = RouteParameters::from_payment_params_and_value(pay_params, amount_msat);
|
||||
route_params.max_total_routing_fee_msat = *max_total_routing_fee_msat;
|
||||
route_params.max_total_routing_fee_msat = route_params_config.max_total_routing_fee_msat;
|
||||
|
||||
if let Err(()) = onion_utils::set_max_path_length(
|
||||
&mut route_params, &RecipientOnionFields::spontaneous_empty(), Some(keysend_preimage),
|
||||
|
@ -1710,7 +1713,7 @@ impl OutboundPayments {
|
|||
#[cfg(feature = "dnssec")]
|
||||
pub(super) fn add_new_awaiting_offer(
|
||||
&self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry,
|
||||
max_total_routing_fee_msat: Option<u64>, amount_msats: u64,
|
||||
route_params_config: RouteParametersConfig, amount_msats: u64,
|
||||
) -> Result<(), ()> {
|
||||
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
|
||||
match pending_outbounds.entry(payment_id) {
|
||||
|
@ -1719,7 +1722,7 @@ impl OutboundPayments {
|
|||
entry.insert(PendingOutboundPayment::AwaitingOffer {
|
||||
expiration,
|
||||
retry_strategy,
|
||||
max_total_routing_fee_msat,
|
||||
route_params_config,
|
||||
amount_msats,
|
||||
});
|
||||
|
||||
|
@ -1746,12 +1749,12 @@ impl OutboundPayments {
|
|||
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
|
||||
hash_map::Entry::Occupied(entry) => match entry.get() {
|
||||
PendingOutboundPayment::AwaitingOffer {
|
||||
expiration, retry_strategy, max_total_routing_fee_msat, ..
|
||||
expiration, retry_strategy, route_params_config, ..
|
||||
} => {
|
||||
let mut new_val = PendingOutboundPayment::AwaitingInvoice {
|
||||
expiration: *expiration,
|
||||
retry_strategy: *retry_strategy,
|
||||
max_total_routing_fee_msat: *max_total_routing_fee_msat,
|
||||
route_params_config: *route_params_config,
|
||||
retryable_invoice_request,
|
||||
};
|
||||
core::mem::swap(&mut new_val, entry.into_mut());
|
||||
|
@ -1765,7 +1768,7 @@ impl OutboundPayments {
|
|||
|
||||
pub(super) fn add_new_awaiting_invoice(
|
||||
&self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry,
|
||||
max_total_routing_fee_msat: Option<u64>, retryable_invoice_request: Option<RetryableInvoiceRequest>
|
||||
route_params_config: RouteParametersConfig, retryable_invoice_request: Option<RetryableInvoiceRequest>
|
||||
) -> Result<(), ()> {
|
||||
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
|
||||
match pending_outbounds.entry(payment_id) {
|
||||
|
@ -1777,7 +1780,7 @@ impl OutboundPayments {
|
|||
entry.insert(PendingOutboundPayment::AwaitingInvoice {
|
||||
expiration,
|
||||
retry_strategy,
|
||||
max_total_routing_fee_msat,
|
||||
route_params_config,
|
||||
retryable_invoice_request,
|
||||
});
|
||||
|
||||
|
@ -2411,13 +2414,35 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
|
|||
(5, AwaitingInvoice) => {
|
||||
(0, expiration, required),
|
||||
(2, retry_strategy, required),
|
||||
(4, max_total_routing_fee_msat, option),
|
||||
(4, _max_total_routing_fee_msat, (legacy, u64,
|
||||
|us: &PendingOutboundPayment| match us {
|
||||
PendingOutboundPayment::AwaitingInvoice { route_params_config, .. } => route_params_config.max_total_routing_fee_msat,
|
||||
_ => None,
|
||||
}
|
||||
)),
|
||||
(5, retryable_invoice_request, option),
|
||||
(7, route_params_config, (default_value, (
|
||||
_max_total_routing_fee_msat.map_or(
|
||||
RouteParametersConfig::default(),
|
||||
|fee_msat| RouteParametersConfig::default().with_max_total_routing_fee_msat(fee_msat)
|
||||
)
|
||||
))),
|
||||
},
|
||||
(7, InvoiceReceived) => {
|
||||
(0, payment_hash, required),
|
||||
(2, retry_strategy, required),
|
||||
(4, max_total_routing_fee_msat, option),
|
||||
(4, _max_total_routing_fee_msat, (legacy, u64,
|
||||
|us: &PendingOutboundPayment| match us {
|
||||
PendingOutboundPayment::InvoiceReceived { route_params_config, .. } => route_params_config.max_total_routing_fee_msat,
|
||||
_ => None,
|
||||
}
|
||||
)),
|
||||
(5, route_params_config, (default_value, (
|
||||
_max_total_routing_fee_msat.map_or(
|
||||
RouteParametersConfig::default(),
|
||||
|fee_msat| RouteParametersConfig::default().with_max_total_routing_fee_msat(fee_msat)
|
||||
)
|
||||
))),
|
||||
},
|
||||
// Added in 0.1. Prior versions will drop these outbounds on downgrade, which is safe because no
|
||||
// HTLCs are in-flight.
|
||||
|
@ -2433,7 +2458,18 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
|
|||
(11, AwaitingOffer) => {
|
||||
(0, expiration, required),
|
||||
(2, retry_strategy, required),
|
||||
(4, max_total_routing_fee_msat, option),
|
||||
(4, _max_total_routing_fee_msat, (legacy, u64,
|
||||
|us: &PendingOutboundPayment| match us {
|
||||
PendingOutboundPayment::AwaitingOffer { route_params_config, .. } => route_params_config.max_total_routing_fee_msat,
|
||||
_ => None,
|
||||
}
|
||||
)),
|
||||
(5, route_params_config, (default_value, (
|
||||
_max_total_routing_fee_msat.map_or(
|
||||
RouteParametersConfig::default(),
|
||||
|fee_msat| RouteParametersConfig::default().with_max_total_routing_fee_msat(fee_msat)
|
||||
)
|
||||
))),
|
||||
(6, amount_msats, required),
|
||||
},
|
||||
);
|
||||
|
@ -2459,7 +2495,7 @@ mod tests {
|
|||
use crate::offers::offer::OfferBuilder;
|
||||
use crate::offers::test_utils::*;
|
||||
use crate::routing::gossip::NetworkGraph;
|
||||
use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters};
|
||||
use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters, RouteParametersConfig};
|
||||
use crate::sync::{Arc, Mutex, RwLock};
|
||||
use crate::util::errors::APIError;
|
||||
use crate::util::hash_tables::new_hash_map;
|
||||
|
@ -2670,7 +2706,7 @@ mod tests {
|
|||
assert!(!outbound_payments.has_pending_payments());
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
@ -2700,14 +2736,14 @@ mod tests {
|
|||
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_err()
|
||||
);
|
||||
}
|
||||
|
@ -2723,7 +2759,7 @@ mod tests {
|
|||
assert!(!outbound_payments.has_pending_payments());
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
@ -2753,14 +2789,14 @@ mod tests {
|
|||
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_err()
|
||||
);
|
||||
}
|
||||
|
@ -2775,7 +2811,7 @@ mod tests {
|
|||
assert!(!outbound_payments.has_pending_payments());
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
@ -2813,7 +2849,7 @@ mod tests {
|
|||
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), None, None,
|
||||
payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
@ -2874,10 +2910,12 @@ mod tests {
|
|||
.build().unwrap()
|
||||
.sign(recipient_sign).unwrap();
|
||||
|
||||
let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee_msat(invoice.amount_msats() / 100 + 50_000);
|
||||
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0),
|
||||
Some(invoice.amount_msats() / 100 + 50_000), None,
|
||||
route_params_config, None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
@ -2974,9 +3012,11 @@ mod tests {
|
|||
assert!(!outbound_payments.has_pending_payments());
|
||||
assert!(pending_events.lock().unwrap().is_empty());
|
||||
|
||||
let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee_msat(1234);
|
||||
|
||||
assert!(
|
||||
outbound_payments.add_new_awaiting_invoice(
|
||||
payment_id, expiration, Retry::Attempts(0), Some(1234), None,
|
||||
payment_id, expiration, Retry::Attempts(0), route_params_config, None,
|
||||
).is_ok()
|
||||
);
|
||||
assert!(outbound_payments.has_pending_payments());
|
||||
|
|
|
@ -943,6 +943,21 @@ impl PaymentParameters {
|
|||
}
|
||||
}
|
||||
|
||||
/// Updates the parameters with the given route parameters configuration.
|
||||
///
|
||||
/// Note:
|
||||
/// We *do not* apply `max_total_routing_fee_msat` here, as it is unique to each route.
|
||||
/// Instead, we apply only the parameters that are common across multiple route-finding sessions
|
||||
/// for a payment across retries.
|
||||
pub(crate) fn with_user_config_ignoring_fee_limit(self, params_config: RouteParametersConfig) -> Self {
|
||||
Self {
|
||||
max_total_cltv_expiry_delta: params_config.max_total_cltv_expiry_delta,
|
||||
max_path_count: params_config.max_path_count,
|
||||
max_channel_saturation_power_of_half: params_config.max_channel_saturation_power_of_half,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Includes the payee's features. Errors if the parameters were not initialized with
|
||||
/// [`PaymentParameters::from_bolt12_invoice`].
|
||||
///
|
||||
|
@ -1030,6 +1045,93 @@ impl PaymentParameters {
|
|||
}
|
||||
}
|
||||
|
||||
/// A struct for configuring parameters for routing the payment.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RouteParametersConfig {
|
||||
/// The maximum total fees, in millisatoshi, that may accrue during route finding.
|
||||
///
|
||||
/// This limit also applies to the total fees that may arise while retrying failed payment
|
||||
/// paths.
|
||||
///
|
||||
/// Note that values below a few sats may result in some paths being spuriously ignored.
|
||||
///
|
||||
/// Defaults to 1% of the payment amount + 50 sats
|
||||
pub max_total_routing_fee_msat: Option<u64>,
|
||||
|
||||
/// The maximum total CLTV delta we accept for the route.
|
||||
/// Defaults to [`DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA`].
|
||||
pub max_total_cltv_expiry_delta: u32,
|
||||
|
||||
/// The maximum number of paths that may be used by (MPP) payments.
|
||||
/// Defaults to [`DEFAULT_MAX_PATH_COUNT`].
|
||||
pub max_path_count: u8,
|
||||
|
||||
/// Selects the maximum share of a channel's total capacity which will be sent over a channel,
|
||||
/// as a power of 1/2. A higher value prefers to send the payment using more MPP parts whereas
|
||||
/// a lower value prefers to send larger MPP parts, potentially saturating channels and
|
||||
/// increasing failure probability for those paths.
|
||||
///
|
||||
/// Note that this restriction will be relaxed during pathfinding after paths which meet this
|
||||
/// restriction have been found. While paths which meet this criteria will be searched for, it
|
||||
/// is ultimately up to the scorer to select them over other paths.
|
||||
///
|
||||
/// A value of 0 will allow payments up to and including a channel's total announced usable
|
||||
/// capacity, a value of one will only use up to half its capacity, two 1/4, etc.
|
||||
///
|
||||
/// Default value: 2
|
||||
pub max_channel_saturation_power_of_half: u8,
|
||||
}
|
||||
|
||||
impl_writeable_tlv_based!(RouteParametersConfig, {
|
||||
(1, max_total_routing_fee_msat, option),
|
||||
(3, max_total_cltv_expiry_delta, required),
|
||||
(5, max_path_count, required),
|
||||
(7, max_channel_saturation_power_of_half, required),
|
||||
});
|
||||
|
||||
impl RouteParametersConfig {
|
||||
/// Set the maximum total fees, in millisatoshi, that may accrue during route finding.
|
||||
///
|
||||
/// This is not exported to bindings users since bindings don't support move semantics
|
||||
pub fn with_max_total_routing_fee_msat(self, fee_msat: u64) -> Self {
|
||||
Self { max_total_routing_fee_msat: Some(fee_msat), ..self }
|
||||
}
|
||||
|
||||
/// Includes a limit for the total CLTV expiry delta which is considered during routing
|
||||
///
|
||||
/// This is not exported to bindings users since bindings don't support move semantics
|
||||
pub fn with_max_total_cltv_expiry_delta(self, max_total_cltv_expiry_delta: u32) -> Self {
|
||||
Self { max_total_cltv_expiry_delta, ..self }
|
||||
}
|
||||
|
||||
/// Includes a limit for the maximum number of payment paths that may be used.
|
||||
///
|
||||
/// This is not exported to bindings users since bindings don't support move semantics
|
||||
pub fn with_max_path_count(self, max_path_count: u8) -> Self {
|
||||
Self { max_path_count, ..self }
|
||||
}
|
||||
|
||||
/// Includes a limit for the maximum share of a channel's total capacity that can be sent over, as
|
||||
/// a power of 1/2. See [`PaymentParameters::max_channel_saturation_power_of_half`].
|
||||
///
|
||||
/// This is not exported to bindings users since bindings don't support move semantics
|
||||
pub fn with_max_channel_saturation_power_of_half(self, max_channel_saturation_power_of_half: u8) -> Self {
|
||||
Self { max_channel_saturation_power_of_half, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RouteParametersConfig {
|
||||
/// Initates an new set of route parameter configs with default parameters.
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_total_routing_fee_msat: None,
|
||||
max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
|
||||
max_path_count: DEFAULT_MAX_PATH_COUNT,
|
||||
max_channel_saturation_power_of_half: DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The recipient of a payment, differing based on whether they've hidden their identity with route
|
||||
/// blinding.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
|
|
|
@ -40,7 +40,7 @@ macro_rules! _encode_tlv {
|
|||
}
|
||||
};
|
||||
($stream: expr, $optional_type: expr, $optional_field: expr, (legacy, $fieldty: ty, $write: expr) $(, $self: ident)?) => {
|
||||
$crate::_encode_tlv!($stream, $optional_type, $write($($self)?), option);
|
||||
$crate::_encode_tlv!($stream, $optional_type, { let value: Option<$fieldty> = $write($($self)?); value }, option);
|
||||
};
|
||||
($stream: expr, $type: expr, $field: expr, optional_vec $(, $self: ident)?) => {
|
||||
if !$field.is_empty() {
|
||||
|
|
Loading…
Add table
Reference in a new issue