mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
f53387cc46
For me this happened only under valgrind with test_option_upfront_shutdown_script (in a pending branch): ==5063== by 0x51FC076: raise (raise.c:48) ==5063== by 0x51DD534: abort (abort.c:79) ==5063== by 0x1292D2: fatal (log.c:647) ==5063== by 0x116570: channel_set_state (channel.c:340) ==5063== by 0x116E04: lockin_complete (channel_control.c:73) ==5063== by 0x116F15: peer_got_funding_locked (channel_control.c:108) ==5063== by 0x117354: channel_msg (channel_control.c:208) No CHANGELOG: this was introduced in a recent refactor. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
525 lines
15 KiB
C
525 lines
15 KiB
C
#include <bitcoin/pubkey.h>
|
|
#include <bitcoin/script.h>
|
|
#include <channeld/gen_channel_wire.h>
|
|
#include <common/memleak.h>
|
|
#include <common/timeout.h>
|
|
#include <common/utils.h>
|
|
#include <common/wire_error.h>
|
|
#include <errno.h>
|
|
#include <gossipd/gossip_constants.h>
|
|
#include <hsmd/gen_hsm_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 update_feerates(struct lightningd *ld, struct channel *channel)
|
|
{
|
|
u8 *msg;
|
|
u32 feerate = unilateral_feerate(ld->topology);
|
|
|
|
/* Nothing to do if we don't know feerate. */
|
|
if (!feerate)
|
|
return;
|
|
|
|
msg = towire_channel_feerates(NULL, feerate,
|
|
feerate_min(ld, NULL),
|
|
feerate_max(ld, NULL));
|
|
subd_send_msg(channel->owner, take(msg));
|
|
}
|
|
|
|
static void try_update_feerates(struct lightningd *ld, struct channel *channel)
|
|
{
|
|
/* No point until funding locked in */
|
|
if (!channel_fees_can_change(channel))
|
|
return;
|
|
|
|
/* Can't if no daemon listening. */
|
|
if (!channel->owner)
|
|
return;
|
|
|
|
update_feerates(ld, channel);
|
|
}
|
|
|
|
void notify_feerate_change(struct lightningd *ld)
|
|
{
|
|
struct peer *peer;
|
|
|
|
/* FIXME: We should notify onchaind about NORMAL fee change in case
|
|
* it's going to generate more txs. */
|
|
list_for_each(&ld->peers, peer, list) {
|
|
struct channel *channel = peer_active_channel(peer);
|
|
|
|
if (!channel)
|
|
continue;
|
|
|
|
/* FIXME: We choose not to drop to chain if we can't contact
|
|
* peer. We *could* do so, however. */
|
|
try_update_feerates(ld, channel);
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
/* We might have already started shutting down */
|
|
if (channel->state != CHANNELD_AWAITING_LOCKIN) {
|
|
log_debug(channel->log, "Lockin complete, but state %s",
|
|
channel_state_name(channel));
|
|
return;
|
|
}
|
|
|
|
channel_set_state(channel, CHANNELD_AWAITING_LOCKIN, CHANNELD_NORMAL);
|
|
|
|
/* Fees might have changed (and we use IMMEDIATE once we're funded),
|
|
* so update now. */
|
|
try_update_feerates(channel->peer->ld, channel);
|
|
}
|
|
|
|
/* 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:
|
|
*
|
|
* 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:
|
|
*...
|
|
* - if the `scriptpubkey` is not in one of the above forms:
|
|
* - SHOULD fail the connection.
|
|
*/
|
|
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 channel_fail_fallen_behind(struct channel *channel, const u8 *msg)
|
|
{
|
|
struct pubkey per_commitment_point;
|
|
|
|
if (!fromwire_channel_fail_fallen_behind(msg, &per_commitment_point)) {
|
|
channel_internal_error(channel,
|
|
"bad channel_fail_fallen_behind %s",
|
|
tal_hex(tmpctx, msg));
|
|
return;
|
|
}
|
|
|
|
channel->future_per_commitment_point
|
|
= tal_dup(channel, struct pubkey, &per_commitment_point);
|
|
|
|
/* Peer sees this, so send a generic msg about unilateral close. */
|
|
channel_fail_permanent(channel, "Awaiting unilateral close");
|
|
}
|
|
|
|
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;
|
|
case WIRE_CHANNEL_FAIL_FALLEN_BEHIND:
|
|
channel_fail_fallen_behind(sd->channel, msg);
|
|
break;
|
|
|
|
/* And we never get these from channeld. */
|
|
case WIRE_CHANNEL_INIT:
|
|
case WIRE_CHANNEL_FUNDING_DEPTH:
|
|
case WIRE_CHANNEL_OFFER_HTLC:
|
|
case WIRE_CHANNEL_FULFILL_HTLC:
|
|
case WIRE_CHANNEL_FAIL_HTLC:
|
|
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:
|
|
case WIRE_CHANNEL_SPECIFIC_FEERATES:
|
|
case WIRE_CHANNEL_DEV_MEMLEAK:
|
|
/* Replies go to requests. */
|
|
case WIRE_CHANNEL_OFFER_HTLC_REPLY:
|
|
case WIRE_CHANNEL_DEV_REENABLE_COMMIT_REPLY:
|
|
case WIRE_CHANNEL_DEV_MEMLEAK_REPLY:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void peer_start_channeld(struct channel *channel,
|
|
const struct crypto_state *cs,
|
|
int peer_fd, int gossip_fd,
|
|
const u8 *funding_signed,
|
|
bool reconnected)
|
|
{
|
|
u8 *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;
|
|
struct secret last_remote_per_commit_secret;
|
|
|
|
hsmfd = hsm_get_client_fd(ld, &channel->peer->id,
|
|
channel->dbid,
|
|
HSM_CAP_SIGN_GOSSIP
|
|
| HSM_CAP_ECDH
|
|
| HSM_CAP_COMMITMENT_POINT
|
|
| HSM_CAP_SIGN_REMOTE_TX);
|
|
|
|
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),
|
|
false);
|
|
|
|
if (!channel->owner) {
|
|
log_unusual(channel->log, "Could not subdaemon channel: %s",
|
|
strerror(errno));
|
|
channel_fail_transient(channel, "Failed to subdaemon channel");
|
|
return;
|
|
}
|
|
|
|
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);
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* - if it supports `option_data_loss_protect`:
|
|
* - if `next_remote_revocation_number` equals 0:
|
|
* - MUST set `your_last_per_commitment_secret` to all zeroes
|
|
* - otherwise:
|
|
* - MUST set `your_last_per_commitment_secret` to the last
|
|
* `per_commitment_secret` it received
|
|
*/
|
|
if (num_revocations == 0)
|
|
memset(&last_remote_per_commit_secret, 0,
|
|
sizeof(last_remote_per_commit_secret));
|
|
else if (!shachain_get_secret(&channel->their_shachain.chain,
|
|
num_revocations-1,
|
|
&last_remote_per_commit_secret)) {
|
|
channel_fail_permanent(channel,
|
|
"Could not get revocation secret %"PRIu64,
|
|
num_revocations-1);
|
|
return;
|
|
}
|
|
|
|
/* 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,
|
|
channel->minimum_depth,
|
|
&channel->our_config,
|
|
&channel->channel_info.their_config,
|
|
channel->channel_info.feerate_per_kw,
|
|
feerate_min(ld, NULL),
|
|
feerate_max(ld, NULL),
|
|
&channel->last_sig,
|
|
cs,
|
|
&channel->channel_info.remote_fundingkey,
|
|
&channel->channel_info.theirbase,
|
|
&channel->channel_info.remote_per_commit,
|
|
&channel->channel_info.old_remote_per_commit,
|
|
channel->funder,
|
|
channel->feerate_base,
|
|
channel->feerate_ppm,
|
|
channel->our_msat,
|
|
&channel->local_basepoints,
|
|
&channel->local_funding_pubkey,
|
|
&ld->id,
|
|
&channel->peer->id,
|
|
cfg->commit_time_ms,
|
|
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,
|
|
&last_remote_per_commit_secret,
|
|
channel->peer->localfeatures);
|
|
|
|
/* We don't expect a response: we are triggered by funding_depth_cb. */
|
|
subd_send_msg(channel->owner, take(initmsg));
|
|
|
|
/* On restart, feerate might not be what we expect: adjust now. */
|
|
if (channel->funder == LOCAL)
|
|
try_update_feerates(ld, channel);
|
|
}
|
|
|
|
bool channel_tell_depth(struct lightningd *ld,
|
|
struct channel *channel,
|
|
const struct bitcoin_txid *txid,
|
|
u32 depth)
|
|
{
|
|
const char *txidstr;
|
|
|
|
txidstr = type_to_string(tmpctx, struct bitcoin_txid, txid);
|
|
|
|
/* If not awaiting lockin/announce, it doesn't care any more */
|
|
if (channel->state != CHANNELD_AWAITING_LOCKIN
|
|
&& channel->state != CHANNELD_NORMAL) {
|
|
log_debug(channel->log,
|
|
"Funding tx %s confirmed, but peer in state %s",
|
|
txidstr, channel_state_name(channel));
|
|
return true;
|
|
}
|
|
|
|
if (!channel->owner) {
|
|
log_debug(channel->log,
|
|
"Funding tx %s confirmed, but peer disconnected",
|
|
txidstr);
|
|
return false;
|
|
}
|
|
|
|
subd_send_msg(channel->owner,
|
|
take(towire_channel_funding_depth(NULL, channel->scid,
|
|
depth)));
|
|
|
|
if (channel->remote_funding_locked
|
|
&& channel->state == CHANNELD_AWAITING_LOCKIN
|
|
&& depth >= channel->minimum_depth)
|
|
lockin_complete(channel);
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Check if we are the fundee of this channel, the channel
|
|
* funding transaction is still not yet seen onchain, and
|
|
* it has been too long since the channel was first opened.
|
|
* If so, we should forget the channel. */
|
|
static bool
|
|
is_fundee_should_forget(struct lightningd *ld,
|
|
struct channel *channel,
|
|
u32 block_height)
|
|
{
|
|
u32 max_funding_unconfirmed = ld->max_funding_unconfirmed;
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* A non-funding node (fundee):
|
|
* - SHOULD forget the channel if it does not see the
|
|
* funding transaction after a reasonable timeout.
|
|
*/
|
|
|
|
/* Only applies if we are fundee. */
|
|
if (channel->funder == LOCAL)
|
|
return false;
|
|
|
|
/* Does not apply if we already saw the funding tx. */
|
|
if (channel->scid)
|
|
return false;
|
|
|
|
/* Not even reached previous starting blocknum.
|
|
* (e.g. if --rescan option is used) */
|
|
if (block_height < channel->first_blocknum)
|
|
return false;
|
|
|
|
/* Timeout in blocks not yet reached. */
|
|
if (block_height - channel->first_blocknum < max_funding_unconfirmed)
|
|
return false;
|
|
|
|
/* Ah forget it! */
|
|
return true;
|
|
}
|
|
|
|
/* Notify all channels of new blocks. */
|
|
void channel_notify_new_block(struct lightningd *ld,
|
|
u32 block_height)
|
|
{
|
|
struct peer *peer;
|
|
struct channel *channel;
|
|
struct channel **to_forget = tal_arr(NULL, struct channel *, 0);
|
|
size_t i;
|
|
|
|
list_for_each (&ld->peers, peer, list) {
|
|
list_for_each (&peer->channels, channel, list)
|
|
if (is_fundee_should_forget(ld, channel, block_height)) {
|
|
tal_arr_expand(&to_forget, channel);
|
|
}
|
|
}
|
|
|
|
/* Need to forget in a separate loop, else the above
|
|
* nested loops may crash due to the last channel of
|
|
* a peer also deleting the peer, making the inner
|
|
* loop crash.
|
|
* list_for_each_safe does not work because it is not
|
|
* just the freeing of the channel that occurs, but the
|
|
* potential destruction of the peer that invalidates
|
|
* memory the inner loop is accessing. */
|
|
for (i = 0; i < tal_count(to_forget); ++i) {
|
|
channel = to_forget[i];
|
|
/* Report it first. */
|
|
log_unusual(channel->log,
|
|
"Forgetting channel: "
|
|
"It has been %"PRIu32" blocks without the "
|
|
"funding transaction %s getting deeply "
|
|
"confirmed. "
|
|
"We are fundee and can forget channel without "
|
|
"loss of funds.",
|
|
block_height - channel->first_blocknum,
|
|
type_to_string(tmpctx, struct bitcoin_txid,
|
|
&channel->funding_txid));
|
|
/* FIXME: Send an error packet for this case! */
|
|
/* And forget it. */
|
|
delete_channel(channel);
|
|
}
|
|
|
|
tal_free(to_forget);
|
|
}
|