Skip to content

Commit d8ba3eb

Browse files
committed
closingd: allow higher closing fee if anchor_outputs.
This follows lightning/bolts#847. For anchor_outputs, we pass down a max_feerate to closingd, and set the fee ceiling to MAX. It uses that to estimate the desired closing fee. Signed-off-by: Rusty Russell <[email protected]> Changelog-EXPERIMENTAL: Anchor output mutual close allow a fee higher than the final commitment transaction (as per lightning-rfc ElementsProject#847)
1 parent be91ee2 commit d8ba3eb

File tree

5 files changed

+98
-36
lines changed

5 files changed

+98
-36
lines changed

closingd/closingd.c

+62-28
Original file line numberDiff line numberDiff line change
@@ -584,16 +584,59 @@ static size_t closing_tx_weight_estimate(u8 *scriptpubkey[NUM_SIDES],
584584
static void calc_fee_bounds(size_t expected_weight,
585585
u32 min_feerate,
586586
u32 desired_feerate,
587-
struct amount_sat maxfee,
587+
u32 *max_feerate,
588+
struct amount_sat commitment_fee,
589+
struct amount_sat funding,
590+
enum side opener,
588591
struct amount_sat *minfee,
589-
struct amount_sat *desiredfee)
592+
struct amount_sat *desiredfee,
593+
struct amount_sat *maxfee)
590594
{
591595
*minfee = amount_tx_fee(min_feerate, expected_weight);
592596
*desiredfee = amount_tx_fee(desired_feerate, expected_weight);
593597

598+
/* BOLT-closing-fee_range #2:
599+
* - if it is not the funder:
600+
* - SHOULD set `max_fee_satoshis` to at least the `max_fee_satoshis`
601+
* received
602+
*...
603+
* Note that the non-funder is not paying the fee, so there is
604+
* no reason for it to have a maximum feerate.
605+
*/
606+
if (opener == REMOTE) {
607+
*maxfee = funding;
608+
/* BOLT-closing-fee_range #2:
609+
* - If the channel does not use `option_anchor_outputs`:
610+
* - MUST set `fee_satoshis` less than or equal to the base fee of
611+
* the final commitment transaction, as calculated in
612+
* [BOLT #3](03-transactions.md#fee-calculation).
613+
*/
614+
} else if (max_feerate) {
615+
*maxfee = amount_tx_fee(*max_feerate, expected_weight);
616+
617+
status_debug("deriving max fee from rate %u -> %s (not %s)",
618+
*max_feerate,
619+
type_to_string(tmpctx, struct amount_sat, maxfee),
620+
type_to_string(tmpctx, struct amount_sat, &commitment_fee));
621+
622+
/* option_anchor_outputs sets commitment_fee to max, so this
623+
* doesn't do anything */
624+
if (amount_sat_greater(*maxfee, commitment_fee)) {
625+
status_unusual("Maximum feerate %u would give fee %s:"
626+
" we must limit it to the final commitment fee %s",
627+
*max_feerate,
628+
type_to_string(tmpctx, struct amount_sat,
629+
maxfee),
630+
type_to_string(tmpctx, struct amount_sat,
631+
&commitment_fee));
632+
*maxfee = commitment_fee;
633+
}
634+
} else
635+
*maxfee = commitment_fee;
636+
594637
/* Can't exceed maxfee. */
595-
if (amount_sat_greater(*minfee, maxfee))
596-
*minfee = maxfee;
638+
if (amount_sat_greater(*minfee, *maxfee))
639+
*minfee = *maxfee;
597640

598641
if (amount_sat_less(*desiredfee, *minfee)) {
599642
status_unusual("Our ideal fee is %s (%u sats/perkw),"
@@ -603,20 +646,20 @@ static void calc_fee_bounds(size_t expected_weight,
603646
type_to_string(tmpctx, struct amount_sat, minfee));
604647
*desiredfee = *minfee;
605648
}
606-
if (amount_sat_greater(*desiredfee, maxfee)) {
649+
if (amount_sat_greater(*desiredfee, *maxfee)) {
607650
status_unusual("Our ideal fee is %s (%u sats/perkw),"
608651
" but our maximum is %s: using that",
609652
type_to_string(tmpctx, struct amount_sat, desiredfee),
610653
desired_feerate,
611-
type_to_string(tmpctx, struct amount_sat, &maxfee));
612-
*desiredfee = maxfee;
654+
type_to_string(tmpctx, struct amount_sat, maxfee));
655+
*desiredfee = *maxfee;
613656
}
614657

615658
status_debug("Expected closing weight = %zu, fee %s (min %s, max %s)",
616659
expected_weight,
617660
type_to_string(tmpctx, struct amount_sat, desiredfee),
618661
type_to_string(tmpctx, struct amount_sat, minfee),
619-
type_to_string(tmpctx, struct amount_sat, &maxfee));
662+
type_to_string(tmpctx, struct amount_sat, maxfee));
620663
}
621664

