mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-20 10:39:49 +01:00
8a16963f22
If channeld dies for some reason (eg, reconnect) and we didn't yet announce the channel, we can miss doing so. This is unusual, because if lightningd restarts it rearms the callback which gives us funding_locked, so it only happens if just channel dies before sending the announcement message. This problem applies to both temporary announcement (for gossipd) and the real one. For the temporary one, simply re-send on startup, and remote the error msg gossipd gives if it sees a second one. For the real one, we need a flag to tell us the depth is sufficient; the peer will ignore re-sends anyway. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
325 lines
9.9 KiB
C
325 lines
9.9 KiB
C
#include <bitcoin/script.h>
|
|
#include <ccan/fdpass/fdpass.h>
|
|
#include <channeld/gen_channel_wire.h>
|
|
#include <errno.h>
|
|
#include <hsmd/capabilities.h>
|
|
#include <hsmd/gen_hsm_client_wire.h>
|
|
#include <inttypes.h>
|
|
#include <lightningd/channel_control.h>
|
|
#include <lightningd/closing_control.h>
|
|
#include <lightningd/hsm_control.h>
|
|
#include <lightningd/lightningd.h>
|
|
#include <lightningd/log.h>
|
|
#include <lightningd/peer_control.h>
|
|
#include <lightningd/subd.h>
|
|
#include <wire/wire_sync.h>
|
|
|
|
static void lockin_complete(struct channel *channel)
|
|
{
|
|
/* We set this once we're locked in. */
|
|
assert(channel->scid);
|
|
/* We set this once they're locked in. */
|
|
assert(channel->remote_funding_locked);
|
|
channel_set_state(channel, CHANNELD_AWAITING_LOCKIN, CHANNELD_NORMAL);
|
|
}
|
|
|
|
/* We were informed by channeld that it announced the channel and sent
|
|
* an update, so we can now start sending a node_announcement. The
|
|
* first step is to build the provisional announcement and ask the HSM
|
|
* to sign it. */
|
|
|
|
static void peer_got_funding_locked(struct channel *channel, const u8 *msg)
|
|
{
|
|
struct pubkey next_per_commitment_point;
|
|
|
|
if (!fromwire_channel_got_funding_locked(msg,
|
|
&next_per_commitment_point)) {
|
|
channel_internal_error(channel,
|
|
"bad channel_got_funding_locked %s",
|
|
tal_hex(channel, msg));
|
|
return;
|
|
}
|
|
|
|
if (channel->remote_funding_locked) {
|
|
channel_internal_error(channel,
|
|
"channel_got_funding_locked twice");
|
|
return;
|
|
}
|
|
update_per_commit_point(channel, &next_per_commitment_point);
|
|
|
|
log_debug(channel->log, "Got funding_locked");
|
|
channel->remote_funding_locked = true;
|
|
|
|
if (channel->scid)
|
|
lockin_complete(channel);
|
|
}
|
|
|
|
static void peer_got_shutdown(struct channel *channel, const u8 *msg)
|
|
{
|
|
u8 *scriptpubkey;
|
|
struct lightningd *ld = channel->peer->ld;
|
|
|
|
if (!fromwire_channel_got_shutdown(channel, msg, &scriptpubkey)) {
|
|
channel_internal_error(channel, "bad channel_got_shutdown %s",
|
|
tal_hex(msg, msg));
|
|
return;
|
|
}
|
|
|
|
/* FIXME: Add to spec that we must allow repeated shutdown! */
|
|
tal_free(channel->remote_shutdown_scriptpubkey);
|
|
channel->remote_shutdown_scriptpubkey = scriptpubkey;
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* A sending node MUST set `scriptpubkey` to one of the following forms:
|
|
*
|
|
* 1. `OP_DUP` `OP_HASH160` `20` 20-bytes `OP_EQUALVERIFY` `OP_CHECKSIG`
|
|
* (pay to pubkey hash), OR
|
|
* 2. `OP_HASH160` `20` 20-bytes `OP_EQUAL` (pay to script hash), OR
|
|
* 3. `OP_0` `20` 20-bytes (version 0 pay to witness pubkey), OR
|
|
* 4. `OP_0` `32` 32-bytes (version 0 pay to witness script hash)
|
|
*
|
|
* A receiving node SHOULD fail the connection if the `scriptpubkey`
|
|
* is not one of those forms. */
|
|
if (!is_p2pkh(scriptpubkey, NULL) && !is_p2sh(scriptpubkey, NULL)
|
|
&& !is_p2wpkh(scriptpubkey, NULL) && !is_p2wsh(scriptpubkey, NULL)) {
|
|
channel_fail_permanent(channel, "Bad shutdown scriptpubkey %s",
|
|
tal_hex(channel, scriptpubkey));
|
|
return;
|
|
}
|
|
|
|
/* If we weren't already shutting down, we are now */
|
|
if (channel->state != CHANNELD_SHUTTING_DOWN)
|
|
channel_set_state(channel,
|
|
channel->state, CHANNELD_SHUTTING_DOWN);
|
|
|
|
/* TODO(cdecker) Selectively save updated fields to DB */
|
|
wallet_channel_save(ld->wallet, channel);
|
|
}
|
|
|
|
static void peer_start_closingd_after_shutdown(struct channel *channel,
|
|
const u8 *msg,
|
|
const int *fds)
|
|
{
|
|
struct crypto_state cs;
|
|
|
|
/* We expect 2 fds. */
|
|
assert(tal_count(fds) == 2);
|
|
|
|
if (!fromwire_channel_shutdown_complete(msg, &cs)) {
|
|
channel_internal_error(channel, "bad shutdown_complete: %s",
|
|
tal_hex(msg, msg));
|
|
return;
|
|
}
|
|
|
|
/* This sets channel->owner, closes down channeld. */
|
|
peer_start_closingd(channel, &cs, fds[0], fds[1], false, NULL);
|
|
channel_set_state(channel, CHANNELD_SHUTTING_DOWN, CLOSINGD_SIGEXCHANGE);
|
|
}
|
|
|
|
static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
|
|
{
|
|
enum channel_wire_type t = fromwire_peektype(msg);
|
|
|
|
switch (t) {
|
|
case WIRE_CHANNEL_SENDING_COMMITSIG:
|
|
peer_sending_commitsig(sd->channel, msg);
|
|
break;
|
|
case WIRE_CHANNEL_GOT_COMMITSIG:
|
|
peer_got_commitsig(sd->channel, msg);
|
|
break;
|
|
case WIRE_CHANNEL_GOT_REVOKE:
|
|
peer_got_revoke(sd->channel, msg);
|
|
break;
|
|
case WIRE_CHANNEL_GOT_FUNDING_LOCKED:
|
|
peer_got_funding_locked(sd->channel, msg);
|
|
break;
|
|
case WIRE_CHANNEL_GOT_SHUTDOWN:
|
|
peer_got_shutdown(sd->channel, msg);
|
|
break;
|
|
case WIRE_CHANNEL_SHUTDOWN_COMPLETE:
|
|
/* We expect 2 fds. */
|
|
if (!fds)
|
|
return 2;
|
|
peer_start_closingd_after_shutdown(sd->channel, msg, fds);
|
|
break;
|
|
|
|
/* And we never get these from channeld. */
|
|
case WIRE_CHANNEL_INIT:
|
|
case WIRE_CHANNEL_FUNDING_LOCKED:
|
|
case WIRE_CHANNEL_FUNDING_ANNOUNCE_DEPTH:
|
|
case WIRE_CHANNEL_OFFER_HTLC:
|
|
case WIRE_CHANNEL_FULFILL_HTLC:
|
|
case WIRE_CHANNEL_FAIL_HTLC:
|
|
case WIRE_CHANNEL_PING:
|
|
case WIRE_CHANNEL_GOT_COMMITSIG_REPLY:
|
|
case WIRE_CHANNEL_GOT_REVOKE_REPLY:
|
|
case WIRE_CHANNEL_SENDING_COMMITSIG_REPLY:
|
|
case WIRE_CHANNEL_SEND_SHUTDOWN:
|
|
case WIRE_CHANNEL_DEV_REENABLE_COMMIT:
|
|
case WIRE_CHANNEL_FEERATES:
|
|
/* Replies go to requests. */
|
|
case WIRE_CHANNEL_OFFER_HTLC_REPLY:
|
|
case WIRE_CHANNEL_PING_REPLY:
|
|
case WIRE_CHANNEL_DEV_REENABLE_COMMIT_REPLY:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool peer_start_channeld(struct channel *channel,
|
|
const struct crypto_state *cs,
|
|
int peer_fd, int gossip_fd,
|
|
const u8 *funding_signed,
|
|
bool reconnected)
|
|
{
|
|
u8 *msg, *initmsg;
|
|
int hsmfd;
|
|
struct added_htlc *htlcs;
|
|
enum htlc_state *htlc_states;
|
|
struct fulfilled_htlc *fulfilled_htlcs;
|
|
enum side *fulfilled_sides;
|
|
const struct failed_htlc **failed_htlcs;
|
|
enum side *failed_sides;
|
|
struct short_channel_id funding_channel_id;
|
|
u64 num_revocations;
|
|
struct lightningd *ld = channel->peer->ld;
|
|
const struct config *cfg = &ld->config;
|
|
bool reached_announce_depth;
|
|
|
|
msg = towire_hsm_client_hsmfd(tmpctx, &channel->peer->id, HSM_CAP_SIGN_GOSSIP | HSM_CAP_ECDH);
|
|
if (!wire_sync_write(ld->hsm_fd, take(msg)))
|
|
fatal("Could not write to HSM: %s", strerror(errno));
|
|
|
|
msg = hsm_sync_read(tmpctx, ld);
|
|
if (!fromwire_hsm_client_hsmfd_reply(msg))
|
|
fatal("Bad reply from HSM: %s", tal_hex(tmpctx, msg));
|
|
|
|
hsmfd = fdpass_recv(ld->hsm_fd);
|
|
if (hsmfd < 0)
|
|
fatal("Could not read fd from HSM: %s", strerror(errno));
|
|
|
|
channel_set_owner(channel,
|
|
new_channel_subd(ld,
|
|
"lightning_channeld", channel,
|
|
channel->log, true,
|
|
channel_wire_type_name,
|
|
channel_msg,
|
|
channel_errmsg,
|
|
channel_set_billboard,
|
|
take(&peer_fd),
|
|
take(&gossip_fd),
|
|
take(&hsmfd), NULL));
|
|
|
|
if (!channel->owner) {
|
|
log_unusual(channel->log, "Could not subdaemon channel: %s",
|
|
strerror(errno));
|
|
channel_fail_transient(channel, "Failed to subdaemon channel");
|
|
return true;
|
|
}
|
|
|
|
peer_htlcs(tmpctx, channel, &htlcs, &htlc_states, &fulfilled_htlcs,
|
|
&fulfilled_sides, &failed_htlcs, &failed_sides);
|
|
|
|
if (channel->scid) {
|
|
funding_channel_id = *channel->scid;
|
|
reached_announce_depth
|
|
= (short_channel_id_blocknum(&funding_channel_id)
|
|
+ ANNOUNCE_MIN_DEPTH <= get_block_height(ld->topology));
|
|
log_debug(channel->log, "Already have funding locked in%s",
|
|
reached_announce_depth
|
|
? " (and ready to announce)" : "");
|
|
} else {
|
|
log_debug(channel->log, "Waiting for funding confirmations");
|
|
memset(&funding_channel_id, 0, sizeof(funding_channel_id));
|
|
reached_announce_depth = false;
|
|
}
|
|
|
|
num_revocations = revocations_received(&channel->their_shachain.chain);
|
|
|
|
/* Warn once. */
|
|
if (ld->config.ignore_fee_limits)
|
|
log_debug(channel->log, "Ignoring fee limits!");
|
|
|
|
initmsg = towire_channel_init(tmpctx,
|
|
&get_chainparams(ld)->genesis_blockhash,
|
|
&channel->funding_txid,
|
|
channel->funding_outnum,
|
|
channel->funding_satoshi,
|
|
&channel->our_config,
|
|
&channel->channel_info.their_config,
|
|
channel->channel_info.feerate_per_kw,
|
|
feerate_min(ld),
|
|
feerate_max(ld),
|
|
&channel->last_sig,
|
|
cs,
|
|
&channel->channel_info.remote_fundingkey,
|
|
&channel->channel_info.theirbase.revocation,
|
|
&channel->channel_info.theirbase.payment,
|
|
&channel->channel_info.theirbase.htlc,
|
|
&channel->channel_info.theirbase.delayed_payment,
|
|
&channel->channel_info.remote_per_commit,
|
|
&channel->channel_info.old_remote_per_commit,
|
|
channel->funder,
|
|
cfg->fee_base,
|
|
cfg->fee_per_satoshi,
|
|
channel->our_msatoshi,
|
|
&channel->seed,
|
|
&ld->id,
|
|
&channel->peer->id,
|
|
time_to_msec(cfg->commit_time),
|
|
cfg->cltv_expiry_delta,
|
|
channel->last_was_revoke,
|
|
channel->last_sent_commit,
|
|
channel->next_index[LOCAL],
|
|
channel->next_index[REMOTE],
|
|
num_revocations,
|
|
channel->next_htlc_id,
|
|
htlcs, htlc_states,
|
|
fulfilled_htlcs, fulfilled_sides,
|
|
failed_htlcs, failed_sides,
|
|
channel->scid != NULL,
|
|
channel->remote_funding_locked,
|
|
&funding_channel_id,
|
|
reconnected,
|
|
channel->state == CHANNELD_SHUTTING_DOWN,
|
|
channel->remote_shutdown_scriptpubkey != NULL,
|
|
p2wpkh_for_keyidx(tmpctx, ld,
|
|
channel->final_key_idx),
|
|
channel->channel_flags,
|
|
funding_signed,
|
|
reached_announce_depth);
|
|
|
|
/* We don't expect a response: we are triggered by funding_depth_cb. */
|
|
subd_send_msg(channel->owner, take(initmsg));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool channel_tell_funding_locked(struct lightningd *ld,
|
|
struct channel *channel,
|
|
const struct bitcoin_txid *txid)
|
|
{
|
|
/* If not awaiting lockin, it doesn't care any more */
|
|
if (channel->state != CHANNELD_AWAITING_LOCKIN) {
|
|
log_debug(channel->log,
|
|
"Funding tx confirmed, but peer in state %s",
|
|
channel_state_name(channel));
|
|
return true;
|
|
}
|
|
|
|
if (!channel->owner) {
|
|
log_debug(channel->log,
|
|
"Funding tx confirmed, but peer disconnected");
|
|
return false;
|
|
}
|
|
|
|
subd_send_msg(channel->owner,
|
|
take(towire_channel_funding_locked(NULL, channel->scid)));
|
|
|
|
if (channel->remote_funding_locked)
|
|
lockin_complete(channel);
|
|
return true;
|
|
}
|