mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-01 17:47:30 +01:00
closingd: use a more accurate fee for closing fee negotiation.
We were actually using the last commit tx's size, since we were setting it in lightningd. Instead, hand the min and desired feerates to closingd, and (as it knows the weight of the closing tx), and have it start negotiation from there. This can be significantly less when anchor outputs are enabled: for example in test_closing.py, the commit tx weight is 1124 Sipa, the close is 672 Sipa! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Changed: Protocol: Use a more accurate fee for mutual close negotiation.
This commit is contained in:
parent
1a74d8284c
commit
8f33f46960
8 changed files with 134 additions and 53 deletions
|
@ -491,6 +491,84 @@ static void closing_dev_memleak(const tal_t *ctx,
|
||||||
}
|
}
|
||||||
#endif /* DEVELOPER */
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
|
/* Figure out what weight we actually expect for this closing tx (using zero fees
|
||||||
|
* gives the largest possible tx: larger values might omit outputs). */
|
||||||
|
static size_t closing_tx_weight_estimate(u8 *scriptpubkey[NUM_SIDES],
|
||||||
|
const u8 *funding_wscript,
|
||||||
|
const struct amount_sat *out,
|
||||||
|
struct amount_sat funding,
|
||||||
|
struct amount_sat dust_limit)
|
||||||
|
{
|
||||||
|
/* We create a dummy close */
|
||||||
|
struct bitcoin_tx *tx;
|
||||||
|
struct bitcoin_txid dummy_txid;
|
||||||
|
struct bitcoin_signature dummy_sig;
|
||||||
|
struct privkey dummy_privkey;
|
||||||
|
struct pubkey dummy_pubkey;
|
||||||
|
u8 **witness;
|
||||||
|
|
||||||
|
memset(&dummy_txid, 0, sizeof(dummy_txid));
|
||||||
|
tx = create_close_tx(tmpctx, chainparams,
|
||||||
|
scriptpubkey[LOCAL], scriptpubkey[REMOTE],
|
||||||
|
funding_wscript,
|
||||||
|
&dummy_txid, 0,
|
||||||
|
funding,
|
||||||
|
out[LOCAL],
|
||||||
|
out[REMOTE],
|
||||||
|
dust_limit);
|
||||||
|
|
||||||
|
/* Create a signature, any signature, so we can weigh fully "signed"
|
||||||
|
* tx. */
|
||||||
|
dummy_sig.sighash_type = SIGHASH_ALL;
|
||||||
|
memset(&dummy_privkey, 1, sizeof(dummy_privkey));
|
||||||
|
sign_hash(&dummy_privkey, &dummy_txid.shad, &dummy_sig.s);
|
||||||
|
pubkey_from_privkey(&dummy_privkey, &dummy_pubkey);
|
||||||
|
witness = bitcoin_witness_2of2(NULL, &dummy_sig, &dummy_sig,
|
||||||
|
&dummy_pubkey, &dummy_pubkey);
|
||||||
|
bitcoin_tx_input_set_witness(tx, 0, take(witness));
|
||||||
|
|
||||||
|
return bitcoin_tx_weight(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the minimum and desired fees */
|
||||||
|
static void calc_fee_bounds(size_t expected_weight,
|
||||||
|
u32 min_feerate,
|
||||||
|
u32 desired_feerate,
|
||||||
|
struct amount_sat maxfee,
|
||||||
|
struct amount_sat *minfee,
|
||||||
|
struct amount_sat *desiredfee)
|
||||||
|
{
|
||||||
|
*minfee = amount_tx_fee(min_feerate, expected_weight);
|
||||||
|
*desiredfee = amount_tx_fee(desired_feerate, expected_weight);
|
||||||
|
|
||||||
|
/* Can't exceed 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),"
|
||||||
|
" but our minimum is %s: using that",
|
||||||
|
type_to_string(tmpctx, struct amount_sat, desiredfee),
|
||||||
|
desired_feerate,
|
||||||
|
type_to_string(tmpctx, struct amount_sat, minfee));
|
||||||
|
*desiredfee = *minfee;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
setup_locale();
|
setup_locale();
|
||||||
|
@ -504,6 +582,7 @@ int main(int argc, char *argv[])
|
||||||
struct amount_sat funding, out[NUM_SIDES];
|
struct amount_sat funding, out[NUM_SIDES];
|
||||||
struct amount_sat our_dust_limit;
|
struct amount_sat our_dust_limit;
|
||||||
struct amount_sat min_fee_to_accept, commitment_fee, offer[NUM_SIDES];
|
struct amount_sat min_fee_to_accept, commitment_fee, offer[NUM_SIDES];
|
||||||
|
u32 min_feerate, initial_feerate;
|
||||||
struct feerange feerange;
|
struct feerange feerange;
|
||||||
enum side opener;
|
enum side opener;
|
||||||
u8 *scriptpubkey[NUM_SIDES], *funding_wscript;
|
u8 *scriptpubkey[NUM_SIDES], *funding_wscript;
|
||||||
|
@ -531,8 +610,8 @@ int main(int argc, char *argv[])
|
||||||
&out[LOCAL],
|
&out[LOCAL],
|
||||||
&out[REMOTE],
|
&out[REMOTE],
|
||||||
&our_dust_limit,
|
&our_dust_limit,
|
||||||
&min_fee_to_accept, &commitment_fee,
|
&min_feerate, &initial_feerate,
|
||||||
&offer[LOCAL],
|
&commitment_fee,
|
||||||
&scriptpubkey[LOCAL],
|
&scriptpubkey[LOCAL],
|
||||||
&scriptpubkey[REMOTE],
|
&scriptpubkey[REMOTE],
|
||||||
&fee_negotiation_step,
|
&fee_negotiation_step,
|
||||||
|
@ -544,6 +623,17 @@ int main(int argc, char *argv[])
|
||||||
/* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = hsmd */
|
/* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = hsmd */
|
||||||
per_peer_state_set_fds(notleak(pps), 3, 4, 5);
|
per_peer_state_set_fds(notleak(pps), 3, 4, 5);
|
||||||
|
|
||||||
|
funding_wscript = bitcoin_redeem_2of2(ctx,
|
||||||
|
&funding_pubkey[LOCAL],
|
||||||
|
&funding_pubkey[REMOTE]);
|
||||||
|
|
||||||
|
/* Start at what we consider a reasonable feerate for this tx. */
|
||||||
|
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]);
|
||||||
|
|
||||||
snprintf(fee_negotiation_step_str, sizeof(fee_negotiation_step_str),
|
snprintf(fee_negotiation_step_str, sizeof(fee_negotiation_step_str),
|
||||||
"%" PRIu64 "%s", fee_negotiation_step,
|
"%" PRIu64 "%s", fee_negotiation_step,
|
||||||
fee_negotiation_step_unit ==
|
fee_negotiation_step_unit ==
|
||||||
|
@ -565,10 +655,6 @@ int main(int argc, char *argv[])
|
||||||
&wrong_funding->txid),
|
&wrong_funding->txid),
|
||||||
wrong_funding->n);
|
wrong_funding->n);
|
||||||
|
|
||||||
funding_wscript = bitcoin_redeem_2of2(ctx,
|
|
||||||
&funding_pubkey[LOCAL],
|
|
||||||
&funding_pubkey[REMOTE]);
|
|
||||||
|
|
||||||
peer_billboard(
|
peer_billboard(
|
||||||
true,
|
true,
|
||||||
"Negotiating closing fee between %s and %s satoshi (ideal %s) "
|
"Negotiating closing fee between %s and %s satoshi (ideal %s) "
|
||||||
|
|
|
@ -17,9 +17,9 @@ msgdata,closingd_init,opener,enum side,
|
||||||
msgdata,closingd_init,local_sat,amount_sat,
|
msgdata,closingd_init,local_sat,amount_sat,
|
||||||
msgdata,closingd_init,remote_sat,amount_sat,
|
msgdata,closingd_init,remote_sat,amount_sat,
|
||||||
msgdata,closingd_init,our_dust_limit,amount_sat,
|
msgdata,closingd_init,our_dust_limit,amount_sat,
|
||||||
msgdata,closingd_init,min_fee_satoshi,amount_sat,
|
msgdata,closingd_init,min_feerate_perksipa,u32,
|
||||||
|
msgdata,closingd_init,preferred_feerate_perksipa,u32,
|
||||||
msgdata,closingd_init,fee_limit_satoshi,amount_sat,
|
msgdata,closingd_init,fee_limit_satoshi,amount_sat,
|
||||||
msgdata,closingd_init,initial_fee_satoshi,amount_sat,
|
|
||||||
msgdata,closingd_init,local_scriptpubkey_len,u16,
|
msgdata,closingd_init,local_scriptpubkey_len,u16,
|
||||||
msgdata,closingd_init,local_scriptpubkey,u8,local_scriptpubkey_len
|
msgdata,closingd_init,local_scriptpubkey,u8,local_scriptpubkey_len
|
||||||
msgdata,closingd_init,remote_scriptpubkey_len,u16,
|
msgdata,closingd_init,remote_scriptpubkey_len,u16,
|
||||||
|
|
|
14
closingd/closingd_wiregen.c
generated
14
closingd/closingd_wiregen.c
generated
|
@ -48,7 +48,7 @@ bool closingd_wire_is_defined(u16 type)
|
||||||
|
|
||||||
/* WIRE: CLOSINGD_INIT */
|
/* WIRE: CLOSINGD_INIT */
|
||||||
/* Begin! (passes peer fd */
|
/* 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, struct amount_sat min_fee_satoshi, struct amount_sat fee_limit_satoshi, struct amount_sat initial_fee_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, 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, struct amount_sat fee_limit_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool dev_fast_gossip, const struct bitcoin_outpoint *shutdown_wrong_funding)
|
||||||
{
|
{
|
||||||
u16 local_scriptpubkey_len = tal_count(local_scriptpubkey);
|
u16 local_scriptpubkey_len = tal_count(local_scriptpubkey);
|
||||||
u16 remote_scriptpubkey_len = tal_count(remote_scriptpubkey);
|
u16 remote_scriptpubkey_len = tal_count(remote_scriptpubkey);
|
||||||
|
@ -67,9 +67,9 @@ u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams
|
||||||
towire_amount_sat(&p, local_sat);
|
towire_amount_sat(&p, local_sat);
|
||||||
towire_amount_sat(&p, remote_sat);
|
towire_amount_sat(&p, remote_sat);
|
||||||
towire_amount_sat(&p, our_dust_limit);
|
towire_amount_sat(&p, our_dust_limit);
|
||||||
towire_amount_sat(&p, min_fee_satoshi);
|
towire_u32(&p, min_feerate_perksipa);
|
||||||
|
towire_u32(&p, preferred_feerate_perksipa);
|
||||||
towire_amount_sat(&p, fee_limit_satoshi);
|
towire_amount_sat(&p, fee_limit_satoshi);
|
||||||
towire_amount_sat(&p, initial_fee_satoshi);
|
|
||||||
towire_u16(&p, local_scriptpubkey_len);
|
towire_u16(&p, local_scriptpubkey_len);
|
||||||
towire_u8_array(&p, local_scriptpubkey, local_scriptpubkey_len);
|
towire_u8_array(&p, local_scriptpubkey, local_scriptpubkey_len);
|
||||||
towire_u16(&p, remote_scriptpubkey_len);
|
towire_u16(&p, remote_scriptpubkey_len);
|
||||||
|
@ -86,7 +86,7 @@ u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams
|
||||||
|
|
||||||
return memcheck(p, tal_count(p));
|
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, struct amount_sat *min_fee_satoshi, struct amount_sat *fee_limit_satoshi, struct amount_sat *initial_fee_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, 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, struct amount_sat *fee_limit_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding)
|
||||||
{
|
{
|
||||||
u16 local_scriptpubkey_len;
|
u16 local_scriptpubkey_len;
|
||||||
u16 remote_scriptpubkey_len;
|
u16 remote_scriptpubkey_len;
|
||||||
|
@ -108,9 +108,9 @@ bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainp
|
||||||
*local_sat = fromwire_amount_sat(&cursor, &plen);
|
*local_sat = fromwire_amount_sat(&cursor, &plen);
|
||||||
*remote_sat = fromwire_amount_sat(&cursor, &plen);
|
*remote_sat = fromwire_amount_sat(&cursor, &plen);
|
||||||
*our_dust_limit = fromwire_amount_sat(&cursor, &plen);
|
*our_dust_limit = fromwire_amount_sat(&cursor, &plen);
|
||||||
*min_fee_satoshi = fromwire_amount_sat(&cursor, &plen);
|
*min_feerate_perksipa = fromwire_u32(&cursor, &plen);
|
||||||
|
*preferred_feerate_perksipa = fromwire_u32(&cursor, &plen);
|
||||||
*fee_limit_satoshi = fromwire_amount_sat(&cursor, &plen);
|
*fee_limit_satoshi = fromwire_amount_sat(&cursor, &plen);
|
||||||
*initial_fee_satoshi = fromwire_amount_sat(&cursor, &plen);
|
|
||||||
local_scriptpubkey_len = fromwire_u16(&cursor, &plen);
|
local_scriptpubkey_len = fromwire_u16(&cursor, &plen);
|
||||||
// 2nd case local_scriptpubkey
|
// 2nd case local_scriptpubkey
|
||||||
*local_scriptpubkey = local_scriptpubkey_len ? tal_arr(ctx, u8, local_scriptpubkey_len) : NULL;
|
*local_scriptpubkey = local_scriptpubkey_len ? tal_arr(ctx, u8, local_scriptpubkey_len) : NULL;
|
||||||
|
@ -195,4 +195,4 @@ bool fromwire_closingd_complete(const void *p)
|
||||||
return false;
|
return false;
|
||||||
return cursor != NULL;
|
return cursor != NULL;
|
||||||
}
|
}
|
||||||
// SHA256STAMP:cbcaa37f43a9705e657ef6905e276ac4b703171a3f9dcd6f6ca352e3d753a6f2
|
// SHA256STAMP:a8b0af1ae87e71bc448585060b8d449c3e5f0d0f4f3ac195dcd4d84f8176ae17
|
||||||
|
|
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 */
|
/* WIRE: CLOSINGD_INIT */
|
||||||
/* Begin! (passes peer fd */
|
/* 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, struct amount_sat min_fee_satoshi, struct amount_sat fee_limit_satoshi, struct amount_sat initial_fee_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, 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, struct amount_sat fee_limit_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, 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, struct amount_sat *min_fee_satoshi, struct amount_sat *fee_limit_satoshi, struct amount_sat *initial_fee_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, 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, struct amount_sat *fee_limit_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding);
|
||||||
|
|
||||||
/* WIRE: CLOSINGD_RECEIVED_SIGNATURE */
|
/* WIRE: CLOSINGD_RECEIVED_SIGNATURE */
|
||||||
/* We received an offer */
|
/* We received an offer */
|
||||||
|
@ -56,4 +56,4 @@ bool fromwire_closingd_complete(const void *p);
|
||||||
|
|
||||||
|
|
||||||
#endif /* LIGHTNING_CLOSINGD_CLOSINGD_WIREGEN_H */
|
#endif /* LIGHTNING_CLOSINGD_CLOSINGD_WIREGEN_H */
|
||||||
// SHA256STAMP:cbcaa37f43a9705e657ef6905e276ac4b703171a3f9dcd6f6ca352e3d753a6f2
|
// SHA256STAMP:a8b0af1ae87e71bc448585060b8d449c3e5f0d0f4f3ac195dcd4d84f8176ae17
|
||||||
|
|
|
@ -197,8 +197,8 @@ void peer_start_closingd(struct channel *channel,
|
||||||
{
|
{
|
||||||
u8 *initmsg;
|
u8 *initmsg;
|
||||||
u32 feerate;
|
u32 feerate;
|
||||||
struct amount_sat minfee, startfee, feelimit;
|
|
||||||
struct amount_msat their_msat;
|
struct amount_msat their_msat;
|
||||||
|
struct amount_sat feelimit;
|
||||||
int hsmfd;
|
int hsmfd;
|
||||||
struct lightningd *ld = channel->peer->ld;
|
struct lightningd *ld = channel->peer->ld;
|
||||||
u32 final_commit_feerate;
|
u32 final_commit_feerate;
|
||||||
|
@ -247,10 +247,6 @@ void peer_start_closingd(struct channel *channel,
|
||||||
feelimit = commit_tx_base_fee(final_commit_feerate, 0,
|
feelimit = commit_tx_base_fee(final_commit_feerate, 0,
|
||||||
channel->option_anchor_outputs);
|
channel->option_anchor_outputs);
|
||||||
|
|
||||||
/* Pick some value above slow feerate (or min possible if unknown) */
|
|
||||||
minfee = commit_tx_base_fee(feerate_min(ld, NULL), 0,
|
|
||||||
channel->option_anchor_outputs);
|
|
||||||
|
|
||||||
/* If we can't determine feerate, start at half unilateral feerate. */
|
/* If we can't determine feerate, start at half unilateral feerate. */
|
||||||
feerate = mutual_close_feerate(ld->topology);
|
feerate = mutual_close_feerate(ld->topology);
|
||||||
if (!feerate) {
|
if (!feerate) {
|
||||||
|
@ -258,13 +254,6 @@ void peer_start_closingd(struct channel *channel,
|
||||||
if (feerate < feerate_floor())
|
if (feerate < feerate_floor())
|
||||||
feerate = feerate_floor();
|
feerate = feerate_floor();
|
||||||
}
|
}
|
||||||
startfee = commit_tx_base_fee(feerate, 0,
|
|
||||||
channel->option_anchor_outputs);
|
|
||||||
|
|
||||||
if (amount_sat_greater(startfee, feelimit))
|
|
||||||
startfee = feelimit;
|
|
||||||
if (amount_sat_greater(minfee, feelimit))
|
|
||||||
minfee = feelimit;
|
|
||||||
|
|
||||||
/* BOLT #3:
|
/* BOLT #3:
|
||||||
*
|
*
|
||||||
|
@ -298,7 +287,7 @@ void peer_start_closingd(struct channel *channel,
|
||||||
amount_msat_to_sat_round_down(channel->our_msat),
|
amount_msat_to_sat_round_down(channel->our_msat),
|
||||||
amount_msat_to_sat_round_down(their_msat),
|
amount_msat_to_sat_round_down(their_msat),
|
||||||
channel->our_config.dust_limit,
|
channel->our_config.dust_limit,
|
||||||
minfee, feelimit, startfee,
|
feerate_min(ld, NULL), feerate, feelimit,
|
||||||
channel->shutdown_scriptpubkey[LOCAL],
|
channel->shutdown_scriptpubkey[LOCAL],
|
||||||
channel->shutdown_scriptpubkey[REMOTE],
|
channel->shutdown_scriptpubkey[REMOTE],
|
||||||
channel->closing_fee_negotiation_step,
|
channel->closing_fee_negotiation_step,
|
||||||
|
|
|
@ -5,7 +5,7 @@ from shutil import copyfile
|
||||||
from pyln.testing.utils import SLOW_MACHINE
|
from pyln.testing.utils import SLOW_MACHINE
|
||||||
from utils import (
|
from utils import (
|
||||||
only_one, sync_blockheight, wait_for, TIMEOUT,
|
only_one, sync_blockheight, wait_for, TIMEOUT,
|
||||||
account_balance, first_channel_id, basic_fee, TEST_NETWORK,
|
account_balance, first_channel_id, closing_fee, TEST_NETWORK,
|
||||||
scriptpubkey_addr
|
scriptpubkey_addr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import unittest
|
||||||
def test_closing(node_factory, bitcoind, chainparams):
|
def test_closing(node_factory, bitcoind, chainparams):
|
||||||
l1, l2 = node_factory.line_graph(2)
|
l1, l2 = node_factory.line_graph(2)
|
||||||
chan = l1.get_channel_scid(l2)
|
chan = l1.get_channel_scid(l2)
|
||||||
fee = basic_fee(3750) if not chainparams['elements'] else 4477
|
fee = closing_fee(3750, 2) if not chainparams['elements'] else 3603
|
||||||
|
|
||||||
l1.pay(l2, 200000000)
|
l1.pay(l2, 200000000)
|
||||||
|
|
||||||
|
@ -377,7 +377,7 @@ def closing_negotiation_step(node_factory, bitcoind, chainparams, opts):
|
||||||
"""Binary search to find feerate"""
|
"""Binary search to find feerate"""
|
||||||
assert minimum != maximum
|
assert minimum != maximum
|
||||||
mid = (minimum + maximum) // 2
|
mid = (minimum + maximum) // 2
|
||||||
mid_fee = basic_fee(mid)
|
mid_fee = closing_fee(mid, 1)
|
||||||
if mid_fee > target:
|
if mid_fee > target:
|
||||||
return feerate_for(target, minimum, mid)
|
return feerate_for(target, minimum, mid)
|
||||||
elif mid_fee < target:
|
elif mid_fee < target:
|
||||||
|
@ -452,11 +452,11 @@ def test_closing_negotiation_step_30pct(node_factory, bitcoind, chainparams):
|
||||||
opts['fee_negotiation_step'] = '30%'
|
opts['fee_negotiation_step'] = '30%'
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'opener'
|
opts['close_initiated_by'] = 'opener'
|
||||||
opts['expected_close_fee'] = 20537 if not chainparams['elements'] else 33870
|
opts['expected_close_fee'] = 20537 if not chainparams['elements'] else 26046
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'peer'
|
opts['close_initiated_by'] = 'peer'
|
||||||
opts['expected_close_fee'] = 20233 if not chainparams['elements'] else 33366
|
opts['expected_close_fee'] = 20233 if not chainparams['elements'] else 25657
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
|
|
||||||
|
@ -466,11 +466,11 @@ def test_closing_negotiation_step_50pct(node_factory, bitcoind, chainparams):
|
||||||
opts['fee_negotiation_step'] = '50%'
|
opts['fee_negotiation_step'] = '50%'
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'opener'
|
opts['close_initiated_by'] = 'opener'
|
||||||
opts['expected_close_fee'] = 20334 if not chainparams['elements'] else 33533
|
opts['expected_close_fee'] = 20334 if not chainparams['elements'] else 25789
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'peer'
|
opts['close_initiated_by'] = 'peer'
|
||||||
opts['expected_close_fee'] = 20334 if not chainparams['elements'] else 33533
|
opts['expected_close_fee'] = 20334 if not chainparams['elements'] else 25789
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ def test_closing_negotiation_step_100pct(node_factory, bitcoind, chainparams):
|
||||||
opts['fee_negotiation_step'] = '100%'
|
opts['fee_negotiation_step'] = '100%'
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'opener'
|
opts['close_initiated_by'] = 'opener'
|
||||||
opts['expected_close_fee'] = 20001 if not chainparams['elements'] else 32985
|
opts['expected_close_fee'] = 20001 if not chainparams['elements'] else 25366
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
# The close fee of 20499 looks strange in this case - one would expect
|
# The close fee of 20499 looks strange in this case - one would expect
|
||||||
|
@ -489,7 +489,7 @@ def test_closing_negotiation_step_100pct(node_factory, bitcoind, chainparams):
|
||||||
# * the opener is always first to propose, he uses 50% step, so he proposes 20500
|
# * the opener is always first to propose, he uses 50% step, so he proposes 20500
|
||||||
# * the range is narrowed to [20001, 20499] and the peer proposes 20499
|
# * the range is narrowed to [20001, 20499] and the peer proposes 20499
|
||||||
opts['close_initiated_by'] = 'peer'
|
opts['close_initiated_by'] = 'peer'
|
||||||
opts['expected_close_fee'] = 20499 if not chainparams['elements'] else 33808
|
opts['expected_close_fee'] = 20499 if not chainparams['elements'] else 25998
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
|
|
||||||
|
@ -499,11 +499,11 @@ def test_closing_negotiation_step_1sat(node_factory, bitcoind, chainparams):
|
||||||
opts['fee_negotiation_step'] = '1'
|
opts['fee_negotiation_step'] = '1'
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'opener'
|
opts['close_initiated_by'] = 'opener'
|
||||||
opts['expected_close_fee'] = 20989 if not chainparams['elements'] else 34621
|
opts['expected_close_fee'] = 20989 if not chainparams['elements'] else 26624
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'peer'
|
opts['close_initiated_by'] = 'peer'
|
||||||
opts['expected_close_fee'] = 20010 if not chainparams['elements'] else 32995
|
opts['expected_close_fee'] = 20010 if not chainparams['elements'] else 25373
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
|
|
||||||
|
@ -513,11 +513,11 @@ def test_closing_negotiation_step_700sat(node_factory, bitcoind, chainparams):
|
||||||
opts['fee_negotiation_step'] = '700'
|
opts['fee_negotiation_step'] = '700'
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'opener'
|
opts['close_initiated_by'] = 'opener'
|
||||||
opts['expected_close_fee'] = 20151 if not chainparams['elements'] else 33459
|
opts['expected_close_fee'] = 20151 if not chainparams['elements'] else 25650
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
opts['close_initiated_by'] = 'peer'
|
opts['close_initiated_by'] = 'peer'
|
||||||
opts['expected_close_fee'] = 20499 if not chainparams['elements'] else 33746
|
opts['expected_close_fee'] = 20499 if not chainparams['elements'] else 25998
|
||||||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1884,8 +1884,8 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
|
||||||
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tag': 'routed'},
|
{'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tag': 'routed'},
|
||||||
{'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tag': 'routed'},
|
{'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tag': 'routed'},
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 4477501, 'tag': 'chain_fees'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 4271501, 'tag': 'chain_fees'},
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 945523000, 'tag': 'withdrawal'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 945729000, 'tag': 'withdrawal'},
|
||||||
]
|
]
|
||||||
|
|
||||||
l2_wallet_mvts = [
|
l2_wallet_mvts = [
|
||||||
|
@ -1898,7 +1898,7 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 8092000, 'tag': 'chain_fees'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 8092000, 'tag': 'chain_fees'},
|
||||||
{'type': 'chain_mvt', 'credit': 991908000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 991908000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'chain_mvt', 'credit': 100001000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 100001000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'chain_mvt', 'credit': 945523000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 945729000, 'debit': 0, 'tag': 'deposit'},
|
||||||
]
|
]
|
||||||
elif EXPERIMENTAL_FEATURES:
|
elif EXPERIMENTAL_FEATURES:
|
||||||
# option_anchor_outputs
|
# option_anchor_outputs
|
||||||
|
@ -1906,8 +1906,8 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
|
||||||
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tag': 'routed'},
|
{'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tag': 'routed'},
|
||||||
{'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tag': 'routed'},
|
{'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tag': 'routed'},
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 4215501, 'tag': 'chain_fees'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 2520501, 'tag': 'chain_fees'},
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 945785000, 'tag': 'withdrawal'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 947480000, 'tag': 'withdrawal'},
|
||||||
]
|
]
|
||||||
|
|
||||||
l2_wallet_mvts = [
|
l2_wallet_mvts = [
|
||||||
|
@ -1921,15 +1921,15 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 4567000, 'tag': 'chain_fees'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 4567000, 'tag': 'chain_fees'},
|
||||||
{'type': 'chain_mvt', 'credit': 995433000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 995433000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'chain_mvt', 'credit': 100001000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 100001000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'chain_mvt', 'credit': 945785000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 947480000, 'debit': 0, 'tag': 'deposit'},
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
l2_l3_mvts = [
|
l2_l3_mvts = [
|
||||||
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tag': 'routed'},
|
{'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tag': 'routed'},
|
||||||
{'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tag': 'routed'},
|
{'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tag': 'routed'},
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 2715501, 'tag': 'chain_fees'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 2520501, 'tag': 'chain_fees'},
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 947285000, 'tag': 'withdrawal'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 947480000, 'tag': 'withdrawal'},
|
||||||
]
|
]
|
||||||
|
|
||||||
l2_wallet_mvts = [
|
l2_wallet_mvts = [
|
||||||
|
@ -1943,7 +1943,7 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
|
||||||
{'type': 'chain_mvt', 'credit': 0, 'debit': 4567000, 'tag': 'chain_fees'},
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 4567000, 'tag': 'chain_fees'},
|
||||||
{'type': 'chain_mvt', 'credit': 995433000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 995433000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'chain_mvt', 'credit': 100001000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 100001000, 'debit': 0, 'tag': 'deposit'},
|
||||||
{'type': 'chain_mvt', 'credit': 947285000, 'debit': 0, 'tag': 'deposit'},
|
{'type': 'chain_mvt', 'credit': 947480000, 'debit': 0, 'tag': 'deposit'},
|
||||||
]
|
]
|
||||||
|
|
||||||
l1, l2, l3 = node_factory.line_graph(3, opts=[
|
l1, l2, l3 = node_factory.line_graph(3, opts=[
|
||||||
|
|
|
@ -151,6 +151,12 @@ def basic_fee(feerate):
|
||||||
return (weight * feerate) // 1000
|
return (weight * feerate) // 1000
|
||||||
|
|
||||||
|
|
||||||
|
def closing_fee(feerate, num_outputs):
|
||||||
|
assert num_outputs == 1 or num_outputs == 2
|
||||||
|
weight = 424 + 124 * num_outputs
|
||||||
|
return (weight * feerate) // 1000
|
||||||
|
|
||||||
|
|
||||||
def scriptpubkey_addr(scriptpubkey):
|
def scriptpubkey_addr(scriptpubkey):
|
||||||
if 'addresses' in scriptpubkey:
|
if 'addresses' in scriptpubkey:
|
||||||
return scriptpubkey['addresses'][0]
|
return scriptpubkey['addresses'][0]
|
||||||
|
|
Loading…
Add table
Reference in a new issue