9
9
10
10
use bitcoin:: secp256k1:: Secp256k1 ;
11
11
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 ;
14
16
use crate :: ln:: functional_test_utils:: * ;
17
+ use crate :: ln:: msgs:: ChannelMessageHandler ;
15
18
use crate :: ln:: outbound_payment:: Retry ;
16
19
use crate :: prelude:: * ;
17
20
use crate :: routing:: router:: { PaymentParameters , RouteParameters } ;
18
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
+
19
167
#[ test]
20
168
fn one_hop_blinded_path ( ) {
21
169
do_one_hop_blinded_path ( true ) ;
@@ -49,7 +197,7 @@ fn do_one_hop_blinded_path(success: bool) {
49
197
final_value_msat : amt_msat
50
198
} ;
51
199
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 ( ) ;
53
201
check_added_monitors ( & nodes[ 0 ] , 1 ) ;
54
202
pass_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] ] ] , amt_msat, payment_hash, payment_secret) ;
55
203
if success {
@@ -58,3 +206,86 @@ fn do_one_hop_blinded_path(success: bool) {
58
206
fail_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , payment_hash) ;
59
207
}
60
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