From 05243ebf019ac7e9dc8bea8dbd131f16145c162c Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Mon, 25 Dec 2023 00:12:30 -0500 Subject: [PATCH] Add rng test coverage for BlindedPayInfo aggregation. --- lightning/src/ln/blinded_payment_tests.rs | 97 +++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index 905ef3e4842..2be26bc55bc 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -1050,3 +1050,100 @@ fn high_prop_fees() { let expected_fee = pass_claimed_payment_along_route(args); expect_payment_sent(&nodes[0], payment_preimage, Some(Some(expected_fee)), true, true); } + +#[cfg(feature = "std")] +#[test] +fn prop_fees_rng() { + do_prop_fees_rng(true); + do_prop_fees_rng(false); +} + +#[cfg(feature = "std")] +fn do_prop_fees_rng(send_min: bool) { + use std::hash::{BuildHasher, Hasher}; + // Ensure the proportional fees are calculated correctly for `BlindedPayInfo`. + let chanmon_cfgs = create_chanmon_cfgs(5); + const PROP_LIMIT: u64 = 1_000_000; + let base_limit: u64 = if send_min { 1_000_000 } else { 15_000_000 }; + const MIN_HTLC_LIMIT: u64 = 15_000_000; + let node_cfgs = create_node_cfgs(5, &chanmon_cfgs); + + let mut node_1_cfg = test_default_channel_config(); + node_1_cfg.channel_config.forwarding_fee_base_msat = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % base_limit) as u32; + node_1_cfg.channel_config.forwarding_fee_proportional_millionths = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % PROP_LIMIT) as u32; + if send_min { + node_1_cfg.channel_handshake_config.our_htlc_minimum_msat = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % MIN_HTLC_LIMIT) as u64; + } + + let mut node_2_cfg = test_default_channel_config(); + node_2_cfg.channel_config.forwarding_fee_base_msat = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % base_limit) as u32; + node_2_cfg.channel_config.forwarding_fee_proportional_millionths = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % PROP_LIMIT) as u32; + if send_min { + node_2_cfg.channel_handshake_config.our_htlc_minimum_msat = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % MIN_HTLC_LIMIT) as u64; + } + + let mut node_3_cfg = test_default_channel_config(); + node_3_cfg.channel_config.forwarding_fee_base_msat = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % base_limit) as u32; + node_3_cfg.channel_config.forwarding_fee_proportional_millionths = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % PROP_LIMIT) as u32; + if send_min { + node_3_cfg.channel_handshake_config.our_htlc_minimum_msat = + (std::collections::hash_map::RandomState::new().build_hasher().finish() % MIN_HTLC_LIMIT) as u64; + } + + let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg), None]); + let nodes = create_network(5, &node_cfgs, &node_chanmgrs); + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); + let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0); + let chan_3_4 = create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0); + + let amt_msat = if send_min { + get_blinded_route_parameters( + 42, PaymentSecret([0; 32]), chan_1_2.1.contents.htlc_minimum_msat, + chan_1_2.1.contents.htlc_maximum_msat, + nodes.iter().skip(1).map(|node| node.node.get_our_node_id()).collect(), + &[&chan_1_2.0.contents, &chan_2_3.0.contents, &chan_3_4.0.contents], + &chanmon_cfgs[4].keys_manager + ) + .payment_params.payee.blinded_route_hints()[0].0.htlc_minimum_msat + } else { 100_000 }; + let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); + + let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret, + chan_1_2.1.contents.htlc_minimum_msat, chan_1_2.1.contents.htlc_maximum_msat, + nodes.iter().skip(1).map(|node| node.node.get_our_node_id()).collect(), + &[&chan_1_2.0.contents, &chan_2_3.0.contents, &chan_3_4.0.contents], + &chanmon_cfgs[4].keys_manager); + route_params.max_total_routing_fee_msat = None; + + nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).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 event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + let expected_path = &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]; + + let args = PassAlongPathArgs::new(&nodes[0], expected_path, amt_msat, payment_hash, event) + .with_payment_secret(payment_secret) + .with_overpay_limit(if send_min { 40 } else { 3 }); + let claimable_ev = do_pass_along_path(args); + let claim_amt = if let Some(crate::events::Event::PaymentClaimable { amount_msat, .. }) = claimable_ev { + amount_msat + } else { panic!() }; + let overpayment_amt = claim_amt.checked_sub(amt_msat).unwrap(); + + nodes[4].node.claim_funds(payment_preimage); + let expected_route = &[&expected_path[..]]; + let mut claim_args = ClaimAlongRouteArgs::new(&nodes[0], &expected_route[..], payment_preimage) + .allow_1_msat_fee_overpay(); + let expected_fee = pass_claimed_payment_along_route(claim_args); + expect_payment_sent(&nodes[0], payment_preimage, Some(Some(expected_fee + overpayment_amt)), true, true); +}