Skip to content

Add max_total_routing_fee_msat for pay_invoice #2719

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions lightning-invoice/src/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use lightning::util::logger::Logger;

use core::fmt::Debug;
use core::ops::Deref;
use core::time::Duration;

/// Pays the given [`Bolt11Invoice`], retrying if needed based on [`Retry`].
///
Expand All @@ -34,12 +33,13 @@ use core::time::Duration;
///
/// If you wish to use a different payment idempotency token, see [`pay_invoice_with_id`].
pub fn pay_invoice<C: Deref>(
invoice: &Bolt11Invoice, retry_strategy: Retry, channelmanager: C
invoice: &Bolt11Invoice, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>,
channelmanager: C
) -> Result<PaymentId, PaymentError>
where C::Target: AChannelManager,
{
let payment_id = PaymentId(invoice.payment_hash().into_inner());
pay_invoice_with_id(invoice, payment_id, retry_strategy, channelmanager.get_cm())
pay_invoice_with_id(invoice, payment_id, retry_strategy, max_total_routing_fee_msat, channelmanager.get_cm())
.map(|()| payment_id)
}

Expand All @@ -54,12 +54,13 @@ where C::Target: AChannelManager,
///
/// See [`pay_invoice`] for a variant which uses the [`PaymentHash`] for the idempotency token.
pub fn pay_invoice_with_id<C: Deref>(
invoice: &Bolt11Invoice, payment_id: PaymentId, retry_strategy: Retry, channelmanager: C
invoice: &Bolt11Invoice, payment_id: PaymentId, retry_strategy: Retry,
max_total_routing_fee_msat: Option<u64>, channelmanager: C
) -> Result<(), PaymentError>
where C::Target: AChannelManager,
{
let amt_msat = invoice.amount_milli_satoshis().ok_or(PaymentError::Invoice("amount missing"))?;
pay_invoice_using_amount(invoice, amt_msat, payment_id, retry_strategy, channelmanager.get_cm())
pay_invoice_using_amount(invoice, amt_msat, payment_id, retry_strategy, max_total_routing_fee_msat, channelmanager.get_cm())
}

/// Pays the given zero-value [`Bolt11Invoice`] using the given amount, retrying if needed based on
Expand All @@ -72,13 +73,13 @@ where C::Target: AChannelManager,
/// If you wish to use a different payment idempotency token, see
/// [`pay_zero_value_invoice_with_id`].
pub fn pay_zero_value_invoice<C: Deref>(
invoice: &Bolt11Invoice, amount_msats: u64, retry_strategy: Retry, channelmanager: C
invoice: &Bolt11Invoice, amount_msats: u64, retry_strategy: Retry,
max_total_routing_fee_msat: Option<u64>, channelmanager: C
) -> Result<PaymentId, PaymentError>
where C::Target: AChannelManager,
{
let payment_id = PaymentId(invoice.payment_hash().into_inner());
pay_zero_value_invoice_with_id(invoice, amount_msats, payment_id, retry_strategy,
channelmanager)
pay_zero_value_invoice_with_id(invoice, amount_msats, payment_id, retry_strategy, max_total_routing_fee_msat, channelmanager)
.map(|()| payment_id)
}

Expand All @@ -95,33 +96,36 @@ where C::Target: AChannelManager,
/// idempotency token.
pub fn pay_zero_value_invoice_with_id<C: Deref>(
invoice: &Bolt11Invoice, amount_msats: u64, payment_id: PaymentId, retry_strategy: Retry,
channelmanager: C
max_total_routing_fee_msat: Option<u64>, channelmanager: C
) -> Result<(), PaymentError>
where C::Target: AChannelManager,
{
if invoice.amount_milli_satoshis().is_some() {
Err(PaymentError::Invoice("amount unexpected"))
} else {
pay_invoice_using_amount(invoice, amount_msats, payment_id, retry_strategy,
channelmanager.get_cm())
pay_invoice_using_amount(invoice, amount_msats, payment_id, retry_strategy, max_total_routing_fee_msat, channelmanager.get_cm())
}
}

