|
| 1 | +// This file is Copyright its original authors, visible in version control |
| 2 | +// history. |
| 3 | +// |
| 4 | +// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE |
| 5 | +// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 6 | +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option. |
| 7 | +// You may not use this file except in accordance with one or both of these |
| 8 | +// licenses. |
| 9 | + |
| 10 | +use bitcoin::secp256k1::Secp256k1; |
| 11 | +use crate::blinded_path::BlindedPath; |
| 12 | +use crate::blinded_path::payment::{ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs}; |
| 13 | +use crate::events::MessageSendEventsProvider; |
| 14 | +use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, RetryableSendFailure}; |
| 15 | +use crate::ln::features::BlindedHopFeatures; |
| 16 | +use crate::ln::functional_test_utils::*; |
| 17 | +use crate::ln::msgs::ChannelMessageHandler; |
| 18 | +use crate::ln::outbound_payment::Retry; |
| 19 | +use crate::prelude::*; |
| 20 | +use crate::routing::router::{PaymentParameters, RouteParameters}; |
| 21 | + |
| 22 | +#[test] |
| 23 | +fn simple_blinded_payment() { |
| 24 | + let chanmon_cfgs = create_chanmon_cfgs(4); |
| 25 | + let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); |
| 26 | + let mut cfg = test_default_channel_config(); |
| 27 | + // Test the fee_proportional_millionths specified in the blinded path's payment constraints. |
| 28 | + cfg.channel_config.forwarding_fee_proportional_millionths = 100; |
| 29 | + let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, Some(cfg), None]); |
| 30 | + let nodes = create_network(4, &node_cfgs, &node_chanmgrs); |
| 31 | + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); |
| 32 | + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); |
| 33 | + let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; |
| 34 | + |
| 35 | + let amt_msat = 5000; |
| 36 | + let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); |
| 37 | + let intermediate_nodes = vec![(nodes[2].node.get_our_node_id(), ForwardTlvs { |
| 38 | + short_channel_id: chan_upd.short_channel_id, |
| 39 | + payment_relay: PaymentRelay { |
| 40 | + cltv_expiry_delta: chan_upd.cltv_expiry_delta, |
| 41 | + fee_proportional_millionths: chan_upd.fee_proportional_millionths, |
| 42 | + fee_base_msat: chan_upd.fee_base_msat, |
| 43 | + }, |
| 44 | + payment_constraints: PaymentConstraints { |
| 45 | + max_cltv_expiry: u32::max_value(), |
| 46 | + htlc_minimum_msat: chan_upd.htlc_minimum_msat, |
| 47 | + }, |
| 48 | + features: BlindedHopFeatures::empty(), |
| 49 | + })]; |
| 50 | + let payee_tlvs = ReceiveTlvs { |
| 51 | + payment_secret, |
| 52 | + payment_constraints: PaymentConstraints { |
| 53 | + max_cltv_expiry: u32::max_value(), |
| 54 | + htlc_minimum_msat: chan_upd.htlc_minimum_msat, |
| 55 | + }, |
| 56 | + }; |
| 57 | + let mut secp_ctx = Secp256k1::new(); |
| 58 | + let blinded_path = BlindedPath::new_for_payment( |
| 59 | + &intermediate_nodes[..], nodes[3].node.get_our_node_id(), payee_tlvs, |
| 60 | + chan_upd.htlc_maximum_msat, &chanmon_cfgs[3].keys_manager, &secp_ctx |
| 61 | + ).unwrap(); |
| 62 | + |
| 63 | + let route_params = RouteParameters { |
| 64 | + payment_params: PaymentParameters::blinded(vec![blinded_path]), |
| 65 | + final_value_msat: amt_msat |
| 66 | + }; |
| 67 | + nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); |
| 68 | + check_added_monitors(&nodes[0], 1); |
| 69 | + pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], amt_msat, payment_hash, payment_secret); |
| 70 | + claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], payment_preimage); |
| 71 | +} |
| 72 | + |
| 73 | +#[test] |
| 74 | +fn blinded_intercept_payment() { |
| 75 | + let chanmon_cfgs = create_chanmon_cfgs(3); |
| 76 | + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); |
| 77 | + let mut intercept_forwards_config = test_default_channel_config(); |
| 78 | + intercept_forwards_config.accept_intercept_htlcs = true; |
| 79 | + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), None]); |
| 80 | + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); |
| 81 | + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); |
| 82 | + let chan = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); |
| 83 | + let (channel_id, chan_upd) = (chan.2, chan.0.contents); |
| 84 | + |
| 85 | + let amt_msat = 5000; |
| 86 | + let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); |
| 87 | + let intercept_scid = nodes[1].node.get_intercept_scid(); |
| 88 | + let intermediate_nodes = vec![(nodes[1].node.get_our_node_id(), ForwardTlvs { |
| 89 | + short_channel_id: intercept_scid, |
| 90 | + payment_relay: PaymentRelay { |
| 91 | + cltv_expiry_delta: chan_upd.cltv_expiry_delta, |
| 92 | + fee_proportional_millionths: chan_upd.fee_proportional_millionths, |
| 93 | + fee_base_msat: chan_upd.fee_base_msat, |
| 94 | + }, |
| 95 | + payment_constraints: PaymentConstraints { |
| 96 | + max_cltv_expiry: u32::max_value(), |
| 97 | + htlc_minimum_msat: chan_upd.htlc_minimum_msat, |
| 98 | + }, |
| 99 | + features: BlindedHopFeatures::empty(), |
| 100 | + })]; |
| 101 | + let payee_tlvs = ReceiveTlvs { |
| 102 | + payment_secret, |
| 103 | + payment_constraints: PaymentConstraints { |
| 104 | + max_cltv_expiry: u32::max_value(), |
| 105 | + htlc_minimum_msat: chan_upd.htlc_minimum_msat, |
| 106 | + }, |
| 107 | + }; |
| 108 | + let mut secp_ctx = Secp256k1::new(); |
| 109 | + let blinded_path = BlindedPath::new_for_payment( |
| 110 | + &intermediate_nodes[..], nodes[2].node.get_our_node_id(), payee_tlvs, |
| 111 | + chan_upd.htlc_maximum_msat, &chanmon_cfgs[2].keys_manager, &secp_ctx |
| 112 | + ).unwrap(); |
| 113 | + |
| 114 | + let route_params = RouteParameters { |
| 115 | + payment_params: PaymentParameters::blinded(vec![blinded_path]), |
| 116 | + final_value_msat: amt_msat |
| 117 | + }; |
| 118 | + nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), |
| 119 | + PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); |
| 120 | + check_added_monitors(&nodes[0], 1); |
| 121 | + let payment_event = { |
| 122 | + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); |
| 123 | + assert_eq!(events.len(), 1); |
| 124 | + SendEvent::from_event(events.remove(0)) |
| 125 | + }; |
| 126 | + nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); |
| 127 | + commitment_signed_dance!(nodes[1], nodes[0], &payment_event.commitment_msg, false, true); |
| 128 | + |
| 129 | + let events = nodes[1].node.get_and_clear_pending_events(); |
| 130 | + assert_eq!(events.len(), 1); |
| 131 | + let (intercept_id, expected_outbound_amount_msat) = match events[0] { |
| 132 | + crate::events::Event::HTLCIntercepted { |
| 133 | + intercept_id, expected_outbound_amount_msat, payment_hash: pmt_hash, |
| 134 | + requested_next_hop_scid: short_channel_id, .. |
| 135 | + } => { |
| 136 | + assert_eq!(pmt_hash, payment_hash); |
| 137 | + assert_eq!(short_channel_id, intercept_scid); |
| 138 | + (intercept_id, expected_outbound_amount_msat) |
| 139 | + }, |
| 140 | + _ => panic!() |
| 141 | + }; |
| 142 | + |
| 143 | + nodes[1].node.forward_intercepted_htlc(intercept_id, &channel_id, nodes[2].node.get_our_node_id(), |
| 144 | + expected_outbound_amount_msat).unwrap(); |
| 145 | + expect_pending_htlcs_forwardable!(nodes[1]); |
| 146 | + |
| 147 | + let payment_event = { |
| 148 | + { |
| 149 | + let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); |
| 150 | + assert_eq!(added_monitors.len(), 1); |
| 151 | + added_monitors.clear(); |
| 152 | + } |
| 153 | + let mut events = nodes[1].node.get_and_clear_pending_msg_events(); |
| 154 | + assert_eq!(events.len(), 1); |
| 155 | + SendEvent::from_event(events.remove(0)) |
| 156 | + }; |
| 157 | + nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); |
| 158 | + commitment_signed_dance!(nodes[2], nodes[1], &payment_event.commitment_msg, false, true); |
| 159 | + expect_pending_htlcs_forwardable!(nodes[2]); |
| 160 | + |
| 161 | + expect_payment_claimable!(&nodes[2], payment_hash, payment_secret, amt_msat, None, |
| 162 | + nodes[2].node.get_our_node_id()); |
| 163 | + do_claim_payment_along_route(&nodes[0], &vec!(&vec!(&nodes[1], &nodes[2])[..]), false, payment_preimage); |
| 164 | + expect_payment_sent(&nodes[0], payment_preimage, Some(Some(1000)), true, true); |
| 165 | +} |
| 166 | + |
| 167 | +#[test] |
| 168 | +fn one_hop_blinded_path() { |
| 169 | + do_one_hop_blinded_path(true); |
| 170 | + do_one_hop_blinded_path(false); |
| 171 | +} |
| 172 | + |
| 173 | +fn do_one_hop_blinded_path(success: bool) { |
| 174 | + let chanmon_cfgs = create_chanmon_cfgs(2); |
| 175 | + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); |
| 176 | + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); |
| 177 | + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); |
| 178 | + let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; |
| 179 | + |
| 180 | + let amt_msat = 5000; |
| 181 | + let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); |
| 182 | + let payee_tlvs = ReceiveTlvs { |
| 183 | + payment_secret, |
| 184 | + payment_constraints: PaymentConstraints { |
| 185 | + max_cltv_expiry: u32::max_value(), |
| 186 | + htlc_minimum_msat: chan_upd.htlc_minimum_msat, |
| 187 | + }, |
| 188 | + }; |
| 189 | + let mut secp_ctx = Secp256k1::new(); |
| 190 | + let blinded_path = BlindedPath::new_for_payment( |
| 191 | + &[], nodes[1].node.get_our_node_id(), payee_tlvs, chan_upd.htlc_maximum_msat, |
| 192 | + &chanmon_cfgs[1].keys_manager, &secp_ctx |
| 193 | + ).unwrap(); |
| 194 | + |
| 195 | + let route_params = RouteParameters { |
| 196 | + payment_params: PaymentParameters::blinded(vec![blinded_path]), |
| 197 | + final_value_msat: amt_msat |
| 198 | + }; |
| 199 | + nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), |
| 200 | + PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); |
| 201 | + check_added_monitors(&nodes[0], 1); |
| 202 | + pass_along_route(&nodes[0], &[&[&nodes[1]]], amt_msat, payment_hash, payment_secret); |
| 203 | + if success { |
| 204 | + claim_payment(&nodes[0], &[&nodes[1]], payment_preimage); |
| 205 | + } else { |
| 206 | + fail_payment(&nodes[0], &[&nodes[1]], payment_hash); |
| 207 | + } |
| 208 | +} |
| 209 | + |
| 210 | +#[test] |
| 211 | +fn min_htlc() { |
| 212 | + // The min htlc of a blinded path is the max (htlc_min - following_fees) along the path. Make sure |
| 213 | + // the payment succeeds when we calculate the min htlc this way. |
| 214 | + let chanmon_cfgs = create_chanmon_cfgs(4); |
| 215 | + let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); |
| 216 | + let mut node_0_cfg = test_default_channel_config(); |
| 217 | + let mut node_1_cfg = test_default_channel_config(); |
| 218 | + node_1_cfg.channel_handshake_config.our_htlc_minimum_msat = 2000; |
| 219 | + node_1_cfg.channel_config.forwarding_fee_base_msat = 1000; |
| 220 | + let mut node_2_cfg = test_default_channel_config(); |
| 221 | + node_2_cfg.channel_handshake_config.our_htlc_minimum_msat = 5000; |
| 222 | + node_2_cfg.channel_config.forwarding_fee_base_msat = 200; |
| 223 | + let mut node_3_cfg = test_default_channel_config(); |
| 224 | + node_3_cfg.channel_handshake_config.our_htlc_minimum_msat = 2000; |
| 225 | + let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[Some(node_0_cfg), Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg)]); |
| 226 | + let nodes = create_network(4, &node_cfgs, &node_chanmgrs); |
| 227 | + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; |
| 228 | + let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); |
| 229 | + let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0); |
| 230 | + let chan_upd_1_2 = chan_1_2.0.contents; |
| 231 | + let chan_upd_2_3 = chan_2_3.0.contents; |
| 232 | + |
| 233 | + let min_htlc_msat = 4800; // the resulting htlc min |
| 234 | + let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(min_htlc_msat), None); |
| 235 | + let intermediate_nodes = vec![(nodes[1].node.get_our_node_id(), ForwardTlvs { |
| 236 | + short_channel_id: chan_upd_1_2.short_channel_id, |
| 237 | + payment_relay: PaymentRelay { |
| 238 | + cltv_expiry_delta: chan_upd_1_2.cltv_expiry_delta, |
| 239 | + fee_proportional_millionths: chan_upd_1_2.fee_proportional_millionths, |
| 240 | + fee_base_msat: chan_upd_1_2.fee_base_msat, |
| 241 | + }, |
| 242 | + payment_constraints: PaymentConstraints { |
| 243 | + max_cltv_expiry: u32::max_value(), |
| 244 | + htlc_minimum_msat: chan_upd_1_2.htlc_minimum_msat, |
| 245 | + }, |
| 246 | + features: BlindedHopFeatures::empty(), |
| 247 | + }), (nodes[2].node.get_our_node_id(), ForwardTlvs { |
| 248 | + short_channel_id: chan_upd_2_3.short_channel_id, |
| 249 | + payment_relay: PaymentRelay { |
| 250 | + cltv_expiry_delta: chan_upd_2_3.cltv_expiry_delta, |
| 251 | + fee_proportional_millionths: chan_upd_2_3.fee_proportional_millionths, |
| 252 | + fee_base_msat: chan_upd_2_3.fee_base_msat, |
| 253 | + }, |
| 254 | + payment_constraints: PaymentConstraints { |
| 255 | + max_cltv_expiry: u32::max_value(), |
| 256 | + htlc_minimum_msat: chan_upd_2_3.htlc_minimum_msat, |
| 257 | + }, |
| 258 | + features: BlindedHopFeatures::empty(), |
| 259 | + })]; |
| 260 | + let payee_tlvs = ReceiveTlvs { |
| 261 | + payment_secret, |
| 262 | + payment_constraints: PaymentConstraints { |
| 263 | + max_cltv_expiry: u32::max_value(), |
| 264 | + htlc_minimum_msat: 1, |
| 265 | + }, |
| 266 | + }; |
| 267 | + let mut secp_ctx = Secp256k1::new(); |
| 268 | + let blinded_path = BlindedPath::new_for_payment( |
| 269 | + &intermediate_nodes[..], nodes[3].node.get_our_node_id(), payee_tlvs, |
| 270 | + chan_upd_2_3.htlc_maximum_msat, &chanmon_cfgs[3].keys_manager, &secp_ctx |
| 271 | + ).unwrap(); |
| 272 | + assert_eq!(min_htlc_msat, blinded_path.0.htlc_minimum_msat); |
| 273 | + |
| 274 | + let route_params = RouteParameters { |
| 275 | + payment_params: PaymentParameters::blinded(vec![blinded_path.clone()]), |
| 276 | + final_value_msat: min_htlc_msat, |
| 277 | + }; |
| 278 | + nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); |
| 279 | + check_added_monitors(&nodes[0], 1); |
| 280 | + pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], min_htlc_msat, payment_hash, payment_secret); |
| 281 | + claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], payment_preimage); |
| 282 | + |
| 283 | + // Paying 1 less than the min fails. |
| 284 | + let route_params = RouteParameters { |
| 285 | + payment_params: PaymentParameters::blinded(vec![blinded_path]), |
| 286 | + final_value_msat: min_htlc_msat - 1, |
| 287 | + }; |
| 288 | + if let Err(e) = nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)) { |
| 289 | + assert_eq!(e, RetryableSendFailure::RouteNotFound); |
| 290 | + } else { panic!() } |
| 291 | +} |
0 commit comments