Skip to content

Commit 616a432

Browse files
committed
bcli: use a more urgent feerate for HTLCs and penalty transactions
A CONSERVATIVE/3 target for them. Some noisy changes to the tests as we had to update the estimatesmartfee mock. Changelog-Changed: We now use a higher feerate for resolving onchain HTLCs and for penalty transactions
1 parent abba2b4 commit 616a432

File tree

6 files changed

+121
-65
lines changed

6 files changed

+121
-65
lines changed

contrib/pyln-testing/pyln/testing/utils.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -853,10 +853,12 @@ def mock_estimatesmartfee(r):
853853
params = r['params']
854854
if params == [2, 'CONSERVATIVE']:
855855
feerate = feerates[0] * 4
856-
elif params == [4, 'ECONOMICAL']:
856+
elif params == [3, 'CONSERVATIVE']:
857857
feerate = feerates[1] * 4
858-
elif params == [100, 'ECONOMICAL']:
858+
elif params == [4, 'ECONOMICAL']:
859859
feerate = feerates[2] * 4
860+
elif params == [100, 'ECONOMICAL']:
861+
feerate = feerates[3] * 4
860862
else:
861863
raise ValueError()
862864
return {
@@ -871,7 +873,8 @@ def mock_estimatesmartfee(r):
871873
# Technically, this waits until it's called, not until it's processed.
872874
# We wait until all three levels have been called.
873875
if wait_for_effect:
874-
wait_for(lambda: self.daemon.rpcproxy.mock_counts['estimatesmartfee'] >= 3)
876+
wait_for(lambda:
877+
self.daemon.rpcproxy.mock_counts['estimatesmartfee'] >= 4)
875878

876879
def wait_for_onchaind_broadcast(self, name, resolve=None):
877880
"""Wait for onchaind to drop tx name to resolve (if any)"""
@@ -989,7 +992,7 @@ def get_nodes(self, num_nodes, opts=None):
989992
return [j.result() for j in jobs]
990993

991994
def get_node(self, node_id=None, options=None, dbfile=None,
992-
feerates=(15000, 7500, 3750), start=True,
995+
feerates=(15000, 11000, 7500, 3750), start=True,
993996
wait_for_bitcoind_sync=True, expect_fail=False, **kwargs):
994997

995998
node_id = self.get_node_id() if not node_id else node_id

plugins/bcli.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ static struct command_result *process_getblockchaininfo(struct bitcoin_cli *bcli
456456

457457
struct estimatefees_stash {
458458
/* FIXME: We use u64 but lightningd will store them as u32. */
459-
u64 urgent, normal, slow;
459+
u64 very_urgent, urgent, normal, slow;
460460
};
461461

462462
static struct command_result *
@@ -532,10 +532,10 @@ static struct command_result *estimatefees_final_step(struct bitcoin_cli *bcli)
532532
response = jsonrpc_stream_success(bcli->cmd);
533533
json_add_u64(response, "opening", stash->normal);
534534
json_add_u64(response, "mutual_close", stash->normal);
535-
json_add_u64(response, "unilateral_close", stash->urgent);
535+
json_add_u64(response, "unilateral_close", stash->very_urgent);
536536
json_add_u64(response, "delayed_to_us", stash->normal);
537-
json_add_u64(response, "htlc_resolution", stash->normal);
538-
json_add_u64(response, "penalty", stash->normal);
537+
json_add_u64(response, "htlc_resolution", stash->urgent);
538+
json_add_u64(response, "penalty", stash->urgent);
539539
/* We divide the slow feerate for the minimum acceptable, lightningd
540540
* will use floor if it's hit, though. */
541541
json_add_u64(response, "min_acceptable", stash->slow / 2);
@@ -546,13 +546,13 @@ static struct command_result *estimatefees_final_step(struct bitcoin_cli *bcli)
546546
* margin (say 5x the expected fee requirement)
547547
*/
548548
json_add_u64(response, "max_acceptable",
549-
stash->urgent * bitcoind->max_fee_multiplier);
549+
stash->very_urgent * bitcoind->max_fee_multiplier);
550550

551551
return command_finished(bcli->cmd, response);
552552
}
553553

