@@ -2436,6 +2436,110 @@ def test_lockup_drain(node_factory, bitcoind):
2436
2436
l2 .pay (l1 , total // 2 )
2437
2437
2438
2438
2439
+ @pytest .mark .developer ("needs DEVELOPER=1 for dev_ignore_htlcs" )
2440
+ def test_htlc_too_dusty_outgoing (node_factory , bitcoind ):
2441
+ """ Try to hit the 'too much dust' limit, should fail the HTLC """
2442
+ feerate = 10000
2443
+ max_dust_limit_sat = 50000
2444
+
2445
+ l1 , l2 = node_factory .line_graph (2 , opts = {'may_reconnect' : True ,
2446
+ 'feerates' : (feerate , feerate , feerate , feerate ),
2447
+ 'max-dust-htlc-exposure-msat' : '{}sat' .format (max_dust_limit_sat ),
2448
+ 'allow_warning' : True })
2449
+
2450
+ # l2 holds all of l1's htlcs hostage
2451
+ l2 .rpc .dev_ignore_htlcs (id = l1 .info ['id' ], ignore = True )
2452
+
2453
+ # l2's max dust limit is set to 100k
2454
+ htlc_val_sat = 5000
2455
+ htlc_val_msat = htlc_val_sat * 1000
2456
+ num_dusty_htlcs = max_dust_limit_sat // htlc_val_sat
2457
+
2458
+ # add a some non-dusty htlcs, these will fail when we raise the dust limit
2459
+ route = l1 .rpc .getroute (l2 .info ['id' ], 10000 * 1000 , 1 )['route' ]
2460
+ for i in range (0 , 3 ):
2461
+ inv = l2 .rpc .invoice ((10000 * 1000 ), str (i + 100 ), str (i + 100 ))
2462
+ l1 .rpc .sendpay (route , inv ['payment_hash' ], payment_secret = inv ['payment_secret' ])
2463
+ l2 .daemon .wait_for_log (r'their htlc .* dev_ignore_htlcs' )
2464
+ res = only_one (l1 .rpc .listsendpays (payment_hash = inv ['payment_hash' ])['payments' ])
2465
+ assert res ['status' ] == 'pending'
2466
+
2467
+ # add some dusty-htlcs
2468
+ route = l1 .rpc .getroute (l2 .info ['id' ], htlc_val_msat , 1 )['route' ]
2469
+ for i in range (0 , num_dusty_htlcs ):
2470
+ inv = l2 .rpc .invoice (htlc_val_msat , str (i ), str (i ))
2471
+ l1 .rpc .sendpay (route , inv ['payment_hash' ], payment_secret = inv ['payment_secret' ])
2472
+ l2 .daemon .wait_for_log (r'their htlc .* dev_ignore_htlcs' )
2473
+ res = only_one (l1 .rpc .listsendpays (payment_hash = inv ['payment_hash' ])['payments' ])
2474
+ assert res ['status' ] == 'pending'
2475
+
2476
+ # one more should tip it over, and return a payment failure
2477
+ inv = l2 .rpc .invoice (htlc_val_msat , str (num_dusty_htlcs ), str (num_dusty_htlcs ))
2478
+ l1 .rpc .sendpay (route , inv ['payment_hash' ], payment_secret = inv ['payment_secret' ])
2479
+ l1 .daemon .wait_for_log ('CHANNEL_ERR_DUST_FAILURE' )
2480
+ wait_for (lambda : only_one (l1 .rpc .listsendpays (payment_hash = inv ['payment_hash' ])['payments' ])['status' ] == 'failed' )
2481
+
2482
+ # but we can still add a non dust htlc
2483
+ route = l1 .rpc .getroute (l2 .info ['id' ], 10000 * 1000 , 1 )['route' ]
2484
+ inv = l2 .rpc .invoice ((10000 * 1000 ), str (120 ), str (120 ))
2485
+ l1 .rpc .sendpay (route , inv ['payment_hash' ], payment_secret = inv ['payment_secret' ])
2486
+ l2 .daemon .wait_for_log (r'their htlc .* dev_ignore_htlcs' )
2487
+ res = only_one (l1 .rpc .listsendpays (payment_hash = inv ['payment_hash' ])['payments' ])
2488
+ assert res ['status' ] == 'pending'
2489
+
2490
+ # Ok, adjust our feerate upward, so the non-dust htlcs are now dust
2491
+ # note that this is above the buffer we've been keeping, so the channel
2492
+ # should automatically fail
2493
+ l1 .set_feerates ([feerate * 2 ] * 4 , False )
2494
+ l1 .restart ()
2495
+
2496
+ # the channel should fail -- too much dust
2497
+ inv = l2 .rpc .invoice (htlc_val_msat , str (num_dusty_htlcs + 1 ), str (num_dusty_htlcs + 1 ))
2498
+ with pytest .raises (RpcError , match = r'WIRE_UNKNOWN_NEXT_PEER' ):
2499
+ l1 .rpc .sendpay (route , inv ['payment_hash' ], payment_secret = inv ['payment_secret' ])
2500
+
2501
+
2502
+ @pytest .mark .developer ("needs DEVELOPER=1 for dev_ignore_htlcs" )
2503
+ def test_htlc_too_dusty_incoming (node_factory , bitcoind ):
2504
+ """ Try to hit the 'too much dust' limit, should fail the HTLC """
2505
+ feerate = 30000
2506
+ l1 , l2 , l3 = node_factory .line_graph (3 , opts = [{'may_reconnect' : True ,
2507
+ 'feerates' : (feerate , feerate , feerate , feerate ),
2508
+ 'max-dust-htlc-exposure-msat' : '200000sat' },
2509
+ {'may_reconnect' : True ,
2510
+ 'feerates' : (feerate , feerate , feerate , feerate ),
2511
+ 'max-dust-htlc-exposure-msat' : '100000sat' ,
2512
+ 'fee-base' : 0 ,
2513
+ 'fee-per-satoshi' : 0 },
2514
+ {}],
2515
+ wait_for_announce = True )
2516
+
2517
+ # on the l2->l3, and l3 holds all the htlcs hostage
2518
+ # have l3 hold onto all the htlcs and not fulfill them
2519
+ l3 .rpc .dev_ignore_htlcs (id = l2 .info ['id' ], ignore = True )
2520
+
2521
+ # l2's max dust limit is set to 100k
2522
+ max_dust_limit_sat = 100000
2523
+ htlc_val_sat = 10000
2524
+ htlc_val_msat = htlc_val_sat * 1000
2525
+ num_dusty_htlcs = max_dust_limit_sat // htlc_val_sat
2526
+ route = l1 .rpc .getroute (l3 .info ['id' ], htlc_val_msat , 1 )['route' ]
2527
+
2528
+ # l1 sends as much money as it can
2529
+ for i in range (0 , num_dusty_htlcs ):
2530
+ inv = l3 .rpc .invoice (htlc_val_msat , str (i ), str (i ))
2531
+ l1 .rpc .sendpay (route , inv ['payment_hash' ], payment_secret = inv ['payment_secret' ])
2532
+ l3 .daemon .wait_for_log (r'their htlc .* dev_ignore_htlcs' )
2533
+ res = only_one (l1 .rpc .listsendpays (payment_hash = inv ['payment_hash' ])['payments' ])
2534
+ assert res ['status' ] == 'pending'
2535
+
2536
+ # one more should tip it over, and return a payment failure
2537
+ inv = l3 .rpc .invoice (htlc_val_msat , str (num_dusty_htlcs ), str (num_dusty_htlcs ))
2538
+ l1 .rpc .sendpay (route , inv ['payment_hash' ], payment_secret = inv ['payment_secret' ])
2539
+ l2 .daemon .wait_for_log ('failing immediately, as requested' )
2540
+ wait_for (lambda : only_one (l1 .rpc .listsendpays (payment_hash = inv ['payment_hash' ])['payments' ])['status' ] == 'failed' )
2541
+
2542
+
2439
2543
def test_error_returns_blockheight (node_factory , bitcoind ):
2440
2544
"""Test that incorrect_or_unknown_payment_details returns block height"""
2441
2545
l1 , l2 = node_factory .line_graph (2 )
0 commit comments