Skip to content

Commit f8e2639

Browse files
Functionally test min htlc BlindedPayInfo calculation.
1 parent 61c9146 commit f8e2639

File tree

1 file changed

+65
-1
lines changed

1 file changed

+65
-1
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::ln::msgs;
2020
use crate::ln::msgs::ChannelMessageHandler;
2121
use crate::ln::onion_utils;
2222
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
23-
use crate::ln::outbound_payment::Retry;
23+
use crate::ln::outbound_payment::{Retry, IDEMPOTENCY_TIMEOUT_TICKS};
2424
use crate::prelude::*;
2525
use crate::routing::router::{Payee, PaymentParameters, RouteParameters};
2626
use crate::util::config::UserConfig;
@@ -935,3 +935,67 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
935935
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
936936
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
937937
}
938+
939+
#[test]
940+
fn min_htlc() {
941+
// The min htlc of a blinded path is the max (htlc_min - following_fees) along the path. Make sure
942+
// the payment succeeds when we calculate the min htlc this way.
943+
let chanmon_cfgs = create_chanmon_cfgs(4);
944+
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
945+
let mut node_1_cfg = test_default_channel_config();
946+
node_1_cfg.channel_handshake_config.our_htlc_minimum_msat = 2000;
947+
node_1_cfg.channel_config.forwarding_fee_base_msat = 1000;
948+
node_1_cfg.channel_config.forwarding_fee_proportional_millionths = 100_000;
949+
let mut node_2_cfg = test_default_channel_config();
950+
node_2_cfg.channel_handshake_config.our_htlc_minimum_msat = 5000;
951+
node_2_cfg.channel_config.forwarding_fee_base_msat = 200;
952+
node_2_cfg.channel_config.forwarding_fee_proportional_millionths = 150_000;
953+
let mut node_3_cfg = test_default_channel_config();
954+
node_3_cfg.channel_handshake_config.our_htlc_minimum_msat = 2000;
955+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg)]);
956+
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
957+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
958+
let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
959+
let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0);
960+
961+
let min_htlc_msat = 4174; // the resulting htlc min
962+
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(min_htlc_msat), None);
963+
let mut route_params = get_blinded_route_parameters(
964+
min_htlc_msat, payment_secret, chan_1_2.1.contents.htlc_minimum_msat,
965+
chan_1_2.1.contents.htlc_maximum_msat, vec![nodes[1].node.get_our_node_id(),
966+
nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()],
967+
&[&chan_1_2.0.contents, &chan_2_3.0.contents], &chanmon_cfgs[3].keys_manager);
968+
assert_eq!(min_htlc_msat,
969+
route_params.payment_params.payee.blinded_route_hints()[0].0.htlc_minimum_msat);
970+
971+
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap();
972+
check_added_monitors(&nodes[0], 1);
973+
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], min_htlc_msat, payment_hash, payment_secret);
974+
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], payment_preimage);
975+
976+
// Paying 1 less than the min fails.
977+
for _ in 0..IDEMPOTENCY_TIMEOUT_TICKS + 1 {
978+
nodes[0].node.timer_tick_occurred();
979+
}
980+
if let Payee::Blinded { ref mut route_hints, .. } = route_params.payment_params.payee {
981+
route_hints[0].0.htlc_minimum_msat -= 1;
982+
} else { panic!() }
983+
route_params.final_value_msat -= 1;
984+
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
985+
check_added_monitors(&nodes[0], 1);
986+
987+
let mut payment_event_0_1 = {
988+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
989+
assert_eq!(events.len(), 1);
990+
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
991+
SendEvent::from_event(ev)
992+
};
993+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event_0_1.msgs[0]);
994+
check_added_monitors!(nodes[1], 0);
995+
do_commitment_signed_dance(&nodes[1], &nodes[0], &payment_event_0_1.commitment_msg, true, true);
996+
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
997+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
998+
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
999+
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
1000+
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
1001+
}

0 commit comments

Comments
 (0)