622665
/* We've received one offer; if we're opener, that means we've already sent one
@@ -802,8 +845,9 @@ int main(int argc, char *argv[])
802845
u16 funding_txout;
803846
struct amount_sat funding, out[NUM_SIDES];
804847
struct amount_sat our_dust_limit;
805-
struct amount_sat min_fee_to_accept, commitment_fee, offer[NUM_SIDES];
806-
u32 min_feerate, initial_feerate;
848+
struct amount_sat min_fee_to_accept, commitment_fee, offer[NUM_SIDES],
849+
max_fee_to_accept;
850+
u32 min_feerate, initial_feerate, *max_feerate;
807851
struct feerange feerange;
808852
enum side opener;
809853
u8 *scriptpubkey[NUM_SIDES], *funding_wscript;
@@ -833,7 +877,7 @@ int main(int argc, char *argv[])
833877
&out[LOCAL],
834878
&out[REMOTE],
835879
&our_dust_limit,
836-
&min_feerate, &initial_feerate,
880+
&min_feerate, &initial_feerate, &max_feerate,
837881
&commitment_fee,
838882
&scriptpubkey[LOCAL],
839883
&scriptpubkey[REMOTE],
@@ -855,8 +899,9 @@ int main(int argc, char *argv[])
855899
calc_fee_bounds(closing_tx_weight_estimate(scriptpubkey,
856900
funding_wscript,
857901
out, funding, our_dust_limit),
858-
min_feerate, initial_feerate, commitment_fee,
859-
&min_fee_to_accept, &offer[LOCAL]);
902+
min_feerate, initial_feerate, max_feerate,
903+
commitment_fee, funding, opener,
904+
&min_fee_to_accept, &offer[LOCAL], &max_fee_to_accept);
860905

861906
/* Write values into tlv for updated closing fee neg */
862907
their_feerange = tal(ctx, struct tlv_closing_signed_tlvs_fee_range *);
@@ -865,19 +910,7 @@ int main(int argc, char *argv[])
865910
if (use_quickclose) {
866911
our_feerange = tal(ctx, struct tlv_closing_signed_tlvs_fee_range);
867912
our_feerange->min_fee_satoshis = min_fee_to_accept;
868-
869-
/* BOLT-closing-fee_range #2:
870-
* - if it is not the funder:
871-
* - SHOULD set `max_fee_satoshis` to at least the
872-
* `max_fee_satoshis` received
873-
*...
874-
* Note that the non-funder is not paying the fee, so there is
875-
* no reason for it to have a maximum feerate.
876-
*/
877-
if (opener == REMOTE)
878-
our_feerange->max_fee_satoshis = funding;
879-
else
880-
our_feerange->max_fee_satoshis = commitment_fee;
913+
our_feerange->max_fee_satoshis = max_fee_to_accept;
881914
} else
882915
our_feerange = NULL;
883916

