Skip to content

Commit ef57ab0

Browse files
Support forwarding blinded payments.
Error handling will be completed in later commit(s).
1 parent b364170 commit ef57ab0

File tree

2 files changed

+337
-14
lines changed

2 files changed

+337
-14
lines changed

lightning/src/ln/blinded_payment_tests.rs

+234-3
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,161 @@
99

1010
use bitcoin::secp256k1::Secp256k1;
1111
use crate::blinded_path::BlindedPath;
12-
use crate::blinded_path::payment::{PaymentConstraints, ReceiveTlvs};
13-
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
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;
1416
use crate::ln::functional_test_utils::*;
17+
use crate::ln::msgs::ChannelMessageHandler;
1518
use crate::ln::outbound_payment::Retry;
1619
use crate::prelude::*;
1720
use crate::routing::router::{PaymentParameters, RouteParameters};
1821

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+
19167
#[test]
20168
fn one_hop_blinded_path() {
21169
do_one_hop_blinded_path(true);
@@ -49,7 +197,7 @@ fn do_one_hop_blinded_path(success: bool) {
49197
final_value_msat: amt_msat
50198
};
51199
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(),
52-
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
200+
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
53201
check_added_monitors(&nodes[0], 1);
54202
pass_along_route(&nodes[0], &[&[&nodes[1]]], amt_msat, payment_hash, payment_secret);
55203
if success {
@@ -58,3 +206,86 @@ fn do_one_hop_blinded_path(success: bool) {
58206
fail_payment(&nodes[0], &[&nodes[1]], payment_hash);
59207
}
60208
}
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

Comments
 (0)