Skip to content

Commit 47aa874

Browse files
committed
splice: Make feerate opening + feerate_offset
Splicing feerate was being derived by `default_feerate` which was actually `unilateral_feerate`, which is incorrect. Instead we define an explicit `splice_feerate` in the chain topology that is `opening` + `feerate_offset`. This slipped through testing because regtest isn’t a great test of fees we see in the wild. Changelog-Fixed: Fixes high fee issue that caused `splicein` and `spliceout` to abort.
1 parent 36f02d3 commit 47aa874

7 files changed

Lines changed: 50 additions & 42 deletions

File tree

channeld/channeld.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3600,9 +3600,9 @@ static struct amount_sat check_balances(struct peer *peer,
36003600
/* As a safeguard max feerate is checked (only) locally, if it's
36013601
* particularly high we fail and tell the user but allow them to
36023602
* override with `splice_force_feerate` */
3603-
max_accepter_fee = amount_tx_fee(peer->feerate_opening,
3603+
max_accepter_fee = amount_tx_fee(peer->feerate_max,
36043604
calc_weight(TX_ACCEPTER, psbt, false));
3605-
max_initiator_fee = amount_tx_fee(peer->feerate_opening,
3605+
max_initiator_fee = amount_tx_fee(peer->feerate_max,
36063606
calc_weight(TX_INITIATOR, psbt, opener));
36073607

36083608
if (opener) {
@@ -3620,10 +3620,13 @@ static struct amount_sat check_balances(struct peer *peer,
36203620
false);
36213621
wire_sync_write(MASTER_FD, take(msg));
36223622
splice_abort(peer, NULL,
3623-
"%s fee (%s) was too low, must be at least %s",
3623+
"%s fee (%s) was too low, must be at least %s"
3624+
" weight: %"PRIu64", splicing->feerate_per_kw: %"PRIu32,
36243625
opener ? "Our" : "Your",
36253626
fmt_amount_msat(tmpctx, initiator_fee),
3626-
fmt_amount_sat(tmpctx, min_initiator_fee));
3627+
fmt_amount_sat(tmpctx, min_initiator_fee),
3628+
calc_weight(TX_INITIATOR, psbt, false),
3629+
peer->splicing->feerate_per_kw);
36273630
}
36283631
if (!peer->splicing->force_feerate && opener
36293632
&& amount_msat_greater_sat(initiator_fee, max_initiator_fee)) {
@@ -3660,7 +3663,7 @@ static struct amount_sat check_balances(struct peer *peer,
36603663
fmt_amount_msat(tmpctx, accepter_fee),
36613664
fmt_amount_sat(tmpctx, min_accepter_fee),
36623665
calc_weight(TX_INITIATOR, psbt, false),
3663-
peer->feerate_opening);
3666+
peer->feerate_max);
36643667
}
36653668
if (!peer->splicing->force_feerate && !opener
36663669
&& amount_msat_greater_sat(accepter_fee, max_accepter_fee)) {

lightningd/chaintopology.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,15 @@ u32 opening_feerate(struct chain_topology *topo)
617617
conversions[FEERATE_OPENING].blockcount);
618618
}
619619

