|  | 
| 10 | 10 | use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; | 
| 11 | 11 | use crate::blinded_path::BlindedPath; | 
| 12 | 12 | use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs}; | 
| 13 |  | -use crate::events::{HTLCDestination, MessageSendEvent, MessageSendEventsProvider}; | 
|  | 13 | +use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider}; | 
| 14 | 14 | use crate::ln::PaymentSecret; | 
| 15 | 15 | use crate::ln::channelmanager; | 
| 16 | 16 | use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; | 
| @@ -1050,3 +1050,100 @@ fn high_prop_fees() { | 
| 1050 | 1050 | 	let expected_fee = pass_claimed_payment_along_route(args); | 
| 1051 | 1051 | 	expect_payment_sent(&nodes[0], payment_preimage, Some(Some(expected_fee)), true, true); | 
| 1052 | 1052 | } | 
|  | 1053 | + | 
|  | 1054 | +#[cfg(feature = "std")] | 
|  | 1055 | +#[test] | 
|  | 1056 | +fn prop_fees_rng() { | 
|  | 1057 | +	do_prop_fees_rng(true); | 
|  | 1058 | +	do_prop_fees_rng(false); | 
|  | 1059 | +} | 
|  | 1060 | + | 
|  | 1061 | +#[cfg(feature = "std")] | 
|  | 1062 | +fn do_prop_fees_rng(send_min: bool) { | 
|  | 1063 | +	use std::hash::{BuildHasher, Hasher}; | 
|  | 1064 | +	// Ensure the proportional fees are calculated correctly for `BlindedPayInfo`. | 
|  | 1065 | +	let chanmon_cfgs = create_chanmon_cfgs(5); | 
|  | 1066 | +	const PROP_LIMIT: u64 = 1_000_000; | 
|  | 1067 | +	let base_limit: u64 = if send_min { 1_000_000 } else { 15_000_000 }; | 
|  | 1068 | +	const MIN_HTLC_LIMIT: u64 = 15_000_000; | 
|  | 1069 | +	let node_cfgs = create_node_cfgs(5, &chanmon_cfgs); | 
|  | 1070 | + | 
|  | 1071 | +	let mut node_1_cfg = test_default_channel_config(); | 
|  | 1072 | +	node_1_cfg.channel_config.forwarding_fee_base_msat = | 
|  | 1073 | +		(std::collections::hash_map::RandomState::new().build_hasher().finish() % base_limit) as u32; | 
|  | 1074 | +	node_1_cfg.channel_config.forwarding_fee_proportional_millionths = | 
|  | 1075 | +		(std::collections::hash_map::RandomState::new().build_hasher().finish() % PROP_LIMIT) as u32; | 
|  | 1076 | +	if send_min { | 
|  | 1077 | +		node_1_cfg.channel_handshake_config.our_htlc_minimum_msat = | 
|  | 1078 | +			(std::collections::hash_map::RandomState::new().build_hasher().finish() % MIN_HTLC_LIMIT) as u64; | 
|  | 1079 | +	} | 
|  | 1080 | + | 
|  | 1081 | +	let mut node_2_cfg = test_default_channel_config(); | 
|  | 1082 | +	node_2_cfg.channel_config.forwarding_fee_base_msat = | 
|  | 1083 | +		(std::collections::hash_map::RandomState::new().build_hasher().finish() % base_limit) as u32; | 
|  | 1084 | +	node_2_cfg.channel_config.forwarding_fee_proportional_millionths = | 
|  | 1085 | +		(std::collections::hash_map::RandomState::new().build_hasher().finish() % PROP_LIMIT) as u32; | 
|  | 1086 | +	if send_min { | 
|  | 1087 | +		node_2_cfg.channel_handshake_config.our_htlc_minimum_msat = | 
|  | 1088 | +			(std::collections::hash_map::RandomState::new().build_hasher().finish() % MIN_HTLC_LIMIT) as u64; | 
|  | 1089 | +	} | 
|  | 1090 | + | 
|  | 1091 | +	let mut node_3_cfg = test_default_channel_config(); | 
|  | 1092 | +	node_3_cfg.channel_config.forwarding_fee_base_msat = | 
|  | 1093 | +		(std::collections::hash_map::RandomState::new().build_hasher().finish() % base_limit) as u32; | 
|  | 1094 | +	node_3_cfg.channel_config.forwarding_fee_proportional_millionths = | 
|  | 1095 | +		(std::collections::hash_map::RandomState::new().build_hasher().finish() % PROP_LIMIT) as u32; | 
|  | 1096 | +	if send_min { | 
|  | 1097 | +		node_3_cfg.channel_handshake_config.our_htlc_minimum_msat = | 
|  | 1098 | +			(std::collections::hash_map::RandomState::new().build_hasher().finish() % MIN_HTLC_LIMIT) as u64; | 
|  | 1099 | +	} | 
|  | 1100 | + | 
|  | 1101 | +	let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg), None]); | 
|  | 1102 | +	let nodes = create_network(5, &node_cfgs, &node_chanmgrs); | 
|  | 1103 | +	create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); | 
|  | 1104 | +	let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); | 
|  | 1105 | +	let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0); | 
|  | 1106 | +	let chan_3_4 = create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0); | 
|  | 1107 | + | 
|  | 1108 | +	let amt_msat = if send_min { | 
|  | 1109 | +		get_blinded_route_parameters( | 
|  | 1110 | +			42, PaymentSecret([0; 32]), chan_1_2.1.contents.htlc_minimum_msat, | 
|  | 1111 | +			chan_1_2.1.contents.htlc_maximum_msat, | 
|  | 1112 | +			nodes.iter().skip(1).map(|node| node.node.get_our_node_id()).collect(), | 
|  | 1113 | +			&[&chan_1_2.0.contents, &chan_2_3.0.contents, &chan_3_4.0.contents], | 
|  | 1114 | +			&chanmon_cfgs[4].keys_manager | 
|  | 1115 | +		) | 
|  | 1116 | +			.payment_params.payee.blinded_route_hints()[0].0.htlc_minimum_msat | 
|  | 1117 | +	} else { 100_000 }; | 
|  | 1118 | +	let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); | 
|  | 1119 | + | 
|  | 1120 | +	let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret, | 
|  | 1121 | +		chan_1_2.1.contents.htlc_minimum_msat, chan_1_2.1.contents.htlc_maximum_msat, | 
|  | 1122 | +		nodes.iter().skip(1).map(|node| node.node.get_our_node_id()).collect(), | 
|  | 1123 | +		&[&chan_1_2.0.contents, &chan_2_3.0.contents, &chan_3_4.0.contents], | 
|  | 1124 | +		&chanmon_cfgs[4].keys_manager); | 
|  | 1125 | +	route_params.max_total_routing_fee_msat = None; | 
|  | 1126 | + | 
|  | 1127 | +	nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap(); | 
|  | 1128 | +	check_added_monitors(&nodes[0], 1); | 
|  | 1129 | +	let mut events = nodes[0].node.get_and_clear_pending_msg_events(); | 
|  | 1130 | +	assert_eq!(events.len(), 1); | 
|  | 1131 | +	let event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); | 
|  | 1132 | +	let expected_path = &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]; | 
|  | 1133 | + | 
|  | 1134 | +	let args = PassAlongPathArgs::new(&nodes[0], expected_path, amt_msat, payment_hash, event) | 
|  | 1135 | +		.with_payment_secret(payment_secret) | 
|  | 1136 | +		.with_overpay_limit(if send_min { 40 } else { 3 }); | 
|  | 1137 | +	let claimable_ev = do_pass_along_path(args); | 
|  | 1138 | +	let claim_amt = if let Some(Event::PaymentClaimable { amount_msat, .. }) = claimable_ev { | 
|  | 1139 | +		amount_msat | 
|  | 1140 | +	} else { panic!() }; | 
|  | 1141 | +	let overpayment_amt = claim_amt.checked_sub(amt_msat).unwrap(); | 
|  | 1142 | + | 
|  | 1143 | +	nodes[4].node.claim_funds(payment_preimage); | 
|  | 1144 | +	let expected_route = &[&expected_path[..]]; | 
|  | 1145 | +	let mut claim_args = ClaimAlongRouteArgs::new(&nodes[0], &expected_route[..], payment_preimage) | 
|  | 1146 | +		.allow_1_msat_fee_overpay(); | 
|  | 1147 | +	let expected_fee = pass_claimed_payment_along_route(claim_args); | 
|  | 1148 | +	expect_payment_sent(&nodes[0], payment_preimage, Some(Some(expected_fee + overpayment_amt)), true, true); | 
|  | 1149 | +} | 
0 commit comments