554554
/* We got the response for the normal feerate, now treat the slow one. */
555-
static struct command_result *estimatefees_third_step(struct bitcoin_cli *bcli)
555+
static struct command_result *estimatefees_fourth_step(struct bitcoin_cli *bcli)
556556
{
557557
struct command_result *err;
558558
struct estimatefees_stash *stash = bcli->stash;
@@ -575,7 +575,7 @@ static struct command_result *estimatefees_third_step(struct bitcoin_cli *bcli)
575575
}
576576

577577
/* We got the response for the urgent feerate, now treat the normal one. */
578-
static struct command_result *estimatefees_second_step(struct bitcoin_cli *bcli)
578+
static struct command_result *estimatefees_third_step(struct bitcoin_cli *bcli)
579579
{
580580
struct command_result *err;
581581
struct estimatefees_stash *stash = bcli->stash;
@@ -591,6 +591,29 @@ static struct command_result *estimatefees_second_step(struct bitcoin_cli *bcli)
591591

592592
params[0] = "4";
593593
params[1] = "ECONOMICAL";
594+
start_bitcoin_cli(NULL, bcli->cmd, estimatefees_fourth_step, true,
595+
BITCOIND_LOW_PRIO, "estimatesmartfee", params, stash);
596+
597+
return command_still_pending(bcli->cmd);
598+
}
599+
600+
/* We got the response for the very urgent feerate, now treat the normal one. */
601+
static struct command_result *estimatefees_second_step(struct bitcoin_cli *bcli)
602+
{
603+
struct command_result *err;
604+
struct estimatefees_stash *stash = bcli->stash;
605+
const char **params = tal_arr(bcli->cmd, const char *, 2);
606+
607+
/* If we cannot estimatefees, no need to continue bothering bitcoind. */
608+
if (*bcli->exitstatus != 0)
609+
return estimatefees_null_response(bcli);
610+
611+
err = estimatefees_parse_feerate(bcli, &stash->very_urgent);
612+
if (err)
613+
return err;
614+
615+
params[0] = "3";
616+
params[1] = "CONSERVATIVE";
594617
start_bitcoin_cli(NULL, bcli->cmd, estimatefees_third_step, true,
595618
BITCOIND_LOW_PRIO, "estimatesmartfee", params, stash);
596619

@@ -726,8 +749,9 @@ static struct command_result *getchaininfo(struct command *cmd,
726749
return command_still_pending(cmd);
727750
}
728751

729-
/* Get the current feerates. We use an urgent feerate for unilateral_close and max,
730-
* a slow feerate for min, and a normal for all others.
752+
/* Get the current feerates. We us an urgent feerate for unilateral_close and max,
753+
* a slightly less urgent feerate for htlc_resolution and penalty transactions,
754+
* a slow feerate for min, and a normal one for all others.
731755
*
732756
* Calls `estimatesmartfee` with targets 2/CONSERVATIVE (urgent),
733757
* 4/ECONOMICAL (normal), and 100/ECONOMICAL (slow) then returns the

tests/test_closing.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ def test_closing_torture(node_factory, executor, bitcoind):
216216
def test_closing_different_fees(node_factory, bitcoind, executor):
217217
l1 = node_factory.get_node()
218218

219-
# Default feerate = 15000/7500/1000
219+
# Default feerate = 15000/11000/7500/1000
220220
# It will start at the second number, accepting anything above the first.
221-
feerates = [[20000, 15000, 7400], [8000, 1001, 100]]
221+
feerates = [[20000, 11000, 15000, 7400], [8000, 6000, 1001, 100]]
222222
amounts = [0, 545999, 546000]
223223
num_peers = len(feerates) * len(amounts)
224224

@@ -395,10 +395,10 @@ def test_deprecated_closing_compat(node_factory, bitcoind, chainparams):
395395

396396
def closing_fee(node_factory, bitcoind, chainparams, opts):
397397
rate = opts['funder_feerate_per_kw']
398-
funder = node_factory.get_node(feerates=(rate, rate, rate))
398+
funder = node_factory.get_node(feerates=(rate, rate, rate, rate))
399399

400400
rate = opts['fundee_feerate_per_kw']
401-
fundee = node_factory.get_node(feerates=(rate, rate, rate))
401+
fundee = node_factory.get_node(feerates=(rate, rate, rate, rate))
402402

403403
funder_id = funder.info['id']
404404
fundee_id = fundee.info['id']
@@ -479,7 +479,9 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams):
479479
"""Test penalty transaction with an incoming HTLC"""
480480
# We suppress each one after first commit; HTLC gets added not fulfilled.
481481
# Feerates identical so we don't get gratuitous commit to update them
482-
l1 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED-nocommit'], may_fail=True, feerates=(7500, 7500, 7500), allow_broken_log=True)
482+
l1 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED-nocommit'],
483+
may_fail=True, feerates=(7500, 7500, 7500, 7500),
484+
allow_broken_log=True)
483485
l2 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED-nocommit'])
484486

485487
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -520,6 +522,7 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams):
520522
bitcoind.generate_block(1)
521523

522524
l2.daemon.wait_for_log(' to ONCHAIN')
525+
523526
# FIXME: l1 should try to stumble along!
524527
wait_for(lambda: len(l2.getactivechannels()) == 0)
525528

@@ -542,7 +545,7 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams):
542545
outputs = l2.rpc.listfunds()['outputs']
543546
assert [o['status'] for o in outputs] == ['confirmed'] * 2
544547
# Allow some lossage for fees.
545-
slack = 27000 if chainparams['elements'] else 15000
548+
slack = 30000 if chainparams['elements'] else 20000
546549
assert sum(o['value'] for o in outputs) < 10**6
547550
assert sum(o['value'] for o in outputs) > 10**6 - slack
548551

@@ -552,7 +555,9 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams):
552555
"""Test penalty transaction with an outgoing HTLC"""
553556
# First we need to get funds to l2, so suppress after second.
554557
# Feerates identical so we don't get gratuitous commit to update them
555-
l1 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED*3-nocommit'], may_fail=True, feerates=(7500, 7500, 7500), allow_broken_log=True)
558+
l1 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED*3-nocommit'],
559+
may_fail=True, feerates=(7500, 7500, 7500, 7500),
560+
allow_broken_log=True)
556561
l2 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED*3-nocommit'])
557562

558563
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -622,7 +627,7 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams):
622627
outputs = l2.rpc.listfunds()['outputs']
623628
assert [o['status'] for o in outputs] == ['confirmed'] * 3
624629
# Allow some lossage for fees.
625-
slack = 27000 if chainparams['elements'] else 15000
630+
slack = 30000 if chainparams['elements'] else 20000
626631
assert sum(o['value'] for o in outputs) < 10**6
627632
assert sum(o['value'] for o in outputs) > 10**6 - slack
628633

@@ -720,7 +725,8 @@ def test_onchaind_replay(node_factory, bitcoind):
720725
disconnects = ['+WIRE_REVOKE_AND_ACK', 'permfail']
721726
options = {'watchtime-blocks': 201, 'cltv-delta': 101}
722727
# Feerates identical so we don't get gratuitous commit to update them
723-
l1 = node_factory.get_node(options=options, disconnect=disconnects, feerates=(7500, 7500, 7500))
728+
l1 = node_factory.get_node(options=options, disconnect=disconnects,
729+
feerates=(7500, 7500, 7500, 7500))
724730
l2 = node_factory.get_node(options=options)
725731

726732
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -773,7 +779,8 @@ def test_onchain_dust_out(node_factory, bitcoind, executor):
773779
# HTLC 1->2, 1 fails after it's irrevocably committed
774780
disconnects = ['@WIRE_REVOKE_AND_ACK', 'permfail']
775781
# Feerates identical so we don't get gratuitous commit to update them
776-
l1 = node_factory.get_node(disconnect=disconnects, feerates=(7500, 7500, 7500))
782+
l1 = node_factory.get_node(disconnect=disconnects,
783+
feerates=(7500, 7500, 7500, 7500))
777784
l2 = node_factory.get_node()
778785

779786
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -836,7 +843,8 @@ def test_onchain_timeout(node_factory, bitcoind, executor):
836843
# HTLC 1->2, 1 fails just after it's irrevocably committed
837844
disconnects = ['+WIRE_REVOKE_AND_ACK*3', 'permfail']
838845
# Feerates identical so we don't get gratuitous commit to update them
839-
l1 = node_factory.get_node(disconnect=disconnects, feerates=(7500, 7500, 7500))
846+
l1 = node_factory.get_node(disconnect=disconnects,
847+
feerates=(7500, 7500, 7500, 7500))
840848
l2 = node_factory.get_node()
841849

842850
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -1071,7 +1079,8 @@ def test_onchain_all_dust(node_factory, bitcoind, executor):
10711079
# is generated on-the-fly, and is thus feerate sensitive.
10721080
disconnects = ['-WIRE_UPDATE_FAIL_HTLC', 'permfail']
10731081
# Feerates identical so we don't get gratuitous commit to update them
1074-
l1 = node_factory.get_node(options={'dev-no-reconnect': None}, feerates=(7500, 7500, 7500))
1082+
l1 = node_factory.get_node(options={'dev-no-reconnect': None},
1083+
feerates=(7500, 7500, 7500, 7500))
10751084
l2 = node_factory.get_node(disconnect=disconnects)
10761085

10771086
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -1093,7 +1102,7 @@ def test_onchain_all_dust(node_factory, bitcoind, executor):
10931102
l2.wait_for_channel_onchain(l1.info['id'])
10941103

10951104
# Make l1's fees really high (and wait for it to exceed 50000)
1096-
l1.set_feerates((100000, 100000, 100000))
1105+
l1.set_feerates((100000, 100000, 100000, 100000))
10971106
l1.daemon.wait_for_log('Feerate estimate for unilateral_close set to [56789][0-9]{4}')
10981107

10991108
bitcoind.generate_block(1)
@@ -1130,12 +1139,12 @@ def test_onchain_different_fees(node_factory, bitcoind, executor):
11301139
p1 = executor.submit(l1.pay, l2, 1000000000)
11311140
l1.daemon.wait_for_log('htlc 0: RCVD_ADD_ACK_COMMIT->SENT_ADD_ACK_REVOCATION')
11321141

1133-
l1.set_feerates((16000, 7500, 3750))
1142+
l1.set_feerates((16000, 11000, 7500, 3750))
11341143
p2 = executor.submit(l1.pay, l2, 900000000)
11351144
l1.daemon.wait_for_log('htlc 1: RCVD_ADD_ACK_COMMIT->SENT_ADD_ACK_REVOCATION')
11361145

11371146
# Restart with different feerate for second HTLC.
1138-
l1.set_feerates((5000, 5000, 3750))
1147+
l1.set_feerates((5000, 5000, 5000, 3750))
11391148
l1.restart()
11401149
l1.daemon.wait_for_log('peer_out WIRE_UPDATE_FEE')
11411150

@@ -1189,7 +1198,8 @@ def test_permfail_new_commit(node_factory, bitcoind, executor):
11891198
# Test case where we have two possible commits: it will use new one.
11901199
disconnects = ['-WIRE_REVOKE_AND_ACK', 'permfail']
11911200
# Feerates identical so we don't get gratuitous commit to update them
1192-
l1 = node_factory.get_node(options={'dev-no-reconnect': None}, feerates=(7500, 7500, 7500))
1201+
l1 = node_factory.get_node(options={'dev-no-reconnect': None},
1202+
feerates=(7500, 7500, 7500, 7500))
11931203
l2 = node_factory.get_node(disconnect=disconnects)
11941204

11951205
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -1490,7 +1500,8 @@ def test_permfail_htlc_in(node_factory, bitcoind, executor):
14901500
# Test case where we fail with unsettled incoming HTLC.
14911501
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
14921502
# Feerates identical so we don't get gratuitous commit to update them
1493-
l1 = node_factory.get_node(options={'dev-no-reconnect': None}, feerates=(7500, 7500, 7500))
1503+
l1 = node_factory.get_node(options={'dev-no-reconnect': None},
1504+
feerates=(7500, 7500, 7500, 7500))
14941505
l2 = node_factory.get_node(disconnect=disconnects)
14951506

14961507
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -1536,7 +1547,8 @@ def test_permfail_htlc_out(node_factory, bitcoind, executor):
15361547
disconnects = ['+WIRE_REVOKE_AND_ACK', 'permfail']
15371548
l1 = node_factory.get_node(options={'dev-no-reconnect': None})
15381549
# Feerates identical so we don't get gratuitous commit to update them
1539-
l2 = node_factory.get_node(disconnect=disconnects, feerates=(7500, 7500, 7500))
1550+
l2 = node_factory.get_node(disconnect=disconnects,
1551+
feerates=(7500, 7500, 7500, 7500))
15401552

15411553
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
15421554
l2.daemon.wait_for_log('openingd-chan#1: Handed peer, entering loop'.format(l1.info['id']))

0 commit comments

Comments
 (0)