Skip to content

Commit

Permalink
rfc-proposal: relax closing fee requirements
Browse files Browse the repository at this point in the history
Implementation of lightning/bolts#847

In particular see comment:

	OK, perhaps we should split this further, to make it explicit that there's no back-and-forth if both sides support this?

	If you both include the TLV, there's no back-and-forth, it's either two messages or three.
	If nodes receive the tlv, it picks from that range for its reply: if it doesn't care, uses the same rate.
	If reply has different rate (and it's acceptable), reply with using that rate. Otherwise it's complete.
	That will be a nice simplification in future...

Needs tests, and interop check.

Waiting for finalized wording before importing more spec notes.
  • Loading branch information
niftynei committed May 18, 2021
1 parent 0d68feb commit d865278
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 11 deletions.
127 changes: 118 additions & 9 deletions closingd/closingd.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,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,
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:
Expand Down Expand Up @@ -323,8 +325,14 @@ 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 */
close_tlvs = tlv_closing_signed_tlvs_new(msg);
close_tlvs->fee_range = tlv_fees;

assert(our_sig.sighash_type == SIGHASH_ALL);
msg = towire_closing_signed(NULL, channel_id, fee_to_offer, &our_sig.s);
msg = towire_closing_signed(NULL, channel_id, fee_to_offer, &our_sig.s,
close_tlvs);

sync_crypto_write(pps, take(msg));
}

Expand Down Expand Up @@ -361,13 +369,15 @@ 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;
struct amount_sat received_fee;
struct bitcoin_signature their_sig;
struct bitcoin_tx *tx;
struct tlv_closing_signed_tlvs *close_tlvs;

/* Wait for them to say something interesting */
do {
Expand All @@ -391,8 +401,10 @@ receive_offer(struct per_peer_state *pps,
} while (!msg);

their_sig.sighash_type = SIGHASH_ALL;
close_tlvs = tlv_closing_signed_tlvs_new(msg);
if (!fromwire_closing_signed(msg, &their_channel_id,
&received_fee, &their_sig.s))
&received_fee, &their_sig.s,
close_tlvs))
peer_failed_warn(pps, channel_id,
"Expected closing_signed: %s",
tal_hex(tmpctx, msg));
Expand Down Expand Up @@ -466,6 +478,11 @@ receive_offer(struct per_peer_state *pps,
status_debug("Received fee offer %s",
type_to_string(tmpctx, struct amount_sat, &received_fee));

if (close_tlvs)
*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");
Expand Down Expand Up @@ -531,6 +548,23 @@ static void adjust_feerange(struct feerange *feerange,
"Overflow in updating fee range");
}

static bool
evaluate_their_offer(struct amount_sat their_offer,
const struct tlv_closing_signed_tlvs_fee_range *our_range,
const struct tlv_closing_signed_tlvs_fee_range *their_range)
{
/* They'd better be within their own range */
if (amount_sat_greater(their_offer, their_range->max_fee_satoshis))
return false;
if (amount_sat_less(their_offer, their_range->min_fee_satoshis))
return false;
if (amount_sat_greater(their_offer, our_range->max_fee_satoshis))
return false;
if (amount_sat_less(their_offer, our_range->min_fee_satoshis))
return false;
return true;
}

/* Figure out what we should offer now. */
static struct amount_sat
adjust_offer(struct per_peer_state *pps, const struct channel_id *channel_id,
Expand Down Expand Up @@ -654,6 +688,7 @@ int main(int argc, char *argv[])
u8 *channel_reestablish;
struct secret last_remote_per_commit_secret;
struct bitcoin_outpoint *wrong_funding;
struct tlv_closing_signed_tlvs_fee_range *our_feerange, **their_feerange;

subdaemon_setup(argc, argv);

Expand All @@ -672,7 +707,8 @@ int main(int argc, char *argv[])
&out[LOCAL],
&out[REMOTE],
&our_dust_limit,
&min_fee_to_accept, &commitment_fee,
&min_fee_to_accept,
&commitment_fee,
&offer[LOCAL],
&scriptpubkey[LOCAL],
&scriptpubkey[REMOTE],
Expand All @@ -691,6 +727,13 @@ int main(int argc, char *argv[])
/* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = hsmd */
per_peer_state_set_fds(notleak(pps), 3, 4, 5);

/* Write values into tlv for updated closing fee neg */
their_feerange = tal(ctx, struct tlv_closing_signed_tlvs_fee_range *);
*their_feerange = NULL;
our_feerange = tal(ctx, struct tlv_closing_signed_tlvs_fee_range);
our_feerange->min_fee_satoshis = min_fee_to_accept;
our_feerange->max_fee_satoshis = commitment_fee;

snprintf(fee_negotiation_step_str, sizeof(fee_negotiation_step_str),
"%" PRIu64 "%s", fee_negotiation_step,
fee_negotiation_step_unit ==
Expand Down Expand Up @@ -748,7 +791,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"
Expand All @@ -770,7 +814,69 @@ int main(int argc, char *argv[])
our_dust_limit,
min_fee_to_accept,
wrong_funding,
&closing_txid);
&closing_txid,
their_feerange);

