@@ -96,6 +96,7 @@ fn run_onion_failure_test<F1, F2>(
96
96
// 3: final node fails backward (but tamper onion payloads from node0)
97
97
// 100: trigger error in the intermediate node and tamper returning fail_htlc
98
98
// 200: trigger error in the final node and tamper returning fail_htlc
99
+ // 201: trigger error in the final node and delay
99
100
fn run_onion_failure_test_with_fail_intercept < F1 , F2 , F3 > (
100
101
_name : & str , test_case : u8 , nodes : & Vec < Node > , route : & Route , payment_hash : & PaymentHash ,
101
102
payment_secret : & PaymentSecret , mut callback_msg : F1 , mut callback_fail : F2 ,
@@ -160,11 +161,11 @@ fn run_onion_failure_test_with_fail_intercept<F1, F2, F3>(
160
161
assert ! ( fail_len + malformed_len == 1 && ( fail_len == 1 || malformed_len == 1 ) ) ;
161
162
update_1_0
162
163
} ,
163
- 1 | 2 | 3 | 200 => {
164
+ 1 | 2 | 3 | 200 | 201 => {
164
165
// final node failure; forwarding to 2
165
166
assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
166
167
// forwarding on 1
167
- if test_case != 200 {
168
+ if test_case != 200 && test_case != 201 {
168
169
callback_node ( ) ;
169
170
}
170
171
expect_htlc_forward ! ( & nodes[ 1 ] ) ;
@@ -182,29 +183,41 @@ fn run_onion_failure_test_with_fail_intercept<F1, F2, F3>(
182
183
nodes[ 2 ] . node . handle_update_add_htlc ( nodes[ 1 ] . node . get_our_node_id ( ) , & update_add_1) ;
183
184
commitment_signed_dance ! ( nodes[ 2 ] , nodes[ 1 ] , update_1. commitment_signed, false , true ) ;
184
185
185
- if test_case == 2 || test_case == 200 {
186
- expect_htlc_forward ! ( & nodes[ 2 ] ) ;
187
- expect_event ! ( & nodes[ 2 ] , Event :: PaymentClaimable ) ;
188
- callback_node ( ) ;
189
- expect_pending_htlcs_forwardable_and_htlc_handling_failed ! (
190
- nodes[ 2 ] ,
191
- vec![ HTLCHandlingFailureType :: Receive { payment_hash: payment_hash. clone( ) } ]
192
- ) ;
193
- } else if test_case == 1 || test_case == 3 {
194
- expect_htlc_forward ! ( & nodes[ 2 ] ) ;
195
- expect_htlc_handling_failed_destinations ! (
196
- nodes[ 2 ] . node. get_and_clear_pending_events( ) ,
197
- vec![ expected_failure_type. clone( ) . unwrap( ) ]
198
- ) ;
186
+ match test_case {
187
+ 2 | 200 | 201 => {
188
+ expect_htlc_forward ! ( & nodes[ 2 ] ) ;
189
+ expect_event ! ( & nodes[ 2 ] , Event :: PaymentClaimable ) ;
190
+ callback_node ( ) ;
191
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed ! (
192
+ nodes[ 2 ] ,
193
+ vec![ HTLCHandlingFailureType :: Receive {
194
+ payment_hash: payment_hash. clone( )
195
+ } ]
196
+ ) ;
197
+ } ,
198
+ 1 | 3 => {
199
+ expect_htlc_forward ! ( & nodes[ 2 ] ) ;
200
+ expect_htlc_handling_failed_destinations ! (
201
+ nodes[ 2 ] . node. get_and_clear_pending_events( ) ,
202
+ vec![ expected_failure_type. clone( ) . unwrap( ) ]
203
+ ) ;
204
+ } ,
205
+ _ => { } ,
199
206
}
200
207
check_added_monitors ! ( & nodes[ 2 ] , 1 ) ;
201
208
202
209
let update_2_1 = get_htlc_update_msgs ! ( nodes[ 2 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
203
210
assert ! ( update_2_1. update_fail_htlcs. len( ) == 1 ) ;
204
211
205
212
let mut fail_msg = update_2_1. update_fail_htlcs [ 0 ] . clone ( ) ;
206
- if test_case == 200 {
207
- callback_fail ( & mut fail_msg) ;
213
+ match test_case {
214
+ // Trigger error in the final node and tamper returning fail_htlc.
215
+ 200 => callback_fail ( & mut fail_msg) ,
216
+ // Trigger error in the final node and delay.
217
+ 201 => {
218
+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 200 ) ) ;
219
+ } ,
220
+ _ => { } ,
208
221
}
209
222
210
223
// 2 => 1
@@ -242,9 +255,17 @@ fn run_onion_failure_test_with_fail_intercept<F1, F2, F3>(
242
255
ref short_channel_id,
243
256
ref error_code,
244
257
failure : PathFailure :: OnPath { ref network_update } ,
258
+ ref hold_times,
245
259
..
246
260
} = & events[ 0 ]
247
261
{
262
+ // When resolution is delayed, we expect that to show up in the hold times. Hold times are only reported in std.
263
+ if test_case == 201 {
264
+ #[ cfg( feature = "std" ) ]
265
+ assert ! ( hold_times. iter( ) . any( |ht| * ht > 0 ) ) ;
266
+ #[ cfg( not( feature = "std" ) ) ]
267
+ assert ! ( hold_times. iter( ) . all( |ht| * ht == 0 ) ) ;
268
+ }
248
269
assert_eq ! ( * payment_failed_permanently, !expected_retryable) ;
249
270
assert_eq ! ( error_code. is_none( ) , expected_error_reason. is_none( ) ) ;
250
271
if let Some ( expected_reason) = expected_error_reason {
@@ -1501,6 +1522,23 @@ fn test_onion_failure() {
1501
1522
Some ( channels[ 1 ] . 0 . contents . short_channel_id ) ,
1502
1523
None ,
1503
1524
) ;
1525
+ run_onion_failure_test (
1526
+ "delayed_fail" ,
1527
+ 201 ,
1528
+ & nodes,
1529
+ & route,
1530
+ & payment_hash,
1531
+ & payment_secret,
1532
+ |_| { } ,
1533
+ || {
1534
+ nodes[ 2 ] . node . fail_htlc_backwards ( & payment_hash) ;
1535
+ } ,
1536
+ false ,
1537
+ Some ( LocalHTLCFailureReason :: IncorrectPaymentDetails ) ,
1538
+ None ,
1539
+ None ,
1540
+ None ,
1541
+ ) ;
1504
1542
}
1505
1543
1506
1544
#[ test]
0 commit comments