mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 18:11:28 +01:00
ab9d9ef3b8
(This was sitting in my gossip-enchancement patch queue, but it simplifies
this set too, so I moved it here).
In 94711969f
we added an explicit gossip_index so when gossipd gets
peers back from other daemons, it knows what gossip it has sent (since
gossipd can send gossip after the other daemon is already complete).
This solution is insufficient for the more general case where gossipd
wants to send other messages reliably, so replace it with the other
solution: have gossipd drain the "gossip fd" which the daemon returns.
This turns out to be quite simple, and is probably how I should have
done it originally :(
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
220 lines
6.6 KiB
C
220 lines
6.6 KiB
C
#include <bitcoin/script.h>
|
|
#include <closingd/gen_closing_wire.h>
|
|
#include <common/close_tx.h>
|
|
#include <common/initial_commit_tx.h>
|
|
#include <common/utils.h>
|
|
#include <errno.h>
|
|
#include <gossipd/gen_gossip_wire.h>
|
|
#include <inttypes.h>
|
|
#include <lightningd/chaintopology.h>
|
|
#include <lightningd/channel.h>
|
|
#include <lightningd/closing_control.h>
|
|
#include <lightningd/lightningd.h>
|
|
#include <lightningd/log.h>
|
|
#include <lightningd/options.h>
|
|
#include <lightningd/peer_control.h>
|
|
#include <lightningd/subd.h>
|
|
|
|
/* Is this better than the last tx we were holding? This can happen
|
|
* even without closingd misbehaving, if we have multiple,
|
|
* interrupted, rounds of negotiation. */
|
|
static bool better_closing_fee(struct lightningd *ld,
|
|
struct channel *channel,
|
|
const struct bitcoin_tx *tx)
|
|
{
|
|
u64 weight, fee, last_fee, min_fee;
|
|
size_t i;
|
|
|
|
/* Calculate actual fee (adds in eliminated outputs) */
|
|
fee = channel->funding_satoshi;
|
|
for (i = 0; i < tal_count(tx->output); i++)
|
|
fee -= tx->output[i].amount;
|
|
|
|
last_fee = channel->funding_satoshi;
|
|
for (i = 0; i < tal_count(channel->last_tx->output); i++)
|
|
last_fee -= channel->last_tx->output[i].amount;
|
|
|
|
log_debug(channel->log, "Their actual closing tx fee is %"PRIu64
|
|
" vs previous %"PRIu64, fee, last_fee);
|
|
|
|
/* Weight once we add in sigs. */
|
|
weight = measure_tx_weight(tx) + 74 * 2;
|
|
|
|
min_fee = get_feerate(ld->topology, FEERATE_SLOW) * weight / 1000;
|
|
if (fee < min_fee) {
|
|
log_debug(channel->log, "... That's below our min %"PRIu64
|
|
" for weight %"PRIu64" at feerate %u",
|
|
min_fee, weight,
|
|
get_feerate(ld->topology, FEERATE_SLOW));
|
|
return false;
|
|
}
|
|
|
|
/* Prefer lower fee: in case of a tie, prefer new over old: this
|
|
* covers the preference for a mutual close over a unilateral one. */
|
|
return fee <= last_fee;
|
|
}
|
|
|
|
static void peer_received_closing_signature(struct channel *channel,
|
|
const u8 *msg)
|
|
{
|
|
secp256k1_ecdsa_signature sig;
|
|
struct bitcoin_tx *tx;
|
|
struct lightningd *ld = channel->peer->ld;
|
|
|
|
if (!fromwire_closing_received_signature(msg, msg, &sig, &tx)) {
|
|
channel_internal_error(channel, "Bad closing_received_signature %s",
|
|
tal_hex(msg, msg));
|
|
return;
|
|
}
|
|
|
|
/* FIXME: Make sure signature is correct! */
|
|
if (better_closing_fee(ld, channel, tx)) {
|
|
channel_set_last_tx(channel, tx, &sig);
|
|
/* TODO(cdecker) Selectively save updated fields to DB */
|
|
wallet_channel_save(ld->wallet, channel);
|
|
}
|
|
|
|
/* OK, you can continue now. */
|
|
subd_send_msg(channel->owner,
|
|
take(towire_closing_received_signature_reply(channel)));
|
|
}
|
|
|
|
static void peer_closing_complete(struct channel *channel, const u8 *msg)
|
|
{
|
|
if (!fromwire_closing_complete(msg)) {
|
|
channel_internal_error(channel, "Bad closing_complete %s",
|
|
tal_hex(msg, msg));
|
|
return;
|
|
}
|
|
|
|
/* Don't report spurious failure when closingd exits. */
|
|
channel_set_owner(channel, NULL);
|
|
/* Clear any transient negotiation messages */
|
|
channel_set_billboard(channel, false, NULL);
|
|
|
|
/* Retransmission only, ignore closing. */
|
|
if (channel->state == CLOSINGD_COMPLETE)
|
|
return;
|
|
|
|
/* Tell gossipd we no longer need to keep connection to this peer */
|
|
msg = towire_gossipctl_peer_important(NULL, &channel->peer->id, false);
|
|
subd_send_msg(channel->peer->ld->gossip, take(msg));
|
|
|
|
/* Channel gets dropped to chain cooperatively. */
|
|
drop_to_chain(channel->peer->ld, channel, true);
|
|
channel_set_state(channel, CLOSINGD_SIGEXCHANGE, CLOSINGD_COMPLETE);
|
|
}
|
|
|
|
static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds UNUSED)
|
|
{
|
|
enum closing_wire_type t = fromwire_peektype(msg);
|
|
|
|
switch (t) {
|
|
case WIRE_CLOSING_RECEIVED_SIGNATURE:
|
|
peer_received_closing_signature(sd->channel, msg);
|
|
break;
|
|
|
|
case WIRE_CLOSING_COMPLETE:
|
|
peer_closing_complete(sd->channel, msg);
|
|
break;
|
|
|
|
/* We send these, not receive them */
|
|
case WIRE_CLOSING_INIT:
|
|
case WIRE_CLOSING_RECEIVED_SIGNATURE_REPLY:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void peer_start_closingd(struct channel *channel,
|
|
const struct crypto_state *cs,
|
|
int peer_fd, int gossip_fd,
|
|
bool reconnected,
|
|
const u8 *channel_reestablish)
|
|
{
|
|
u8 *initmsg;
|
|
u64 minfee, startfee, feelimit;
|
|
u64 num_revocations;
|
|
u64 funding_msatoshi, our_msatoshi, their_msatoshi;
|
|
struct lightningd *ld = channel->peer->ld;
|
|
|
|
if (!channel->remote_shutdown_scriptpubkey) {
|
|
channel_internal_error(channel,
|
|
"Can't start closing: no remote info");
|
|
return;
|
|
}
|
|
|
|
channel_set_owner(channel, new_channel_subd(ld,
|
|
"lightning_closingd",
|
|
channel, channel->log,
|
|
closing_wire_type_name, closing_msg,
|
|
channel_errmsg,
|
|
channel_set_billboard,
|
|
take(&peer_fd), take(&gossip_fd),
|
|
NULL));
|
|
if (!channel->owner) {
|
|
log_unusual(channel->log, "Could not subdaemon closing: %s",
|
|
strerror(errno));
|
|
channel_fail_transient(channel, "Failed to subdaemon closing");
|
|
return;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* A sending node MUST set `fee_satoshis` lower than or equal
|
|
* to the base fee of the final commitment transaction as
|
|
* calculated in [BOLT
|
|
* #3](03-transactions.md#fee-calculation).
|
|
*/
|
|
feelimit = commit_tx_base_fee(channel->channel_info.feerate_per_kw[LOCAL],
|
|
0);
|
|
|
|
minfee = commit_tx_base_fee(get_feerate(ld->topology, FEERATE_SLOW), 0);
|
|
startfee = commit_tx_base_fee(get_feerate(ld->topology, FEERATE_NORMAL),
|
|
0);
|
|
|
|
if (startfee > feelimit)
|
|
startfee = feelimit;
|
|
if (minfee > feelimit)
|
|
minfee = feelimit;
|
|
|
|
num_revocations
|
|
= revocations_received(&channel->their_shachain.chain);
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* The amounts for each output MUST BE rounded down to whole satoshis.
|
|
*/
|
|
/* Convert unit */
|
|
funding_msatoshi = channel->funding_satoshi * 1000;
|
|
/* What is not ours is theirs */
|
|
our_msatoshi = channel->our_msatoshi;
|
|
their_msatoshi = funding_msatoshi - our_msatoshi;
|
|
initmsg = towire_closing_init(tmpctx,
|
|
cs,
|
|
&channel->seed,
|
|
&channel->funding_txid,
|
|
channel->funding_outnum,
|
|
channel->funding_satoshi,
|
|
&channel->channel_info.remote_fundingkey,
|
|
channel->funder,
|
|
our_msatoshi / 1000, /* Rounds down */
|
|
their_msatoshi / 1000, /* Rounds down */
|
|
channel->our_config.dust_limit_satoshis,
|
|
minfee, feelimit, startfee,
|
|
p2wpkh_for_keyidx(tmpctx, ld,
|
|
channel->final_key_idx),
|
|
channel->remote_shutdown_scriptpubkey,
|
|
reconnected,
|
|
channel->next_index[LOCAL],
|
|
channel->next_index[REMOTE],
|
|
num_revocations,
|
|
deprecated_apis,
|
|
channel_reestablish);
|
|
|
|
/* We don't expect a response: it will give us feedback on
|
|
* signatures sent and received, then closing_complete. */
|
|
subd_send_msg(channel->owner, take(initmsg));
|
|
}
|