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