fn pay_invoice_using_amount<P: Deref>(
invoice: &Bolt11Invoice, amount_msats: u64, payment_id: PaymentId, retry_strategy: Retry,
payer: P
max_total_routing_fee_msat: Option<u64>, payer: P
) -> Result<(), PaymentError> where P::Target: Payer {
let payment_hash = PaymentHash((*invoice.payment_hash()).into_inner());
let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret());
recipient_onion.payment_metadata = invoice.payment_metadata().map(|v| v.clone());
let mut payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key(),
invoice.min_final_cltv_expiry_delta() as u32)
.with_expiry_time(expiry_time_from_unix_epoch(invoice).as_secs())
.with_expiry_time(invoice.expires_at().unwrap().as_secs())
.with_route_hints(invoice.route_hints()).unwrap();
if let Some(features) = invoice.features() {
payment_params = payment_params.with_bolt11_features(features.clone()).unwrap();
}
let route_params = RouteParameters::from_payment_params_and_value(payment_params, amount_msats);
let route_params = RouteParameters {
payment_params,
final_value_msat: amount_msats,
max_total_routing_fee_msat,
};

payer.send_payment(payment_hash, recipient_onion, payment_id, route_params, retry_strategy)
}
Expand All @@ -144,7 +148,7 @@ where C::Target: AChannelManager,
invoice.recover_payee_pub_key(),
invoice.min_final_cltv_expiry_delta() as u32,
)
.with_expiry_time(expiry_time_from_unix_epoch(invoice).as_secs())
.with_expiry_time(invoice.expires_at().unwrap().as_secs())
.with_route_hints(invoice.route_hints())
.unwrap();

Expand Down Expand Up @@ -175,7 +179,7 @@ where C::Target: AChannelManager,
invoice.recover_payee_pub_key(),
invoice.min_final_cltv_expiry_delta() as u32,
)
.with_expiry_time(expiry_time_from_unix_epoch(invoice).as_secs())
.with_expiry_time(invoice.expires_at().unwrap().as_secs())
.with_route_hints(invoice.route_hints())
.unwrap();

Expand All @@ -188,10 +192,6 @@ where C::Target: AChannelManager,
.map_err(ProbingError::Sending)
}

fn expiry_time_from_unix_epoch(invoice: &Bolt11Invoice) -> Duration {
invoice.signed_invoice.raw_invoice.data.timestamp.0 + invoice.expiry_time()
}

/// An error that may occur when making a payment.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PaymentError {
Expand Down Expand Up @@ -357,7 +357,7 @@ mod tests {
let final_value_msat = invoice.amount_milli_satoshis().unwrap();

let payer = TestPayer::new().expect_send(Amount(final_value_msat));
pay_invoice_using_amount(&invoice, final_value_msat, payment_id, Retry::Attempts(0), &payer).unwrap();
pay_invoice_using_amount(&invoice, final_value_msat, payment_id, Retry::Attempts(0), None, &payer).unwrap();
}

#[test]
Expand All @@ -368,7 +368,7 @@ mod tests {
let amt_msat = 10_000;

let payer = TestPayer::new().expect_send(Amount(amt_msat));
pay_invoice_using_amount(&invoice, amt_msat, payment_id, Retry::Attempts(0), &payer).unwrap();
pay_invoice_using_amount(&invoice, amt_msat, payment_id, Retry::Attempts(0), None, &payer).unwrap();
}

#[test]
Expand All @@ -382,7 +382,7 @@ mod tests {
let invoice = invoice(payment_preimage);
let amt_msat = 10_000;

match pay_zero_value_invoice(&invoice, amt_msat, Retry::Attempts(0), nodes[0].node) {
match pay_zero_value_invoice(&invoice, amt_msat, Retry::Attempts(0), None, nodes[0].node) {
Err(PaymentError::Invoice("amount unexpected")) => {},
_ => panic!()
}
Expand Down Expand Up @@ -418,7 +418,7 @@ mod tests {
})
.unwrap();

pay_invoice(&invoice, Retry::Attempts(0), nodes[0].node).unwrap();
pay_invoice(&invoice, Retry::Attempts(0), None, nodes[0].node).unwrap();
check_added_monitors(&nodes[0], 1);
let send_event = SendEvent::from_node(&nodes[0]);
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]);
Expand Down