if (*their_feerange) {
if (!evaluate_their_offer(offer[REMOTE],
our_feerange,
*their_feerange)) {
peer_billboard(true,
"Unable to agree on"
" a feerate."
" Our range %s-%s,"
" their 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));
goto exit_thru_the_giftshop;
}

peer_billboard(true, "Using quick-close."
" Updated our offer to match"
" theirs (was %s, now %s",
type_to_string(tmpctx,
struct amount_sat,
&offer[LOCAL]),
type_to_string(tmpctx,
struct amount_sat,
&offer[REMOTE]));

/* We mirror it back */
if (i == 1 && !amount_sat_eq(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[REMOTE],
wrong_funding,
our_feerange);
}

/* BOLT-9a0b1f68d6c6feefe2c459e28adee3475d02a62e #2:
* The receiving node:
* - if `fee_satoshis` matches its previously sent
* `fee_range`:
* - SHOULD use `fee_satoshis` to sign and
* broadcast the final closing transaction
*/
offer[LOCAL] = offer[REMOTE];
}
}
}

Expand Down Expand Up @@ -799,7 +905,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:"
Expand All @@ -816,7 +923,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;
Expand All @@ -826,6 +934,7 @@ 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);
Expand Down
13 changes: 13 additions & 0 deletions wire/extracted_peer_04_closing_fee_nego.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--- wire/peer_wire.csv 2021-05-18 11:15:05.539134131 -0500
+++ - 2021-05-18 11:15:15.690789516 -0500
@@ -90,6 +90,10 @@
msgdata,closing_signed,channel_id,channel_id,
msgdata,closing_signed,fee_satoshis,u64,
msgdata,closing_signed,signature,signature,
+msgdata,closing_signed,tlvs,closing_signed_tlvs,
+tlvtype,closing_signed_tlvs,fee_range,1
+tlvdata,closing_signed_tlvs,fee_range,min_fee_satoshis,u64,
+tlvdata,closing_signed_tlvs,fee_range,max_fee_satoshis,u64,
msgtype,update_add_htlc,128
msgdata,update_add_htlc,channel_id,channel_id,
msgdata,update_add_htlc,id,u64,
11 changes: 9 additions & 2 deletions wire/test/run-peer-wire.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,20 +611,27 @@ static struct msg_funding_signed *fromwire_struct_funding_signed(const tal_t *ct
static void *towire_struct_closing_signed(const tal_t *ctx,
const struct msg_closing_signed *s)
{
struct tlv_closing_signed_tlvs *close_tlvs;

close_tlvs = tlv_closing_signed_tlvs_new(ctx);
return towire_closing_signed(ctx,
&s->channel_id,
s->fee_satoshis,
&s->signature);
&s->signature,
close_tlvs);
}

static struct msg_closing_signed *fromwire_struct_closing_signed(const tal_t *ctx, const void *p)
{
struct msg_closing_signed *s = tal(ctx, struct msg_closing_signed);
struct tlv_closing_signed_tlvs *close_tlvs;

close_tlvs = tlv_closing_signed_tlvs_new(ctx);
if (fromwire_closing_signed(p,
&s->channel_id,
&s->fee_satoshis,
&s->signature))
&s->signature,
close_tlvs))
return s;
return tal_free(s);
}
Expand Down

0 comments on commit d865278

Please sign in to comment.