mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
closingd: allow higher closing fee if anchor_outputs.
This follows https://github.com/lightningnetwork/lightning-rfc/pull/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 <rusty@rustcorp.com.au> Changelog-EXPERIMENTAL: Anchor output mutual close allow a fee higher than the final commitment transaction (as per lightning-rfc #847)
This commit is contained in:
@@ -584,16 +584,59 @@ static size_t closing_tx_weight_estimate(u8 *scriptpubkey[NUM_SIDES],
|
||||
static void calc_fee_bounds(size_t expected_weight,
|
||||
u32 min_feerate,
|
||||
u32 desired_feerate,
|
||||
struct amount_sat maxfee,
|
||||
u32 *max_feerate,
|
||||
struct amount_sat commitment_fee,
|
||||
struct amount_sat funding,
|
||||
enum side opener,
|
||||
struct amount_sat *minfee,
|
||||
struct amount_sat *desiredfee)
|
||||
struct amount_sat *desiredfee,
|
||||
struct amount_sat *maxfee)
|
||||
{
|
||||
*minfee = amount_tx_fee(min_feerate, expected_weight);
|
||||
*desiredfee = amount_tx_fee(desired_feerate, expected_weight);
|
||||
|
||||
/* BOLT-closing-fee_range #2:
|
||||
* - if it is not the funder:
|
||||
* - SHOULD set `max_fee_satoshis` to at least the `max_fee_satoshis`
|
||||
* received
|
||||
*...
|
||||
* Note that the non-funder is not paying the fee, so there is
|
||||
* no reason for it to have a maximum feerate.
|
||||
*/
|
||||
if (opener == REMOTE) {
|
||||
*maxfee = funding;
|
||||
/* BOLT-closing-fee_range #2:
|
||||
* - If the channel does not use `option_anchor_outputs`:
|
||||
* - MUST set `fee_satoshis` less than or equal to the base fee of
|
||||
* the final commitment transaction, as calculated in
|
||||
* [BOLT #3](03-transactions.md#fee-calculation).
|
||||
*/
|
||||
} else if (max_feerate) {
|
||||
*maxfee = amount_tx_fee(*max_feerate, expected_weight);
|
||||
|
||||
status_debug("deriving max fee from rate %u -> %s (not %s)",
|
||||
*max_feerate,
|
||||
type_to_string(tmpctx, struct amount_sat, maxfee),
|
||||
type_to_string(tmpctx, struct amount_sat, &commitment_fee));
|
||||
|
||||
/* option_anchor_outputs sets commitment_fee to max, so this
|
||||
* doesn't do anything */
|
||||
if (amount_sat_greater(*maxfee, commitment_fee)) {
|
||||
status_unusual("Maximum feerate %u would give fee %s:"
|
||||
" we must limit it to the final commitment fee %s",
|
||||
*max_feerate,
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
maxfee),
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&commitment_fee));
|
||||
*maxfee = commitment_fee;
|
||||
}
|
||||
} else
|
||||
*maxfee = commitment_fee;
|
||||
|
||||
/* Can't exceed maxfee. */
|
||||
if (amount_sat_greater(*minfee, maxfee))
|
||||
*minfee = maxfee;
|
||||
if (amount_sat_greater(*minfee, *maxfee))
|
||||
*minfee = *maxfee;
|
||||
|
||||
if (amount_sat_less(*desiredfee, *minfee)) {
|
||||
status_unusual("Our ideal fee is %s (%u sats/perkw),"
|
||||
@@ -603,20 +646,20 @@ static void calc_fee_bounds(size_t expected_weight,
|
||||
type_to_string(tmpctx, struct amount_sat, minfee));
|
||||
*desiredfee = *minfee;
|
||||
}
|
||||
if (amount_sat_greater(*desiredfee, maxfee)) {
|
||||
if (amount_sat_greater(*desiredfee, *maxfee)) {
|
||||
status_unusual("Our ideal fee is %s (%u sats/perkw),"
|
||||
" but our maximum is %s: using that",
|
||||
type_to_string(tmpctx, struct amount_sat, desiredfee),
|
||||
desired_feerate,
|
||||
type_to_string(tmpctx, struct amount_sat, &maxfee));
|
||||
*desiredfee = maxfee;
|
||||
type_to_string(tmpctx, struct amount_sat, maxfee));
|
||||
*desiredfee = *maxfee;
|
||||
}
|
||||
|
||||
status_debug("Expected closing weight = %zu, fee %s (min %s, max %s)",
|
||||
expected_weight,
|
||||
type_to_string(tmpctx, struct amount_sat, desiredfee),
|
||||
type_to_string(tmpctx, struct amount_sat, minfee),
|
||||
type_to_string(tmpctx, struct amount_sat, &maxfee));
|
||||
type_to_string(tmpctx, struct amount_sat, maxfee));
|
||||
}
|
||||
|
||||
/* 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[])
|
||||
u16 funding_txout;
|
||||
struct amount_sat funding, out[NUM_SIDES];
|
||||
struct amount_sat our_dust_limit;
|
||||
struct amount_sat min_fee_to_accept, commitment_fee, offer[NUM_SIDES];
|
||||
u32 min_feerate, initial_feerate;
|
||||
struct amount_sat min_fee_to_accept, commitment_fee, offer[NUM_SIDES],
|
||||
max_fee_to_accept;
|
||||
u32 min_feerate, initial_feerate, *max_feerate;
|
||||
struct feerange feerange;
|
||||
enum side opener;
|
||||
u8 *scriptpubkey[NUM_SIDES], *funding_wscript;
|
||||
@@ -833,7 +877,7 @@ int main(int argc, char *argv[])
|
||||
&out[LOCAL],
|
||||
&out[REMOTE],
|
||||
&our_dust_limit,
|
||||
&min_feerate, &initial_feerate,
|
||||
&min_feerate, &initial_feerate, &max_feerate,
|
||||
&commitment_fee,
|
||||
&scriptpubkey[LOCAL],
|
||||
&scriptpubkey[REMOTE],
|
||||
@@ -855,8 +899,9 @@ int main(int argc, char *argv[])
|
||||
calc_fee_bounds(closing_tx_weight_estimate(scriptpubkey,
|
||||
funding_wscript,
|
||||
out, funding, our_dust_limit),
|
||||
min_feerate, initial_feerate, commitment_fee,
|
||||
&min_fee_to_accept, &offer[LOCAL]);
|
||||
min_feerate, initial_feerate, max_feerate,
|
||||
commitment_fee, funding, opener,
|
||||
&min_fee_to_accept, &offer[LOCAL], &max_fee_to_accept);
|
||||
|
||||
/* Write values into tlv for updated closing fee neg */
|
||||
their_feerange = tal(ctx, struct tlv_closing_signed_tlvs_fee_range *);
|
||||
@@ -865,19 +910,7 @@ int main(int argc, char *argv[])
|
||||
if (use_quickclose) {
|
||||
our_feerange = tal(ctx, struct tlv_closing_signed_tlvs_fee_range);
|
||||
our_feerange->min_fee_satoshis = min_fee_to_accept;
|
||||
|
||||
/* BOLT-closing-fee_range #2:
|
||||
* - if it is not the funder:
|
||||
* - SHOULD set `max_fee_satoshis` to at least the
|
||||
* `max_fee_satoshis` received
|
||||
*...
|
||||
* Note that the non-funder is not paying the fee, so there is
|
||||
* no reason for it to have a maximum feerate.
|
||||
*/
|
||||
if (opener == REMOTE)
|
||||
our_feerange->max_fee_satoshis = funding;
|
||||
else
|
||||
our_feerange->max_fee_satoshis = commitment_fee;
|
||||
our_feerange->max_fee_satoshis = max_fee_to_accept;
|
||||
} else
|
||||
our_feerange = NULL;
|
||||
|
||||
@@ -907,7 +940,7 @@ int main(int argc, char *argv[])
|
||||
"Negotiating closing fee between %s and %s satoshi (ideal %s) "
|
||||
"using step %s",
|
||||
type_to_string(tmpctx, struct amount_sat, &min_fee_to_accept),
|
||||
type_to_string(tmpctx, struct amount_sat, &commitment_fee),
|
||||
type_to_string(tmpctx, struct amount_sat, &max_fee_to_accept),
|
||||
type_to_string(tmpctx, struct amount_sat, &offer[LOCAL]),
|
||||
fee_negotiation_step_str);
|
||||
|
||||
@@ -970,7 +1003,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Now we have first two points, we can init fee range. */
|
||||
init_feerange(&feerange, commitment_fee, offer);
|
||||
init_feerange(&feerange, max_fee_to_accept, offer);
|
||||
|
||||
/* Apply (and check) opener offer now. */
|
||||
adjust_feerange(&feerange, offer[opener], opener);
|
||||
@@ -1029,6 +1062,7 @@ exit_thru_the_giftshop:
|
||||
tal_free(wrong_funding);
|
||||
tal_free(our_feerange);
|
||||
tal_free(their_feerange);
|
||||
tal_free(max_feerate);
|
||||
closing_dev_memleak(ctx, scriptpubkey, funding_wscript);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ msgdata,closingd_init,remote_sat,amount_sat,
|
||||
msgdata,closingd_init,our_dust_limit,amount_sat,
|
||||
msgdata,closingd_init,min_feerate_perksipa,u32,
|
||||
msgdata,closingd_init,preferred_feerate_perksipa,u32,
|
||||
msgdata,closingd_init,max_feerate_perksipa,?u32,
|
||||
msgdata,closingd_init,fee_limit_satoshi,amount_sat,
|
||||
msgdata,closingd_init,local_scriptpubkey_len,u16,
|
||||
msgdata,closingd_init,local_scriptpubkey,u8,local_scriptpubkey_len
|
||||
|
||||
|
18
closingd/closingd_wiregen.c
generated
18
closingd/closingd_wiregen.c
generated
@@ -48,7 +48,7 @@ bool closingd_wire_is_defined(u16 type)
|
||||
|
||||
/* WIRE: CLOSINGD_INIT */
|
||||
/* Begin! (passes peer fd */
|
||||
u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, u32 min_feerate_perksipa, u32 preferred_feerate_perksipa, struct amount_sat fee_limit_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool use_quickclose, bool dev_fast_gossip, const struct bitcoin_outpoint *shutdown_wrong_funding)
|
||||
u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, u32 min_feerate_perksipa, u32 preferred_feerate_perksipa, u32 *max_feerate_perksipa, struct amount_sat fee_limit_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool use_quickclose, bool dev_fast_gossip, const struct bitcoin_outpoint *shutdown_wrong_funding)
|
||||
{
|
||||
u16 local_scriptpubkey_len = tal_count(local_scriptpubkey);
|
||||
u16 remote_scriptpubkey_len = tal_count(remote_scriptpubkey);
|
||||
@@ -69,6 +69,12 @@ u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams
|
||||
towire_amount_sat(&p, our_dust_limit);
|
||||
towire_u32(&p, min_feerate_perksipa);
|
||||
towire_u32(&p, preferred_feerate_perksipa);
|
||||
if (!max_feerate_perksipa)
|
||||
towire_bool(&p, false);
|
||||
else {
|
||||
towire_bool(&p, true);
|
||||
towire_u32(&p, *max_feerate_perksipa);
|
||||
}
|
||||
towire_amount_sat(&p, fee_limit_satoshi);
|
||||
towire_u16(&p, local_scriptpubkey_len);
|
||||
towire_u8_array(&p, local_scriptpubkey, local_scriptpubkey_len);
|
||||
@@ -87,7 +93,7 @@ u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams
|
||||
|
||||
return memcheck(p, tal_count(p));
|
||||
}
|
||||
bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, u32 *min_feerate_perksipa, u32 *preferred_feerate_perksipa, struct amount_sat *fee_limit_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *use_quickclose, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding)
|
||||
bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, u32 *min_feerate_perksipa, u32 *preferred_feerate_perksipa, u32 **max_feerate_perksipa, struct amount_sat *fee_limit_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *use_quickclose, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding)
|
||||
{
|
||||
u16 local_scriptpubkey_len;
|
||||
u16 remote_scriptpubkey_len;
|
||||
@@ -111,6 +117,12 @@ bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainp
|
||||
*our_dust_limit = fromwire_amount_sat(&cursor, &plen);
|
||||
*min_feerate_perksipa = fromwire_u32(&cursor, &plen);
|
||||
*preferred_feerate_perksipa = fromwire_u32(&cursor, &plen);
|
||||
if (!fromwire_bool(&cursor, &plen))
|
||||
*max_feerate_perksipa = NULL;
|
||||
else {
|
||||
*max_feerate_perksipa = tal(ctx, u32);
|
||||
**max_feerate_perksipa = fromwire_u32(&cursor, &plen);
|
||||
}
|
||||
*fee_limit_satoshi = fromwire_amount_sat(&cursor, &plen);
|
||||
local_scriptpubkey_len = fromwire_u16(&cursor, &plen);
|
||||
// 2nd case local_scriptpubkey
|
||||
@@ -197,4 +209,4 @@ bool fromwire_closingd_complete(const void *p)
|
||||
return false;
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:b736e1d2c03a883962558ddcd5675d26cb09dcf3462c0cf82b3d49f1fd980c8a
|
||||
// SHA256STAMP:be6dbb532dfd3c159212838acedd4bad3c8b4b16b5193b8c2a752697a15c8ab1
|
||||
|
||||
6
closingd/closingd_wiregen.h
generated
6
closingd/closingd_wiregen.h
generated
@@ -37,8 +37,8 @@ bool closingd_wire_is_defined(u16 type);
|
||||
|
||||
/* WIRE: CLOSINGD_INIT */
|
||||
/* Begin! (passes peer fd */
|
||||
u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, u32 min_feerate_perksipa, u32 preferred_feerate_perksipa, struct amount_sat fee_limit_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool use_quickclose, bool dev_fast_gossip, const struct bitcoin_outpoint *shutdown_wrong_funding);
|
||||
bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, u32 *min_feerate_perksipa, u32 *preferred_feerate_perksipa, struct amount_sat *fee_limit_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *use_quickclose, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding);
|
||||
u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, u32 min_feerate_perksipa, u32 preferred_feerate_perksipa, u32 *max_feerate_perksipa, struct amount_sat fee_limit_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool use_quickclose, bool dev_fast_gossip, const struct bitcoin_outpoint *shutdown_wrong_funding);
|
||||
bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, u32 *min_feerate_perksipa, u32 *preferred_feerate_perksipa, u32 **max_feerate_perksipa, struct amount_sat *fee_limit_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *use_quickclose, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding);
|
||||
|
||||
/* WIRE: CLOSINGD_RECEIVED_SIGNATURE */
|
||||
/* We received an offer */
|
||||
@@ -56,4 +56,4 @@ bool fromwire_closingd_complete(const void *p);
|
||||
|
||||
|
||||
#endif /* LIGHTNING_CLOSINGD_CLOSINGD_WIREGEN_H */
|
||||
// SHA256STAMP:b736e1d2c03a883962558ddcd5675d26cb09dcf3462c0cf82b3d49f1fd980c8a
|
||||
// SHA256STAMP:be6dbb532dfd3c159212838acedd4bad3c8b4b16b5193b8c2a752697a15c8ab1
|
||||
|
||||
@@ -193,7 +193,7 @@ void peer_start_closingd(struct channel *channel,
|
||||
struct per_peer_state *pps)
|
||||
{
|
||||
u8 *initmsg;
|
||||
u32 feerate;
|
||||
u32 feerate, *max_feerate;
|
||||
struct amount_msat their_msat;
|
||||
struct amount_sat feelimit;
|
||||
int hsmfd;
|
||||
@@ -253,6 +253,19 @@ void peer_start_closingd(struct channel *channel,
|
||||
feerate = feerate_floor();
|
||||
}
|
||||
|
||||
/* We use a feerate if anchor_outputs, otherwise max fee is set by
|
||||
* the final unilateral. */
|
||||
if (channel->option_anchor_outputs) {
|
||||
max_feerate = tal(tmpctx, u32);
|
||||
/* Aim for reasonable max, but use final if we don't know. */
|
||||
*max_feerate = unilateral_feerate(ld->topology);
|
||||
if (!*max_feerate)
|
||||
*max_feerate = final_commit_feerate;
|
||||
/* No other limit on fees */
|
||||
feelimit = channel->funding;
|
||||
} else
|
||||
max_feerate = NULL;
|
||||
|
||||
/* BOLT #3:
|
||||
*
|
||||
* Each node offering a signature:
|
||||
@@ -285,7 +298,9 @@ void peer_start_closingd(struct channel *channel,
|
||||
amount_msat_to_sat_round_down(channel->our_msat),
|
||||
amount_msat_to_sat_round_down(their_msat),
|
||||
channel->our_config.dust_limit,
|
||||
feerate_min(ld, NULL), feerate, feelimit,
|
||||
feerate_min(ld, NULL), feerate,
|
||||
max_feerate,
|
||||
feelimit,
|
||||
channel->shutdown_scriptpubkey[LOCAL],
|
||||
channel->shutdown_scriptpubkey[REMOTE],
|
||||
channel->closing_fee_negotiation_step,
|
||||
|
||||
Reference in New Issue
Block a user