Skip to content

Commit 0b22ccd

Browse files
Functionally test min htlc BlindedPayInfo calculation.
1 parent 7b85d01 commit 0b22ccd

File tree

1 file changed

+71
-1
lines changed

1 file changed

+71
-1
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 71 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::offers::invoice::BlindedPayInfo;
2525
use crate::prelude::*;
2626
use crate::routing::router::{Payee, PaymentParameters, RouteParameters};
@@ -1062,3 +1062,73 @@ fn blinded_path_retries() {
10621062
_ => panic!()
10631063
}
10641064
}
1065+
1066+
#[test]
1067+
fn min_htlc() {
1068+
// The min htlc of a blinded path is the max (htlc_min - following_fees) along the path. Make sure
1069+
// the payment succeeds when we calculate the min htlc this way.
1070+
let chanmon_cfgs = create_chanmon_cfgs(4);
1071+
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
1072+
let mut node_1_cfg = test_default_channel_config();
1073+
node_1_cfg.channel_handshake_config.our_htlc_minimum_msat = 2000;
1074+
node_1_cfg.channel_config.forwarding_fee_base_msat = 1000;
1075+
node_1_cfg.channel_config.forwarding_fee_proportional_millionths = 100_000;
1076+
let mut node_2_cfg = test_default_channel_config();
1077+
node_2_cfg.channel_handshake_config.our_htlc_minimum_msat = 5000;
1078+
node_2_cfg.channel_config.forwarding_fee_base_msat = 200;
1079+
node_2_cfg.channel_config.forwarding_fee_proportional_millionths = 150_000;
1080+
let mut node_3_cfg = test_default_channel_config();
1081+
node_3_cfg.channel_handshake_config.our_htlc_minimum_msat = 2000;
1082+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg)]);
1083+
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
1084+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
1085+
let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
1086+
let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0);
1087+
1088+
let min_htlc_msat = {
1089+
// The min htlc for this setup is nodes[2]'s htlc_minimum_msat minus the
1090+
// following fees.
1091+
let post_base_fee = chan_2_3.1.contents.htlc_minimum_msat - chan_2_3.0.contents.fee_base_msat as u64;
1092+
let prop_fee = chan_2_3.0.contents.fee_proportional_millionths as u64;
1093+
(post_base_fee * 1_000_000 + 1_000_000 + prop_fee - 1) / (prop_fee + 1_000_000)
1094+
};
1095+
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(min_htlc_msat), None);
1096+
let mut route_params = get_blinded_route_parameters(
1097+
min_htlc_msat, payment_secret, chan_1_2.1.contents.htlc_minimum_msat,
1098+
chan_1_2.1.contents.htlc_maximum_msat, vec![nodes[1].node.get_our_node_id(),
1099+
nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()],
1100+
&[&chan_1_2.0.contents, &chan_2_3.0.contents], &chanmon_cfgs[3].keys_manager);
1101+
assert_eq!(min_htlc_msat,
1102+
route_params.payment_params.payee.blinded_route_hints()[0].0.htlc_minimum_msat);
1103+
1104+
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap();
1105+
check_added_monitors(&nodes[0], 1);
1106+
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], min_htlc_msat, payment_hash, payment_secret);
1107+
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], payment_preimage);
1108+
1109+
// Paying 1 less than the min fails.
1110+
for _ in 0..IDEMPOTENCY_TIMEOUT_TICKS + 1 {
1111+
nodes[0].node.timer_tick_occurred();
1112+
}
1113+
if let Payee::Blinded { ref mut route_hints, .. } = route_params.payment_params.payee {
1114+
route_hints[0].0.htlc_minimum_msat -= 1;
1115+
} else { panic!() }
1116+
route_params.final_value_msat -= 1;
1117+
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
1118+
check_added_monitors(&nodes[0], 1);
1119+
1120+
let mut payment_event_0_1 = {
1121+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
1122+
assert_eq!(events.len(), 1);
1123+
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
1124+
SendEvent::from_event(ev)
1125+
};
1126+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event_0_1.msgs[0]);
1127+
check_added_monitors!(nodes[1], 0);
1128+
do_commitment_signed_dance(&nodes[1], &nodes[0], &payment_event_0_1.commitment_msg, true, true);
1129+
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1130+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
1131+
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
1132+
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
1133+
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
1134+
}

0 commit comments

Comments
 (0)