mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-15 20:09:18 +01:00
--experimental-quick-close to enable quick-close negotiation
Based on a commit by @niftynei, but: - Separated quickclose logic from main loop. - I made it indep of anchor_outputs, use and option instead. - Disable if they've specified how to negotiate. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
23a6c00496
commit
79d7e83f51
17 changed files with 337 additions and 20 deletions
|
@ -141,10 +141,12 @@ static void send_offer(struct per_peer_state *pps,
|
|||
enum side opener,
|
||||
struct amount_sat our_dust_limit,
|
||||
struct amount_sat fee_to_offer,
|
||||
const struct bitcoin_outpoint *wrong_funding)
|
||||
const struct bitcoin_outpoint *wrong_funding,
|
||||
const struct tlv_closing_signed_tlvs_fee_range *tlv_fees)
|
||||
{
|
||||
struct bitcoin_tx *tx;
|
||||
struct bitcoin_signature our_sig;
|
||||
struct tlv_closing_signed_tlvs *close_tlvs;
|
||||
u8 *msg;
|
||||
|
||||
/* BOLT #2:
|
||||
|
@ -184,8 +186,19 @@ static void send_offer(struct per_peer_state *pps,
|
|||
status_debug("sending fee offer %s",
|
||||
type_to_string(tmpctx, struct amount_sat, &fee_to_offer));
|
||||
|
||||
/* Add the new close_tlvs with our fee range */
|
||||
if (tlv_fees) {
|
||||
close_tlvs = tlv_closing_signed_tlvs_new(msg);
|
||||
close_tlvs->fee_range
|
||||
= cast_const(struct tlv_closing_signed_tlvs_fee_range *,
|
||||
tlv_fees);
|
||||
} else
|
||||
close_tlvs = NULL;
|
||||
|
||||
assert(our_sig.sighash_type == SIGHASH_ALL);
|
||||
msg = towire_closing_signed(NULL, channel_id, fee_to_offer, &our_sig.s, NULL);
|
||||
msg = towire_closing_signed(NULL, channel_id, fee_to_offer, &our_sig.s,
|
||||
close_tlvs);
|
||||
|
||||
sync_crypto_write(pps, take(msg));
|
||||
}
|
||||
|
||||
|
@ -222,7 +235,8 @@ receive_offer(struct per_peer_state *pps,
|
|||
struct amount_sat our_dust_limit,
|
||||
struct amount_sat min_fee_to_accept,
|
||||
const struct bitcoin_outpoint *wrong_funding,
|
||||
struct bitcoin_txid *closing_txid)
|
||||
struct bitcoin_txid *closing_txid,
|
||||
struct tlv_closing_signed_tlvs_fee_range **tlv_fees)
|
||||
{
|
||||
u8 *msg;
|
||||
struct channel_id their_channel_id;
|
||||
|
@ -330,6 +344,13 @@ receive_offer(struct per_peer_state *pps,
|
|||
status_debug("Received fee offer %s",
|
||||
type_to_string(tmpctx, struct amount_sat, &received_fee));
|
||||
|
||||
if (tlv_fees) {
|
||||
if (close_tlvs)
|
||||
*tlv_fees = tal_steal(tlv_fees, close_tlvs->fee_range);
|
||||
else
|
||||
*tlv_fees = NULL;
|
||||
}
|
||||
|
||||
/* Master sorts out what is best offer, we just tell it any above min */
|
||||
if (amount_sat_greater_eq(received_fee, min_fee_to_accept)) {
|
||||
status_debug("...offer is reasonable");
|
||||
|
@ -397,6 +418,32 @@ static void adjust_feerange(struct feerange *feerange,
|
|||
"Overflow in updating fee range");
|
||||
}
|
||||
|
||||
/* Do these two ranges overlap? If so, return that range. */
|
||||
static bool get_overlap(const struct tlv_closing_signed_tlvs_fee_range *r1,
|
||||
const struct tlv_closing_signed_tlvs_fee_range *r2,
|
||||
struct tlv_closing_signed_tlvs_fee_range *overlap)
|
||||
{
|
||||
if (amount_sat_greater(r1->min_fee_satoshis, r2->min_fee_satoshis))
|
||||
overlap->min_fee_satoshis = r1->min_fee_satoshis;
|
||||
else
|
||||
overlap->min_fee_satoshis = r2->min_fee_satoshis;
|
||||
if (amount_sat_less(r1->max_fee_satoshis, r2->max_fee_satoshis))
|
||||
overlap->max_fee_satoshis = r1->max_fee_satoshis;
|
||||
else
|
||||
overlap->max_fee_satoshis = r2->max_fee_satoshis;
|
||||
|
||||
return amount_sat_less_eq(overlap->min_fee_satoshis,
|
||||
overlap->max_fee_satoshis);
|
||||
}
|
||||
|
||||
/* Is this amount in this range? */
|
||||
static bool amount_in_range(struct amount_sat amount,
|
||||
const struct tlv_closing_signed_tlvs_fee_range *r)
|
||||
{
|
||||
return amount_sat_greater_eq(amount, r->min_fee_satoshis)
|
||||
&& amount_sat_less_eq(amount, r->max_fee_satoshis);
|
||||
}
|
||||
|
||||
/* Figure out what we should offer now. */
|
||||
static struct amount_sat
|
||||
adjust_offer(struct per_peer_state *pps, const struct channel_id *channel_id,
|
||||
|
@ -572,6 +619,177 @@ static void calc_fee_bounds(size_t expected_weight,
|
|||
type_to_string(tmpctx, struct amount_sat, &maxfee));
|
||||
}
|
||||
|
||||
/* We've received one offer; if we're opener, that means we've already sent one
|
||||
* too. */
|
||||
static void do_quickclose(struct amount_sat offer[NUM_SIDES],
|
||||
struct per_peer_state *pps,
|
||||
const struct channel_id *channel_id,
|
||||
const struct pubkey funding_pubkey[NUM_SIDES],
|
||||
const u8 *funding_wscript,
|
||||
u8 *scriptpubkey[NUM_SIDES],
|
||||
const struct bitcoin_txid *funding_txid,
|
||||
unsigned int funding_txout,
|
||||
struct amount_sat funding,
|
||||
const struct amount_sat out[NUM_SIDES],
|
||||
enum side opener,
|
||||
struct amount_sat our_dust_limit,
|
||||
const struct bitcoin_outpoint *wrong_funding,
|
||||
struct bitcoin_txid *closing_txid,
|
||||
const struct tlv_closing_signed_tlvs_fee_range *our_feerange,
|
||||
const struct tlv_closing_signed_tlvs_fee_range *their_feerange)
|
||||
{
|
||||
struct tlv_closing_signed_tlvs_fee_range overlap;
|
||||
|
||||
|
||||
/* BOLT-closing-fee_range #2:
|
||||
* - if the message contains a `fee_range`:
|
||||
* - if there is no overlap between that and its own `fee_range`:
|
||||
* - SHOULD fail the connection
|
||||
*/
|
||||
if (!get_overlap(our_feerange, their_feerange, &overlap)) {
|
||||
peer_failed_warn(pps, channel_id,
|
||||
"Unable to agree on a feerate."
|
||||
" Our range %s-%s, other range %s-%s",
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&our_feerange->min_fee_satoshis),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&our_feerange->max_fee_satoshis),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&their_feerange->min_fee_satoshis),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&their_feerange->max_fee_satoshis));
|
||||
return;
|
||||
}
|
||||
|
||||
status_info("performing quickclose in range %s-%s",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&overlap.min_fee_satoshis),
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&overlap.max_fee_satoshis));
|
||||
|
||||
/* BOLT-closing-fee_range #2:
|
||||
* - otherwise:
|
||||
* - if it is the funder:
|
||||
* - if `fee_satoshis` is not in the overlap between the sent
|
||||
* and received `fee_range`:
|
||||
* - SHOULD fail the connection
|
||||
* - otherwise:
|
||||
* - MUST reply with the same `fee_satoshis`.
|
||||
*/
|
||||
if (opener == LOCAL) {
|
||||
if (!amount_in_range(offer[REMOTE], &overlap)) {
|
||||
peer_failed_warn(pps, channel_id,
|
||||
"Your fee %s was not in range:"
|
||||
" Our range %s-%s, other range %s-%s",
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat, &offer[REMOTE]),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&our_feerange->min_fee_satoshis),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&our_feerange->max_fee_satoshis),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&their_feerange->min_fee_satoshis),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&their_feerange->max_fee_satoshis));
|
||||
return;
|
||||
}
|
||||
/* Only reply if we didn't already completely agree. */
|
||||
if (!amount_sat_eq(offer[LOCAL], offer[REMOTE])) {
|
||||
offer[LOCAL] = offer[REMOTE];
|
||||
send_offer(pps, chainparams,
|
||||
channel_id, funding_pubkey, funding_wscript,
|
||||
scriptpubkey, funding_txid, funding_txout,
|
||||
funding, out, opener,
|
||||
our_dust_limit,
|
||||
offer[LOCAL],
|
||||
wrong_funding,
|
||||
our_feerange);
|
||||
}
|
||||
} else {
|
||||
/* BOLT-closing-fee_range #2:
|
||||
* - otherwise (it is not the funder):
|
||||
* - if it has already sent a `closing_signed`:
|
||||
* - if `fee_satoshis` is not the same as the value it sent:
|
||||
* - SHOULD fail the connection.
|
||||
* - otherwise:
|
||||
* - MUST propose a `fee_satoshis` in the overlap between
|
||||
* received and (about-to-be) sent `fee_range`.
|
||||
*/
|
||||
if (!amount_in_range(offer[LOCAL], &overlap)) {
|
||||
/* Hmm, go to edges. */
|
||||
if (amount_sat_greater(offer[LOCAL],
|
||||
overlap.max_fee_satoshis)) {
|
||||
offer[LOCAL] = overlap.max_fee_satoshis;
|
||||
status_unusual("Lowered offer to max allowable"
|
||||
" %s",
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&offer[LOCAL]));
|
||||
} else if (amount_sat_less(offer[LOCAL],
|
||||
overlap.min_fee_satoshis)) {
|
||||
offer[LOCAL] = overlap.min_fee_satoshis;
|
||||
status_unusual("Increased offer to min allowable"
|
||||
" %s",
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat,
|
||||
&offer[LOCAL]));
|
||||
}
|
||||
}
|
||||
send_offer(pps, chainparams,
|
||||
channel_id, funding_pubkey, funding_wscript,
|
||||
scriptpubkey, funding_txid, funding_txout,
|
||||
funding, out, opener,
|
||||
our_dust_limit,
|
||||
offer[LOCAL],
|
||||
wrong_funding,
|
||||
our_feerange);
|
||||
|
||||
/* They will reply unless we completely agreed. */
|
||||
if (!amount_sat_eq(offer[LOCAL], offer[REMOTE])) {
|
||||
offer[REMOTE]
|
||||
= receive_offer(pps, chainparams,
|
||||
channel_id, funding_pubkey,
|
||||
funding_wscript,
|
||||
scriptpubkey, funding_txid,
|
||||
funding_txout, funding,
|
||||
out, opener,
|
||||
our_dust_limit,
|
||||
our_feerange->min_fee_satoshis,
|
||||
wrong_funding,
|
||||
closing_txid,
|
||||
NULL);
|
||||
/* BOLT-closing-fee_range #2:
|
||||
* - otherwise (it is not the funder):
|
||||
* - if it has already sent a `closing_signed`:
|
||||
* - if `fee_satoshis` is not the same as the value
|
||||
* it sent:
|
||||
* - SHOULD fail the connection.
|
||||
*/
|
||||
if (!amount_sat_eq(offer[LOCAL], offer[REMOTE])) {
|
||||
peer_failed_warn(pps, channel_id,
|
||||
"Your fee %s was not equal to %s",
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat, &offer[REMOTE]),
|
||||
type_to_string(tmpctx,
|
||||
struct amount_sat, &offer[LOCAL]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peer_billboard(true, "We agreed on a closing fee of %"PRIu64" satoshi for tx:%s",
|
||||
offer[LOCAL],
|
||||
type_to_string(tmpctx, struct bitcoin_txid, closing_txid));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
setup_locale();
|
||||
|
@ -594,6 +812,8 @@ int main(int argc, char *argv[])
|
|||
char fee_negotiation_step_str[32]; /* fee_negotiation_step + "sat" */
|
||||
struct channel_id channel_id;
|
||||
enum side whose_turn;
|
||||
bool use_quickclose;
|
||||
struct tlv_closing_signed_tlvs_fee_range *our_feerange, **their_feerange;
|
||||
struct bitcoin_outpoint *wrong_funding;
|
||||
|
||||
subdaemon_setup(argc, argv);
|
||||
|
@ -619,6 +839,7 @@ int main(int argc, char *argv[])
|
|||
&scriptpubkey[REMOTE],
|
||||
&fee_negotiation_step,
|
||||
&fee_negotiation_step_unit,
|
||||
&use_quickclose,
|
||||
&dev_fast_gossip,
|
||||
&wrong_funding))
|
||||
master_badmsg(WIRE_CLOSINGD_INIT, msg);
|
||||
|
@ -637,6 +858,29 @@ int main(int argc, char *argv[])
|
|||
min_feerate, initial_feerate, commitment_fee,
|
||||
&min_fee_to_accept, &offer[LOCAL]);
|
||||
|
||||
/* Write values into tlv for updated closing fee neg */
|
||||
their_feerange = tal(ctx, struct tlv_closing_signed_tlvs_fee_range *);
|
||||
*their_feerange = NULL;
|
||||
|
||||
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;
|
||||
} else
|
||||
our_feerange = NULL;
|
||||
|
||||
snprintf(fee_negotiation_step_str, sizeof(fee_negotiation_step_str),
|
||||
"%" PRIu64 "%s", fee_negotiation_step,
|
||||
fee_negotiation_step_unit ==
|
||||
|
@ -683,7 +927,8 @@ int main(int argc, char *argv[])
|
|||
funding, out, opener,
|
||||
our_dust_limit,
|
||||
offer[LOCAL],
|
||||
wrong_funding);
|
||||
wrong_funding,
|
||||
our_feerange);
|
||||
} else {
|
||||
if (i == 0)
|
||||
peer_billboard(false, "Waiting for their initial"
|
||||
|
@ -705,7 +950,22 @@ int main(int argc, char *argv[])
|
|||
our_dust_limit,
|
||||
min_fee_to_accept,
|
||||
wrong_funding,
|
||||
&closing_txid);
|
||||
&closing_txid,
|
||||
their_feerange);
|
||||
|
||||
if (our_feerange && *their_feerange) {
|
||||
do_quickclose(offer,
|
||||
pps, &channel_id, funding_pubkey,
|
||||
funding_wscript,
|
||||
scriptpubkey,
|
||||
&funding_txid, funding_txout,
|
||||
funding, out, opener,
|
||||
our_dust_limit,
|
||||
wrong_funding,
|
||||
&closing_txid,
|
||||
our_feerange, *their_feerange);
|
||||
goto exit_thru_the_giftshop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -734,7 +994,8 @@ int main(int argc, char *argv[])
|
|||
funding, out, opener,
|
||||
our_dust_limit,
|
||||
offer[LOCAL],
|
||||
wrong_funding);
|
||||
wrong_funding,
|
||||
our_feerange);
|
||||
} else {
|
||||
peer_billboard(false, "Waiting for another"
|
||||
" closing fee offer:"
|
||||
|
@ -751,7 +1012,8 @@ int main(int argc, char *argv[])
|
|||
our_dust_limit,
|
||||
min_fee_to_accept,
|
||||
wrong_funding,
|
||||
&closing_txid);
|
||||
&closing_txid,
|
||||
their_feerange);
|
||||
}
|
||||
|
||||
whose_turn = !whose_turn;
|
||||
|
@ -761,9 +1023,12 @@ int main(int argc, char *argv[])
|
|||
offer[LOCAL],
|
||||
type_to_string(tmpctx, struct bitcoin_txid, &closing_txid));
|
||||
|
||||
exit_thru_the_giftshop:
|
||||
#if DEVELOPER
|
||||
/* We don't listen for master commands, so always check memleak here */
|
||||
tal_free(wrong_funding);
|
||||
tal_free(our_feerange);
|
||||
tal_free(their_feerange);
|
||||
closing_dev_memleak(ctx, scriptpubkey, funding_wscript);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ msgdata,closingd_init,remote_scriptpubkey_len,u16,
|
|||
msgdata,closingd_init,remote_scriptpubkey,u8,remote_scriptpubkey_len
|
||||
msgdata,closingd_init,fee_negotiation_step,u64,
|
||||
msgdata,closingd_init,fee_negotiation_step_unit,u8,
|
||||
msgdata,closingd_init,use_quickclose,bool,
|
||||
msgdata,closingd_init,dev_fast_gossip,bool,
|
||||
msgdata,closingd_init,shutdown_wrong_funding,?bitcoin_outpoint,
|
||||
|
||||
|
|
|
8
closingd/closingd_wiregen.c
generated
8
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 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 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);
|
||||
|
@ -76,6 +76,7 @@ u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams
|
|||
towire_u8_array(&p, remote_scriptpubkey, remote_scriptpubkey_len);
|
||||
towire_u64(&p, fee_negotiation_step);
|
||||
towire_u8(&p, fee_negotiation_step_unit);
|
||||
towire_bool(&p, use_quickclose);
|
||||
towire_bool(&p, dev_fast_gossip);
|
||||
if (!shutdown_wrong_funding)
|
||||
towire_bool(&p, false);
|
||||
|
@ -86,7 +87,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 *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 *use_quickclose, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding)
|
||||
{
|
||||
u16 local_scriptpubkey_len;
|
||||
u16 remote_scriptpubkey_len;
|
||||
|
@ -121,6 +122,7 @@ bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainp
|
|||
fromwire_u8_array(&cursor, &plen, *remote_scriptpubkey, remote_scriptpubkey_len);
|
||||
*fee_negotiation_step = fromwire_u64(&cursor, &plen);
|
||||
*fee_negotiation_step_unit = fromwire_u8(&cursor, &plen);
|
||||
*use_quickclose = fromwire_bool(&cursor, &plen);
|
||||
*dev_fast_gossip = fromwire_bool(&cursor, &plen);
|
||||
if (!fromwire_bool(&cursor, &plen))
|
||||
*shutdown_wrong_funding = NULL;
|
||||
|
@ -195,4 +197,4 @@ bool fromwire_closingd_complete(const void *p)
|
|||
return false;
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:961ca5ceef03f911684ba0e7863d69993e692b9b418108e6038a567cb7cc7b3e
|
||||
// SHA256STAMP:b736e1d2c03a883962558ddcd5675d26cb09dcf3462c0cf82b3d49f1fd980c8a
|
||||
|
|
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 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 *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, 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);
|
||||
|
||||
/* 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:961ca5ceef03f911684ba0e7863d69993e692b9b418108e6038a567cb7cc7b3e
|
||||
// SHA256STAMP:b736e1d2c03a883962558ddcd5675d26cb09dcf3462c0cf82b3d49f1fd980c8a
|
||||
|
|
4
doc/lightning-listconfigs.7
generated
4
doc/lightning-listconfigs.7
generated
|
@ -90,6 +90,8 @@ On success, an object is returned, containing:
|
|||
.IP \[bu]
|
||||
\fBexperimental-offers\fR (boolean, optional): \fBexperimental-offers\fR field from config or cmdline, or default
|
||||
.IP \[bu]
|
||||
\fBexperimental-quick-close\fR (boolean, optional): \fBexperimental-quick-close\fR field from config or cmdline, or default
|
||||
.IP \[bu]
|
||||
\fBexperimental-shutdown-wrong-funding\fR (boolean, optional): \fBexperimental-shutdown-wrong-funding\fR field from config or cmdline, or default
|
||||
.IP \[bu]
|
||||
\fBrgb\fR (hex, optional): \fBrgb\fR field from config or cmdline, or default (always 6 characters)
|
||||
|
@ -270,4 +272,4 @@ Vincenzo Palazzo \fI<vincenzo.palazzo@protonmail.com\fR> wrote the initial versi
|
|||
|
||||
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
|
||||
|
||||
\" SHA256STAMP:b6e48314de5642ec61a3e2c989ac0197630c2a3c0e8e6d86020b597679049400
|
||||
\" SHA256STAMP:fd8f2ae862627712b6baf51741670a6d60db8342f839580871617deed0c75317
|
||||
|
|
|
@ -55,6 +55,7 @@ On success, an object is returned, containing:
|
|||
- **experimental-dual-fund** (boolean, optional): `experimental-dual-fund` field from config or cmdline, or default
|
||||
- **experimental-onion-messages** (boolean, optional): `experimental-onion-messages` field from config or cmdline, or default
|
||||
- **experimental-offers** (boolean, optional): `experimental-offers` field from config or cmdline, or default
|
||||
- **experimental-quick-close** (boolean, optional): `experimental-quick-close` field from config or cmdline, or default
|
||||
- **experimental-shutdown-wrong-funding** (boolean, optional): `experimental-shutdown-wrong-funding` field from config or cmdline, or default
|
||||
- **rgb** (hex, optional): `rgb` field from config or cmdline, or default (always 6 characters)
|
||||
- **alias** (string, optional): `alias` field from config or cmdline, or default
|
||||
|
@ -205,4 +206,4 @@ RESOURCES
|
|||
---------
|
||||
|
||||
Main web site: <https://github.com/ElementsProject/lightning>
|
||||
[comment]: # ( SHA256STAMP:7bb40fc8fac201b32d9701b02596d0fa59eb14a3baf606439cbf96dc11548ed4)
|
||||
[comment]: # ( SHA256STAMP:8b198154e70e1c0acb6c9ccdbe9e41e35ddab55738be9ea9076c5384da965cb8)
|
||||
|
|
|
@ -625,6 +625,16 @@ about whether to add funds or not to a proposed channel is handled
|
|||
automatically by a plugin that implements the appropriate logic for
|
||||
your needs\. The default behavior is to not contribute funds\.
|
||||
|
||||
|
||||
\fBexperimental-quick-close\fR
|
||||
|
||||
|
||||
Specifying this means we send our range of acceptable fees to the peer
|
||||
on mutual close\. If they support it too, we'll simply use that for
|
||||
closing (unless \fIfee_negotiation_step\fR is set, see \fBlightning-close\fR(7))\.
|
||||
We always use this on channels which negotiation \fBoption_anchor_outputs\fR,
|
||||
as the spec requires that\.
|
||||
|
||||
.SH BUGS
|
||||
|
||||
You should report bugs on our github issues page, and maybe submit a fix
|
||||
|
@ -650,4 +660,4 @@ Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
|
|||
Note: the modules in the ccan/ directory have their own licenses, but
|
||||
the rest of the code is covered by the BSD-style MIT license\.
|
||||
|
||||
\" SHA256STAMP:1c392f3fee66dc6c1fc2c34200204a9be1d79e53fd5fb1720ad169fc671f71c0
|
||||
\" SHA256STAMP:0d2474276b325cb002191211fb1d0da2409ebc859ff3ccc6dd3e688b10d4550c
|
||||
|
|
|
@ -517,6 +517,14 @@ about whether to add funds or not to a proposed channel is handled
|
|||
automatically by a plugin that implements the appropriate logic for
|
||||
your needs. The default behavior is to not contribute funds.
|
||||
|
||||
**experimental-quick-close**
|
||||
|
||||
Specifying this means we send our range of acceptable fees to the peer
|
||||
on mutual close. If they support it too, we'll simply use that for
|
||||
closing (unless *fee_negotiation_step* is set, see lightning-close(7)).
|
||||
We always use this on channels which negotiation `option_anchor_outputs`,
|
||||
as the spec requires that.
|
||||
|
||||
BUGS
|
||||
----
|
||||
|
||||
|
|
|
@ -117,6 +117,10 @@
|
|||
"type": "boolean",
|
||||
"description": "`experimental-offers` field from config or cmdline, or default"
|
||||
},
|
||||
"experimental-quick-close": {
|
||||
"type": "boolean",
|
||||
"description": "`experimental-quick-close` field from config or cmdline, or default"
|
||||
},
|
||||
"experimental-shutdown-wrong-funding": {
|
||||
"type": "boolean",
|
||||
"description": "`experimental-shutdown-wrong-funding` field from config or cmdline, or default"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <bitcoin/script.h>
|
||||
#include <closingd/closingd_wiregen.h>
|
||||
#include <common/close_tx.h>
|
||||
#include <common/closing_fee.h>
|
||||
#include <common/fee_states.h>
|
||||
#include <common/initial_commit_tx.h>
|
||||
#include <common/per_peer_state.h>
|
||||
|
@ -289,6 +290,12 @@ void peer_start_closingd(struct channel *channel,
|
|||
channel->shutdown_scriptpubkey[REMOTE],
|
||||
channel->closing_fee_negotiation_step,
|
||||
channel->closing_fee_negotiation_step_unit,
|
||||
(ld->use_quickclose
|
||||
/* Don't quickclose if they specified how to negotiate! */
|
||||
&& channel->closing_fee_negotiation_step == 50
|
||||
&& channel->closing_fee_negotiation_step_unit == CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE)
|
||||
/* Always use quickclose with anchors */
|
||||
|| channel->option_anchor_outputs,
|
||||
IFDEV(ld->dev_fast_gossip, false),
|
||||
channel->shutdown_wrong_funding);
|
||||
|
||||
|
|
|
@ -295,6 +295,11 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
|
|||
* case this is a pointer to an enum feerate-indexed array of values */
|
||||
ld->force_feerates = NULL;
|
||||
|
||||
/*~ We don't enable new network features until they've been approved
|
||||
* and tested in the spec (i.e. some other implementation has also
|
||||
* implemented and tested!). Until then we use a flag: */
|
||||
ld->use_quickclose = false;
|
||||
|
||||
return ld;
|
||||
}
|
||||
|
||||
|
|
|
@ -283,6 +283,9 @@ struct lightningd {
|
|||
/* Should we re-exec ourselves instead of just exiting? */
|
||||
bool try_reexec;
|
||||
|
||||
/* --experimental-quick-close */
|
||||
bool use_quickclose;
|
||||
|
||||
/* Array of (even) TLV types that we should allow. This is required
|
||||
* since we otherwise would outright reject them. */
|
||||
u64 *accept_extra_tlv_types;
|
||||
|
|
|
@ -1062,6 +1062,10 @@ static void register_opts(struct lightningd *ld)
|
|||
"--subdaemon=hsmd:remote_signer "
|
||||
"would use a hypothetical remote signing subdaemon.");
|
||||
|
||||
opt_register_noarg("--experimental-quick-close",
|
||||
opt_set_bool, &ld->use_quickclose,
|
||||
"EXPERIMENTAL: offer range to mutual close");
|
||||
|
||||
opt_register_logging(ld);
|
||||
opt_register_version();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from pyln.testing.utils import SLOW_MACHINE
|
|||
from utils import (
|
||||
only_one, sync_blockheight, wait_for, TIMEOUT,
|
||||
account_balance, first_channel_id, closing_fee, TEST_NETWORK,
|
||||
scriptpubkey_addr, calc_lease_fee
|
||||
scriptpubkey_addr, calc_lease_fee, EXPERIMENTAL_FEATURES
|
||||
)
|
||||
|
||||
import os
|
||||
|
@ -446,6 +446,7 @@ def closing_negotiation_step(node_factory, bitcoind, chainparams, opts):
|
|||
assert opts['expected_close_fee'] == fee_mempool
|
||||
|
||||
|
||||
@unittest.skipIf(EXPERIMENTAL_FEATURES, "anchors uses quick-close, not negotiation")
|
||||
def test_closing_negotiation_step_30pct(node_factory, bitcoind, chainparams):
|
||||
"""Test that the closing fee negotiation step works, 30%"""
|
||||
opts = {}
|
||||
|
@ -460,6 +461,7 @@ def test_closing_negotiation_step_30pct(node_factory, bitcoind, chainparams):
|
|||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||
|
||||
|
||||
@unittest.skipIf(EXPERIMENTAL_FEATURES, "anchors uses quick-close, not negotiation")
|
||||
def test_closing_negotiation_step_50pct(node_factory, bitcoind, chainparams):
|
||||
"""Test that the closing fee negotiation step works, 50%, the default"""
|
||||
opts = {}
|
||||
|
@ -474,6 +476,7 @@ def test_closing_negotiation_step_50pct(node_factory, bitcoind, chainparams):
|
|||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||
|
||||
|
||||
@unittest.skipIf(EXPERIMENTAL_FEATURES, "anchors uses quick-close, not negotiation")
|
||||
def test_closing_negotiation_step_100pct(node_factory, bitcoind, chainparams):
|
||||
"""Test that the closing fee negotiation step works, 100%"""
|
||||
opts = {}
|
||||
|
@ -493,6 +496,7 @@ def test_closing_negotiation_step_100pct(node_factory, bitcoind, chainparams):
|
|||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||
|
||||
|
||||
@unittest.skipIf(EXPERIMENTAL_FEATURES, "anchors uses quick-close, not negotiation")
|
||||
def test_closing_negotiation_step_1sat(node_factory, bitcoind, chainparams):
|
||||
"""Test that the closing fee negotiation step works, 1sat"""
|
||||
opts = {}
|
||||
|
@ -507,6 +511,7 @@ def test_closing_negotiation_step_1sat(node_factory, bitcoind, chainparams):
|
|||
closing_negotiation_step(node_factory, bitcoind, chainparams, opts)
|
||||
|
||||
|
||||
@unittest.skipIf(EXPERIMENTAL_FEATURES, "anchors uses quick-close, not negotiation")
|
||||
def test_closing_negotiation_step_700sat(node_factory, bitcoind, chainparams):
|
||||
"""Test that the closing fee negotiation step works, 700sat"""
|
||||
opts = {}
|
||||
|
|
2
wallet/db_postgres_sqlgen.c
generated
2
wallet/db_postgres_sqlgen.c
generated
|
@ -2074,4 +2074,4 @@ struct db_query db_postgres_queries[] = {
|
|||
|
||||
#endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */
|
||||
|
||||
// SHA256STAMP:219fccaaf2391eeabadd4cc15b4a3431c7ecab9d17755582e6962a34c74982c5
|
||||
// SHA256STAMP:56ce3adfaa2de5ef901e32e7f698b9500859a0015d869470ea1be779847b32e3
|
||||
|
|
2
wallet/db_sqlite3_sqlgen.c
generated
2
wallet/db_sqlite3_sqlgen.c
generated
|
@ -2074,4 +2074,4 @@ struct db_query db_sqlite3_queries[] = {
|
|||
|
||||
#endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */
|
||||
|
||||
// SHA256STAMP:219fccaaf2391eeabadd4cc15b4a3431c7ecab9d17755582e6962a34c74982c5
|
||||
// SHA256STAMP:56ce3adfaa2de5ef901e32e7f698b9500859a0015d869470ea1be779847b32e3
|
||||
|
|
2
wallet/statements_gettextgen.po
generated
2
wallet/statements_gettextgen.po
generated
|
@ -1369,4 +1369,4 @@ msgstr ""
|
|||
#: wallet/test/run-wallet.c:1753
|
||||
msgid "INSERT INTO channels (id) VALUES (1);"
|
||||
msgstr ""
|
||||
# SHA256STAMP:d098fea63dcba84aefff5cf924cbc455caf9d2ec13cb28ad9ab929bb001a12e6
|
||||
# SHA256STAMP:a433fb1866ae16a28b87177ef67fc99669c03a6cd47a0433e1460884367bbf34
|
||||
|
|
Loading…
Add table
Reference in a new issue