Skip to content
Open
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions lightning-liquidity/tests/lsps2_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,7 @@ fn client_trusts_lsp_end_to_end_test() {
&invoice,
PaymentId(invoice.payment_hash().to_byte_array()),
None,
vec![],
Default::default(),
Retry::Attempts(3),
)
Expand Down Expand Up @@ -1694,6 +1695,7 @@ fn late_payment_forwarded_and_safe_after_force_close_does_not_broadcast() {
&invoice,
PaymentId(invoice.payment_hash().to_byte_array()),
None,
vec![],
Default::default(),
Retry::Attempts(3),
)
Expand Down Expand Up @@ -1885,6 +1887,7 @@ fn htlc_timeout_before_client_claim_results_in_handling_failed() {
&invoice,
PaymentId(invoice.payment_hash().to_byte_array()),
None,
vec![],
Default::default(),
Retry::Attempts(3),
)
Expand Down Expand Up @@ -2222,6 +2225,7 @@ fn client_trusts_lsp_partial_fee_does_not_trigger_broadcast() {
&invoice,
PaymentId(invoice.payment_hash().to_byte_array()),
None,
vec![],
Default::default(),
Retry::Attempts(3),
)
Expand Down
4 changes: 4 additions & 0 deletions lightning/src/ln/bolt11_payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ fn payment_metadata_end_to_end_for_invoice_with_amount() {
&invoice,
PaymentId(payment_hash.0),
Some(100),
vec![],
RouteParametersConfig::default(),
Retry::Attempts(0),
) {
Expand All @@ -68,6 +69,7 @@ fn payment_metadata_end_to_end_for_invoice_with_amount() {
&invoice,
PaymentId(payment_hash.0),
None,
vec![],
RouteParametersConfig::default(),
Retry::Attempts(0),
)
Expand Down Expand Up @@ -123,6 +125,7 @@ fn payment_metadata_end_to_end_for_invoice_with_no_amount() {
&invoice,
PaymentId(payment_hash.0),
None,
vec![],
RouteParametersConfig::default(),
Retry::Attempts(0),
) {
Expand All @@ -136,6 +139,7 @@ fn payment_metadata_end_to_end_for_invoice_with_no_amount() {
&invoice,
PaymentId(payment_hash.0),
Some(50_000),
vec![],
RouteParametersConfig::default(),
Retry::Attempts(0),
)
Expand Down
9 changes: 7 additions & 2 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2272,8 +2272,11 @@ where
/// # let channel_manager = channel_manager.get_cm();
/// # let payment_id = PaymentId([42; 32]);
/// # let payment_hash = PaymentHash((*invoice.payment_hash()).to_byte_array());
/// # let custom_tlvs = vec![
/// # (343493u64, b"hello".to_vec()),
/// # ];
/// match channel_manager.pay_for_bolt11_invoice(
/// invoice, payment_id, None, route_params_config, retry
/// invoice, payment_id, None, custom_tlvs, route_params_config, retry
/// ) {
/// Ok(()) => println!("Sending payment with hash {}", payment_hash),
/// Err(e) => println!("Failed sending payment with hash {}: {:?}", payment_hash, e),
Expand Down Expand Up @@ -5542,14 +5545,16 @@ where
/// To use default settings, call the function with [`RouteParametersConfig::default`].
pub fn pay_for_bolt11_invoice(
&self, invoice: &Bolt11Invoice, payment_id: PaymentId, amount_msats: Option<u64>,
route_params_config: RouteParametersConfig, retry_strategy: Retry,
custom_tlvs: Vec<(u64, Vec<u8>)>, route_params_config: RouteParametersConfig,
retry_strategy: Retry,
) -> Result<(), Bolt11PaymentError> {
let best_block_height = self.best_block.read().unwrap().height;
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
self.pending_outbound_payments.pay_for_bolt11_invoice(
invoice,
payment_id,
amount_msats,
custom_tlvs,
route_params_config,
retry_strategy,
&self.router,
Expand Down
49 changes: 42 additions & 7 deletions lightning/src/ln/invoice_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,7 @@ where
mod test {
use super::*;
use crate::chain::channelmonitor::HTLC_FAIL_BACK_BUFFER;
use crate::events::Event;
use crate::ln::channelmanager::{
Bolt11InvoiceParameters, PaymentId, PhantomRouteHints, RecipientOnionFields, Retry,
MIN_FINAL_CLTV_EXPIRY_DELTA,
Expand Down Expand Up @@ -663,7 +664,7 @@ mod test {
}

#[test]
fn create_and_pay_for_bolt11_invoice() {
fn create_and_pay_for_bolt11_invoice_with_custom_tlvs() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
Expand Down Expand Up @@ -694,6 +695,11 @@ mod test {
Duration::from_secs(non_default_invoice_expiry_secs.into())
);

let (payment_hash, payment_secret) =
(PaymentHash(invoice.payment_hash().to_byte_array()), *invoice.payment_secret());

let preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap();

// Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
// available.
let chan = &nodes[1].node.list_usable_channels()[0];
Expand All @@ -708,20 +714,49 @@ mod test {
assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan.inbound_htlc_maximum_msat);

let retry = Retry::Attempts(0);
let custom_tlvs = vec![(65537, vec![42; 42])];

nodes[0]
.node
.pay_for_bolt11_invoice(&invoice, PaymentId([42; 32]), None, Default::default(), retry)
.pay_for_bolt11_invoice(
&invoice,
PaymentId([42; 32]),
None,
custom_tlvs.clone(),
Default::default(),
retry,
)
.unwrap();
check_added_monitors(&nodes[0], 1);

let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let payment_event = SendEvent::from_event(events.remove(0));
nodes[1].node.handle_update_add_htlc(node_a_id, &payment_event.msgs[0]);
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &payment_event.commitment_msg);
check_added_monitors(&nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 2);
check_added_monitors(&nodes[1], 0);
do_commitment_signed_dance(
&nodes[1],
&nodes[0],
&payment_event.commitment_msg,
false,
false,
);
expect_and_process_pending_htlcs(&nodes[1], false);

let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);

match events[0] {
Event::PaymentClaimable { ref onion_fields, .. } => {
assert_eq!(onion_fields.clone().unwrap().custom_tlvs().clone(), custom_tlvs);
},
_ => panic!("Unexpected event"),
}

claim_payment_along_route(
ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], preimage)
.with_custom_tlvs(custom_tlvs),
);
}

fn do_create_invoice_min_final_cltv_delta(with_custom_delta: bool) {
Expand Down Expand Up @@ -1207,7 +1242,7 @@ mod test {
}

fn do_test_multi_node_receive(user_generated_pmt_hash: bool) {
use crate::events::{Event, EventsProvider};
use crate::events::EventsProvider;
use core::cell::RefCell;

let mut chanmon_cfgs = create_chanmon_cfgs(3);
Expand Down
8 changes: 7 additions & 1 deletion lightning/src/ln/outbound_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ pub enum RetryableSendFailure {
///
/// [`BlindedPaymentPath`]: crate::blinded_path::payment::BlindedPaymentPath
OnionPacketSizeExceeded,
/// The provided [`RecipientOnionFields::custom_tlvs`] are of invalid range
InvalidCustomTlvs,
}

/// If a payment fails to send to a route, it can be in one of several states. This enum is returned
Expand Down Expand Up @@ -919,6 +921,7 @@ where
pub(super) fn pay_for_bolt11_invoice<R: Deref, ES: Deref, NS: Deref, IH, SP>(
&self, invoice: &Bolt11Invoice, payment_id: PaymentId,
amount_msats: Option<u64>,
custom_tlvs: Vec<(u64, Vec<u8>)>,
route_params_config: RouteParametersConfig,
retry_strategy: Retry,
router: &R,
Expand All @@ -942,7 +945,9 @@ where
(None, None) => return Err(Bolt11PaymentError::InvalidAmount),
};

let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret());
let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret())
.with_custom_tlvs(custom_tlvs)
.map_err(|_| Bolt11PaymentError::SendingFailed(RetryableSendFailure::InvalidCustomTlvs))?;
recipient_onion.payment_metadata = invoice.payment_metadata().map(|v| v.clone());

let payment_params = PaymentParameters::from_bolt11_invoice(invoice)
Expand Down Expand Up @@ -1061,6 +1066,7 @@ where
RetryableSendFailure::RouteNotFound => PaymentFailureReason::RouteNotFound,
RetryableSendFailure::DuplicatePayment => PaymentFailureReason::UnexpectedError,
RetryableSendFailure::OnionPacketSizeExceeded => PaymentFailureReason::UnexpectedError,
RetryableSendFailure::InvalidCustomTlvs => PaymentFailureReason::UnexpectedError,
};
self.abandon_payment(payment_id, reason, pending_events);
return Err(Bolt12PaymentError::SendingFailed(e));
Expand Down
5 changes: 4 additions & 1 deletion lightning/src/ln/payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5400,7 +5400,10 @@ fn max_out_mpp_path() {

let id = PaymentId([42; 32]);
let retry = Retry::Attempts(0);
nodes[0].node.pay_for_bolt11_invoice(&invoice, id, None, route_params_cfg, retry).unwrap();
nodes[0]
.node
.pay_for_bolt11_invoice(&invoice, id, None, vec![], route_params_cfg, retry)
.unwrap();

assert!(nodes[0].node.list_recent_payments().len() == 1);
check_added_monitors(&nodes[0], 2); // one monitor update per MPP part
Expand Down
Loading