@@ -907,7 +940,7 @@ int main(int argc, char *argv[])
907940
"Negotiating closing fee between %s and %s satoshi (ideal %s) "
908941
"using step %s",
909942
type_to_string(tmpctx, struct amount_sat, &min_fee_to_accept),
910-
type_to_string(tmpctx, struct amount_sat, &commitment_fee),
943+
type_to_string(tmpctx, struct amount_sat, &max_fee_to_accept),
911944
type_to_string(tmpctx, struct amount_sat, &offer[LOCAL]),
912945
fee_negotiation_step_str);
913946

@@ -970,7 +1003,7 @@ int main(int argc, char *argv[])
9701003
}
9711004

9721005
/* Now we have first two points, we can init fee range. */
973-
init_feerange(&feerange, commitment_fee, offer);
1006+
init_feerange(&feerange, max_fee_to_accept, offer);
9741007

9751008
/* Apply (and check) opener offer now. */
9761009
adjust_feerange(&feerange, offer[opener], opener);
@@ -1029,6 +1062,7 @@ int main(int argc, char *argv[])
10291062
tal_free(wrong_funding);
10301063
tal_free(our_feerange);
10311064
tal_free(their_feerange);
1065+
tal_free(max_feerate);
10321066
closing_dev_memleak(ctx, scriptpubkey, funding_wscript);
10331067
#endif
10341068

closingd/closingd_wire.csv

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ msgdata,closingd_init,remote_sat,amount_sat,
1919
msgdata,closingd_init,our_dust_limit,amount_sat,
2020
msgdata,closingd_init,min_feerate_perksipa,u32,
2121
msgdata,closingd_init,preferred_feerate_perksipa,u32,
22+
msgdata,closingd_init,max_feerate_perksipa,?u32,
2223
msgdata,closingd_init,fee_limit_satoshi,amount_sat,
2324
msgdata,closingd_init,local_scriptpubkey_len,u16,
2425
msgdata,closingd_init,local_scriptpubkey,u8,local_scriptpubkey_len

closingd/closingd_wiregen.c

+15-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

closingd/closingd_wiregen.h

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lightningd/closing_control.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ void peer_start_closingd(struct channel *channel,
193193
struct per_peer_state *pps)
194194
{
195195
u8 *initmsg;
196-
u32 feerate;
196+
u32 feerate, *max_feerate;
197197
struct amount_msat their_msat;
198198
struct amount_sat feelimit;
199199
int hsmfd;
@@ -253,6 +253,19 @@ void peer_start_closingd(struct channel *channel,
253253
feerate = feerate_floor();
254254
}
255255

256+
/* We use a feerate if anchor_outputs, otherwise max fee is set by
257+
* the final unilateral. */
258+
if (channel->option_anchor_outputs) {
259+
max_feerate = tal(tmpctx, u32);
260+
/* Aim for reasonable max, but use final if we don't know. */
261+
*max_feerate = unilateral_feerate(ld->topology);
262+
if (!*max_feerate)
263+
*max_feerate = final_commit_feerate;
264+
/* No other limit on fees */
265+
feelimit = channel->funding;
266+
} else
267+
max_feerate = NULL;
268+
256269
/* BOLT #3:
257270
*
258271
* Each node offering a signature:
@@ -285,7 +298,9 @@ void peer_start_closingd(struct channel *channel,
285298
amount_msat_to_sat_round_down(channel->our_msat),
286299
amount_msat_to_sat_round_down(their_msat),
287300
channel->our_config.dust_limit,
288-
feerate_min(ld, NULL), feerate, feelimit,
301+
feerate_min(ld, NULL), feerate,
302+
max_feerate,
303+
feelimit,
289304
channel->shutdown_scriptpubkey[LOCAL],
290305
channel->shutdown_scriptpubkey[REMOTE],
291306
channel->closing_fee_negotiation_step,

0 commit comments

Comments
 (0)