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:
Rusty Russell 2021-06-28 14:38:10 +09:30
parent 1a74d8284c
commit 8f33f46960
8 changed files with 134 additions and 53 deletions

View file

@ -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) "

View file

@ -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,

1 #include <bitcoin/tx.h>
17 msgdata,closingd_init,local_sat,amount_sat,
18 msgdata,closingd_init,remote_sat,amount_sat,
19 msgdata,closingd_init,our_dust_limit,amount_sat,
20 msgdata,closingd_init,min_fee_satoshi,amount_sat, msgdata,closingd_init,min_feerate_perksipa,u32,
21 msgdata,closingd_init,preferred_feerate_perksipa,u32,
22 msgdata,closingd_init,fee_limit_satoshi,amount_sat,
msgdata,closingd_init,initial_fee_satoshi,amount_sat,
23 msgdata,closingd_init,local_scriptpubkey_len,u16,
24 msgdata,closingd_init,local_scriptpubkey,u8,local_scriptpubkey_len
25 msgdata,closingd_init,remote_scriptpubkey_len,u16,

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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)

View file

@ -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=[

View file

@ -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]