//! Tests for calculating the maximum length of a path based on the payment metadata, custom TLVs,
//! and/or blinded paths present.
-use bitcoin::secp256k1::Secp256k1;
-use crate::blinded_path::BlindedPath;
+use bitcoin::secp256k1::{Secp256k1, PublicKey};
+use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode};
use crate::blinded_path::payment::{PaymentConstraints, PaymentContext, ReceiveTlvs};
-use crate::events::MessageSendEventsProvider;
+use crate::events::{Event, MessageSendEventsProvider};
use crate::ln::PaymentSecret;
use crate::ln::blinded_payment_tests::get_blinded_route_parameters;
use crate::ln::channelmanager::PaymentId;
+use crate::ln::features::BlindedHopFeatures;
use crate::ln::functional_test_utils::*;
use crate::ln::msgs;
+use crate::ln::msgs::OnionMessageHandler;
use crate::ln::onion_utils;
use crate::ln::onion_utils::MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY;
use crate::ln::outbound_payment::{RecipientOnionFields, Retry, RetryableSendFailure};
+use crate::offers::invoice::BlindedPayInfo;
use crate::prelude::*;
use crate::routing::router::{DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, PaymentParameters, RouteParameters};
use crate::util::errors::APIError;
.with_payment_secret(payment_secret)
.with_payment_metadata(payment_metadata.clone());
do_pass_along_path(args);
- claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
+ );
// Check that the payment parameter for max path length will prevent us from routing past our
// next-hop peer given the payment_metadata size.
.with_payment_secret(payment_secret_2)
.with_payment_metadata(recipient_onion_allows_2_hops.payment_metadata.unwrap());
do_pass_along_path(args);
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage_2);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage_2)
+ );
}
#[test]
.with_payment_secret(payment_secret)
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone());
do_pass_along_path(args);
- claim_payment_along_route(&nodes[1], &[&[&nodes[2]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2]]], payment_preimage)
+ .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone())
+ );
// If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding.
let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone();
let path = &[&nodes[1], &nodes[2]];
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap())
.with_payment_secret(payment_secret)
- .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs);
+ .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone());
do_pass_along_path(args);
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+ .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs)
+ );
}
#[test]
.with_payment_secret(payment_secret)
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone());
do_pass_along_path(args);
- claim_payment_along_route(&nodes[1], &[&[&nodes[2], &nodes[3]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2], &nodes[3]]], payment_preimage)
+ .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone())
+ );
// If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding.
let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone();
let path = &[&nodes[1], &nodes[2], &nodes[3]];
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap())
.with_payment_secret(payment_secret)
- .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs);
+ .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone());
do_pass_along_path(args);
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], payment_preimage)
+ .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs)
+ );
+}
+
+#[test]
+fn bolt12_invoice_too_large_blinded_paths() {
+ // Check that we'll fail paying BOLT 12 invoices with too-large blinded paths prior to
+ // pathfinding.
+ 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]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ nodes[1].router.expect_blinded_payment_paths(vec![(
+ BlindedPayInfo {
+ fee_base_msat: 42,
+ fee_proportional_millionths: 42,
+ cltv_expiry_delta: 42,
+ htlc_minimum_msat: 42,
+ htlc_maximum_msat: 42_000_000,
+ features: BlindedHopFeatures::empty(),
+ },
+ BlindedPath {
+ introduction_node: IntroductionNode::NodeId(PublicKey::from_slice(&[2; 33]).unwrap()),
+ blinding_point: PublicKey::from_slice(&[2; 33]).unwrap(),
+ blinded_hops: vec![
+ BlindedHop {
+ blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(),
+ encrypted_payload: vec![42; 1300],
+ },
+ BlindedHop {
+ blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(),
+ encrypted_payload: vec![42; 1300],
+ },
+ ],
+ }
+ )]);
+
+ 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();
+ 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();
+ nodes[0].onion_messenger.handle_onion_message(&nodes[1].node.get_our_node_id(), &invoice_om);
+ // TODO: assert on the invoice error once we support replying to invoice OMs with failure info
+ nodes[0].logger.assert_log_contains("lightning::ln::channelmanager", "Failed paying invoice: OnionPacketSizeExceeded", 1);
+
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentFailed { payment_id: id, .. } => {
+ assert_eq!(id, payment_id)
+ },
+ _ => panic!("Unexpected event"),
+ }
}