620+
u32 splice_feerate(struct chain_topology *topo, struct lightningd *ld)
621+
{
622+
u32 rate = opening_feerate(topo);
623+
rate += ld->config.feerate_offset;
624+
if (rate > feerate_max(ld, NULL))
625+
rate = feerate_max(ld, NULL);
626+
return rate;
627+
}
628+
620629
u32 mutual_close_feerate(struct chain_topology *topo)
621630
{
622631
if (topo->ld->force_feerates)
@@ -717,14 +726,9 @@ static struct command_result *json_feerates(struct command *cmd,
717726
if (rate)
718727
json_add_num(response, "penalty",
719728
feerate_to_style(rate, *style));
720-
rate = unilateral_feerate(topo, true);
721-
if (rate) {
722-
rate += cmd->ld->config.feerate_offset;
723-
if (rate > feerate_max(cmd->ld, NULL))
724-
rate = feerate_max(cmd->ld, NULL);
725-
json_add_num(response, "splice",
726-
feerate_to_style(rate, *style));
727-
}
729+
rate = splice_feerate(topo, cmd->ld);
730+
if (rate)
731+
json_add_num(response, "splice", feerate_to_style(rate, *style));
728732

729733
json_add_u64(response, "min_acceptable",
730734
feerate_to_style(feerate_min(cmd->ld, NULL), *style));

lightningd/chaintopology.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ u32 feerate_max(struct lightningd *ld, bool *unknown);
196196

197197
/* These return 0 if unknown */
198198
u32 opening_feerate(struct chain_topology *topo);
199+
u32 splice_feerate(struct chain_topology *topo, struct lightningd *ld);
199200
u32 mutual_close_feerate(struct chain_topology *topo);
200201
u32 unilateral_feerate(struct chain_topology *topo, bool option_anchors);
201202
/* For onchain resolution. */

lightningd/channel_control.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void channel_update_feerates(struct lightningd *ld, const struct channel *channe
8181
u32 min_feerate, max_feerate;
8282
bool anchors = channel_type_has_anchors(channel->type);
8383
u32 feerate = default_feerate(ld, channel, (channel->opener == LOCAL));
84-
u32 feerate_splice = default_feerate(ld, channel, true);
84+
u32 feerate_splice = splice_feerate(ld->topology, ld);
8585

8686
/* Nothing to do if we don't know feerate. */
8787
if (!feerate)
@@ -1900,7 +1900,7 @@ bool peer_start_channeld(struct channel *channel,
19001900
tal_arr_expand(&inflights, infcopy);
19011901
}
19021902

1903-
feerate_splice = default_feerate(ld, channel, true);
1903+
feerate_splice = splice_feerate(ld->topology, ld);
19041904

19051905
initmsg = towire_channeld_init(tmpctx,
19061906
chainparams,
@@ -2347,7 +2347,7 @@ static struct command_result *json_splice_init(struct command *cmd,
23472347

23482348
if (!feerate_per_kw) {
23492349
feerate_per_kw = tal(cmd, u32);
2350-
*feerate_per_kw = default_feerate(cmd->ld, channel, true);
2350+
*feerate_per_kw = splice_feerate(cmd->ld->topology, cmd->ld);
23512351
}
23522352

23532353
if (!initialpsbt)
@@ -2720,7 +2720,7 @@ static struct command_result *json_dev_feerate(struct command *cmd,
27202720
feerate_max(cmd->ld, NULL),
27212721
penalty_feerate(cmd->ld->topology),
27222722
opening_feerate(cmd->ld->topology),
2723-
default_feerate(cmd->ld, channel, true));
2723+
splice_feerate(cmd->ld->topology, cmd->ld));
27242724
subd_send_msg(channel->owner, take(msg));
27252725

27262726
response = json_stream_success(cmd);

tests/test_splice.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,9 @@ def test_script_two_chan_splice_inout(node_factory, bitcoind):
488488
chan_id2 = l2.get_channel_id(l3)
489489

490490
# move sats from chan 2 into chan 1
491-
# By adding 10000 from wallet, the fee will be taken from this and the
491+
# By adding 100000 from wallet, the fee will be taken from this and the
492492
# extra placed back into the wallet by default
493-
result = l2.rpc.splice(f"wallet -> 10000; 100000 -> {chan_id1}; {chan_id2} -> 100000")
493+
result = l2.rpc.splice(f"wallet -> 100000; 100000 -> {chan_id1}; {chan_id2} -> 100000")
494494

495495
l3.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
496496
l2.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
@@ -639,15 +639,15 @@ def execute_script(node_factory, bitcoind, script, expected_balances=None, fee_m
639639
@pytest.mark.openchannel('v2')
640640
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
641641
def test_script_two_chan_splice_b(node_factory, bitcoind):
642-
execute_script(node_factory, bitcoind, "wallet -> 10000; {} -> 100000; {} -> 100000",
642+
execute_script(node_factory, bitcoind, "wallet -> 100000; {} -> 100000; {} -> 100000",
643643
[500000 - 100000, 500000 - 100000])
644644

645645

646646
@pytest.mark.openchannel('v1')
647647
@pytest.mark.openchannel('v2')
648648
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
649649
def test_script_two_chan_splice_c(node_factory, bitcoind):
650-
execute_script(node_factory, bitcoind, "wallet -> 10000; 100000 -> {}; {} -> 100000",
650+
execute_script(node_factory, bitcoind, "wallet -> 100000; 100000 -> {}; {} -> 100000",
651651
[500000 + 100000, 500000 - 100000])
652652

653653

@@ -711,8 +711,8 @@ def test_script_two_chan_splice_j(node_factory, bitcoind):
711711
@pytest.mark.openchannel('v2')
712712
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
713713
def test_script_two_chan_splice_k(node_factory, bitcoind):
714-
execute_script(node_factory, bitcoind, "{} -> 10000; 1000 -> {}",
715-
[500000 - 10000, 500000 + 1000])
714+
execute_script(node_factory, bitcoind, "{} -> 100000; 1000 -> {}",
715+
[500000 - 100000, 500000 + 1000])
716716

717717

718718
@pytest.mark.openchannel('v1')
@@ -807,8 +807,8 @@ def test_script_two_chan_splice_v(node_factory, bitcoind):
807807
@pytest.mark.openchannel('v2')
808808
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
809809
def test_script_two_chan_splice_x(node_factory, bitcoind):
810-
execute_script(node_factory, bitcoind, "* -> wallet; * -> {}; {} -> 100000",
811-
[500000 + 50000, 500000 - 100000], [-0.5, 0])
810+
execute_script(node_factory, bitcoind, "* -> wallet; * -> {}; {} -> 200000",
811+
[500000 + 100000 + 1, 500000 - 200000], [-0.5, 0]) # (+1 to track rounded sat)
812812

813813

814814
@pytest.mark.openchannel('v1')

tests/test_splicing.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_splice(node_factory, bitcoind):
1717
chan_id = l1.get_channel_id(l2)
1818

1919
# add extra sats to pay fee
20-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
20+
funds_result = l1.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
2121

2222
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
2323
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -59,7 +59,7 @@ def test_two_chan_splice_in(node_factory, bitcoind):
5959
chan_id2 = l2.get_channel_id(l3)
6060

6161
# add extra sats to pay fee
62-
funds_result = l2.rpc.fundpsbt("205790sat", 0, 0, excess_as_change=True)
62+
funds_result = l2.rpc.fundpsbt("211722sat", 0, 0, excess_as_change=True)
6363

6464
# Intiate splices to both channels
6565
result = l2.rpc.splice_init(chan_id1, 100000, funds_result['psbt'])
@@ -130,8 +130,8 @@ def test_splice_rbf(node_factory, bitcoind):
130130

131131
funds_result = l1.rpc.addpsbtoutput(100000)
132132

133-
# Pay with fee by subtracting 5000 from channel balance
134-
result = l1.rpc.splice_init(chan_id, -105000, funds_result['psbt'])
133+
# Pay with fee by subtracting 5801 from channel balance
134+
result = l1.rpc.splice_init(chan_id, -105801, funds_result['psbt'])
135135
result = l1.rpc.splice_update(chan_id, result['psbt'])
136136
assert(result['commitments_secured'] is False)
137137
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -151,7 +151,7 @@ def test_splice_rbf(node_factory, bitcoind):
151151
funds_result = l1.rpc.addpsbtoutput(100000)
152152

153153
# Pay with fee by subtracting 5790 from channel balance
154-
result = l1.rpc.splice_init(chan_id, -105790, funds_result['psbt'])
154+
result = l1.rpc.splice_init(chan_id, -111722, funds_result['psbt'])
155155
result = l1.rpc.splice_update(chan_id, result['psbt'])
156156
assert(result['commitments_secured'] is False)
157157
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -189,7 +189,7 @@ def test_splice_nosign(node_factory, bitcoind):
189189
chan_id = l1.get_channel_id(l2)
190190

191191
# add extra sats to pay fee
192-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
192+
funds_result = l1.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
193193

194194
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
195195
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -214,7 +214,7 @@ def test_splice_gossip(node_factory, bitcoind):
214214
pre_splice_scid = first_scid(l1, l2)
215215

216216
# add extra sats to pay fee
217-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
217+
funds_result = l1.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
218218

219219
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
220220
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -277,7 +277,7 @@ def test_splice_listnodes(node_factory, bitcoind):
277277
chan_id = l1.get_channel_id(l2)
278278

279279
# add extra sats to pay fee
280-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
280+
funds_result = l1.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
281281

282282
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
283283
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -314,8 +314,8 @@ def test_splice_out(node_factory, bitcoind):
314314

315315
funds_result = l1.rpc.addpsbtoutput(100000)
316316

317-
# Pay with fee by subjtracting 5000 from channel balance
318-
result = l1.rpc.splice_init(chan_id, -105000, funds_result['psbt'])
317+
# Pay with fee by subjtracting 5801 from channel balance
318+
result = l1.rpc.splice_init(chan_id, -105801, funds_result['psbt'])
319319
result = l1.rpc.splice_update(chan_id, result['psbt'])
320320
assert(result['commitments_secured'] is False)
321321
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -372,7 +372,7 @@ def test_invalid_splice(node_factory, bitcoind):
372372
assert l1.db_query("SELECT count(*) as c FROM channel_funding_inflights;")[0]['c'] == 0
373373

374374
# Now we do a real splice to confirm everything works after restart
375-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
375+
funds_result = l1.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
376376

377377
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
378378
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -408,7 +408,7 @@ def test_commit_crash_splice(node_factory, bitcoind):
408408

409409
chan_id = l1.get_channel_id(l2)
410410

411-
result = l1.rpc.splice_init(chan_id, -105000, l1.rpc.addpsbtoutput(100000)['psbt'])
411+
result = l1.rpc.splice_init(chan_id, -105801, l1.rpc.addpsbtoutput(100000)['psbt'])
412412
result = l1.rpc.splice_update(chan_id, result['psbt'])
413413
assert(result['commitments_secured'] is False)
414414
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -467,7 +467,7 @@ def test_splice_stuck_htlc(node_factory, bitcoind, executor):
467467
chan_id = l1.get_channel_id(l2)
468468

469469
# add extra sats to pay fee
470-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
470+
funds_result = l1.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
471471

472472
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
473473
result = l1.rpc.splice_update(chan_id, result['psbt'])
@@ -513,7 +513,7 @@ def test_route_by_old_scid(node_factory, bitcoind):
513513
route = l1.rpc.getroute(l3.info['id'], 10000000, 1, cltv=16)['route']
514514

515515
# Do a splice
516-
funds_result = l2.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
516+
funds_result = l2.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
517517
chan_id = l2.get_channel_id(l3)
518518
result = l2.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
519519
result = l2.rpc.splice_update(chan_id, result['psbt'])
@@ -533,7 +533,7 @@ def test_route_by_old_scid(node_factory, bitcoind):
533533

534534
# Let's splice again, so the original scid is two behind the times.
535535
l3.fundwallet(200000)
536-
funds_result = l3.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
536+
funds_result = l3.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
537537
chan_id = l3.get_channel_id(l2)
538538
result = l3.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
539539
result = l3.rpc.splice_update(chan_id, result['psbt'])
@@ -566,7 +566,7 @@ def test_splice_unannounced(node_factory, bitcoind):
566566
chan_id = l1.get_channel_id(l2)
567567

568568
# add extra sats to pay fee
569-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
569+
funds_result = l1.rpc.fundpsbt("111722sat", 0, 0, excess_as_change=True)
570570
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
571571
result = l1.rpc.splice_update(chan_id, result['psbt'])
572572
assert(result['commitments_secured'] is False)

tests/test_splicing_insane.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def make_pending_splice(node_factory):
99

1010
chan_id = l1.get_channel_id(l2)
1111

12-
funds_result = l1.rpc.fundpsbt("105790sat", 0, 0, excess_as_change=True)
12+
funds_result = l1.rpc.fundpsbt("107527sat", 0, 0, excess_as_change=True)
1313

1414
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
1515
result = l1.rpc.splice_update(chan_id, result['psbt'])

0 commit comments

Comments
 (0)