From 32411de90e1f35c8dc6289b3ca89df105dea9613 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 12 Feb 2018 20:42:55 +1030 Subject: [PATCH] lightningd: split struct peer into struct peer and struct channel. Much like the database; peer contains id, address, channel contains per-channel information. Where we create a channel, we always create the peer too. For the moment, peer->log and channel->log coexist side-by-side, to reduce some of the churn. Note that this changes the API to dev-forget-channel: if we have more than one channel, we insist they specify the short-channel-id. Signed-off-by: Rusty Russell --- lightningd/Makefile | 1 + lightningd/dev_ping.c | 14 +- lightningd/lightningd.c | 33 +- lightningd/lightningd.h | 17 - lightningd/peer_control.c | 807 +++++++++++++++-------------- lightningd/peer_control.h | 137 +---- lightningd/peer_htlcs.c | 157 +++--- lightningd/peer_state.h | 1 + lightningd/subd.c | 4 +- lightningd/test/run-find_my_path.c | 8 +- tests/test_lightningd.py | 2 +- wallet/test/run-wallet.c | 655 ++++++++++++++++++++--- wallet/wallet.c | 317 +++++------ wallet/wallet.h | 28 +- wallet/walletrpc.c | 35 +- 15 files changed, 1294 insertions(+), 922 deletions(-) diff --git a/lightningd/Makefile b/lightningd/Makefile index 6c6bb4bf3..42846bce7 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -49,6 +49,7 @@ LIGHTNINGD_SRC := \ lightningd/bitcoind.c \ lightningd/build_utxos.c \ lightningd/chaintopology.c \ + lightningd/channel.c \ lightningd/gossip_control.c \ lightningd/gossip_msg.c \ lightningd/hsm_control.c \ diff --git a/lightningd/dev_ping.c b/lightningd/dev_ping.c index e3a20d8d0..7fdb5d8e0 100644 --- a/lightningd/dev_ping.c +++ b/lightningd/dev_ping.c @@ -79,15 +79,19 @@ static void json_dev_ping(struct command *cmd, /* First, see if it's in channeld. */ peer = peer_by_id(cmd->ld, &id); if (peer) { - if (!peer->owner || - !streq(peer->owner->name, "lightning_channeld")) { + struct channel *channel = peer_active_channel(peer); + + if (!channel + || !channel->owner + || !streq(channel->owner->name, "lightning_channeld")) { command_fail(cmd, "Peer in %s", - peer->owner - ? peer->owner->name : "unattached"); + channel && channel->owner + ? channel->owner->name + : "unattached"); return; } msg = towire_channel_ping(cmd, pongbytes, len); - owner = peer->owner; + owner = channel->owner; } else { /* We assume it's in gossipd. */ msg = towire_gossip_ping(cmd, &id, pongbytes, len); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 1a84d961e..69644a731 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -188,20 +188,6 @@ static const char *find_daemon_dir(const tal_t *ctx, const char *argv0) return find_my_pkglibexec_path(ctx, take(my_path)); } -void derive_peer_seed(struct lightningd *ld, struct privkey *peer_seed, - const struct pubkey *peer_id, const u64 channel_id) -{ - u8 input[PUBKEY_DER_LEN + sizeof(channel_id)]; - char *info = "per-peer seed"; - pubkey_to_der(input, peer_id); - memcpy(input + PUBKEY_DER_LEN, &channel_id, sizeof(channel_id)); - - hkdf_sha256(peer_seed, sizeof(*peer_seed), - input, sizeof(input), - &ld->peer_seed, sizeof(ld->peer_seed), - info, strlen(info)); -} - static void shutdown_subdaemons(struct lightningd *ld) { struct peer *p; @@ -306,18 +292,21 @@ int main(int argc, char *argv[]) gossip_init(ld); /* Load peers from database */ - wallet_channels_load_active(ld, ld->wallet, &ld->peers); + if (!wallet_channels_load_active(ld, ld->wallet)) + fatal("Could not load channels from the database"); /* TODO(cdecker) Move this into common location for initialization */ struct peer *peer; list_for_each(&ld->peers, peer, list) { - populate_peer(ld, peer); - peer->seed = tal(peer, struct privkey); - derive_peer_seed(ld, peer->seed, &peer->id, peer->channel->id); - peer->owner = NULL; - if (!wallet_htlcs_load_for_channel(ld->wallet, peer->channel, - &ld->htlcs_in, &ld->htlcs_out)) { - fatal("could not load htlcs for channel"); + struct channel *channel; + + list_for_each(&peer->channels, channel, list) { + if (!wallet_htlcs_load_for_channel(ld->wallet, + channel, + &ld->htlcs_in, + &ld->htlcs_out)) { + fatal("could not load htlcs for channel"); + } } } if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out)) diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index d6d7d5275..e5cce9cb5 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -162,23 +162,6 @@ struct lightningd { #endif /* DEVELOPER */ }; -/** - * derive_peer_seed - Generate a unique secret for this peer's channel - * - * @ld: the lightning daemon to get global secret from - * @peer_seed: where to store the generated secret - * @peer_id: the id node_id of the remote peer - * @chan_id: channel ID - * - * This method generates a unique secret from the given parameters. It - * is important that this secret be unique for each channel, but it - * must be reproducible for the same channel in case of - * reconnection. We use the DB channel ID to guarantee unique secrets - * per channel. - */ -void derive_peer_seed(struct lightningd *ld, struct privkey *peer_seed, - const struct pubkey *peer_id, const u64 channel_id); - struct chainparams *get_chainparams(const struct lightningd *ld); /* State for performing backtraces. */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 387195b05..7736bd03e 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -55,6 +55,13 @@ struct connect { /* FIXME: Reorder */ struct funding_channel; +static void copy_to_parent_log(const char *prefix, + enum log_level level, + bool continued, + const struct timeabs *time, + const char *str, + const u8 *io, + struct peer *peer); static void peer_offer_channel(struct lightningd *ld, struct funding_channel *fc, const struct wireaddr *addr, @@ -84,8 +91,9 @@ static void peer_accept_channel(struct lightningd *ld, static void peer_set_owner(struct peer *peer, struct subd *owner) { - struct subd *old_owner = peer->owner; - peer->owner = owner; + struct channel *channel = peer2channel(peer); + struct subd *old_owner = channel->owner; + channel->owner = owner; if (old_owner) subd_release_peer(old_owner, peer); @@ -105,7 +113,7 @@ static void destroy_peer(struct peer *peer) if (hout->key.peer != peer) continue; fatal("Freeing peer %s has hout %s", - peer_state_name(peer->state), + channel_state_name(peer2channel(peer)), htlc_state_name(hout->hstate)); } @@ -115,7 +123,7 @@ static void destroy_peer(struct peer *peer) if (hin->key.peer != peer) continue; fatal("Freeing peer %s has hin %s", - peer_state_name(peer->state), + channel_state_name(peer2channel(peer)), htlc_state_name(hin->hstate)); } @@ -124,6 +132,45 @@ static void destroy_peer(struct peer *peer) list_del_from(&peer->ld->peers, &peer->list); } +struct peer *new_peer(struct lightningd *ld, u64 dbid, + const struct pubkey *id, + const struct wireaddr *addr) +{ + struct peer *peer = tal(ld, struct peer); + const char *idname; + + peer->ld = ld; + peer->dbid = dbid; + peer->id = *id; + if (addr) + peer->addr = *addr; + else + peer->addr.type = ADDR_TYPE_PADDING; + list_head_init(&peer->channels); + peer->direction = get_channel_direction(&peer->ld->id, &peer->id); + + /* Max 128k per peer. */ + peer->log_book = new_log_book(peer, 128*1024, + get_log_level(ld->log_book)); + idname = type_to_string(peer, struct pubkey, id); + peer->log = new_log(peer, peer->log_book, "peer %s:", idname); + tal_free(idname); + set_log_outfn(peer->log_book, copy_to_parent_log, peer); + list_add_tail(&ld->peers, &peer->list); + tal_add_destructor(peer, destroy_peer); + return peer; +} + +struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid) +{ + struct peer *p; + + list_for_each(&ld->peers, p, list) + if (p->dbid == dbid) + return p; + return NULL; +} + static void sign_last_tx(struct peer *peer) { const tal_t *tmpctx = tal_tmpctx(peer); @@ -131,28 +178,29 @@ static void sign_last_tx(struct peer *peer) struct pubkey local_funding_pubkey; struct secrets secrets; secp256k1_ecdsa_signature sig; + struct channel *channel = peer2channel(peer); - assert(!peer->last_tx->input[0].witness); + assert(!channel->last_tx->input[0].witness); - derive_basepoints(peer->seed, &local_funding_pubkey, NULL, &secrets, + derive_basepoints(&channel->seed, &local_funding_pubkey, NULL, &secrets, NULL); funding_wscript = bitcoin_redeem_2of2(tmpctx, &local_funding_pubkey, - &peer->channel_info->remote_fundingkey); + &channel->channel_info->remote_fundingkey); /* Need input amount for signing */ - peer->last_tx->input[0].amount = tal_dup(peer->last_tx->input, u64, - &peer->funding_satoshi); - sign_tx_input(peer->last_tx, 0, NULL, funding_wscript, + channel->last_tx->input[0].amount = tal_dup(channel->last_tx->input, u64, + &channel->funding_satoshi); + sign_tx_input(channel->last_tx, 0, NULL, funding_wscript, &secrets.funding_privkey, &local_funding_pubkey, &sig); - peer->last_tx->input[0].witness - = bitcoin_witness_2of2(peer->last_tx->input, - peer->last_sig, + channel->last_tx->input[0].witness + = bitcoin_witness_2of2(channel->last_tx->input, + channel->last_sig, &sig, - &peer->channel_info->remote_fundingkey, + &channel->channel_info->remote_fundingkey, &local_funding_pubkey); tal_free(tmpctx); @@ -170,18 +218,18 @@ static void drop_to_chain(struct peer *peer) /* Keep broadcasting until we say stop (can fail due to dup, * if they beat us to the broadcast). */ - broadcast_tx(peer->ld->topology, peer, peer->last_tx, NULL); - remove_sig(peer->last_tx); + broadcast_tx(peer->ld->topology, peer, peer2channel(peer)->last_tx, NULL); + remove_sig(peer2channel(peer)->last_tx); } /* This lets us give a more detailed error than just a destructor. */ static void free_peer(struct peer *peer, const char *why) { - if (peer->opening_cmd) { - command_fail(peer->opening_cmd, "%s", why); - peer->opening_cmd = NULL; + if (peer2channel(peer)->opening_cmd) { + command_fail(peer2channel(peer)->opening_cmd, "%s", why); + peer2channel(peer)->opening_cmd = NULL; } - wallet_channel_delete(peer->ld->wallet, peer->channel->id, peer->dbid); + wallet_channel_delete(peer->ld->wallet, peer2channel(peer)->dbid, peer->dbid); tal_free(peer); } @@ -190,21 +238,24 @@ void peer_fail_permanent(struct peer *peer, const char *fmt, ...) va_list ap; char *why; u8 *msg; + struct channel *channel = peer2channel(peer); va_start(ap, fmt); why = tal_vfmt(peer, fmt, ap); va_end(ap); - if (peer->scid) { - msg = towire_gossip_disable_channel(peer, peer->scid, peer->direction, false); + if (channel->scid) { + msg = towire_gossip_disable_channel(peer, + channel->scid, + peer->direction, false); subd_send_msg(peer->ld->gossip, take(msg)); } log_unusual(peer->log, "Peer permanent failure in %s: %s", - peer_state_name(peer->state), why); + peer_state_name(channel->state), why); /* We can have multiple errors, eg. onchaind failures. */ - if (!peer->error) { + if (!channel->error) { /* BOLT #1: * * The channel is referred to by `channel_id` unless `channel_id` is @@ -212,7 +263,7 @@ void peer_fail_permanent(struct peer *peer, const char *fmt, ...) * channels. */ static const struct channel_id all_channels; u8 *msg = tal_dup_arr(peer, u8, (const u8 *)why, strlen(why), 0); - peer->error = towire_error(peer, &all_channels, msg); + channel->error = towire_error(peer, &all_channels, msg); tal_free(msg); } @@ -230,7 +281,7 @@ void peer_internal_error(struct peer *peer, const char *fmt, ...) va_start(ap, fmt); log_broken(peer->log, "Peer internal error %s: ", - peer_state_name(peer->state)); + channel_state_name(peer2channel(peer))); logv_add(peer->log, fmt, ap); va_end(ap); @@ -246,7 +297,7 @@ void peer_fail_transient(struct peer *peer, const char *fmt, ...) why = tal_vfmt(peer, fmt, ap); va_end(ap); log_info(peer->log, "Peer transient failure in %s: %s", - peer_state_name(peer->state), why); + channel_state_name(peer2channel(peer)), why); #if DEVELOPER if (dev_disconnect_permanent(peer->ld)) { @@ -261,14 +312,14 @@ void peer_fail_transient(struct peer *peer, const char *fmt, ...) /* If we haven't reached awaiting locked, we don't need to reconnect */ if (!peer_persists(peer)) { log_info(peer->log, "Only reached state %s: forgetting", - peer_state_name(peer->state)); + channel_state_name(peer2channel(peer))); free_peer(peer, why); return; } tal_free(why); /* Reconnect unless we've dropped/are dropping to chain. */ - if (!peer_on_chain(peer) && peer->state != CLOSINGD_COMPLETE) { + if (!peer_on_chain(peer) && peer2channel(peer)->state != CLOSINGD_COMPLETE) { #if DEVELOPER /* Don't schedule an attempt if we disabled reconnections with * the `--dev-no-reconnect` flag */ @@ -283,19 +334,21 @@ void peer_fail_transient(struct peer *peer, const char *fmt, ...) void peer_set_condition(struct peer *peer, enum peer_state old_state, enum peer_state state) { + struct channel *channel = peer2channel(peer); + log_info(peer->log, "State changed from %s to %s", - peer_state_name(peer->state), peer_state_name(state)); - if (peer->state != old_state) + channel_state_name(channel), peer_state_name(state)); + if (channel->state != old_state) fatal("peer state %s should be %s", - peer_state_name(peer->state), peer_state_name(old_state)); + channel_state_name(channel), peer_state_name(old_state)); - peer->state = state; + channel->state = state; /* We only persist channels/peers that have reached the opening state */ if (peer_persists(peer)) { - assert(peer->channel != NULL); + assert(channel != NULL); /* TODO(cdecker) Selectively save updated fields to DB */ - wallet_channel_save(peer->ld->wallet, peer->channel); + wallet_channel_save(peer->ld->wallet, channel); } } @@ -347,82 +400,6 @@ static void connect_failed(struct lightningd *ld, const struct pubkey *id, } } -static struct peer *new_peer(struct lightningd *ld, - const struct pubkey *id, - const struct wireaddr *addr, - const u8 *gfeatures, const u8 *lfeatures, - int peer_fd) -{ - struct peer *peer; - - /* Need to memset since storing will access all fields */ - peer = talz(ld, struct peer); - peer->error = NULL; - peer->id = *id; - peer->addr = *addr; - peer->funding_txid = NULL; - peer->remote_funding_locked = false; - peer->scid = NULL; - peer->seed = NULL; - peer->our_msatoshi = NULL; - peer->state = UNINITIALIZED; - peer->opening_cmd = NULL; - peer->channel_info = NULL; - peer->last_tx = NULL; - peer->last_sig = NULL; - peer->last_htlc_sigs = NULL; - peer->last_was_revoke = false; - peer->last_sent_commit = NULL; - peer->remote_shutdown_scriptpubkey = NULL; - peer->local_shutdown_idx = -1; - peer->next_index[LOCAL] - = peer->next_index[REMOTE] = 0; - peer->next_htlc_id = 0; - wallet_shachain_init(ld->wallet, &peer->their_shachain); - - /* FIXME: db should be keyed by (peer_id, channel_id) */ - - /* If we have the peer in the DB, this'll populate the fields, - * failure just indicates that the peer wasn't found in the - * DB */ - wallet_peer_by_nodeid(ld->wallet, id, peer); - - /* peer->channel gets populated as soon as we start opening a channel */ - peer->channel = NULL; - - list_add_tail(&ld->peers, &peer->list); - populate_peer(ld, peer); - - return peer; -} - -/** - * peer_channel_new -- Instantiate a new channel for the given peer and save it - * - * We are about to open a channel with the peer, either due to a - * nongossip message from remote, or because we initiated an - * open. This creates the `struct wallet_channel` for the peer and - * stores it in the database. - * - * @w: the wallet to store the information in - * @peer: the peer we are opening a channel to - * - * This currently overwrites peer->channel, so can only be used if we - * allow a single channel per peer. - */ -static struct wallet_channel *peer_channel_new(struct wallet *w, - struct peer *peer) -{ - struct wallet_channel *wc = tal(peer, struct wallet_channel); - wc->peer = peer; - - wallet_peer_by_nodeid(w, &peer->id, peer); - wc->id = 0; - wc->first_blocknum = get_block_height(peer->ld->topology); - wallet_channel_save(w, wc); - return wc; -} - static void channel_config(struct lightningd *ld, struct channel_config *ours, u32 *max_to_self_delay, @@ -508,24 +485,26 @@ void peer_connected(struct lightningd *ld, const u8 *msg, /* Now, do we already know this peer? */ peer = peer_by_id(ld, &id); if (peer) { + struct channel *channel = peer2channel(peer); + log_debug(peer->log, "Peer has reconnected, state %s", - peer_state_name(peer->state)); + channel_state_name(channel)); /* FIXME: We can have errors for multiple channels. */ - if (peer->error) { - error = peer->error; + if (channel->error) { + error = channel->error; goto send_error; } #if DEVELOPER if (dev_disconnect_permanent(ld)) { peer_internal_error(peer, "dev_disconnect permfail"); - error = peer->error; + error = channel->error; goto send_error; } #endif - switch (peer->state) { + switch (channel->state) { /* This can't happen. */ case UNINITIALIZED: abort(); @@ -667,7 +646,7 @@ void peer_sent_nongossip(struct lightningd *ld, error = towire_errorfmt(ld, channel_id, "Unexpected message %i in state %s", fromwire_peektype(in_msg), - peer_state_name(peer->state)); + channel_state_name(peer2channel(peer))); goto send_error; } @@ -711,23 +690,6 @@ static void copy_to_parent_log(const char *prefix, log_(peer->ld->log, level, "%s %s", prefix, str); } -void populate_peer(struct lightningd *ld, struct peer *peer) -{ - const char *idname; - struct pubkey *id = &peer->id; - idname = type_to_string(peer, struct pubkey, id); - - peer->ld = ld; - - /* Max 128k per peer. */ - peer->log_book = new_log_book(peer, 128*1024, - get_log_level(ld->log_book)); - peer->log = new_log(peer, peer->log_book, "peer %s:", idname); - set_log_outfn(peer->log_book, copy_to_parent_log, peer); - tal_free(idname); - tal_add_destructor(peer, destroy_peer); -} - struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id) { struct peer *p; @@ -837,13 +799,15 @@ static void gossipd_getpeers_complete(struct subd *gossip, const u8 *msg, json_array_start(response, "peers"); list_for_each(&gpa->cmd->ld->peers, p, list) { bool connected; + struct channel *channel; if (gpa->specific_id && !pubkey_eq(gpa->specific_id, &p->id)) continue; json_object_start(response, NULL); json_add_pubkey(response, "id", &p->id); - connected = (p->owner != NULL && !peer_state_on_chain(p->state)); + channel = peer_active_channel(p); + connected = (channel && channel->owner != NULL); json_add_bool(response, "connected", connected); if (connected) { @@ -856,35 +820,46 @@ static void gossipd_getpeers_complete(struct subd *gossip, const u8 *msg, json_array_end(response); } - /* FIXME: We only support one channel per peer, but API must - * support multiple already! */ json_array_start(response, "channels"); - json_object_start(response, NULL); - json_add_string(response, "state", peer_state_name(p->state)); - if (p->owner) - json_add_string(response, "owner", p->owner->name); - if (p->scid) - json_add_short_channel_id(response, - "short_channel_id", p->scid); - if (p->funding_txid) - json_add_txid(response, - "funding_txid", p->funding_txid); - if (p->our_msatoshi) { - json_add_u64(response, "msatoshi_to_us", - *p->our_msatoshi); - json_add_u64(response, "msatoshi_total", - p->funding_satoshi * 1000); - } - - /* channel config */ - json_add_u64(response, "dust_limit_satoshis", p->our_config.dust_limit_satoshis); - json_add_u64(response, "max_htlc_value_in_flight_msat", p->our_config.max_htlc_value_in_flight_msat); - json_add_u64(response, "channel_reserve_satoshis", p->our_config.channel_reserve_satoshis); - json_add_u64(response, "htlc_minimum_msat", p->our_config.htlc_minimum_msat); - json_add_num(response, "to_self_delay", p->our_config.to_self_delay); - json_add_num(response, "max_accepted_htlcs", p->our_config.max_accepted_htlcs); + connected = false; + list_for_each(&p->channels, channel, list) { + json_object_start(response, NULL); + json_add_string(response, "state", + channel_state_name(channel)); + if (channel->owner) + json_add_string(response, "owner", + channel->owner->name); + if (channel->scid) + json_add_short_channel_id(response, + "short_channel_id", + channel->scid); + if (channel->funding_txid) + json_add_txid(response, + "funding_txid", + channel->funding_txid); + if (channel->our_msatoshi) { + json_add_u64(response, "msatoshi_to_us", + *channel->our_msatoshi); + json_add_u64(response, "msatoshi_total", + channel->funding_satoshi * 1000); + } - json_object_end(response); + /* channel config */ + json_add_u64(response, "dust_limit_satoshis", + channel->our_config.dust_limit_satoshis); + json_add_u64(response, "max_htlc_value_in_flight_msat", + channel->our_config.max_htlc_value_in_flight_msat); + json_add_u64(response, "channel_reserve_satoshis", + channel->our_config.channel_reserve_satoshis); + json_add_u64(response, "htlc_minimum_msat", + channel->our_config.htlc_minimum_msat); + json_add_num(response, "to_self_delay", + channel->our_config.to_self_delay); + json_add_num(response, "max_accepted_htlcs", + channel->our_config.max_accepted_htlcs); + + json_object_end(response); + } json_array_end(response); if (gpa->ll) @@ -1006,20 +981,22 @@ static enum watch_result funding_announce_cb(struct peer *peer, unsigned int depth, void *unused) { + struct channel *channel = peer2channel(peer); + if (depth < ANNOUNCE_MIN_DEPTH) { return KEEP_WATCHING; } - if (!peer->owner || !streq(peer->owner->name, "lightning_channeld")) { + if (!channel->owner || !streq(channel->owner->name, "lightning_channeld")) { log_debug(peer->log, "Funding tx announce ready, but peer state %s" " owned by %s", - peer_state_name(peer->state), - peer->owner ? peer->owner->name : "none"); + channel_state_name(channel), + channel->owner ? channel->owner->name : "none"); return KEEP_WATCHING; } - subd_send_msg(peer->owner, + subd_send_msg(channel->owner, take(towire_channel_funding_announce_depth(peer))); return DELETE_WATCH; } @@ -1031,6 +1008,7 @@ static void onchaind_tell_fulfill(struct peer *peer) struct htlc_in_map_iter ini; struct htlc_in *hin; u8 *msg; + struct channel *channel = peer2channel(peer); for (hin = htlc_in_map_first(&peer->ld->htlcs_in, &ini); hin; @@ -1055,7 +1033,7 @@ static void onchaind_tell_fulfill(struct peer *peer) continue; msg = towire_onchain_known_preimage(peer, hin->preimage); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(channel->owner, take(msg)); } } @@ -1068,7 +1046,7 @@ static void handle_onchain_init_reply(struct peer *peer, const u8 *msg) return; } - if (!peer_state_on_chain(state)) { + if (!channel_state_on_chain(state)) { peer_internal_error(peer, "Invalid onchain_init_reply state %u (%s)", state, peer_state_name(state)); @@ -1103,7 +1081,7 @@ static enum watch_result onchain_tx_watched(struct peer *peer, bitcoin_txid(tx, &txid); msg = towire_onchain_depth(peer, &txid, depth); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(peer2channel(peer)->owner, take(msg)); return KEEP_WATCHING; } @@ -1121,7 +1099,7 @@ static enum watch_result onchain_txo_watched(struct peer *peer, watch_tx_and_outputs(peer, tx); msg = towire_onchain_spent(peer, tx, input_num, block->height); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(peer2channel(peer)->owner, take(msg)); /* We don't need to keep watching: If this output is double-spent * (reorg), we'll get a zero depth cb to onchain_tx_watched, and @@ -1135,11 +1113,12 @@ static void watch_tx_and_outputs(struct peer *peer, { struct bitcoin_txid txid; struct txwatch *txw; + struct channel *channel = peer2channel(peer); bitcoin_txid(tx, &txid); /* Make txwatch a parent of txo watches, so we can unwatch together. */ - txw = watch_tx(peer->owner, peer->ld->topology, peer, tx, + txw = watch_tx(channel->owner, peer->ld->topology, peer, tx, onchain_tx_watched, NULL); for (size_t i = 0; i < tal_count(tx->output); i++) @@ -1285,7 +1264,7 @@ static void onchain_add_utxo(struct peer *peer, const u8 *msg) u->is_p2sh = true; u->keyindex = 0; u->status = output_state_available; - u->close_info->channel_id = peer->channel->id; + u->close_info->channel_id = peer2channel(peer)->dbid; u->close_info->peer_id = peer->id; if (!fromwire_onchain_add_utxo(msg, NULL, &u->txid, &u->outnum, @@ -1402,11 +1381,12 @@ static enum watch_result funding_spent(struct peer *peer, struct pubkey ourkey; struct htlc_stub *stubs; const tal_t *tmpctx = tal_tmpctx(peer); + struct channel *channel = peer2channel(peer); peer_fail_permanent(peer, "Funding transaction spent"); /* We could come from almost any state. */ - peer_set_condition(peer, peer->state, FUNDING_SPEND_SEEN); + peer_set_condition(peer, channel->state, FUNDING_SPEND_SEEN); peer_set_owner(peer, new_peer_subd(peer->ld, "lightning_onchaind", peer, @@ -1414,14 +1394,14 @@ static enum watch_result funding_spent(struct peer *peer, onchain_msg, NULL)); - if (!peer->owner) { + if (!channel->owner) { log_broken(peer->log, "Could not subdaemon onchain: %s", strerror(errno)); tal_free(tmpctx); return KEEP_WATCHING; } - stubs = wallet_htlc_stubs(tmpctx, peer->ld->wallet, peer->channel); + stubs = wallet_htlc_stubs(tmpctx, peer->ld->wallet, channel); if (!stubs) { log_broken(peer->log, "Could not load htlc_stubs"); tal_free(tmpctx); @@ -1429,8 +1409,8 @@ static enum watch_result funding_spent(struct peer *peer, } /* We re-use this key to send other outputs to. */ - if (peer->local_shutdown_idx >= 0) - keyindex = peer->local_shutdown_idx; + if (channel->local_shutdown_idx >= 0) + keyindex = channel->local_shutdown_idx; else { keyindex = wallet_get_newindex(peer->ld); if (keyindex < 0) { @@ -1458,39 +1438,40 @@ static enum watch_result funding_spent(struct peer *peer, } /* This could be a mutual close, but it doesn't matter. */ - bitcoin_txid(peer->last_tx, &our_last_txid); + bitcoin_txid(channel->last_tx, &our_last_txid); - msg = towire_onchain_init(peer, peer->seed, &peer->their_shachain.chain, - peer->funding_satoshi, - &peer->channel_info->old_remote_per_commit, - &peer->channel_info->remote_per_commit, + msg = towire_onchain_init(peer, + &channel->seed, &channel->their_shachain.chain, + channel->funding_satoshi, + &channel->channel_info->old_remote_per_commit, + &channel->channel_info->remote_per_commit, /* BOLT #2: * `to_self_delay` is the number of blocks * that the other nodes to-self outputs * must be delayed */ /* So, these are reversed: they specify ours, * we specify theirs. */ - peer->channel_info->their_config.to_self_delay, - peer->our_config.to_self_delay, + channel->channel_info->their_config.to_self_delay, + channel->our_config.to_self_delay, get_feerate(peer->ld->topology, FEERATE_NORMAL), - peer->our_config.dust_limit_satoshis, - &peer->channel_info->theirbase.revocation, + channel->our_config.dust_limit_satoshis, + &channel->channel_info->theirbase.revocation, &our_last_txid, scriptpubkey, - peer->remote_shutdown_scriptpubkey, + channel->remote_shutdown_scriptpubkey, &ourkey, - peer->funder, - &peer->channel_info->theirbase.payment, - &peer->channel_info->theirbase.htlc, - &peer->channel_info->theirbase.delayed_payment, + channel->funder, + &channel->channel_info->theirbase.payment, + &channel->channel_info->theirbase.htlc, + &channel->channel_info->theirbase.delayed_payment, tx, block->height, /* FIXME: config for 'reasonable depth' */ 3, - peer->last_htlc_sigs, + channel->last_htlc_sigs, tal_count(stubs)); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(channel->owner, take(msg)); /* FIXME: Don't queue all at once, use an empty cb... */ for (size_t i = 0; i < tal_count(stubs); i++) { @@ -1498,7 +1479,7 @@ static enum watch_result funding_spent(struct peer *peer, bool tell = tell_if_missing(peer, &stubs[i], &tell_immediate); msg = towire_onchain_htlc(peer, &stubs[i], tell, tell_immediate); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(channel->owner, take(msg)); } watch_tx_and_outputs(peer, tx); @@ -1516,40 +1497,41 @@ static enum watch_result funding_lockin_cb(struct peer *peer, struct bitcoin_txid txid; const char *txidstr; struct txlocator *loc; - bool peer_ready; + bool channel_ready; + struct channel *channel = peer2channel(peer); bitcoin_txid(tx, &txid); txidstr = type_to_string(peer, struct bitcoin_txid, &txid); log_debug(peer->log, "Funding tx %s depth %u of %u", - txidstr, depth, peer->minimum_depth); + txidstr, depth, channel->minimum_depth); tal_free(txidstr); - if (depth < peer->minimum_depth) + if (depth < channel->minimum_depth) return KEEP_WATCHING; loc = locate_tx(peer, peer->ld->topology, &txid); /* If we restart, we could already have peer->scid from database */ - if (!peer->scid) { - peer->scid = tal(peer, struct short_channel_id); - peer->scid->blocknum = loc->blkheight; - peer->scid->txnum = loc->index; - peer->scid->outnum = peer->funding_outnum; + if (!channel->scid) { + channel->scid = tal(channel, struct short_channel_id); + channel->scid->blocknum = loc->blkheight; + channel->scid->txnum = loc->index; + channel->scid->outnum = channel->funding_outnum; } tal_free(loc); /* In theory, it could have been buried before we got back * from accepting openingd or disconnected: just wait for next one. */ - peer_ready = (peer->owner && peer->state == CHANNELD_AWAITING_LOCKIN); - if (!peer_ready) { - log_debug(peer->log, + channel_ready = (channel->owner && channel->state == CHANNELD_AWAITING_LOCKIN); + if (!channel_ready) { + log_debug(channel->log, "Funding tx confirmed, but peer state %s %s", - peer_state_name(peer->state), - peer->owner ? peer->owner->name : "unowned"); + channel_state_name(channel), + channel->owner ? channel->owner->name : "unowned"); } else { - subd_send_msg(peer->owner, - take(towire_channel_funding_locked(peer, - peer->scid))); + subd_send_msg(channel->owner, + take(towire_channel_funding_locked(channel, + channel->scid))); } /* BOLT #7: @@ -1558,7 +1540,7 @@ static enum watch_result funding_lockin_cb(struct peer *peer, * then both nodes must send the `announcement_signatures` message, * otherwise they MUST NOT. */ - if (!(peer->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)) + if (!(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)) return DELETE_WATCH; /* Tell channeld that we have reached the announce_depth and @@ -1584,6 +1566,7 @@ static void opening_got_hsm_funding_sig(struct funding_channel *fc, u8 *linear; u64 change_satoshi; struct json_result *response = new_json_result(fc->cmd); + struct channel *channel = peer2channel(fc->peer); if (!fromwire_hsm_sign_funding_reply(fc, resp, NULL, &tx)) fatal("HSM gave bad sign_funding_reply %s", @@ -1599,16 +1582,16 @@ static void opening_got_hsm_funding_sig(struct funding_channel *fc, /* FIXME: Remove arg from cb? */ watch_txo(fc->peer, fc->peer->ld->topology, fc->peer, - fc->peer->funding_txid, fc->peer->funding_outnum, + channel->funding_txid, channel->funding_outnum, funding_spent, NULL); json_object_start(response, NULL); linear = linearize_tx(response, tx); json_add_hex(response, "tx", linear, tal_len(linear)); - json_add_txid(response, "txid", fc->peer->funding_txid); + json_add_txid(response, "txid", channel->funding_txid); json_object_end(response); - command_success(fc->peer->opening_cmd, response); - fc->peer->opening_cmd = NULL; + command_success(channel->opening_cmd, response); + channel->opening_cmd = NULL; /* Start normal channel daemon. */ peer_start_channeld(fc->peer, cs, gossip_index, @@ -1627,6 +1610,7 @@ static void opening_got_hsm_funding_sig(struct funding_channel *fc, static void peer_got_funding_locked(struct peer *peer, const u8 *msg) { struct pubkey next_per_commitment_point; + struct channel *channel = peer2channel(peer); if (!fromwire_channel_got_funding_locked(msg, NULL, &next_per_commitment_point)) { @@ -1635,19 +1619,20 @@ static void peer_got_funding_locked(struct peer *peer, const u8 *msg) return; } - if (peer->remote_funding_locked) { + if (channel->remote_funding_locked) { peer_internal_error(peer, "channel_got_funding_locked twice"); return; } update_per_commit_point(peer, &next_per_commitment_point); log_debug(peer->log, "Got funding_locked"); - peer->remote_funding_locked = true; + channel->remote_funding_locked = true; } static void peer_got_shutdown(struct peer *peer, const u8 *msg) { u8 *scriptpubkey; + struct channel *channel = peer2channel(peer); if (!fromwire_channel_got_shutdown(peer, msg, NULL, &scriptpubkey)) { peer_internal_error(peer, "bad channel_got_shutdown %s", @@ -1656,8 +1641,8 @@ static void peer_got_shutdown(struct peer *peer, const u8 *msg) } /* FIXME: Add to spec that we must allow repeated shutdown! */ - tal_free(peer->remote_shutdown_scriptpubkey); - peer->remote_shutdown_scriptpubkey = scriptpubkey; + tal_free(channel->remote_shutdown_scriptpubkey); + channel->remote_shutdown_scriptpubkey = scriptpubkey; /* BOLT #2: * @@ -1678,11 +1663,11 @@ static void peer_got_shutdown(struct peer *peer, const u8 *msg) return; } - if (peer->local_shutdown_idx == -1) { + if (channel->local_shutdown_idx == -1) { u8 *scriptpubkey; - peer->local_shutdown_idx = wallet_get_newindex(peer->ld); - if (peer->local_shutdown_idx == -1) { + channel->local_shutdown_idx = wallet_get_newindex(peer->ld); + if (channel->local_shutdown_idx == -1) { peer_internal_error(peer, "Can't get local shutdown index"); return; @@ -1698,11 +1683,11 @@ static void peer_got_shutdown(struct peer *peer, const u8 *msg) * ...3. `OP_0` `20` 20-bytes (version 0 pay to witness pubkey), */ scriptpubkey = p2wpkh_for_keyidx(msg, peer->ld, - peer->local_shutdown_idx); + channel->local_shutdown_idx); if (!scriptpubkey) { peer_internal_error(peer, "Can't get shutdown script %"PRIu64, - peer->local_shutdown_idx); + channel->local_shutdown_idx); return; } @@ -1714,58 +1699,62 @@ static void peer_got_shutdown(struct peer *peer, const u8 *msg) * `shutdown` once there are no outstanding updates on the * peer, unless it has already sent a `shutdown`. */ - subd_send_msg(peer->owner, + subd_send_msg(channel->owner, take(towire_channel_send_shutdown(peer, scriptpubkey))); } /* TODO(cdecker) Selectively save updated fields to DB */ - wallet_channel_save(peer->ld->wallet, peer->channel); + wallet_channel_save(peer->ld->wallet, channel); } void peer_last_tx(struct peer *peer, struct bitcoin_tx *tx, const secp256k1_ecdsa_signature *sig) { - tal_free(peer->last_sig); - peer->last_sig = tal_dup(peer, secp256k1_ecdsa_signature, sig); - tal_free(peer->last_tx); - peer->last_tx = tal_steal(peer, tx); + struct channel *channel = peer2channel(peer); + + tal_free(channel->last_sig); + channel->last_sig = tal_dup(channel, secp256k1_ecdsa_signature, sig); + tal_free(channel->last_tx); + channel->last_tx = tal_steal(channel, tx); } /* 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 peer *peer, const struct bitcoin_tx *tx) +static bool better_closing_fee(struct lightningd *ld, + struct channel *channel, + const struct bitcoin_tx *tx) { u64 weight, fee, last_fee, ideal_fee, min_fee; s64 old_diff, new_diff; size_t i; /* Calculate actual fee (adds in eliminated outputs) */ - fee = peer->funding_satoshi; + fee = channel->funding_satoshi; for (i = 0; i < tal_count(tx->output); i++) fee -= tx->output[i].amount; - last_fee = peer->funding_satoshi; - for (i = 0; i < tal_count(peer->last_tx); i++) - last_fee -= peer->last_tx->output[i].amount; + last_fee = channel->funding_satoshi; + for (i = 0; i < tal_count(channel->last_tx); i++) + last_fee -= channel->last_tx->output[i].amount; - log_debug(peer->log, "Their actual closing tx fee is %"PRIu64 + 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(peer->ld->topology, FEERATE_SLOW) * weight / 1000; + min_fee = get_feerate(ld->topology, FEERATE_SLOW) * weight / 1000; if (fee < min_fee) { - log_debug(peer->log, "... That's below our min %"PRIu64 + log_debug(channel->log, "... That's below our min %"PRIu64 " for weight %"PRIu64" at feerate %u", min_fee, weight, - get_feerate(peer->ld->topology, FEERATE_SLOW)); + get_feerate(ld->topology, FEERATE_SLOW)); return false; } - ideal_fee = get_feerate(peer->ld->topology, FEERATE_NORMAL) * weight / 1000; + ideal_fee = get_feerate(ld->topology, FEERATE_NORMAL) * weight / 1000; /* We prefer fee which is closest to our ideal. */ old_diff = imaxabs((s64)ideal_fee - (s64)last_fee); @@ -1773,7 +1762,7 @@ static bool better_closing_fee(struct peer *peer, const struct bitcoin_tx *tx) /* In case of a tie, prefer new over old: this covers the preference * for a mutual close over a unilateral one. */ - log_debug(peer->log, "... That's %s our ideal %"PRIu64, + log_debug(channel->log, "... That's %s our ideal %"PRIu64, new_diff < old_diff ? "closer to" : new_diff > old_diff @@ -1788,6 +1777,7 @@ static void peer_received_closing_signature(struct peer *peer, const u8 *msg) { secp256k1_ecdsa_signature sig; struct bitcoin_tx *tx; + struct channel *channel = peer2channel(peer); if (!fromwire_closing_received_signature(msg, msg, NULL, &sig, &tx)) { peer_internal_error(peer, "Bad closing_received_signature %s", @@ -1796,14 +1786,14 @@ static void peer_received_closing_signature(struct peer *peer, const u8 *msg) } /* FIXME: Make sure signature is correct! */ - if (better_closing_fee(peer, tx)) { + if (better_closing_fee(peer->ld, channel, tx)) { peer_last_tx(peer, tx, &sig); /* TODO(cdecker) Selectively save updated fields to DB */ - wallet_channel_save(peer->ld->wallet, peer->channel); + wallet_channel_save(peer->ld->wallet, channel); } /* OK, you can continue now. */ - subd_send_msg(peer->owner, + subd_send_msg(peer2channel(peer)->owner, take(towire_closing_received_signature_reply(peer))); } @@ -1819,7 +1809,7 @@ static void peer_closing_complete(struct peer *peer, const u8 *msg) } /* Retransmission only, ignore closing. */ - if (peer->state == CLOSINGD_COMPLETE) + if (peer2channel(peer)->state == CLOSINGD_COMPLETE) return; drop_to_chain(peer); @@ -1859,14 +1849,15 @@ static void peer_start_closingd(struct peer *peer, u64 minfee, startfee, feelimit; u64 num_revocations; u64 funding_msatoshi, our_msatoshi, their_msatoshi; + struct channel *channel = peer2channel(peer); - if (peer->local_shutdown_idx == -1 - || !peer->remote_shutdown_scriptpubkey) { + if (channel->local_shutdown_idx == -1 + || !channel->remote_shutdown_scriptpubkey) { peer_internal_error(peer, "Can't start closing: local %s remote %s", - peer->local_shutdown_idx == -1 + channel->local_shutdown_idx == -1 ? "not shutdown" : "shutdown", - peer->remote_shutdown_scriptpubkey + channel->remote_shutdown_scriptpubkey ? "shutdown" : "not shutdown"); tal_free(tmpctx); return; @@ -1877,7 +1868,7 @@ static void peer_start_closingd(struct peer *peer, closing_wire_type_name, closing_msg, take(&peer_fd), take(&gossip_fd), NULL)); - if (!peer->owner) { + if (!channel->owner) { log_unusual(peer->log, "Could not subdaemon closing: %s", strerror(errno)); peer_fail_transient(peer, "Failed to subdaemon closing"); @@ -1886,7 +1877,7 @@ static void peer_start_closingd(struct peer *peer, } local_scriptpubkey = p2wpkh_for_keyidx(tmpctx, peer->ld, - peer->local_shutdown_idx); + channel->local_shutdown_idx); if (!local_scriptpubkey) { peer_internal_error(peer, "Can't generate local shutdown scriptpubkey"); @@ -1901,7 +1892,7 @@ static void peer_start_closingd(struct peer *peer, * calculated in [BOLT * #3](03-transactions.md#fee-calculation). */ - feelimit = commit_tx_base_fee(peer->channel_info->feerate_per_kw[LOCAL], + feelimit = commit_tx_base_fee(channel->channel_info->feerate_per_kw[LOCAL], 0); minfee = commit_tx_base_fee(get_feerate(peer->ld->topology, @@ -1915,41 +1906,41 @@ static void peer_start_closingd(struct peer *peer, minfee = feelimit; num_revocations - = revocations_received(&peer->their_shachain.chain); + = revocations_received(&channel->their_shachain.chain); /* BOLT #3: * * The amounts for each output MUST BE rounded down to whole satoshis. */ /* Convert unit */ - funding_msatoshi = peer->funding_satoshi * 1000; + funding_msatoshi = channel->funding_satoshi * 1000; /* What is not ours is theirs */ - our_msatoshi = *peer->our_msatoshi; + our_msatoshi = *channel->our_msatoshi; their_msatoshi = funding_msatoshi - our_msatoshi; initmsg = towire_closing_init(tmpctx, cs, gossip_index, - peer->seed, - peer->funding_txid, - peer->funding_outnum, - peer->funding_satoshi, - &peer->channel_info->remote_fundingkey, - peer->funder, + &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 */ - peer->our_config.dust_limit_satoshis, + channel->our_config.dust_limit_satoshis, minfee, feelimit, startfee, local_scriptpubkey, - peer->remote_shutdown_scriptpubkey, + channel->remote_shutdown_scriptpubkey, reconnected, - peer->next_index[LOCAL], - peer->next_index[REMOTE], + channel->next_index[LOCAL], + channel->next_index[REMOTE], num_revocations, deprecated_apis); /* We don't expect a response: it will give us feedback on * signatures sent and received, then closing_complete. */ - subd_send_msg(peer->owner, take(initmsg)); + subd_send_msg(channel->owner, take(initmsg)); tal_free(tmpctx); } @@ -2071,18 +2062,19 @@ static bool peer_start_channeld(struct peer *peer, struct short_channel_id funding_channel_id; const u8 *shutdown_scriptpubkey; u64 num_revocations; + struct channel *channel = peer2channel(peer); /* Now we can consider balance set. */ if (!reconnected) { - assert(!peer->our_msatoshi); - peer->our_msatoshi = tal(peer, u64); - if (peer->funder == LOCAL) - *peer->our_msatoshi - = peer->funding_satoshi * 1000 - peer->push_msat; + assert(!channel->our_msatoshi); + channel->our_msatoshi = tal(channel, u64); + if (channel->funder == LOCAL) + *channel->our_msatoshi + = channel->funding_satoshi * 1000 - channel->push_msat; else - *peer->our_msatoshi = peer->push_msat; + *channel->our_msatoshi = channel->push_msat; } else - assert(peer->our_msatoshi); + assert(channel->our_msatoshi); msg = towire_hsm_client_hsmfd(tmpctx, &peer->id, HSM_CAP_SIGN_GOSSIP | HSM_CAP_ECDH); if (!wire_sync_write(peer->ld->hsm_fd, take(msg))) @@ -2104,7 +2096,7 @@ static bool peer_start_channeld(struct peer *peer, take(&gossip_fd), take(&hsmfd), NULL)); - if (!peer->owner) { + if (!channel->owner) { log_unusual(peer->log, "Could not subdaemon channel: %s", strerror(errno)); peer_fail_transient(peer, "Failed to subdaemon channel"); @@ -2115,78 +2107,76 @@ static bool peer_start_channeld(struct peer *peer, peer_htlcs(tmpctx, peer, &htlcs, &htlc_states, &fulfilled_htlcs, &fulfilled_sides, &failed_htlcs, &failed_sides); - if (peer->scid) { - funding_channel_id = *peer->scid; + if (channel->scid) { + funding_channel_id = *channel->scid; log_debug(peer->log, "Already have funding locked in"); } else { log_debug(peer->log, "Waiting for funding confirmations"); memset(&funding_channel_id, 0, sizeof(funding_channel_id)); } - if (peer->local_shutdown_idx != -1) { + if (channel->local_shutdown_idx != -1) { shutdown_scriptpubkey = p2wpkh_for_keyidx(tmpctx, peer->ld, - peer->local_shutdown_idx); + channel->local_shutdown_idx); } else shutdown_scriptpubkey = NULL; - num_revocations = revocations_received(&peer->their_shachain.chain); + num_revocations = revocations_received(&channel->their_shachain.chain); /* Warn once. */ if (peer->ld->config.ignore_fee_limits) log_debug(peer->log, "Ignoring fee limits!"); - peer->direction = get_channel_direction(&peer->ld->id, &peer->id); - initmsg = towire_channel_init(tmpctx, &get_chainparams(peer->ld) ->genesis_blockhash, - peer->funding_txid, - peer->funding_outnum, - peer->funding_satoshi, - &peer->our_config, - &peer->channel_info->their_config, - peer->channel_info->feerate_per_kw, + 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(peer->ld), feerate_max(peer->ld), - peer->last_sig, + channel->last_sig, cs, gossip_index, - &peer->channel_info->remote_fundingkey, - &peer->channel_info->theirbase.revocation, - &peer->channel_info->theirbase.payment, - &peer->channel_info->theirbase.htlc, - &peer->channel_info->theirbase.delayed_payment, - &peer->channel_info->remote_per_commit, - &peer->channel_info->old_remote_per_commit, - peer->funder, + &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, - *peer->our_msatoshi, - peer->seed, + *channel->our_msatoshi, + &channel->seed, &peer->ld->id, &peer->id, time_to_msec(cfg->commit_time), cfg->cltv_expiry_delta, - peer->last_was_revoke, - peer->last_sent_commit, - peer->next_index[LOCAL], - peer->next_index[REMOTE], + channel->last_was_revoke, + channel->last_sent_commit, + channel->next_index[LOCAL], + channel->next_index[REMOTE], num_revocations, - peer->next_htlc_id, + channel->next_htlc_id, htlcs, htlc_states, fulfilled_htlcs, fulfilled_sides, failed_htlcs, failed_sides, - peer->scid != NULL, - peer->remote_funding_locked, + channel->scid != NULL, + channel->remote_funding_locked, &funding_channel_id, reconnected, shutdown_scriptpubkey, - peer->remote_shutdown_scriptpubkey != NULL, - peer->channel_flags, + channel->remote_shutdown_scriptpubkey != NULL, + channel->channel_flags, funding_signed); /* We don't expect a response: we are triggered by funding_depth_cb. */ - subd_send_msg(peer->owner, take(initmsg)); + subd_send_msg(channel->owner, take(initmsg)); tal_free(tmpctx); return true; @@ -2194,7 +2184,8 @@ static bool peer_start_channeld(struct peer *peer, static bool peer_commit_initial(struct peer *peer) { - peer->next_index[LOCAL] = peer->next_index[REMOTE] = 1; + struct channel *channel = peer2channel(peer); + channel->next_index[LOCAL] = channel->next_index[REMOTE] = 1; return true; } @@ -2213,15 +2204,16 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, secp256k1_ecdsa_signature remote_commit_sig; struct bitcoin_tx *remote_commit; u64 gossip_index; + struct channel *channel = peer2channel(fc->peer); assert(tal_count(fds) == 2); /* At this point, we care about peer */ - fc->peer->channel_info = channel_info - = tal(fc->peer, struct channel_info); + channel->channel_info = channel_info + = tal(channel, struct channel_info); /* This is a new channel_info->their_config so set its ID to 0 */ - fc->peer->channel_info->their_config.id = 0; + channel->channel_info->their_config.id = 0; if (!fromwire_opening_funder_reply(resp, resp, NULL, &channel_info->their_config, @@ -2234,7 +2226,7 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, &channel_info->theirbase.htlc, &channel_info->theirbase.delayed_payment, &channel_info->remote_per_commit, - &fc->peer->minimum_depth, + &channel->minimum_depth, &channel_info->remote_fundingkey, &funding_txid, &channel_info->feerate_per_kw[REMOTE])) { @@ -2258,10 +2250,10 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, &changekey, fc->change_keyindex)) fatal("Error deriving change key %u", fc->change_keyindex); - derive_basepoints(fc->peer->seed, &local_fundingkey, NULL, NULL, NULL); + derive_basepoints(&channel->seed, &local_fundingkey, NULL, NULL, NULL); - fundingtx = funding_tx(tmpctx, &fc->peer->funding_outnum, - fc->utxomap, fc->peer->funding_satoshi, + fundingtx = funding_tx(tmpctx, &channel->funding_outnum, + fc->utxomap, channel->funding_satoshi, &local_fundingkey, &channel_info->remote_fundingkey, fc->change, &changekey, @@ -2279,16 +2271,16 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, &fundingtx->input[i].txid)); } - fc->peer->funding_txid = tal(fc->peer, struct bitcoin_txid); - bitcoin_txid(fundingtx, fc->peer->funding_txid); + channel->funding_txid = tal(channel, struct bitcoin_txid); + bitcoin_txid(fundingtx, channel->funding_txid); - if (!structeq(fc->peer->funding_txid, &funding_txid)) { + if (!structeq(channel->funding_txid, &funding_txid)) { peer_internal_error(fc->peer, "Funding txid mismatch:" " satoshi %"PRIu64" change %"PRIu64 " changeidx %u" " localkey %s remotekey %s", - fc->peer->funding_satoshi, + channel->funding_satoshi, fc->change, fc->change_keyindex, type_to_string(fc, struct pubkey, &local_fundingkey), @@ -2305,7 +2297,7 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, /* Get HSM to sign the funding tx. */ log_debug(fc->peer->log, "Getting HSM to sign funding tx"); - msg = towire_hsm_sign_funding(tmpctx, fc->peer->funding_satoshi, + msg = towire_hsm_sign_funding(tmpctx, channel->funding_satoshi, fc->change, fc->change_keyindex, &local_fundingkey, &channel_info->remote_fundingkey, @@ -2334,16 +2326,17 @@ static void opening_fundee_finished(struct subd *opening, secp256k1_ecdsa_signature remote_commit_sig; struct bitcoin_tx *remote_commit; const tal_t *tmpctx = tal_tmpctx(peer); + struct channel *channel = peer2channel(peer); log_debug(peer->log, "Got opening_fundee_finish_response"); assert(tal_count(fds) == 2); /* At this point, we care about peer */ - peer->channel_info = channel_info = tal(peer, struct channel_info); + channel->channel_info = channel_info = tal(peer, struct channel_info); /* This is a new channel_info->their_config, set its ID to 0 */ - peer->channel_info->their_config.id = 0; + channel->channel_info->their_config.id = 0; - peer->funding_txid = tal(peer, struct bitcoin_txid); + channel->funding_txid = tal(channel, struct bitcoin_txid); if (!fromwire_opening_fundee_reply(tmpctx, reply, NULL, &channel_info->their_config, &remote_commit, @@ -2356,11 +2349,11 @@ static void opening_fundee_finished(struct subd *opening, &channel_info->theirbase.delayed_payment, &channel_info->remote_per_commit, &channel_info->remote_fundingkey, - peer->funding_txid, - &peer->funding_outnum, - &peer->funding_satoshi, - &peer->push_msat, - &peer->channel_flags, + channel->funding_txid, + &channel->funding_outnum, + &channel->funding_satoshi, + &channel->push_msat, + &channel->channel_flags, &channel_info->feerate_per_kw[REMOTE], &funding_signed)) { peer_internal_error(peer, "bad OPENING_FUNDEE_REPLY %s", @@ -2386,13 +2379,13 @@ static void opening_fundee_finished(struct subd *opening, log_debug(peer->log, "Watching funding tx %s", type_to_string(reply, struct bitcoin_txid, - peer->funding_txid)); - watch_txid(peer, peer->ld->topology, peer, peer->funding_txid, + channel->funding_txid)); + watch_txid(peer, peer->ld->topology, peer, channel->funding_txid, funding_lockin_cb, NULL); /* FIXME: Remove arg from cb? */ - watch_txo(peer, peer->ld->topology, peer, peer->funding_txid, - peer->funding_outnum, funding_spent, NULL); + watch_txo(peer, peer->ld->topology, peer, channel->funding_txid, + channel->funding_outnum, funding_spent, NULL); /* Unowned (will free openingd). */ peer_set_owner(peer, NULL); @@ -2453,25 +2446,33 @@ static void peer_accept_channel(struct lightningd *ld, u64 min_effective_htlc_capacity_msat; u8 *msg; struct peer *peer; + struct channel *channel; assert(fromwire_peektype(open_msg) == WIRE_OPEN_CHANNEL); - /* We make a new peer. */ - peer = new_peer(ld, peer_id, addr, gfeatures, lfeatures, peer_fd); + /* We make a new peer if necessary. */ + peer = peer_by_id(ld, peer_id); + if (!peer) + peer = new_peer(ld, 0, peer_id, addr); + + channel = new_channel(peer, 0, get_block_height(ld->topology)); + assert(channel == peer2channel(peer)); + assert(peer == channel2peer(channel)); + peer_set_condition(peer, UNINITIALIZED, OPENINGD); peer_set_owner(peer, new_peer_subd(ld, "lightning_openingd", peer, opening_wire_type_name, opening_negotiation_failed, take(&peer_fd), take(&gossip_fd), NULL)); - if (!peer->owner) { + if (!channel->owner) { peer_fail_transient(peer, "Failed to subdaemon opening: %s", strerror(errno)); return; } /* They will open channel. */ - peer->funder = REMOTE; + channel->funder = REMOTE; /* BOLT #2: * @@ -2479,38 +2480,36 @@ static void peer_accept_channel(struct lightningd *ld, * considers reasonable to avoid double-spending of the funding * transaction. */ - peer->minimum_depth = ld->config.anchor_confirms; + channel->minimum_depth = ld->config.anchor_confirms; - channel_config(ld, &peer->our_config, + channel_config(ld, &channel->our_config, &max_to_self_delay, &max_minimum_depth, &min_effective_htlc_capacity_msat); /* Store the channel in the database in order to get a channel * ID that is unique and which we can base the peer_seed on */ - peer->channel = peer_channel_new(ld->wallet, peer); - peer->seed = tal(peer, struct privkey); - derive_peer_seed(ld, peer->seed, &peer->id, peer->channel->id); + wallet_channel_save(ld->wallet, channel); msg = towire_opening_init(peer, get_chainparams(ld)->index, - &peer->our_config, + &channel->our_config, max_to_self_delay, min_effective_htlc_capacity_msat, - cs, gossip_index, peer->seed); + cs, gossip_index, &channel->seed); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(channel->owner, take(msg)); /* BOLT #2: * * Given the variance in fees, and the fact that the transaction may * be spent in the future, it's a good idea for the fee payer to keep * a good margin, say 5x the expected fee requirement */ - msg = towire_opening_fundee(peer, peer->minimum_depth, + msg = towire_opening_fundee(peer, channel->minimum_depth, get_feerate(ld->topology, FEERATE_SLOW), get_feerate(ld->topology, FEERATE_IMMEDIATE) * 5, open_msg); - subd_req(peer, peer->owner, take(msg), -1, 2, + subd_req(peer, channel->owner, take(msg), -1, 2, opening_fundee_finished, peer); } @@ -2525,12 +2524,19 @@ static void peer_offer_channel(struct lightningd *ld, u8 *msg; u32 max_to_self_delay, max_minimum_depth; u64 min_effective_htlc_capacity_msat; + struct channel *channel; + + /* We make a new peer if necessary. */ + fc->peer = peer_by_id(ld, &fc->peerid); + if (!fc->peer) + fc->peer = new_peer(ld, 0, &fc->peerid, addr); + + channel = new_channel(fc->peer, 0, get_block_height(ld->topology)); + assert(channel == peer2channel(fc->peer)); + assert(fc->peer == channel2peer(channel)); - /* We make a new peer. */ - fc->peer = new_peer(ld, &fc->peerid, addr, - gfeatures, lfeatures, peer_fd); - fc->peer->funding_satoshi = fc->funding_satoshi; - fc->peer->push_msat = fc->push_msat; + channel->funding_satoshi = fc->funding_satoshi; + channel->push_msat = fc->push_msat; peer_set_condition(fc->peer, UNINITIALIZED, OPENINGD); peer_set_owner(fc->peer, @@ -2539,7 +2545,7 @@ static void peer_offer_channel(struct lightningd *ld, opening_wire_type_name, opening_negotiation_failed, take(&peer_fd), take(&gossip_fd), NULL)); - if (!fc->peer->owner) { + if (!channel->owner) { fc->peer = tal_free(fc->peer); command_fail(fc->cmd, "Failed to launch openingd: %s", @@ -2556,41 +2562,38 @@ static void peer_offer_channel(struct lightningd *ld, /* Store the channel in the database in order to get a channel * ID that is unique and which we can base the peer_seed on */ - fc->peer->channel = peer_channel_new(ld->wallet, fc->peer); - fc->peer->seed = tal(fc->peer, struct privkey); - derive_peer_seed(ld, fc->peer->seed, &fc->peer->id, - fc->peer->channel->id); + wallet_channel_save(ld->wallet, channel); /* We will fund channel */ - fc->peer->funder = LOCAL; - channel_config(ld, &fc->peer->our_config, + channel->funder = LOCAL; + channel_config(ld, &channel->our_config, &max_to_self_delay, &max_minimum_depth, &min_effective_htlc_capacity_msat); - fc->peer->channel_flags = OUR_CHANNEL_FLAGS; + channel->channel_flags = OUR_CHANNEL_FLAGS; msg = towire_opening_init(fc, get_chainparams(ld)->index, - &fc->peer->our_config, + &channel->our_config, max_to_self_delay, min_effective_htlc_capacity_msat, - cs, gossip_index, fc->peer->seed); - subd_send_msg(fc->peer->owner, take(msg)); + cs, gossip_index, &channel->seed); + subd_send_msg(channel->owner, take(msg)); - msg = towire_opening_funder(fc, fc->peer->funding_satoshi, - fc->peer->push_msat, + msg = towire_opening_funder(fc, channel->funding_satoshi, + channel->push_msat, get_feerate(ld->topology, FEERATE_NORMAL), max_minimum_depth, fc->change, fc->change_keyindex, - fc->peer->channel_flags, + channel->channel_flags, fc->utxomap, - fc->peer->ld->wallet->bip32_base); + ld->wallet->bip32_base); /* Peer now owns fc; if it dies, we fail fc. */ tal_steal(fc->peer, fc); - fc->peer->opening_cmd = fc->cmd; + channel->opening_cmd = fc->cmd; - subd_req(fc, fc->peer->owner, + subd_req(fc, channel->owner, take(msg), -1, 2, opening_funder_finished, fc); } @@ -2618,7 +2621,7 @@ static void gossip_peer_released(struct subd *gossip, } if (fc->peer) command_fail(fc->cmd, "Peer already %s", - peer_state_name(fc->peer->state)); + channel_state_name(peer2channel(fc->peer))); else command_fail(fc->cmd, "Peer not connected"); return; @@ -2629,7 +2632,7 @@ static void gossip_peer_released(struct subd *gossip, * close this is easiest. */ if (fc->peer) { command_fail(fc->cmd, "Peer already %s", - peer_state_name(fc->peer->state)); + channel_state_name(peer2channel(fc->peer))); close(fds[0]); close(fds[1]); return; @@ -2705,6 +2708,7 @@ static void json_close(struct command *cmd, { jsmntok_t *peertok; struct peer *peer; + struct channel *channel; if (!json_get_params(cmd, buffer, params, "id", &peertok, @@ -2717,26 +2721,27 @@ static void json_close(struct command *cmd, command_fail(cmd, "Could not find peer with that id"); return; } + channel = peer2channel(peer); /* Easy case: peer can simply be forgotten. */ if (!peer_persists(peer)) { peer_fail_permanent(peer, "Peer closed in state %s", - peer_state_name(peer->state)); + channel_state_name(peer2channel(peer))); command_success(cmd, null_response(cmd)); return; } /* Normal case. */ - if (peer->state == CHANNELD_NORMAL) { + if (channel->state == CHANNELD_NORMAL) { u8 *shutdown_scriptpubkey; - peer->local_shutdown_idx = wallet_get_newindex(peer->ld); - if (peer->local_shutdown_idx == -1) { + channel->local_shutdown_idx = wallet_get_newindex(peer->ld); + if (channel->local_shutdown_idx == -1) { command_fail(cmd, "Failed to get new key for shutdown"); return; } shutdown_scriptpubkey = p2wpkh_for_keyidx(cmd, peer->ld, - peer->local_shutdown_idx); + channel->local_shutdown_idx); if (!shutdown_scriptpubkey) { command_fail(cmd, "Failed to get script for shutdown"); return; @@ -2746,15 +2751,15 @@ static void json_close(struct command *cmd, txfilter_add_scriptpubkey(peer->ld->owned_txfilter, shutdown_scriptpubkey); - if (peer->owner) - subd_send_msg(peer->owner, - take(towire_channel_send_shutdown(peer, + if (channel->owner) + subd_send_msg(channel->owner, + take(towire_channel_send_shutdown(channel, shutdown_scriptpubkey))); command_success(cmd, null_response(cmd)); } else command_fail(cmd, "Peer is in state %s", - peer_state_name(peer->state)); + channel_state_name(channel)); } static const struct json_command close_command = { @@ -2778,29 +2783,31 @@ const char *peer_state_name(enum peer_state state) static void activate_peer(struct peer *peer) { u8 *msg; + struct channel *channel = peer2channel(peer); /* Pass gossipd any addrhints we currently have */ msg = towire_gossipctl_peer_addrhint(peer, &peer->id, &peer->addr); subd_send_msg(peer->ld->gossip, take(msg)); /* FIXME: We should never have these in the database! */ - if (!peer->funding_txid) { + if (!channel->funding_txid) { log_broken(peer->log, "activate_peer(%s) with no funding txid?", - peer_state_name(peer->state)); + channel_state_name(peer2channel(peer))); return; } /* This may be unnecessary, but it's harmless. */ - watch_txid(peer, peer->ld->topology, peer, peer->funding_txid, + watch_txid(peer, peer->ld->topology, peer, channel->funding_txid, funding_lockin_cb, NULL); - watch_txo(peer, peer->ld->topology, peer, peer->funding_txid, peer->funding_outnum, + watch_txo(peer, peer->ld->topology, peer, + channel->funding_txid, channel->funding_outnum, funding_spent, NULL); /* If peer->owner then we had a reconnect while loading and * activating the peers, don't ask gossipd to connect in that * case */ - if (!peer->owner && peer_wants_reconnect(peer)) { + if (!channel->owner && peer_wants_reconnect(peer)) { msg = towire_gossipctl_reach_peer(peer, &peer->id); subd_send_msg(peer->ld->gossip, take(msg)); } @@ -2822,6 +2829,7 @@ static void json_sign_last_tx(struct command *cmd, struct peer *peer; struct json_result *response = new_json_result(cmd); u8 *linear; + struct channel *channel; if (!json_get_params(cmd, buffer, params, "id", &peertok, @@ -2834,16 +2842,17 @@ static void json_sign_last_tx(struct command *cmd, command_fail(cmd, "Could not find peer with that id"); return; } - if (!peer->last_tx) { + channel = peer2channel(peer); + if (!channel->last_tx) { command_fail(cmd, "Peer has no final transaction"); return; } log_debug(peer->log, "dev-sign-last-tx: signing tx with %zu outputs", - tal_count(peer->last_tx->output)); + tal_count(channel->last_tx->output)); sign_last_tx(peer); - linear = linearize_tx(cmd, peer->last_tx); - remove_sig(peer->last_tx); + linear = linearize_tx(cmd, channel->last_tx); + remove_sig(channel->last_tx); json_object_start(response, NULL); json_add_hex(response, "tx", linear, tal_len(linear)); @@ -2901,6 +2910,7 @@ static void json_dev_reenable_commit(struct command *cmd, jsmntok_t *peertok; struct peer *peer; u8 *msg; + struct channel *channel; if (!json_get_params(cmd, buffer, params, "id", &peertok, @@ -2914,18 +2924,19 @@ static void json_dev_reenable_commit(struct command *cmd, return; } - if (!peer->owner) { + channel = peer2channel(peer); + if (!channel->owner) { command_fail(cmd, "Peer has no owner"); return; } - if (!streq(peer->owner->name, "lightning_channeld")) { - command_fail(cmd, "Peer owned by %s", peer->owner->name); + if (!streq(channel->owner->name, "lightning_channeld")) { + command_fail(cmd, "Peer owned by %s", channel->owner->name); return; } - msg = towire_channel_dev_reenable_commit(peer); - subd_req(peer, peer->owner, take(msg), -1, 0, + msg = towire_channel_dev_reenable_commit(channel); + subd_req(peer, channel->owner, take(msg), -1, 0, dev_reenable_commit_finished, cmd); command_still_pending(cmd); } @@ -2965,7 +2976,7 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED, json_object_start(response, NULL); json_add_bool(response, "forced", forget->force); json_add_bool(response, "funding_unspent", txout != NULL); - json_add_txid(response, "funding_txid", forget->peer->funding_txid); + json_add_txid(response, "funding_txid", peer2channel(forget->peer)->funding_txid); json_object_end(response); free_peer(forget->peer, "dev-forget-channel called"); @@ -2994,12 +3005,12 @@ static void json_dev_forget_channel(struct command *cmd, const char *buffer, forget->peer = peer_from_json(cmd->ld, buffer, nodeidtok); if (!forget->peer) command_fail(cmd, "Could not find channel with that peer"); - if (!forget->peer->funding_txid) { + if (!peer2channel(forget->peer)->funding_txid) { process_dev_forget_channel(cmd->ld->topology->bitcoind, NULL, forget); } else { bitcoind_gettxout(cmd->ld->topology->bitcoind, - forget->peer->funding_txid, - forget->peer->funding_outnum, + peer2channel(forget->peer)->funding_txid, + peer2channel(forget->peer)->funding_outnum, process_dev_forget_channel, forget); command_still_pending(cmd); } diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 117588bd9..260539d65 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -30,133 +31,27 @@ struct peer { /* ID of peer */ struct pubkey id; - /* Error message (iff in error state) */ - u8 *error; - - /* Their shachain. */ - struct wallet_shachain their_shachain; - - /* What's happening. */ - enum peer_state state; - - /* Which side offered channel? */ - enum side funder; - - /* Command which ordered us to open channel, if any. */ - struct command *opening_cmd; - - /* Is there a single subdaemon responsible for us? */ - struct subd *owner; + /* Our channels */ + struct list_head channels; /* History */ struct log_book *log_book; - struct log *log; - /* Channel flags from opening message. */ - u8 channel_flags; + /* FIXME: Remove in favor of channel->log */ + struct log *log; /* Where we connected to, or it connected from. */ struct wireaddr addr; - /* Our channel config. */ - struct channel_config our_config; - - /* Minimum funding depth (specified by us if they fund). */ - u32 minimum_depth; - - /* Tracking commitment transaction numbers. */ - u64 next_index[NUM_SIDES]; - u64 next_htlc_id; - - /* Funding txid and amounts (once known) */ - struct bitcoin_txid *funding_txid; - u16 funding_outnum; - u64 funding_satoshi, push_msat; - bool remote_funding_locked; - /* Channel if locked locally. */ - struct short_channel_id *scid; - - /* Amount going to us, not counting unfinished HTLCs; if we have one. */ - u64 *our_msatoshi; - - /* Last tx they gave us (if any). */ - struct bitcoin_tx *last_tx; - secp256k1_ecdsa_signature *last_sig; - secp256k1_ecdsa_signature *last_htlc_sigs; - - /* Keys for channel. */ - struct channel_info *channel_info; - - /* Secret seed (FIXME: Move to hsm!) */ - struct privkey *seed; - - /* Their scriptpubkey if they sent shutdown. */ - u8 *remote_shutdown_scriptpubkey; - /* Our key for shutdown (-1 if not chosen yet) */ - s64 local_shutdown_idx; - - /* Reestablishment stuff: last sent commit and revocation details. */ - bool last_was_revoke; - struct changed_htlc *last_sent_commit; - - struct wallet_channel *channel; - /* If we open a channel our direction will be this */ u8 direction; }; -static inline bool peer_can_add_htlc(const struct peer *peer) -{ - return peer->state == CHANNELD_NORMAL; -} - -static inline bool peer_fees_can_change(const struct peer *peer) -{ - return peer->state == CHANNELD_NORMAL - || peer->state == CHANNELD_SHUTTING_DOWN; -} - -static inline bool peer_can_remove_htlc(const struct peer *peer) -{ - return peer->state == CHANNELD_NORMAL - || peer->state == CHANNELD_SHUTTING_DOWN - || peer->state == ONCHAIND_THEIR_UNILATERAL - || peer->state == ONCHAIND_OUR_UNILATERAL; -} - -static inline bool peer_state_on_chain(enum peer_state state) -{ - return state == ONCHAIND_CHEATED - || state == ONCHAIND_THEIR_UNILATERAL - || state == ONCHAIND_OUR_UNILATERAL - || state == ONCHAIND_MUTUAL; -} - -static inline bool peer_on_chain(const struct peer *peer) -{ - return peer_state_on_chain(peer->state); -} - -static inline bool peer_wants_reconnect(const struct peer *peer) -{ - return peer->state >= CHANNELD_AWAITING_LOCKIN - && peer->state <= CLOSINGD_COMPLETE; -} - -/* BOLT #2: - * - * On disconnection, the funder MUST remember the channel for - * reconnection if it has broadcast the funding transaction, otherwise it - * SHOULD NOT. - * - * On disconnection, the non-funding node MUST remember the channel for - * reconnection if it has sent the `funding_signed` message, otherwise - * it SHOULD NOT. - */ -static inline bool peer_persists(const struct peer *peer) -{ - return peer->state >= CHANNELD_AWAITING_LOCKIN; -} +struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid); + +struct peer *new_peer(struct lightningd *ld, u64 dbid, + const struct pubkey *id, + const struct wireaddr *addr); struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id); struct peer *peer_from_json(struct lightningd *ld, @@ -192,18 +87,6 @@ void peer_sent_nongossip(struct lightningd *ld, int peer_fd, int gossip_fd, const u8 *in_msg); -/** - * populate_peer -- Populate daemon fields in a peer - * - * @ld: the daemon to wire the peer into - * @peer: the peer to populate - * - * Creating a new peer, or loading a peer from the database we need to - * populate a number of fields, e.g., the logging handler and the - * pointer to the daemon. populate_peer does exactly that. - */ -void populate_peer(struct lightningd *ld, struct peer *peer); - /* Could be configurable. */ #define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index e0c7100c9..0a3195392 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -99,10 +99,10 @@ static void fail_in_htlc(struct htlc_in *hin, htlc_in_update_state(hin->key.peer, hin, SENT_REMOVE_HTLC); /* Tell peer, if we can. */ - if (!hin->key.peer->owner) + if (!peer2channel(hin->key.peer)->owner) return; - subd_send_msg(hin->key.peer->owner, + subd_send_msg(peer2channel(hin->key.peer)->owner, take(towire_channel_fail_htlc(hin, hin->key.id, hin->failuremsg, @@ -127,7 +127,7 @@ static void fail_out_htlc(struct htlc_out *hout, const char *localfail) assert(hout->failcode || hout->failuremsg); if (hout->in) { fail_in_htlc(hout->in, hout->failcode, hout->failuremsg, - hout->key.peer->scid); + peer2channel(hout->key.peer)->scid); } else { payment_failed(hout->key.peer->ld, hout, localfail); } @@ -202,17 +202,17 @@ static void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage) /* No owner? We'll either send to channeld in peer_htlcs, or * onchaind in onchaind_tell_fulfill. */ - if (!hin->key.peer->owner) { + if (!peer2channel(hin->key.peer)->owner) { log_debug(hin->key.peer->log, "HTLC fulfilled, but no owner."); return; } - if (peer_state_on_chain(hin->key.peer->state)) { + if (peer_on_chain(hin->key.peer)) { msg = towire_onchain_known_preimage(hin, preimage); } else { msg = towire_channel_fulfill_htlc(hin, hin->key.id, preimage); } - subd_send_msg(hin->key.peer->owner, take(msg)); + subd_send_msg(peer2channel(hin->key.peer)->owner, take(msg)); } static void handle_localpay(struct htlc_in *hin, @@ -348,7 +348,7 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds, payment_failed(hout->key.peer->ld, hout, localfail); } else local_fail_htlc(hout->in, failure_code, - hout->key.peer->scid); + peer2channel(hout->key.peer)->scid); /* Prevent hout from being failed twice. */ tal_del_destructor(hout, hout_subd_died); tal_free(hout); @@ -378,28 +378,29 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv, struct htlc_out **houtp) { struct htlc_out *hout; + struct channel *channel = peer2channel(out); u8 *msg; if (!peer_can_add_htlc(out)) { log_info(out->log, "Attempt to send HTLC but not ready (%s)", - peer_state_name(out->state)); + peer_state_name(channel->state)); return WIRE_UNKNOWN_NEXT_PEER; } - if (!out->owner) { + if (!channel->owner) { log_info(out->log, "Attempt to send HTLC but unowned (%s)", - peer_state_name(out->state)); + peer_state_name(channel->state)); return WIRE_TEMPORARY_CHANNEL_FAILURE; } /* Make peer's daemon own it, catch if it dies. */ - hout = new_htlc_out(out->owner, out, amount, cltv, + hout = new_htlc_out(channel->owner, out, amount, cltv, payment_hash, onion_routing_packet, in); tal_add_destructor(hout, hout_subd_died); msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash, onion_routing_packet); - subd_req(out->ld, out->owner, take(msg), -1, 0, rcvd_htlc_reply, hout); + subd_req(out->ld, channel->owner, take(msg), -1, 0, rcvd_htlc_reply, hout); if (houtp) *houtp = hout; @@ -420,7 +421,7 @@ static void forward_htlc(struct htlc_in *hin, struct peer *next = peer_by_id(ld, next_hop); /* Unknown peer, or peer not ready. */ - if (!next || !next->scid) { + if (!next || !peer2channel(next)->scid) { local_fail_htlc(hin, WIRE_UNKNOWN_NEXT_PEER, NULL); return; } @@ -491,7 +492,7 @@ static void forward_htlc(struct htlc_in *hin, return; fail: - local_fail_htlc(hin, failcode, next->scid); + local_fail_htlc(hin, failcode, peer2channel(next)->scid); } /* Temporary information, while we resolve the next hop */ @@ -565,7 +566,7 @@ static bool peer_accepted_htlc(struct peer *peer, * * A sending node SHOULD fail to route any HTLC added after it * sent `shutdown`. */ - if (peer->state == CHANNELD_SHUTTING_DOWN) { + if (peer2channel(peer)->state == CHANNELD_SHUTTING_DOWN) { *failcode = WIRE_PERMANENT_CHANNEL_FAILURE; goto out; } @@ -663,10 +664,11 @@ static void fulfill_our_htlc_out(struct peer *peer, struct htlc_out *hout, payment_succeeded(peer->ld, hout, preimage); } -static bool peer_fulfilled_our_htlc(struct peer *peer, +static bool peer_fulfilled_our_htlc(struct channel *channel, const struct fulfilled_htlc *fulfilled) { struct htlc_out *hout; + struct peer *peer = channel2peer(channel); hout = find_htlc_out(&peer->ld->htlcs_out, peer, fulfilled->id); if (!hout) { @@ -711,10 +713,11 @@ void onchain_fulfilled_htlc(struct peer *peer, const struct preimage *preimage) } } -static bool peer_failed_our_htlc(struct peer *peer, +static bool peer_failed_our_htlc(struct channel *channel, const struct failed_htlc *failed) { struct htlc_out *hout; + struct peer *peer = channel2peer(channel); hout = find_htlc_out(&peer->ld->htlcs_out, peer, failed->id); if (!hout) { @@ -784,7 +787,7 @@ void onchain_failed_our_htlc(const struct peer *peer, tal_free(localfail); } else local_fail_htlc(hout->in, WIRE_PERMANENT_CHANNEL_FAILURE, - hout->key.peer->scid); + peer2channel(hout->key.peer)->scid); } static void remove_htlc_in(struct peer *peer, struct htlc_in *hin) @@ -801,9 +804,9 @@ static void remove_htlc_in(struct peer *peer, struct htlc_in *hin) /* If we fulfilled their HTLC, credit us. */ if (hin->preimage) { log_debug(peer->log, "Balance %"PRIu64" -> %"PRIu64, - *peer->our_msatoshi, - *peer->our_msatoshi + hin->msatoshi); - *peer->our_msatoshi += hin->msatoshi; + *peer2channel(peer)->our_msatoshi, + *peer2channel(peer)->our_msatoshi + hin->msatoshi); + *peer2channel(peer)->our_msatoshi += hin->msatoshi; } tal_free(hin); @@ -825,9 +828,9 @@ static void remove_htlc_out(struct peer *peer, struct htlc_out *hout) } else { /* We paid for this HTLC, so deduct balance. */ log_debug(peer->log, "Balance %"PRIu64" -> %"PRIu64, - *peer->our_msatoshi, - *peer->our_msatoshi - hout->msatoshi); - *peer->our_msatoshi -= hout->msatoshi; + *peer2channel(peer)->our_msatoshi, + *peer2channel(peer)->our_msatoshi - hout->msatoshi); + *peer2channel(peer)->our_msatoshi -= hout->msatoshi; } tal_free(hout); @@ -863,7 +866,7 @@ static bool update_out_htlc(struct peer *peer, u64 id, enum htlc_state newstate) } if (!hout->dbid) { - wallet_htlc_save_out(peer->ld->wallet, peer->channel, hout); + wallet_htlc_save_out(peer->ld->wallet, peer2channel(peer), hout); /* For our own HTLCs, we commit payment to db lazily */ if (hout->origin_htlc_id == 0) @@ -898,15 +901,15 @@ static bool peer_save_commitsig_received(struct peer *peer, u64 commitnum, struct bitcoin_tx *tx, const secp256k1_ecdsa_signature *commit_sig) { - if (commitnum != peer->next_index[LOCAL]) { + if (commitnum != peer2channel(peer)->next_index[LOCAL]) { peer_internal_error(peer, "channel_got_commitsig: expected commitnum %"PRIu64 " got %"PRIu64, - peer->next_index[LOCAL], commitnum); + peer2channel(peer)->next_index[LOCAL], commitnum); return false; } - peer->next_index[LOCAL]++; + peer2channel(peer)->next_index[LOCAL]++; /* Update peer->last_sig and peer->last_tx before saving to db */ peer_last_tx(peer, tx, commit_sig); @@ -916,18 +919,18 @@ static bool peer_save_commitsig_received(struct peer *peer, u64 commitnum, static bool peer_save_commitsig_sent(struct peer *peer, u64 commitnum) { - if (commitnum != peer->next_index[REMOTE]) { + if (commitnum != peer2channel(peer)->next_index[REMOTE]) { peer_internal_error(peer, "channel_sent_commitsig: expected commitnum %"PRIu64 " got %"PRIu64, - peer->next_index[REMOTE], commitnum); + peer2channel(peer)->next_index[REMOTE], commitnum); return false; } - peer->next_index[REMOTE]++; + peer2channel(peer)->next_index[REMOTE]++; /* FIXME: Save to database, with sig and HTLCs. */ - wallet_channel_save(peer->ld->wallet, peer->channel); + wallet_channel_save(peer->ld->wallet, peer2channel(peer)); return true; } @@ -967,37 +970,37 @@ void peer_sending_commitsig(struct peer *peer, const u8 *msg) } if (num_local_added != 0) { - if (maxid != peer->next_htlc_id + num_local_added - 1) { + if (maxid != peer2channel(peer)->next_htlc_id + num_local_added - 1) { peer_internal_error(peer, "channel_sending_commitsig:" " Added %"PRIu64", maxid now %"PRIu64 " from %"PRIu64, - num_local_added, maxid, peer->next_htlc_id); + num_local_added, maxid, peer2channel(peer)->next_htlc_id); return; } - peer->next_htlc_id += num_local_added; + peer2channel(peer)->next_htlc_id += num_local_added; } /* Update their feerate. */ - peer->channel_info->feerate_per_kw[REMOTE] = feerate; + peer2channel(peer)->channel_info->feerate_per_kw[REMOTE] = feerate; if (!peer_save_commitsig_sent(peer, commitnum)) return; /* Last was commit. */ - peer->last_was_revoke = false; - tal_free(peer->last_sent_commit); - peer->last_sent_commit = tal_steal(peer, changed_htlcs); - wallet_channel_save(peer->ld->wallet, peer->channel); + peer2channel(peer)->last_was_revoke = false; + tal_free(peer2channel(peer)->last_sent_commit); + peer2channel(peer)->last_sent_commit = tal_steal(peer, changed_htlcs); + wallet_channel_save(peer->ld->wallet, peer2channel(peer)); /* Tell it we've got it, and to go ahead with commitment_signed. */ - subd_send_msg(peer->owner, + subd_send_msg(peer2channel(peer)->owner, take(towire_channel_sending_commitsig_reply(msg))); } -static bool peer_added_their_htlc(struct peer *peer, - const struct added_htlc *added, - const struct secret *shared_secret) +static bool channel_added_their_htlc(struct channel *channel, + const struct added_htlc *added, + const struct secret *shared_secret) { struct htlc_in *hin; @@ -1007,37 +1010,38 @@ static bool peer_added_their_htlc(struct peer *peer, * - SHOULD fail the channel. */ if (added->amount_msat == 0 - || added->amount_msat < peer->our_config.htlc_minimum_msat) { - peer_internal_error(peer, + || added->amount_msat < channel->our_config.htlc_minimum_msat) { + peer_internal_error(channel2peer(channel), "trying to add HTLC msat %"PRIu64 " but minimum is %"PRIu64, added->amount_msat, - peer->our_config.htlc_minimum_msat); + channel->our_config.htlc_minimum_msat); return false; } /* This stays around even if we fail it immediately: it *is* * part of the current commitment. */ - hin = new_htlc_in(peer, peer, added->id, added->amount_msat, + hin = new_htlc_in(channel, channel2peer(channel), added->id, added->amount_msat, added->cltv_expiry, &added->payment_hash, shared_secret, added->onion_routing_packet); /* Save an incoming htlc to the wallet */ - wallet_htlc_save_in(peer->ld->wallet, peer->channel, hin); + wallet_htlc_save_in(channel->peer->ld->wallet, channel, hin); - log_debug(peer->log, "Adding their HTLC %"PRIu64, added->id); - connect_htlc_in(&peer->ld->htlcs_in, hin); + log_debug(channel->log, "Adding their HTLC %"PRIu64, added->id); + connect_htlc_in(&channel->peer->ld->htlcs_in, hin); return true; } /* The peer doesn't tell us this separately, but logically it's a separate * step to receiving commitsig */ -static bool peer_sending_revocation(struct peer *peer, +static bool peer_sending_revocation(struct channel *channel, struct added_htlc *added, struct fulfilled_htlc *fulfilled, struct failed_htlc **failed, struct changed_htlc *changed) { + struct peer *peer = channel2peer(channel); size_t i; for (i = 0; i < tal_count(added); i++) { @@ -1065,7 +1069,7 @@ static bool peer_sending_revocation(struct peer *peer, } } - peer->last_was_revoke = true; + channel->last_was_revoke = true; return true; } @@ -1083,6 +1087,7 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg) struct changed_htlc *changed; struct bitcoin_tx *tx; size_t i; + struct channel *channel = peer2channel(peer); if (!fromwire_channel_got_commitsig(msg, msg, NULL, &commitnum, @@ -1109,18 +1114,18 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg) /* New HTLCs */ for (i = 0; i < tal_count(added); i++) { - if (!peer_added_their_htlc(peer, &added[i], &shared_secrets[i])) + if (!channel_added_their_htlc(channel, &added[i], &shared_secrets[i])) return; } /* Save information now for fulfilled & failed HTLCs */ for (i = 0; i < tal_count(fulfilled); i++) { - if (!peer_fulfilled_our_htlc(peer, &fulfilled[i])) + if (!peer_fulfilled_our_htlc(channel, &fulfilled[i])) return; } for (i = 0; i < tal_count(failed); i++) { - if (!peer_failed_our_htlc(peer, failed[i])) + if (!peer_failed_our_htlc(channel, failed[i])) return; } @@ -1134,34 +1139,34 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg) /* Update both feerates: if we're funder, REMOTE should already be * that feerate, if we're not, we're about to ACK anyway. */ - peer->channel_info->feerate_per_kw[LOCAL] - = peer->channel_info->feerate_per_kw[REMOTE] + channel->channel_info->feerate_per_kw[LOCAL] + = channel->channel_info->feerate_per_kw[REMOTE] = feerate; /* Since we're about to send revoke, bump state again. */ - if (!peer_sending_revocation(peer, added, fulfilled, failed, changed)) + if (!peer_sending_revocation(channel, added, fulfilled, failed, changed)) return; if (!peer_save_commitsig_received(peer, commitnum, tx, &commit_sig)) return; - wallet_channel_save(peer->ld->wallet, peer->channel); + wallet_channel_save(peer->ld->wallet, channel); - tal_free(peer->last_htlc_sigs); - peer->last_htlc_sigs = tal_steal(peer, htlc_sigs); - wallet_htlc_sigs_save(peer->ld->wallet, peer->channel->id, - peer->last_htlc_sigs); + tal_free(channel->last_htlc_sigs); + channel->last_htlc_sigs = tal_steal(channel, htlc_sigs); + wallet_htlc_sigs_save(peer->ld->wallet, channel->dbid, + channel->last_htlc_sigs); /* Tell it we've committed, and to go ahead with revoke. */ msg = towire_channel_got_commitsig_reply(msg); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(channel->owner, take(msg)); } /* Shuffle them over, forgetting the ancient one. */ void update_per_commit_point(struct peer *peer, const struct pubkey *per_commitment_point) { - struct channel_info *ci = peer->channel_info; + struct channel_info *ci = peer2channel(peer)->channel_info; ci->old_remote_per_commit = ci->remote_per_commit; ci->remote_per_commit = *per_commitment_point; } @@ -1173,6 +1178,7 @@ void peer_got_revoke(struct peer *peer, const u8 *msg) struct pubkey next_per_commitment_point; struct changed_htlc *changed; enum onion_type *failcodes; + struct channel *channel = peer2channel(peer); size_t i; if (!fromwire_channel_got_revoke(msg, msg, NULL, @@ -1211,10 +1217,10 @@ void peer_got_revoke(struct peer *peer, const u8 *msg) return; } - if (revokenum != revocations_received(&peer->their_shachain.chain)) { + if (revokenum != revocations_received(&channel->their_shachain.chain)) { peer_internal_error(peer, "got_revoke: expected %"PRIu64 " got %"PRIu64, - revocations_received(&peer->their_shachain.chain), revokenum); + revocations_received(&channel->their_shachain.chain), revokenum); return; } @@ -1223,7 +1229,8 @@ void peer_got_revoke(struct peer *peer, const u8 *msg) * A receiving node MAY fail if the `per_commitment_secret` was not * generated by the protocol in [BOLT #3] */ - if (!wallet_shachain_add_hash(peer->ld->wallet, &peer->their_shachain, + if (!wallet_shachain_add_hash(peer->ld->wallet, + &channel->their_shachain, shachain_index(revokenum), &per_commitment_secret)) { peer_fail_permanent(peer, @@ -1239,7 +1246,7 @@ void peer_got_revoke(struct peer *peer, const u8 *msg) /* Tell it we've committed, and to go ahead with revoke. */ msg = towire_channel_got_revoke_reply(msg); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(channel->owner, take(msg)); /* Now, any HTLCs we need to immediately fail? */ for (i = 0; i < tal_count(changed); i++) { @@ -1254,7 +1261,7 @@ void peer_got_revoke(struct peer *peer, const u8 *msg) hin = find_htlc_in(&peer->ld->htlcs_in, peer, changed[i].id); local_fail_htlc(hin, failcodes[i], NULL); } - wallet_channel_save(peer->ld->wallet, peer->channel); + wallet_channel_save(peer->ld->wallet, channel); } static void *tal_arr_append_(void **p, size_t size) @@ -1438,7 +1445,7 @@ void notify_new_block(struct lightningd *ld, u32 height) continue; /* Peer already failed, or we hit it? */ - if (hout->key.peer->error) + if (peer2channel(hout->key.peer)->error) continue; peer_fail_permanent(hout->key.peer, @@ -1482,7 +1489,7 @@ void notify_new_block(struct lightningd *ld, u32 height) continue; /* Peer already failed, or we hit it? */ - if (hin->key.peer->error) + if (peer2channel(hin->key.peer)->error) continue; peer_fail_permanent(hin->key.peer, @@ -1511,7 +1518,7 @@ void notify_feerate_change(struct lightningd *ld) /* FIXME: We choose not to drop to chain if we can't contact * peer. We *could* do so, however. */ - if (!peer->owner) + if (!peer2channel(peer)->owner) continue; msg = towire_channel_feerates(peer, @@ -1519,6 +1526,6 @@ void notify_feerate_change(struct lightningd *ld) FEERATE_IMMEDIATE), feerate_min(ld), feerate_max(ld)); - subd_send_msg(peer->owner, take(msg)); + subd_send_msg(peer2channel(peer)->owner, take(msg)); } } diff --git a/lightningd/peer_state.h b/lightningd/peer_state.h index 46227a340..c0e73de6f 100644 --- a/lightningd/peer_state.h +++ b/lightningd/peer_state.h @@ -2,6 +2,7 @@ #define LIGHTNING_LIGHTNINGD_PEER_STATE_H #include "config.h" +/* FIXME: rename channel_state! */ enum peer_state { UNINITIALIZED, diff --git a/lightningd/subd.c b/lightningd/subd.c index 707bf2938..710f00aee 100644 --- a/lightningd/subd.c +++ b/lightningd/subd.c @@ -416,8 +416,8 @@ static bool handle_sent_errmsg(struct subd *sd, const u8 *msg) return false; /* FIXME: if not all channels failed, hand back to gossipd! */ - if (!sd->peer->error) - sd->peer->error = tal_steal(sd->peer, errmsg); + if (!peer2channel(sd->peer)->error) + peer2channel(sd->peer)->error = tal_steal(sd->peer, errmsg); /* Don't free sd; we're may be about to free peer. */ sd->peer = NULL; diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index b0763d923..aae4503d4 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -58,9 +58,6 @@ struct log_book *new_log_book(const tal_t *ctx UNNEEDED, /* Generated stub for new_topology */ struct chain_topology *new_topology(struct lightningd *ld UNNEEDED, struct log *log UNNEEDED) { fprintf(stderr, "new_topology called!\n"); abort(); } -/* Generated stub for populate_peer */ -void populate_peer(struct lightningd *ld UNNEEDED, struct peer *peer UNNEEDED) -{ fprintf(stderr, "populate_peer called!\n"); abort(); } /* Generated stub for register_opts */ void register_opts(struct lightningd *ld UNNEEDED) { fprintf(stderr, "register_opts called!\n"); abort(); } @@ -94,12 +91,11 @@ const char *version(void) u32 wallet_channels_first_blocknum(struct wallet *w UNNEEDED) { fprintf(stderr, "wallet_channels_first_blocknum called!\n"); abort(); } /* Generated stub for wallet_channels_load_active */ -bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, - struct wallet *w UNNEEDED, struct list_head *peers UNNEEDED) +bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED) { fprintf(stderr, "wallet_channels_load_active called!\n"); abort(); } /* Generated stub for wallet_htlcs_load_for_channel */ bool wallet_htlcs_load_for_channel(struct wallet *wallet UNNEEDED, - struct wallet_channel *chan UNNEEDED, + struct channel *chan UNNEEDED, struct htlc_in_map *htlcs_in UNNEEDED, struct htlc_out_map *htlcs_out UNNEEDED) { fprintf(stderr, "wallet_htlcs_load_for_channel called!\n"); abort(); } diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index 4c5a88fa4..682e7f1ee 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -2876,7 +2876,7 @@ class LightningDTests(BaseLightningDTests): # Wait for l1 to notice wait_for(lambda: not 'connected' in l1.rpc.listpeers()['peers'][0]['channels'][0]) - # Now restart l1 and it should reload peers/channels from the DB + # Now restart l2 and it should reload peers/channels from the DB l2.daemon.start() wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 1) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index e79cddcab..9e4aa9eef 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -11,6 +11,8 @@ static void db_log_(struct log *log, enum log_level level, const char *fmt, ...) #include "wallet/wallet.c" #include "lightningd/htlc_end.c" +#include "lightningd/peer_control.c" +#include "lightningd/channel.c" #include "wallet/db.c" @@ -23,7 +25,167 @@ static void db_log_(struct log *log, enum log_level level, const char *fmt, ...) #include #include +bool deprecated_apis = true; + /* AUTOGENERATED MOCKS START */ +/* Generated stub for bip32_pubkey */ +bool bip32_pubkey(const struct ext_key *bip32_base UNNEEDED, + struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED) +{ fprintf(stderr, "bip32_pubkey called!\n"); abort(); } +/* Generated stub for bitcoind_gettxout */ +void bitcoind_gettxout(struct bitcoind *bitcoind UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, const u32 outnum UNNEEDED, + void (*cb)(struct bitcoind *bitcoind UNNEEDED, + const struct bitcoin_tx_output *txout UNNEEDED, + void *arg) UNNEEDED, + void *arg UNNEEDED) +{ fprintf(stderr, "bitcoind_gettxout called!\n"); abort(); } +/* Generated stub for broadcast_tx */ +void broadcast_tx(struct chain_topology *topo UNNEEDED, + struct peer *peer UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, + void (*failed)(struct peer *peer UNNEEDED, + int exitstatus UNNEEDED, + const char *err)) +{ fprintf(stderr, "broadcast_tx called!\n"); abort(); } +/* Generated stub for build_utxos */ +const struct utxo **build_utxos(const tal_t *ctx UNNEEDED, + struct lightningd *ld UNNEEDED, u64 satoshi_out UNNEEDED, + u32 feerate_per_kw UNNEEDED, u64 dust_limit UNNEEDED, + size_t outputscriptlen UNNEEDED, + u64 *change_satoshis UNNEEDED, u32 *change_keyindex UNNEEDED) +{ fprintf(stderr, "build_utxos called!\n"); abort(); } +/* Generated stub for channel_wire_type_name */ +const char *channel_wire_type_name(int e UNNEEDED) +{ fprintf(stderr, "channel_wire_type_name called!\n"); abort(); } +/* Generated stub for closing_wire_type_name */ +const char *closing_wire_type_name(int e UNNEEDED) +{ fprintf(stderr, "closing_wire_type_name called!\n"); abort(); } +/* Generated stub for command_fail */ +void command_fail(struct command *cmd UNNEEDED, const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "command_fail called!\n"); abort(); } +/* Generated stub for command_still_pending */ +void command_still_pending(struct command *cmd UNNEEDED) +{ fprintf(stderr, "command_still_pending called!\n"); abort(); } +/* Generated stub for command_success */ +void command_success(struct command *cmd UNNEEDED, struct json_result *response UNNEEDED) +{ fprintf(stderr, "command_success called!\n"); abort(); } +/* Generated stub for derive_basepoints */ +bool derive_basepoints(const struct privkey *seed UNNEEDED, + struct pubkey *funding_pubkey UNNEEDED, + struct basepoints *basepoints UNNEEDED, + struct secrets *secrets UNNEEDED, + struct sha256 *shaseed UNNEEDED) +{ fprintf(stderr, "derive_basepoints called!\n"); abort(); } +/* Generated stub for extract_channel_id */ +bool extract_channel_id(const u8 *in_pkt UNNEEDED, struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "extract_channel_id called!\n"); abort(); } +/* Generated stub for find_htlc_out_by_ripemd */ +struct htlc_out *find_htlc_out_by_ripemd(const struct peer *peer UNNEEDED, + const struct ripemd160 *ripemd160 UNNEEDED) +{ fprintf(stderr, "find_htlc_out_by_ripemd called!\n"); abort(); } +/* Generated stub for find_txwatch */ +struct txwatch *find_txwatch(struct chain_topology *topo UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + const struct peer *peer UNNEEDED) +{ fprintf(stderr, "find_txwatch called!\n"); abort(); } +/* Generated stub for fromwire_channel_got_funding_locked */ +bool fromwire_channel_got_funding_locked(const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED) +{ fprintf(stderr, "fromwire_channel_got_funding_locked called!\n"); abort(); } +/* Generated stub for fromwire_channel_got_shutdown */ +bool fromwire_channel_got_shutdown(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, u8 **scriptpubkey UNNEEDED) +{ fprintf(stderr, "fromwire_channel_got_shutdown called!\n"); abort(); } +/* Generated stub for fromwire_channel_shutdown_complete */ +bool fromwire_channel_shutdown_complete(const void *p UNNEEDED, size_t *plen UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED) +{ fprintf(stderr, "fromwire_channel_shutdown_complete called!\n"); abort(); } +/* Generated stub for fromwire_closing_complete */ +bool fromwire_closing_complete(const void *p UNNEEDED, size_t *plen UNNEEDED, u64 *gossip_index UNNEEDED) +{ fprintf(stderr, "fromwire_closing_complete called!\n"); abort(); } +/* Generated stub for fromwire_closing_received_signature */ +bool fromwire_closing_received_signature(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_tx **tx UNNEEDED) +{ fprintf(stderr, "fromwire_closing_received_signature called!\n"); abort(); } +/* Generated stub for fromwire_gossipctl_release_peer_reply */ +bool fromwire_gossipctl_release_peer_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct wireaddr *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED) +{ fprintf(stderr, "fromwire_gossipctl_release_peer_reply called!\n"); abort(); } +/* Generated stub for fromwire_gossipctl_release_peer_replyfail */ +bool fromwire_gossipctl_release_peer_replyfail(const void *p UNNEEDED, size_t *plen UNNEEDED) +{ fprintf(stderr, "fromwire_gossipctl_release_peer_replyfail called!\n"); abort(); } +/* Generated stub for fromwire_gossip_getpeers_reply */ +bool fromwire_gossip_getpeers_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey **id UNNEEDED, struct wireaddr **addr UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_getpeers_reply called!\n"); abort(); } +/* Generated stub for fromwire_gossip_peer_already_connected */ +bool fromwire_gossip_peer_already_connected(const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_peer_already_connected called!\n"); abort(); } +/* Generated stub for fromwire_gossip_peer_connected */ +bool fromwire_gossip_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_peer_connected called!\n"); abort(); } +/* Generated stub for fromwire_gossip_peer_connection_failed */ +bool fromwire_gossip_peer_connection_failed(const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED, u32 *timeout UNNEEDED, u32 *attempts UNNEEDED, bool *addr_unknown UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_peer_connection_failed called!\n"); abort(); } +/* Generated stub for fromwire_hsm_client_hsmfd_reply */ +bool fromwire_hsm_client_hsmfd_reply(const void *p UNNEEDED, size_t *plen UNNEEDED) +{ fprintf(stderr, "fromwire_hsm_client_hsmfd_reply called!\n"); abort(); } +/* Generated stub for fromwire_hsm_sign_funding_reply */ +bool fromwire_hsm_sign_funding_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_tx **tx UNNEEDED) +{ fprintf(stderr, "fromwire_hsm_sign_funding_reply called!\n"); abort(); } +/* Generated stub for fromwire_onchain_add_utxo */ +bool fromwire_onchain_add_utxo(const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_txid *prev_out_tx UNNEEDED, u32 *prev_out_index UNNEEDED, struct pubkey *per_commit_point UNNEEDED, u64 *value UNNEEDED) +{ fprintf(stderr, "fromwire_onchain_add_utxo called!\n"); abort(); } +/* Generated stub for fromwire_onchain_broadcast_tx */ +bool fromwire_onchain_broadcast_tx(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_tx **tx UNNEEDED) +{ fprintf(stderr, "fromwire_onchain_broadcast_tx called!\n"); abort(); } +/* Generated stub for fromwire_onchain_extracted_preimage */ +bool fromwire_onchain_extracted_preimage(const void *p UNNEEDED, size_t *plen UNNEEDED, struct preimage *preimage UNNEEDED) +{ fprintf(stderr, "fromwire_onchain_extracted_preimage called!\n"); abort(); } +/* Generated stub for fromwire_onchain_htlc_timeout */ +bool fromwire_onchain_htlc_timeout(const void *p UNNEEDED, size_t *plen UNNEEDED, struct htlc_stub *htlc UNNEEDED) +{ fprintf(stderr, "fromwire_onchain_htlc_timeout called!\n"); abort(); } +/* Generated stub for fromwire_onchain_init_reply */ +bool fromwire_onchain_init_reply(const void *p UNNEEDED, size_t *plen UNNEEDED, u8 *state UNNEEDED) +{ fprintf(stderr, "fromwire_onchain_init_reply called!\n"); abort(); } +/* Generated stub for fromwire_onchain_missing_htlc_output */ +bool fromwire_onchain_missing_htlc_output(const void *p UNNEEDED, size_t *plen UNNEEDED, struct htlc_stub *htlc UNNEEDED) +{ fprintf(stderr, "fromwire_onchain_missing_htlc_output called!\n"); abort(); } +/* Generated stub for fromwire_onchain_unwatch_tx */ +bool fromwire_onchain_unwatch_tx(const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "fromwire_onchain_unwatch_tx called!\n"); abort(); } +/* Generated stub for fromwire_opening_fundee_reply */ +bool fromwire_opening_fundee_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct channel_config *their_config UNNEEDED, struct bitcoin_tx **first_commit UNNEEDED, secp256k1_ecdsa_signature *first_commit_sig UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, struct pubkey *revocation_basepoint UNNEEDED, struct pubkey *payment_basepoint UNNEEDED, struct pubkey *htlc_basepoint UNNEEDED, struct pubkey *delayed_payment_basepoint UNNEEDED, struct pubkey *their_per_commit_point UNNEEDED, struct pubkey *remote_fundingkey UNNEEDED, struct bitcoin_txid *funding_txid UNNEEDED, u16 *funding_txout UNNEEDED, u64 *funding_satoshis UNNEEDED, u64 *push_msat UNNEEDED, u8 *channel_flags UNNEEDED, u32 *feerate_per_kw UNNEEDED, u8 **funding_signed_msg UNNEEDED) +{ fprintf(stderr, "fromwire_opening_fundee_reply called!\n"); abort(); } +/* Generated stub for fromwire_opening_funder_reply */ +bool fromwire_opening_funder_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct channel_config *their_config UNNEEDED, struct bitcoin_tx **first_commit UNNEEDED, secp256k1_ecdsa_signature *first_commit_sig UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, struct pubkey *revocation_basepoint UNNEEDED, struct pubkey *payment_basepoint UNNEEDED, struct pubkey *htlc_basepoint UNNEEDED, struct pubkey *delayed_payment_basepoint UNNEEDED, struct pubkey *their_per_commit_point UNNEEDED, u32 *minimum_depth UNNEEDED, struct pubkey *remote_fundingkey UNNEEDED, struct bitcoin_txid *funding_txid UNNEEDED, u32 *feerate_per_kw UNNEEDED) +{ fprintf(stderr, "fromwire_opening_funder_reply called!\n"); abort(); } +/* Generated stub for fromwire_opening_negotiation_failed */ +bool fromwire_opening_negotiation_failed(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, wirestring **msg UNNEEDED) +{ fprintf(stderr, "fromwire_opening_negotiation_failed called!\n"); abort(); } +/* Generated stub for funding_tx */ +struct bitcoin_tx *funding_tx(const tal_t *ctx UNNEEDED, + u16 *outnum UNNEEDED, + const struct utxo **utxomap UNNEEDED, + u64 funding_satoshis UNNEEDED, + const struct pubkey *local_fundingkey UNNEEDED, + const struct pubkey *remote_fundingkey UNNEEDED, + u64 change_satoshis UNNEEDED, + const struct pubkey *changekey UNNEEDED, + const struct ext_key *bip32_base UNNEEDED) +{ fprintf(stderr, "funding_tx called!\n"); abort(); } +/* Generated stub for get_block_height */ +u32 get_block_height(const struct chain_topology *topo UNNEEDED) +{ fprintf(stderr, "get_block_height called!\n"); abort(); } +/* Generated stub for get_chainparams */ +struct chainparams *get_chainparams(const struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "get_chainparams called!\n"); abort(); } +/* Generated stub for get_feerate */ +u32 get_feerate(const struct chain_topology *topo UNNEEDED, enum feerate feerate UNNEEDED) +{ fprintf(stderr, "get_feerate called!\n"); abort(); } +/* Generated stub for get_supported_global_features */ +u8 *get_supported_global_features(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "get_supported_global_features called!\n"); abort(); } +/* Generated stub for get_supported_local_features */ +u8 *get_supported_local_features(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "get_supported_local_features called!\n"); abort(); } +/* Generated stub for hsm_sync_read */ +u8 *hsm_sync_read(const tal_t *ctx UNNEEDED, struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "hsm_sync_read called!\n"); abort(); } /* Generated stub for invoices_create */ const struct invoice *invoices_create(struct invoices *invoices UNNEEDED, u64 *msatoshi TAKES UNNEEDED, @@ -74,8 +236,292 @@ void invoices_waitone(const tal_t *ctx UNNEEDED, void (*cb)(const struct invoice * UNNEEDED, void*) UNNEEDED, void *cbarg UNNEEDED) { fprintf(stderr, "invoices_waitone called!\n"); abort(); } +/* Generated stub for json_add_bool */ +void json_add_bool(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, + bool value UNNEEDED) +{ fprintf(stderr, "json_add_bool called!\n"); abort(); } +/* Generated stub for json_add_hex */ +void json_add_hex(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, + const void *data UNNEEDED, size_t len UNNEEDED) +{ fprintf(stderr, "json_add_hex called!\n"); abort(); } +/* Generated stub for json_add_log */ +void json_add_log(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, + const struct log_book *lr UNNEEDED, enum log_level minlevel UNNEEDED) +{ fprintf(stderr, "json_add_log called!\n"); abort(); } +/* Generated stub for json_add_num */ +void json_add_num(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, + unsigned int value UNNEEDED) +{ fprintf(stderr, "json_add_num called!\n"); abort(); } +/* Generated stub for json_add_pubkey */ +void json_add_pubkey(struct json_result *response UNNEEDED, + const char *fieldname UNNEEDED, + const struct pubkey *key UNNEEDED) +{ fprintf(stderr, "json_add_pubkey called!\n"); abort(); } +/* Generated stub for json_add_short_channel_id */ +void json_add_short_channel_id(struct json_result *response UNNEEDED, + const char *fieldname UNNEEDED, + const struct short_channel_id *id UNNEEDED) +{ fprintf(stderr, "json_add_short_channel_id called!\n"); abort(); } +/* Generated stub for json_add_string */ +void json_add_string(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, const char *value UNNEEDED) +{ fprintf(stderr, "json_add_string called!\n"); abort(); } +/* Generated stub for json_add_txid */ +void json_add_txid(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "json_add_txid called!\n"); abort(); } +/* Generated stub for json_add_u64 */ +void json_add_u64(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, + uint64_t value UNNEEDED) +{ fprintf(stderr, "json_add_u64 called!\n"); abort(); } +/* Generated stub for json_array_end */ +void json_array_end(struct json_result *ptr UNNEEDED) +{ fprintf(stderr, "json_array_end called!\n"); abort(); } +/* Generated stub for json_array_start */ +void json_array_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED) +{ fprintf(stderr, "json_array_start called!\n"); abort(); } +/* Generated stub for json_get_params */ +bool json_get_params(struct command *cmd UNNEEDED, + const char *buffer UNNEEDED, const jsmntok_t param[] UNNEEDED, ...) +{ fprintf(stderr, "json_get_params called!\n"); abort(); } +/* Generated stub for json_object_end */ +void json_object_end(struct json_result *ptr UNNEEDED) +{ fprintf(stderr, "json_object_end called!\n"); abort(); } +/* Generated stub for json_object_start */ +void json_object_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED) +{ fprintf(stderr, "json_object_start called!\n"); abort(); } +/* Generated stub for json_tok_bool */ +bool json_tok_bool(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool *b UNNEEDED) +{ fprintf(stderr, "json_tok_bool called!\n"); abort(); } +/* Generated stub for json_tok_loglevel */ +bool json_tok_loglevel(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, + enum log_level *level UNNEEDED) +{ fprintf(stderr, "json_tok_loglevel called!\n"); abort(); } +/* Generated stub for json_tok_number */ +bool json_tok_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, + unsigned int *num UNNEEDED) +{ fprintf(stderr, "json_tok_number called!\n"); abort(); } +/* Generated stub for json_tok_pubkey */ +bool json_tok_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, + struct pubkey *pubkey UNNEEDED) +{ fprintf(stderr, "json_tok_pubkey called!\n"); abort(); } +/* Generated stub for json_tok_u64 */ +bool json_tok_u64(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, + uint64_t *num UNNEEDED) +{ fprintf(stderr, "json_tok_u64 called!\n"); abort(); } +/* Generated stub for locate_tx */ +struct txlocator *locate_tx(const void *ctx UNNEEDED, const struct chain_topology *topo UNNEEDED, const struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "locate_tx called!\n"); abort(); } +/* Generated stub for log_add */ +void log_add(struct log *log UNNEEDED, const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "log_add called!\n"); abort(); } +/* Generated stub for log_io */ +void log_io(struct log *log UNNEEDED, enum log_level dir UNNEEDED, const char *comment UNNEEDED, + const void *data UNNEEDED, size_t len UNNEEDED) +{ fprintf(stderr, "log_io called!\n"); abort(); } +/* Generated stub for logv_add */ +void logv_add(struct log *log UNNEEDED, const char *fmt UNNEEDED, va_list ap UNNEEDED) +{ fprintf(stderr, "logv_add called!\n"); abort(); } +/* Generated stub for new_json_result */ +struct json_result *new_json_result(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "new_json_result called!\n"); abort(); } +/* Generated stub for new_peer_subd */ +struct subd *new_peer_subd(struct lightningd *ld UNNEEDED, + const char *name UNNEEDED, + struct peer *peer UNNEEDED, + const char *(*msgname)(int msgtype) UNNEEDED, + unsigned int (*msgcb)(struct subd * UNNEEDED, const u8 * UNNEEDED, + const int *fds) UNNEEDED, + ...) +{ fprintf(stderr, "new_peer_subd called!\n"); abort(); } +/* Generated stub for null_response */ +struct json_result *null_response(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "null_response called!\n"); abort(); } +/* Generated stub for onchain_failed_our_htlc */ +void onchain_failed_our_htlc(const struct peer *peer UNNEEDED, + const struct htlc_stub *htlc UNNEEDED, + const char *why UNNEEDED) +{ fprintf(stderr, "onchain_failed_our_htlc called!\n"); abort(); } +/* Generated stub for onchain_fulfilled_htlc */ +void onchain_fulfilled_htlc(struct peer *peer UNNEEDED, const struct preimage *preimage UNNEEDED) +{ fprintf(stderr, "onchain_fulfilled_htlc called!\n"); abort(); } +/* Generated stub for onchain_wire_type_name */ +const char *onchain_wire_type_name(int e UNNEEDED) +{ fprintf(stderr, "onchain_wire_type_name called!\n"); abort(); } +/* Generated stub for opening_wire_type_name */ +const char *opening_wire_type_name(int e UNNEEDED) +{ fprintf(stderr, "opening_wire_type_name called!\n"); abort(); } +/* Generated stub for peer_got_commitsig */ +void peer_got_commitsig(struct peer *peer UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "peer_got_commitsig called!\n"); abort(); } +/* Generated stub for peer_got_revoke */ +void peer_got_revoke(struct peer *peer UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "peer_got_revoke called!\n"); abort(); } +/* Generated stub for peer_htlcs */ +void peer_htlcs(const tal_t *ctx UNNEEDED, + const struct peer *peer UNNEEDED, + struct added_htlc **htlcs UNNEEDED, + enum htlc_state **htlc_states UNNEEDED, + struct fulfilled_htlc **fulfilled_htlcs UNNEEDED, + enum side **fulfilled_sides UNNEEDED, + const struct failed_htlc ***failed_htlcs UNNEEDED, + enum side **failed_sides UNNEEDED) +{ fprintf(stderr, "peer_htlcs called!\n"); abort(); } +/* Generated stub for peer_sending_commitsig */ +void peer_sending_commitsig(struct peer *peer UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "peer_sending_commitsig called!\n"); abort(); } +/* Generated stub for sanitize_error */ +char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, + struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "sanitize_error called!\n"); abort(); } +/* Generated stub for subd_release_peer */ +void subd_release_peer(struct subd *owner UNNEEDED, struct peer *peer UNNEEDED) +{ fprintf(stderr, "subd_release_peer called!\n"); abort(); } +/* Generated stub for subd_req_ */ +void subd_req_(const tal_t *ctx UNNEEDED, + struct subd *sd UNNEEDED, + const u8 *msg_out UNNEEDED, + int fd_out UNNEEDED, size_t num_fds_in UNNEEDED, + void (*replycb)(struct subd * UNNEEDED, const u8 * UNNEEDED, const int * UNNEEDED, void *) UNNEEDED, + void *replycb_data UNNEEDED) +{ fprintf(stderr, "subd_req_ called!\n"); abort(); } +/* Generated stub for subd_send_fd */ +void subd_send_fd(struct subd *sd UNNEEDED, int fd UNNEEDED) +{ fprintf(stderr, "subd_send_fd called!\n"); abort(); } +/* Generated stub for subd_send_msg */ +void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED) +{ fprintf(stderr, "subd_send_msg called!\n"); abort(); } +/* Generated stub for towire_channel_dev_reenable_commit */ +u8 *towire_channel_dev_reenable_commit(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channel_dev_reenable_commit called!\n"); abort(); } +/* Generated stub for towire_channel_funding_announce_depth */ +u8 *towire_channel_funding_announce_depth(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channel_funding_announce_depth called!\n"); abort(); } +/* Generated stub for towire_channel_funding_locked */ +u8 *towire_channel_funding_locked(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED) +{ fprintf(stderr, "towire_channel_funding_locked called!\n"); abort(); } +/* Generated stub for towire_channel_init */ +u8 *towire_channel_init(const tal_t *ctx UNNEEDED, const struct bitcoin_blkid *chain_hash UNNEEDED, const struct bitcoin_txid *funding_txid UNNEEDED, u16 funding_txout UNNEEDED, u64 funding_satoshi UNNEEDED, const struct channel_config *our_config UNNEEDED, const struct channel_config *their_config UNNEEDED, const u32 feerate_per_kw[2] UNNEEDED, u32 feerate_min UNNEEDED, u32 feerate_max UNNEEDED, const secp256k1_ecdsa_signature *first_commit_sig UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const struct pubkey *remote_fundingkey UNNEEDED, const struct pubkey *remote_revocation_basepoint UNNEEDED, const struct pubkey *remote_payment_basepoint UNNEEDED, const struct pubkey *remote_htlc_basepoint UNNEEDED, const struct pubkey *remote_delayed_payment_basepoint UNNEEDED, const struct pubkey *remote_per_commit UNNEEDED, const struct pubkey *old_remote_per_commit UNNEEDED, enum side funder UNNEEDED, u32 fee_base UNNEEDED, u32 fee_proportional UNNEEDED, u64 local_msatoshi UNNEEDED, const struct privkey *seed UNNEEDED, const struct pubkey *local_node_id UNNEEDED, const struct pubkey *remote_node_id UNNEEDED, u32 commit_msec UNNEEDED, u16 cltv_delta UNNEEDED, bool last_was_revoke UNNEEDED, const struct changed_htlc *last_sent_commit UNNEEDED, u64 next_index_local UNNEEDED, u64 next_index_remote UNNEEDED, u64 revocations_received UNNEEDED, u64 next_htlc_id UNNEEDED, const struct added_htlc *htlcs UNNEEDED, const enum htlc_state *htlc_states UNNEEDED, const struct fulfilled_htlc *fulfilled UNNEEDED, const enum side *fulfilled_sides UNNEEDED, const struct failed_htlc **failed UNNEEDED, const enum side *failed_sides UNNEEDED, bool local_funding_locked UNNEEDED, bool remote_funding_locked UNNEEDED, const struct short_channel_id *funding_short_id UNNEEDED, bool reestablish UNNEEDED, const u8 *shutdown_scriptpubkey UNNEEDED, bool remote_shutdown_received UNNEEDED, u8 flags UNNEEDED, const u8 *init_peer_pkt UNNEEDED) +{ fprintf(stderr, "towire_channel_init called!\n"); abort(); } +/* Generated stub for towire_channel_send_shutdown */ +u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *scriptpubkey UNNEEDED) +{ fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); } +/* Generated stub for towire_closing_init */ +u8 *towire_closing_init(const tal_t *ctx UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const struct privkey *seed UNNEEDED, const struct bitcoin_txid *funding_txid UNNEEDED, u16 funding_txout UNNEEDED, u64 funding_satoshi UNNEEDED, const struct pubkey *remote_fundingkey UNNEEDED, enum side funder UNNEEDED, u64 local_msatoshi UNNEEDED, u64 remote_msatoshi UNNEEDED, u64 our_dust_limit UNNEEDED, u64 min_fee_satoshi UNNEEDED, u64 fee_limit_satoshi UNNEEDED, u64 initial_fee_satoshi UNNEEDED, const u8 *local_scriptpubkey UNNEEDED, const u8 *remote_scriptpubkey UNNEEDED, bool reconnected UNNEEDED, u64 next_index_local UNNEEDED, u64 next_index_remote UNNEEDED, u64 revocations_received UNNEEDED, bool deprecated_api UNNEEDED) +{ fprintf(stderr, "towire_closing_init called!\n"); abort(); } +/* Generated stub for towire_closing_received_signature_reply */ +u8 *towire_closing_received_signature_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_closing_received_signature_reply called!\n"); abort(); } +/* Generated stub for towire_error */ +u8 *towire_error(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, const u8 *data UNNEEDED) +{ fprintf(stderr, "towire_error called!\n"); abort(); } +/* Generated stub for towire_errorfmt */ +u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, + const struct channel_id *channel UNNEEDED, + const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); } +/* Generated stub for towire_gossipctl_hand_back_peer */ +u8 *towire_gossipctl_hand_back_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "towire_gossipctl_hand_back_peer called!\n"); abort(); } +/* Generated stub for towire_gossipctl_peer_addrhint */ +u8 *towire_gossipctl_peer_addrhint(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, const struct wireaddr *addr UNNEEDED) +{ fprintf(stderr, "towire_gossipctl_peer_addrhint called!\n"); abort(); } +/* Generated stub for towire_gossipctl_reach_peer */ +u8 *towire_gossipctl_reach_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) +{ fprintf(stderr, "towire_gossipctl_reach_peer called!\n"); abort(); } +/* Generated stub for towire_gossipctl_release_peer */ +u8 *towire_gossipctl_release_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) +{ fprintf(stderr, "towire_gossipctl_release_peer called!\n"); abort(); } +/* Generated stub for towire_gossip_disable_channel */ +u8 *towire_gossip_disable_channel(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED, u8 direction UNNEEDED, bool active UNNEEDED) +{ fprintf(stderr, "towire_gossip_disable_channel called!\n"); abort(); } +/* Generated stub for towire_gossip_getpeers_request */ +u8 *towire_gossip_getpeers_request(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) +{ fprintf(stderr, "towire_gossip_getpeers_request called!\n"); abort(); } +/* Generated stub for towire_hsm_client_hsmfd */ +u8 *towire_hsm_client_hsmfd(const tal_t *ctx UNNEEDED, const struct pubkey *pubkey UNNEEDED, u64 capabilities UNNEEDED) +{ fprintf(stderr, "towire_hsm_client_hsmfd called!\n"); abort(); } +/* Generated stub for towire_hsm_sign_funding */ +u8 *towire_hsm_sign_funding(const tal_t *ctx UNNEEDED, u64 satoshi_out UNNEEDED, u64 change_out UNNEEDED, u32 change_keyindex UNNEEDED, const struct pubkey *our_pubkey UNNEEDED, const struct pubkey *their_pubkey UNNEEDED, const struct utxo **inputs UNNEEDED) +{ fprintf(stderr, "towire_hsm_sign_funding called!\n"); abort(); } +/* Generated stub for towire_onchain_depth */ +u8 *towire_onchain_depth(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED, u32 depth UNNEEDED) +{ fprintf(stderr, "towire_onchain_depth called!\n"); abort(); } +/* Generated stub for towire_onchain_htlc */ +u8 *towire_onchain_htlc(const tal_t *ctx UNNEEDED, const struct htlc_stub *htlc UNNEEDED, bool tell_if_missing UNNEEDED, bool tell_immediately UNNEEDED) +{ fprintf(stderr, "towire_onchain_htlc called!\n"); abort(); } +/* Generated stub for towire_onchain_init */ +u8 *towire_onchain_init(const tal_t *ctx UNNEEDED, const struct privkey *seed UNNEEDED, const struct shachain *shachain UNNEEDED, u64 funding_amount_satoshi UNNEEDED, const struct pubkey *old_remote_per_commitment_point UNNEEDED, const struct pubkey *remote_per_commitment_point UNNEEDED, u32 local_to_self_delay UNNEEDED, u32 remote_to_self_delay UNNEEDED, u32 feerate_per_kw UNNEEDED, u64 local_dust_limit_satoshi UNNEEDED, const struct pubkey *remote_revocation_basepoint UNNEEDED, const struct bitcoin_txid *our_broadcast_txid UNNEEDED, const u8 *local_scriptpubkey UNNEEDED, const u8 *remote_scriptpubkey UNNEEDED, const struct pubkey *ourwallet_pubkey UNNEEDED, enum side funder UNNEEDED, const struct pubkey *remote_payment_basepoint UNNEEDED, const struct pubkey *remote_htlc_basepoint UNNEEDED, const struct pubkey *remote_delayed_payment_basepoint UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, u32 tx_blockheight UNNEEDED, u32 reasonable_depth UNNEEDED, const secp256k1_ecdsa_signature *htlc_signature UNNEEDED, u64 num_htlcs UNNEEDED) +{ fprintf(stderr, "towire_onchain_init called!\n"); abort(); } +/* Generated stub for towire_onchain_known_preimage */ +u8 *towire_onchain_known_preimage(const tal_t *ctx UNNEEDED, const struct preimage *preimage UNNEEDED) +{ fprintf(stderr, "towire_onchain_known_preimage called!\n"); abort(); } +/* Generated stub for towire_onchain_spent */ +u8 *towire_onchain_spent(const tal_t *ctx UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, u32 input_num UNNEEDED, u32 blockheight UNNEEDED) +{ fprintf(stderr, "towire_onchain_spent called!\n"); abort(); } +/* Generated stub for towire_opening_fundee */ +u8 *towire_opening_fundee(const tal_t *ctx UNNEEDED, u32 minimum_depth UNNEEDED, u32 min_feerate UNNEEDED, u32 max_feerate UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "towire_opening_fundee called!\n"); abort(); } +/* Generated stub for towire_opening_funder */ +u8 *towire_opening_funder(const tal_t *ctx UNNEEDED, u64 funding_satoshis UNNEEDED, u64 push_msat UNNEEDED, u32 feerate_per_kw UNNEEDED, u32 max_minimum_depth UNNEEDED, u64 change_satoshis UNNEEDED, u32 change_keyindex UNNEEDED, u8 channel_flags UNNEEDED, const struct utxo **inputs UNNEEDED, const struct ext_key *bip32 UNNEEDED) +{ fprintf(stderr, "towire_opening_funder called!\n"); abort(); } +/* Generated stub for towire_opening_init */ +u8 *towire_opening_init(const tal_t *ctx UNNEEDED, u32 network_index UNNEEDED, const struct channel_config *our_config UNNEEDED, u32 max_to_self_delay UNNEEDED, u64 min_effective_htlc_capacity_msat UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const struct privkey *seed UNNEEDED) +{ fprintf(stderr, "towire_opening_init called!\n"); abort(); } +/* Generated stub for txfilter_add_scriptpubkey */ +void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, u8 *script UNNEEDED) +{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); } +/* Generated stub for unsupported_features */ +bool unsupported_features(const u8 *gfeatures UNNEEDED, const u8 *lfeatures UNNEEDED) +{ fprintf(stderr, "unsupported_features called!\n"); abort(); } +/* Generated stub for update_per_commit_point */ +void update_per_commit_point(struct peer *peer UNNEEDED, + const struct pubkey *per_commitment_point UNNEEDED) +{ fprintf(stderr, "update_per_commit_point called!\n"); abort(); } +/* Generated stub for watch_tx_ */ +struct txwatch *watch_tx_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + struct peer *peer UNNEEDED, + const struct bitcoin_tx *tx UNNEEDED, + enum watch_result (*cb)(struct peer *peer UNNEEDED, + const struct bitcoin_tx * UNNEEDED, + unsigned int depth UNNEEDED, + void *) UNNEEDED, + void *cbdata UNNEEDED) +{ fprintf(stderr, "watch_tx_ called!\n"); abort(); } +/* Generated stub for watch_txid_ */ +struct txwatch *watch_txid_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + struct peer *peer UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + enum watch_result (*cb)(struct peer *peer UNNEEDED, + const struct bitcoin_tx * UNNEEDED, + unsigned int depth UNNEEDED, + void *) UNNEEDED, + void *cbdata UNNEEDED) +{ fprintf(stderr, "watch_txid_ called!\n"); abort(); } +/* Generated stub for watch_txo_ */ +struct txowatch *watch_txo_(const tal_t *ctx UNNEEDED, + struct chain_topology *topo UNNEEDED, + struct peer *peer UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED, + unsigned int output UNNEEDED, + enum watch_result (*cb)(struct peer *peer UNNEEDED, + const struct bitcoin_tx *tx UNNEEDED, + size_t input_num UNNEEDED, + const struct block *block UNNEEDED, + void *) UNNEEDED, + void *cbdata UNNEEDED) +{ fprintf(stderr, "watch_txo_ called!\n"); abort(); } +/* Generated stub for wire_sync_write */ +bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED) +{ fprintf(stderr, "wire_sync_write called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ +#if DEVELOPER +bool dev_disconnect_permanent(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "dev_disconnect_permanent called!\n"); abort(); } +#endif + static char *wallet_err; static void wallet_fatal(const char *fmt, ...) { @@ -95,6 +541,40 @@ static void wallet_fatal(const char *fmt, ...) #define transaction_wrap(db, ...) \ (db_begin_transaction(db), __VA_ARGS__, db_commit_transaction(db), wallet_err == NULL) +enum log_level get_log_level(struct log_book *lr UNNEEDED) +{ + return LOG_DBG; +} + +struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, const char *fmt UNNEEDED, ...) +{ + return NULL; +} + +struct log_book *new_log_book(const tal_t *ctx UNNEEDED, + size_t max_mem UNNEEDED, + enum log_level printlevel UNNEEDED) +{ + return NULL; +} + +void set_log_outfn_(struct log_book *lr UNNEEDED, + void (*print)(const char *prefix UNNEEDED, + enum log_level level UNNEEDED, + bool continued UNNEEDED, + const struct timeabs *time UNNEEDED, + const char *str UNNEEDED, + const u8 *io UNNEEDED, + void *arg) UNNEEDED, + void *arg UNNEEDED) +{ +} + +const char *log_prefix(const struct log *log UNNEEDED) +{ + return ""; +} + /** * mempat -- Set the memory to a pattern * @@ -109,7 +589,7 @@ static void mempat(void *dst, size_t len) p[i] = n % 251; /* Prime */ } -static struct wallet *create_test_wallet(const tal_t *ctx) +static struct wallet *create_test_wallet(struct lightningd *ld, const tal_t *ctx) { char filename[] = "/tmp/ldb-XXXXXX"; int fd = mkstemp(filename); @@ -121,6 +601,7 @@ static struct wallet *create_test_wallet(const tal_t *ctx) ltmp = tal_tmpctx(ctx); list_head_init(&w->unstored_payments); + w->ld = ld; CHECK_MSG(w->db, "Failed opening the db"); db_migrate(w->db, w->log); @@ -272,29 +753,30 @@ static bool bitcoin_tx_eq(const struct bitcoin_tx *tx1, return eq; } -static bool channelseq(struct wallet_channel *c1, struct wallet_channel *c2) +static bool channelseq(struct channel *c1, struct channel *c2) { struct peer *p1 = c1->peer, *p2 = c2->peer; - struct channel_info *ci1 = p1->channel_info, *ci2 = p2->channel_info; - struct changed_htlc *lc1 = p1->last_sent_commit, *lc2 = p2->last_sent_commit; - CHECK(c1->id == c2->id); + struct channel_info *ci1 = c1->channel_info, *ci2 = c2->channel_info; + struct changed_htlc *lc1 = c1->last_sent_commit, *lc2 = c2->last_sent_commit; + CHECK(c1->dbid == c2->dbid); CHECK(c1->first_blocknum == c2->first_blocknum); CHECK(c1->peer->dbid == c2->peer->dbid); - CHECK(p1->their_shachain.id == p2->their_shachain.id); + CHECK(c1->peer == c2->peer); + CHECK(c1->their_shachain.id == c2->their_shachain.id); CHECK_MSG(pubkey_eq(&p1->id, &p2->id), "NodeIDs do not match"); - CHECK((p1->scid == NULL && p2->scid == NULL) || short_channel_id_eq(p1->scid, p2->scid)); - CHECK((p1->our_msatoshi == NULL) == (p2->our_msatoshi == NULL)); - if (p1->our_msatoshi) - CHECK(*p1->our_msatoshi == *p2->our_msatoshi); - CHECK((p1->remote_shutdown_scriptpubkey == NULL && p2->remote_shutdown_scriptpubkey == NULL) || memeq( - p1->remote_shutdown_scriptpubkey, - tal_len(p1->remote_shutdown_scriptpubkey), - p2->remote_shutdown_scriptpubkey, - tal_len(p2->remote_shutdown_scriptpubkey))); - CHECK((p1->funding_txid == NULL && p2->funding_txid == NULL) || memeq( - p1->funding_txid, + CHECK((c1->scid == NULL && c2->scid == NULL) || short_channel_id_eq(c1->scid, c2->scid)); + CHECK((c1->our_msatoshi == NULL) == (c2->our_msatoshi == NULL)); + if (c1->our_msatoshi) + CHECK(*c1->our_msatoshi == *c2->our_msatoshi); + CHECK((c1->remote_shutdown_scriptpubkey == NULL && c2->remote_shutdown_scriptpubkey == NULL) || memeq( + c1->remote_shutdown_scriptpubkey, + tal_len(c1->remote_shutdown_scriptpubkey), + c2->remote_shutdown_scriptpubkey, + tal_len(c2->remote_shutdown_scriptpubkey))); + CHECK((c1->funding_txid == NULL && c2->funding_txid == NULL) || memeq( + c1->funding_txid, sizeof(struct sha256_double), - p2->funding_txid, + c2->funding_txid, sizeof(struct sha256_double))); CHECK((ci1 != NULL) == (ci2 != NULL)); if(ci1) { @@ -307,54 +789,55 @@ static bool channelseq(struct wallet_channel *c1, struct wallet_channel *c2) CHECK(ci1->their_config.id != 0 && ci1->their_config.id == ci2->their_config.id); } - CHECK(p1->our_config.id != 0 && p1->our_config.id == p2->our_config.id); + CHECK(c1->our_config.id != 0 && c1->our_config.id == c2->our_config.id); CHECK((lc1 != NULL) == (lc2 != NULL)); if(lc1) { CHECK(lc1->newstate == lc2->newstate); CHECK(lc1->id == lc2->id); } - CHECK((p1->last_tx != NULL) == (p2->last_tx != NULL)); - if(p1->last_tx) { - CHECK(bitcoin_tx_eq(p1->last_tx, p2->last_tx)); + CHECK((c1->last_tx != NULL) == (c2->last_tx != NULL)); + if(c1->last_tx) { + CHECK(bitcoin_tx_eq(c1->last_tx, c2->last_tx)); } - CHECK((p1->last_sig != NULL) == (p2->last_sig != NULL)); - if(p1->last_sig) { - CHECK(memeq(p1->last_sig, sizeof(*p1->last_sig), - p2->last_sig, sizeof(*p2->last_sig))); + CHECK((c1->last_sig != NULL) == (c2->last_sig != NULL)); + if(c1->last_sig) { + CHECK(memeq(c1->last_sig, sizeof(*c1->last_sig), + c2->last_sig, sizeof(*c2->last_sig))); } - if (p1->remote_shutdown_scriptpubkey) { - CHECK(p2->remote_shutdown_scriptpubkey); - CHECK(p1->local_shutdown_idx == p2->local_shutdown_idx); + if (c1->remote_shutdown_scriptpubkey) { + CHECK(c2->remote_shutdown_scriptpubkey); + CHECK(c1->local_shutdown_idx == c2->local_shutdown_idx); } - CHECK(p1->last_was_revoke == p2->last_was_revoke); + CHECK(c1->last_was_revoke == c2->last_was_revoke); return true; } -static struct wallet_channel *wallet_channel_load(struct wallet *w, const u64 id) +static struct channel *wallet_channel_load(struct wallet *w, const u64 dbid) { - struct list_head peers; struct peer *peer; - - list_head_init(&peers); + struct channel *channel; /* We expect only one peer, but reuse same code */ - if (!wallet_channels_load_active(w, w, &peers)) + if (!wallet_channels_load_active(w, w)) return NULL; - peer = list_top(&peers, struct peer, list); + peer = list_top(&w->ld->peers, struct peer, list); CHECK(peer); - CHECK(peer->channel->id == id); - return peer->channel; + + /* We load lots of identical dbid channels: use last one */ + channel = list_tail(&peer->channels, struct channel, list); + assert(channel->dbid == dbid); + return channel; } -static bool test_channel_crud(const tal_t *ctx) +static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx) { - struct wallet *w = create_test_wallet(ctx); - struct wallet_channel c1, *c2 = tal(w, struct wallet_channel); - struct peer p; + struct wallet *w = create_test_wallet(ld, ctx); + struct channel c1, *c2 = tal(w, struct channel); + struct peer *p; struct channel_info ci; struct bitcoin_txid *hash = tal(w, struct bitcoin_txid); struct pubkey pk; @@ -366,21 +849,19 @@ static bool test_channel_crud(const tal_t *ctx) memset(&c1, 0, sizeof(c1)); memset(c2, 0, sizeof(*c2)); - memset(&p, 0, sizeof(p)); memset(&ci, 3, sizeof(ci)); mempat(hash, sizeof(*hash)); mempat(sig, sizeof(*sig)); mempat(&last_commit, sizeof(last_commit)); pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk); ci.feerate_per_kw[LOCAL] = ci.feerate_per_kw[REMOTE] = 31337; - mempat(&p.id, sizeof(p.id)); mempat(scriptpubkey, tal_len(scriptpubkey)); c1.first_blocknum = 1; - c1.peer = &p; - p.id = pk; - p.our_msatoshi = NULL; - p.last_tx = NULL; - p.state = CHANNELD_NORMAL; + p = new_peer(ld, 0, &pk, NULL); + c1.peer = p; + c1.our_msatoshi = NULL; + c1.last_tx = NULL; + c1.state = CHANNELD_NORMAL; memset(&ci.their_config, 0, sizeof(struct channel_config)); ci.remote_fundingkey = pk; ci.theirbase.revocation = pk; @@ -397,85 +878,85 @@ static bool test_channel_crud(const tal_t *ctx) wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Load from DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v1)"); /* We just inserted them into an empty DB so this must be 1 */ - CHECK(c1.id == 1); + CHECK(c1.dbid == 1); CHECK(c1.peer->dbid == 1); - CHECK(c1.peer->their_shachain.id == 1); + CHECK(c1.their_shachain.id == 1); /* Variant 2: update with scid set */ - c1.peer->scid = talz(w, struct short_channel_id); + c1.scid = talz(w, struct short_channel_id); wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v2)"); /* Updates should not result in new ids */ - CHECK(c1.id == 1); + CHECK(c1.dbid == 1); CHECK(c1.peer->dbid == 1); - CHECK(c1.peer->their_shachain.id == 1); + CHECK(c1.their_shachain.id == 1); /* Variant 3: update with our_satoshi set */ - c1.peer->our_msatoshi = &msat; - c1.peer->last_was_revoke = !c1.peer->last_was_revoke; + c1.our_msatoshi = &msat; + c1.last_was_revoke = !c1.last_was_revoke; wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v3)"); /* Variant 4: update with funding_tx_id */ - c1.peer->funding_txid = hash; + c1.funding_txid = hash; wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v4)"); /* Variant 5: update with channel_info */ - p.channel_info = &ci; + c1.channel_info = &ci; wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v5)"); /* Variant 6: update with last_commit_sent */ - p.last_sent_commit = &last_commit; + c1.last_sent_commit = &last_commit; wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v6)"); /* Variant 7: update with last_tx (taken from BOLT #3) */ - p.last_tx = bitcoin_tx_from_hex(w, "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", strlen("02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220")); - p.last_sig = sig; + c1.last_tx = bitcoin_tx_from_hex(w, "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", strlen("02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220")); + c1.last_sig = sig; wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v7)"); /* Variant 8: update and add remote_shutdown_scriptpubkey */ - p.remote_shutdown_scriptpubkey = scriptpubkey; - p.local_shutdown_idx = 1337; + c1.remote_shutdown_scriptpubkey = scriptpubkey; + c1.local_shutdown_idx = 1337; wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); - CHECK_MSG(c2 = wallet_channel_load(w, c1.id), tal_fmt(w, "Load from DB")); + CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v8)"); @@ -486,11 +967,11 @@ static bool test_channel_crud(const tal_t *ctx) return true; } -static bool test_channel_config_crud(const tal_t *ctx) +static bool test_channel_config_crud(struct lightningd *ld, const tal_t *ctx) { struct channel_config *cc1 = talz(ctx, struct channel_config), *cc2 = talz(ctx, struct channel_config); - struct wallet *w = create_test_wallet(ctx); + struct wallet *w = create_test_wallet(ld, ctx); CHECK(w); cc1->dust_limit_satoshis = 1; @@ -510,21 +991,21 @@ static bool test_channel_config_crud(const tal_t *ctx) return true; } -static bool test_htlc_crud(const tal_t *ctx) +static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx) { struct htlc_in in, *hin; struct htlc_out out, *hout; struct preimage payment_key; - struct wallet_channel *chan = tal(ctx, struct wallet_channel); + struct channel *chan = tal(ctx, struct channel); struct peer *peer = talz(ctx, struct peer); - struct wallet *w = create_test_wallet(ctx); + struct wallet *w = create_test_wallet(ld, ctx); struct htlc_in_map *htlcs_in = tal(ctx, struct htlc_in_map); struct htlc_out_map *htlcs_out = tal(ctx, struct htlc_out_map); /* Make sure we have our references correct */ CHECK(transaction_wrap(w->db, db_exec(__func__, w->db, "INSERT INTO channels (id) VALUES (1);"))); - chan->id = 1; + chan->dbid = 1; chan->peer = peer; memset(&in, 0, sizeof(in)); @@ -598,10 +1079,10 @@ static bool test_htlc_crud(const tal_t *ctx) return true; } -static bool test_payment_crud(const tal_t *ctx) +static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx) { struct wallet_payment *t = tal(ctx, struct wallet_payment), *t2; - struct wallet *w = create_test_wallet(ctx); + struct wallet *w = create_test_wallet(ld, ctx); mempat(t, sizeof(*t)); memset(&t->destination, 1, sizeof(t->destination)); @@ -642,13 +1123,21 @@ int main(void) { bool ok = true; tal_t *tmpctx = tal_tmpctx(NULL); + struct lightningd *ld = tal(tmpctx, struct lightningd); + + /* Only elements in ld we should access */ + list_head_init(&ld->peers); + pubkey_from_der(tal_hexdata(tmpctx, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &ld->id); + /* Accessed in peer destructor sanity check */ + htlc_in_map_init(&ld->htlcs_in); + htlc_out_map_init(&ld->htlcs_out); ok &= test_wallet_outputs(); ok &= test_shachain_crud(); - ok &= test_channel_crud(tmpctx); - ok &= test_channel_config_crud(tmpctx); - ok &= test_htlc_crud(tmpctx); - ok &= test_payment_crud(tmpctx); + ok &= test_channel_crud(ld, tmpctx); + ok &= test_channel_config_crud(ld, tmpctx); + ok &= test_htlc_crud(ld, tmpctx); + ok &= test_payment_crud(ld, tmpctx); tal_free(tmpctx); return !ok; diff --git a/wallet/wallet.c b/wallet/wallet.c index e65b40602..6b7d98ff6 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -410,29 +410,41 @@ bool wallet_shachain_load(struct wallet *wallet, u64 id, return true; } -static bool wallet_peer_load(struct wallet *w, const u64 id, struct peer *peer) +static struct peer *wallet_peer_load(const tal_t *ctx, + struct wallet *w, const u64 dbid) { - bool ok = true; const unsigned char *addrstr; + struct peer *peer; + struct pubkey id; + struct wireaddr *addrp, addr; sqlite3_stmt *stmt = db_query(__func__, w->db, - "SELECT id, node_id, address FROM peers WHERE id=%"PRIu64";", id); + "SELECT id, node_id, address FROM peers WHERE id=%"PRIu64";", dbid); if (!stmt || sqlite3_step(stmt) != SQLITE_ROW) { sqlite3_finalize(stmt); - return false; + return NULL; + } + if (!sqlite3_column_pubkey(stmt, 1, &id)) { + sqlite3_finalize(stmt); + return NULL; } - peer->dbid = sqlite3_column_int64(stmt, 0); - ok &= sqlite3_column_pubkey(stmt, 1, &peer->id); addrstr = sqlite3_column_text(stmt, 2); + if (addrstr) { + addrp = &addr; + if (!parse_wireaddr((const char*)addrstr, addrp, DEFAULT_PORT)) { + sqlite3_finalize(stmt); + return NULL; + } + } else + addrp = NULL; - if (addrstr) - parse_wireaddr((const char*)addrstr, &peer->addr, DEFAULT_PORT); - + peer = new_peer(w->ld, sqlite3_column_int64(stmt, 0), + &id, addrp); sqlite3_finalize(stmt); - return ok; + return peer; } bool wallet_peer_by_nodeid(struct wallet *w, const struct pubkey *nodeid, @@ -481,61 +493,64 @@ wallet_htlc_sigs_load(const tal_t *ctx, struct wallet *w, u64 channelid) /** * wallet_stmt2channel - Helper to populate a wallet_channel from a sqlite3_stmt - * - * Returns true on success. */ -static bool wallet_stmt2channel(const tal_t *ctx, struct wallet *w, sqlite3_stmt *stmt, - struct wallet_channel *chan) +static struct channel *wallet_stmt2channel(const tal_t *ctx, struct wallet *w, sqlite3_stmt *stmt) { bool ok = true; struct channel_info *channel_info; u64 remote_config_id; - - if (!chan->peer) { - chan->peer = talz(ctx, struct peer); + struct channel *chan; + u64 peer_dbid; + struct peer *peer; + + peer_dbid = sqlite3_column_int64(stmt, 1); + peer = find_peer_by_dbid(w->ld, peer_dbid); + if (!peer) { + peer = wallet_peer_load(ctx, w, peer_dbid); + if (!peer) + return NULL; } - chan->id = sqlite3_column_int64(stmt, 0); - chan->peer->dbid = sqlite3_column_int64(stmt, 1); - wallet_peer_load(w, chan->peer->dbid, chan->peer); + chan = new_channel(peer, sqlite3_column_int64(stmt, 0), + sqlite3_column_int64(stmt, 35)); if (sqlite3_column_type(stmt, 2) != SQLITE_NULL) { - chan->peer->scid = tal(chan->peer, struct short_channel_id); - sqlite3_column_short_channel_id(stmt, 2, chan->peer->scid); + chan->scid = tal(chan->peer, struct short_channel_id); + sqlite3_column_short_channel_id(stmt, 2, chan->scid); } else { - chan->peer->scid = NULL; + chan->scid = NULL; } - chan->peer->our_config.id = sqlite3_column_int64(stmt, 3); - wallet_channel_config_load(w, chan->peer->our_config.id, &chan->peer->our_config); + chan->our_config.id = sqlite3_column_int64(stmt, 3); + wallet_channel_config_load(w, chan->our_config.id, &chan->our_config); remote_config_id = sqlite3_column_int64(stmt, 4); - chan->peer->state = sqlite3_column_int(stmt, 5); - chan->peer->funder = sqlite3_column_int(stmt, 6); - chan->peer->channel_flags = sqlite3_column_int(stmt, 7); - chan->peer->minimum_depth = sqlite3_column_int(stmt, 8); - chan->peer->next_index[LOCAL] = sqlite3_column_int64(stmt, 9); - chan->peer->next_index[REMOTE] = sqlite3_column_int64(stmt, 10); - chan->peer->next_htlc_id = sqlite3_column_int64(stmt, 11); + chan->state = sqlite3_column_int(stmt, 5); + chan->funder = sqlite3_column_int(stmt, 6); + chan->channel_flags = sqlite3_column_int(stmt, 7); + chan->minimum_depth = sqlite3_column_int(stmt, 8); + chan->next_index[LOCAL] = sqlite3_column_int64(stmt, 9); + chan->next_index[REMOTE] = sqlite3_column_int64(stmt, 10); + chan->next_htlc_id = sqlite3_column_int64(stmt, 11); if (sqlite3_column_type(stmt, 12) != SQLITE_NULL) { assert(sqlite3_column_bytes(stmt, 12) == 32); - chan->peer->funding_txid = tal(chan->peer, struct bitcoin_txid); - memcpy(chan->peer->funding_txid, sqlite3_column_blob(stmt, 12), 32); + chan->funding_txid = tal(chan->peer, struct bitcoin_txid); + memcpy(chan->funding_txid, sqlite3_column_blob(stmt, 12), 32); } else { - chan->peer->funding_txid = NULL; + chan->funding_txid = NULL; } - chan->peer->funding_outnum = sqlite3_column_int(stmt, 13); - chan->peer->funding_satoshi = sqlite3_column_int64(stmt, 14); - chan->peer->remote_funding_locked = + chan->funding_outnum = sqlite3_column_int(stmt, 13); + chan->funding_satoshi = sqlite3_column_int64(stmt, 14); + chan->remote_funding_locked = sqlite3_column_int(stmt, 15) != 0; - chan->peer->push_msat = sqlite3_column_int64(stmt, 16); + chan->push_msat = sqlite3_column_int64(stmt, 16); if (sqlite3_column_type(stmt, 17) != SQLITE_NULL) { - chan->peer->our_msatoshi = tal(chan->peer, u64); - *chan->peer->our_msatoshi = sqlite3_column_int64(stmt, 17); + chan->our_msatoshi = tal(chan->peer, u64); + *chan->our_msatoshi = sqlite3_column_int64(stmt, 17); }else { - chan->peer->our_msatoshi = tal_free(chan->peer->our_msatoshi); + chan->our_msatoshi = tal_free(chan->our_msatoshi); } /* See if we have a valid commit_sig indicating the presence @@ -543,12 +558,12 @@ static bool wallet_stmt2channel(const tal_t *ctx, struct wallet *w, sqlite3_stmt if (sqlite3_column_type(stmt, 18) != SQLITE_NULL) { /* OK, so we have a valid sig, instantiate and/or fill * in channel_info */ - if (!chan->peer->channel_info) - chan->peer->channel_info = tal(chan->peer, struct channel_info); - channel_info = chan->peer->channel_info; + if (!chan->channel_info) + chan->channel_info = tal(chan, struct channel_info); + channel_info = chan->channel_info; /* Populate channel_info */ - ok &= sqlite3_column_pubkey(stmt, 18, &chan->peer->channel_info->remote_fundingkey); + ok &= sqlite3_column_pubkey(stmt, 18, &channel_info->remote_fundingkey); ok &= sqlite3_column_pubkey(stmt, 19, &channel_info->theirbase.revocation); ok &= sqlite3_column_pubkey(stmt, 20, &channel_info->theirbase.payment); ok &= sqlite3_column_pubkey(stmt, 21, &channel_info->theirbase.htlc); @@ -557,53 +572,52 @@ static bool wallet_stmt2channel(const tal_t *ctx, struct wallet *w, sqlite3_stmt ok &= sqlite3_column_pubkey(stmt, 24, &channel_info->old_remote_per_commit); channel_info->feerate_per_kw[LOCAL] = sqlite3_column_int(stmt, 25); channel_info->feerate_per_kw[REMOTE] = sqlite3_column_int(stmt, 26); - wallet_channel_config_load(w, remote_config_id, &chan->peer->channel_info->their_config); + wallet_channel_config_load(w, remote_config_id, &chan->channel_info->their_config); } /* Load shachain */ u64 shachain_id = sqlite3_column_int64(stmt, 27); - ok &= wallet_shachain_load(w, shachain_id, &chan->peer->their_shachain); + ok &= wallet_shachain_load(w, shachain_id, &chan->their_shachain); /* Do we have a non-null remote_shutdown_scriptpubkey? */ if (sqlite3_column_type(stmt, 28) != SQLITE_NULL) { - chan->peer->remote_shutdown_scriptpubkey = tal_arr(chan->peer, u8, sqlite3_column_bytes(stmt, 28)); - memcpy(chan->peer->remote_shutdown_scriptpubkey, sqlite3_column_blob(stmt, 28), sqlite3_column_bytes(stmt, 28)); - chan->peer->local_shutdown_idx = sqlite3_column_int64(stmt, 29); + chan->remote_shutdown_scriptpubkey = tal_arr(chan, u8, sqlite3_column_bytes(stmt, 28)); + memcpy(chan->remote_shutdown_scriptpubkey, sqlite3_column_blob(stmt, 28), sqlite3_column_bytes(stmt, 28)); + chan->local_shutdown_idx = sqlite3_column_int64(stmt, 29); } else { - chan->peer->remote_shutdown_scriptpubkey = tal_free(chan->peer->remote_shutdown_scriptpubkey); - chan->peer->local_shutdown_idx = -1; + chan->remote_shutdown_scriptpubkey = tal_free(chan->remote_shutdown_scriptpubkey); + chan->local_shutdown_idx = -1; } /* Do we have a last_sent_commit, if yes, populate */ if (sqlite3_column_type(stmt, 30) != SQLITE_NULL) { - if (!chan->peer->last_sent_commit) { - chan->peer->last_sent_commit = tal(chan->peer, struct changed_htlc); + if (!chan->last_sent_commit) { + chan->last_sent_commit = tal(chan, struct changed_htlc); } - chan->peer->last_sent_commit->newstate = sqlite3_column_int64(stmt, 30); - chan->peer->last_sent_commit->id = sqlite3_column_int64(stmt, 31); + chan->last_sent_commit->newstate = sqlite3_column_int64(stmt, 30); + chan->last_sent_commit->id = sqlite3_column_int64(stmt, 31); } else { - chan->peer->last_sent_commit = tal_free(chan->peer->last_sent_commit); + chan->last_sent_commit = tal_free(chan->last_sent_commit); } /* Do we have last_tx? If so, populate. */ if (sqlite3_column_type(stmt, 32) != SQLITE_NULL) { - chan->peer->last_tx = sqlite3_column_tx(chan->peer, stmt, 32); - chan->peer->last_sig = tal(chan->peer, secp256k1_ecdsa_signature); - sqlite3_column_signature(stmt, 33, chan->peer->last_sig); + chan->last_tx = sqlite3_column_tx(chan, stmt, 32); + chan->last_sig = tal(chan, secp256k1_ecdsa_signature); + sqlite3_column_signature(stmt, 33, chan->last_sig); } else { - chan->peer->last_tx = tal_free(chan->peer->last_tx); - chan->peer->last_sig = tal_free(chan->peer->last_sig); + chan->last_tx = tal_free(chan->last_tx); + chan->last_sig = tal_free(chan->last_sig); } - chan->peer->last_was_revoke = sqlite3_column_int(stmt, 34) != 0; - chan->first_blocknum = sqlite3_column_int64(stmt, 35); - - chan->peer->channel = chan; + chan->last_was_revoke = sqlite3_column_int(stmt, 34) != 0; /* Load any htlc_sigs */ - chan->peer->last_htlc_sigs = wallet_htlc_sigs_load(chan->peer, w, chan->id); + chan->last_htlc_sigs = wallet_htlc_sigs_load(chan, w, chan->dbid); - return ok; + if (!ok) + return tal_free(chan); + return chan; } /* List of fields to retrieve from the channels DB table, in the order @@ -623,7 +637,7 @@ static const char *channel_fields = "last_sent_commit_state, last_sent_commit_id, " "last_tx, last_sig, last_was_revoke, first_blocknum"; -bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w, struct list_head *peers) +bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w) { bool ok = true; sqlite3_stmt *stmt; @@ -641,11 +655,11 @@ bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w, struct list int count = 0; while (ok && stmt && sqlite3_step(stmt) == SQLITE_ROW) { - struct wallet_channel *c = talz(w, struct wallet_channel); - ok &= wallet_stmt2channel(ctx, w, stmt, c); - list_add(peers, &c->peer->list); - /* Peer owns channel. FIXME delete from db if peer freed! */ - tal_steal(c->peer, c); + struct channel *c = wallet_stmt2channel(ctx, w, stmt); + if (!c) { + ok = false; + break; + } count++; } log_debug(w->log, "Loaded %d channels from DB", count); @@ -726,14 +740,13 @@ bool wallet_channel_config_load(struct wallet *w, const u64 id, return ok; } -void wallet_channel_save(struct wallet *w, struct wallet_channel *chan) +void wallet_channel_save(struct wallet *w, struct channel *chan) { - struct peer *p = chan->peer; tal_t *tmpctx = tal_tmpctx(w); sqlite3_stmt *stmt; assert(chan->first_blocknum); - if (p->dbid == 0) { + if (chan->peer->dbid == 0) { /* Need to store the peer first */ stmt = db_prepare(w->db, "INSERT INTO peers (node_id, address) VALUES (?, ?);"); sqlite3_bind_pubkey(stmt, 1, &chan->peer->id); @@ -744,25 +757,27 @@ void wallet_channel_save(struct wallet *w, struct wallet_channel *chan) type_to_string(tmpctx, struct wireaddr, &chan->peer->addr), -1, SQLITE_TRANSIENT); db_exec_prepared(w->db, stmt); - p->dbid = sqlite3_last_insert_rowid(w->db->sql); + chan->peer->dbid = sqlite3_last_insert_rowid(w->db->sql); } /* Insert a stub, that we can update, unifies INSERT and UPDATE paths */ - if (chan->id == 0) { + if (chan->dbid == 0) { stmt = db_prepare(w->db, "INSERT INTO channels (" "peer_id, first_blocknum) VALUES (?, ?);"); - sqlite3_bind_int64(stmt, 1, p->dbid); + sqlite3_bind_int64(stmt, 1, chan->peer->dbid); sqlite3_bind_int(stmt, 2, chan->first_blocknum); db_exec_prepared(w->db, stmt); - chan->id = sqlite3_last_insert_rowid(w->db->sql); + chan->dbid = sqlite3_last_insert_rowid(w->db->sql); + derive_channel_seed(w->ld, &chan->seed, &chan->peer->id, + chan->dbid); } /* Need to initialize the shachain first so we get an id */ - if (p->their_shachain.id == 0) { - wallet_shachain_init(w, &p->their_shachain); + if (chan->their_shachain.id == 0) { + wallet_shachain_init(w, &chan->their_shachain); } - wallet_channel_config_save(w, &p->our_config); + wallet_channel_config_save(w, &chan->our_config); /* Now do the real update */ stmt = db_prepare(w->db, "UPDATE channels SET" @@ -787,46 +802,46 @@ void wallet_channel_save(struct wallet *w, struct wallet_channel *chan) " last_tx=?, last_sig=?," " last_was_revoke=?" " WHERE id=?"); - sqlite3_bind_int64(stmt, 1, p->their_shachain.id); - if (p->scid) - sqlite3_bind_short_channel_id(stmt, 2, p->scid); - sqlite3_bind_int(stmt, 3, p->state); - sqlite3_bind_int(stmt, 4, p->funder); - sqlite3_bind_int(stmt, 5, p->channel_flags); - sqlite3_bind_int(stmt, 6, p->minimum_depth); - - sqlite3_bind_int64(stmt, 7, p->next_index[LOCAL]); - sqlite3_bind_int64(stmt, 8, p->next_index[REMOTE]); - sqlite3_bind_int64(stmt, 9, p->next_htlc_id); - - if (p->funding_txid) - sqlite3_bind_blob(stmt, 10, p->funding_txid, sizeof(*p->funding_txid), SQLITE_TRANSIENT); - - sqlite3_bind_int(stmt, 11, p->funding_outnum); - sqlite3_bind_int64(stmt, 12, p->funding_satoshi); - sqlite3_bind_int(stmt, 13, p->remote_funding_locked); - sqlite3_bind_int64(stmt, 14, p->push_msat); - - if (p->our_msatoshi) - sqlite3_bind_int64(stmt, 15, *p->our_msatoshi); - - if (p->remote_shutdown_scriptpubkey) - sqlite3_bind_blob(stmt, 16, p->remote_shutdown_scriptpubkey, - tal_len(p->remote_shutdown_scriptpubkey), + sqlite3_bind_int64(stmt, 1, chan->their_shachain.id); + if (chan->scid) + sqlite3_bind_short_channel_id(stmt, 2, chan->scid); + sqlite3_bind_int(stmt, 3, chan->state); + sqlite3_bind_int(stmt, 4, chan->funder); + sqlite3_bind_int(stmt, 5, chan->channel_flags); + sqlite3_bind_int(stmt, 6, chan->minimum_depth); + + sqlite3_bind_int64(stmt, 7, chan->next_index[LOCAL]); + sqlite3_bind_int64(stmt, 8, chan->next_index[REMOTE]); + sqlite3_bind_int64(stmt, 9, chan->next_htlc_id); + + if (chan->funding_txid) + sqlite3_bind_blob(stmt, 10, chan->funding_txid, sizeof(*chan->funding_txid), SQLITE_TRANSIENT); + + sqlite3_bind_int(stmt, 11, chan->funding_outnum); + sqlite3_bind_int64(stmt, 12, chan->funding_satoshi); + sqlite3_bind_int(stmt, 13, chan->remote_funding_locked); + sqlite3_bind_int64(stmt, 14, chan->push_msat); + + if (chan->our_msatoshi) + sqlite3_bind_int64(stmt, 15, *chan->our_msatoshi); + + if (chan->remote_shutdown_scriptpubkey) + sqlite3_bind_blob(stmt, 16, chan->remote_shutdown_scriptpubkey, + tal_len(chan->remote_shutdown_scriptpubkey), SQLITE_TRANSIENT); - sqlite3_bind_int64(stmt, 17, p->local_shutdown_idx); - sqlite3_bind_int64(stmt, 18, p->our_config.id); - if (p->last_tx) - sqlite3_bind_tx(stmt, 19, p->last_tx); - if (p->last_sig) - sqlite3_bind_signature(stmt, 20, p->last_sig); - sqlite3_bind_int(stmt, 21, p->last_was_revoke); - sqlite3_bind_int64(stmt, 22, chan->id); + sqlite3_bind_int64(stmt, 17, chan->local_shutdown_idx); + sqlite3_bind_int64(stmt, 18, chan->our_config.id); + if (chan->last_tx) + sqlite3_bind_tx(stmt, 19, chan->last_tx); + if (chan->last_sig) + sqlite3_bind_signature(stmt, 20, chan->last_sig); + sqlite3_bind_int(stmt, 21, chan->last_was_revoke); + sqlite3_bind_int64(stmt, 22, chan->dbid); db_exec_prepared(w->db, stmt); - if (chan->peer->channel_info) { - wallet_channel_config_save(w, &p->channel_info->their_config); + if (chan->channel_info) { + wallet_channel_config_save(w, &chan->channel_info->their_config); stmt = db_prepare(w->db, "UPDATE channels SET" " fundingkey_remote=?," " revocation_basepoint_remote=?," @@ -839,30 +854,30 @@ void wallet_channel_save(struct wallet *w, struct wallet_channel *chan) " remote_feerate_per_kw=?," " channel_config_remote=?" " WHERE id=?"); - sqlite3_bind_pubkey(stmt, 1, &p->channel_info->remote_fundingkey); - sqlite3_bind_pubkey(stmt, 2, &p->channel_info->theirbase.revocation); - sqlite3_bind_pubkey(stmt, 3, &p->channel_info->theirbase.payment); - sqlite3_bind_pubkey(stmt, 4, &p->channel_info->theirbase.htlc); - sqlite3_bind_pubkey(stmt, 5, &p->channel_info->theirbase.delayed_payment); - sqlite3_bind_pubkey(stmt, 6, &p->channel_info->remote_per_commit); - sqlite3_bind_pubkey(stmt, 7, &p->channel_info->old_remote_per_commit); - sqlite3_bind_int(stmt, 8, p->channel_info->feerate_per_kw[LOCAL]); - sqlite3_bind_int(stmt, 9, p->channel_info->feerate_per_kw[REMOTE]); - sqlite3_bind_int64(stmt, 10, p->channel_info->their_config.id); - sqlite3_bind_int64(stmt, 11, chan->id); + sqlite3_bind_pubkey(stmt, 1, &chan->channel_info->remote_fundingkey); + sqlite3_bind_pubkey(stmt, 2, &chan->channel_info->theirbase.revocation); + sqlite3_bind_pubkey(stmt, 3, &chan->channel_info->theirbase.payment); + sqlite3_bind_pubkey(stmt, 4, &chan->channel_info->theirbase.htlc); + sqlite3_bind_pubkey(stmt, 5, &chan->channel_info->theirbase.delayed_payment); + sqlite3_bind_pubkey(stmt, 6, &chan->channel_info->remote_per_commit); + sqlite3_bind_pubkey(stmt, 7, &chan->channel_info->old_remote_per_commit); + sqlite3_bind_int(stmt, 8, chan->channel_info->feerate_per_kw[LOCAL]); + sqlite3_bind_int(stmt, 9, chan->channel_info->feerate_per_kw[REMOTE]); + sqlite3_bind_int64(stmt, 10, chan->channel_info->their_config.id); + sqlite3_bind_int64(stmt, 11, chan->dbid); db_exec_prepared(w->db, stmt); } /* If we have a last_sent_commit, store it */ - if (chan->peer->last_sent_commit) { + if (chan->last_sent_commit) { stmt = db_prepare(w->db, "UPDATE channels SET" " last_sent_commit_state=?," " last_sent_commit_id=?" " WHERE id=?"); - sqlite3_bind_int(stmt, 1, p->last_sent_commit->newstate); - sqlite3_bind_int64(stmt, 2, p->last_sent_commit->id); - sqlite3_bind_int64(stmt, 3, chan->id); + sqlite3_bind_int(stmt, 1, chan->last_sent_commit->newstate); + sqlite3_bind_int64(stmt, 2, chan->last_sent_commit->id); + sqlite3_bind_int64(stmt, 3, chan->dbid); db_exec_prepared(w->db, stmt); } @@ -926,7 +941,7 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, } void wallet_htlc_save_in(struct wallet *wallet, - const struct wallet_channel *chan, struct htlc_in *in) + const struct channel *chan, struct htlc_in *in) { tal_t *tmpctx = tal_tmpctx(wallet); sqlite3_stmt *stmt; @@ -946,7 +961,7 @@ void wallet_htlc_save_in(struct wallet *wallet, " routing_onion) VALUES " "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - sqlite3_bind_int64(stmt, 1, chan->id); + sqlite3_bind_int64(stmt, 1, chan->dbid); sqlite3_bind_int64(stmt, 2, in->key.id); sqlite3_bind_int(stmt, 3, DIRECTION_INCOMING); sqlite3_bind_int64(stmt, 4, in->msatoshi); @@ -969,7 +984,7 @@ void wallet_htlc_save_in(struct wallet *wallet, } void wallet_htlc_save_out(struct wallet *wallet, - const struct wallet_channel *chan, + const struct channel *chan, struct htlc_out *out) { tal_t *tmpctx = tal_tmpctx(wallet); @@ -994,7 +1009,7 @@ void wallet_htlc_save_out(struct wallet *wallet, " hstate," " routing_onion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - sqlite3_bind_int64(stmt, 1, chan->id); + sqlite3_bind_int64(stmt, 1, chan->dbid); sqlite3_bind_int64(stmt, 2, out->key.id); sqlite3_bind_int(stmt, 3, DIRECTION_OUTGOING); if (out->in) @@ -1038,13 +1053,13 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, db_exec_prepared(wallet->db, stmt); } -static bool wallet_stmt2htlc_in(const struct wallet_channel *channel, +static bool wallet_stmt2htlc_in(const struct channel *channel, sqlite3_stmt *stmt, struct htlc_in *in) { bool ok = true; in->dbid = sqlite3_column_int64(stmt, 0); in->key.id = sqlite3_column_int64(stmt, 1); - in->key.peer = channel->peer; + in->key.peer = channel2peer(channel); in->msatoshi = sqlite3_column_int64(stmt, 2); in->cltv_expiry = sqlite3_column_int(stmt, 3); in->hstate = sqlite3_column_int(stmt, 4); @@ -1072,13 +1087,13 @@ static bool wallet_stmt2htlc_in(const struct wallet_channel *channel, return ok; } -static bool wallet_stmt2htlc_out(const struct wallet_channel *channel, +static bool wallet_stmt2htlc_out(const struct channel *channel, sqlite3_stmt *stmt, struct htlc_out *out) { bool ok = true; out->dbid = sqlite3_column_int64(stmt, 0); out->key.id = sqlite3_column_int64(stmt, 1); - out->key.peer = channel->peer; + out->key.peer = channel2peer(channel); out->msatoshi = sqlite3_column_int64(stmt, 2); out->cltv_expiry = sqlite3_column_int(stmt, 3); out->hstate = sqlite3_column_int(stmt, 4); @@ -1112,20 +1127,20 @@ static bool wallet_stmt2htlc_out(const struct wallet_channel *channel, } bool wallet_htlcs_load_for_channel(struct wallet *wallet, - struct wallet_channel *chan, + struct channel *chan, struct htlc_in_map *htlcs_in, struct htlc_out_map *htlcs_out) { bool ok = true; int incount = 0, outcount = 0; - log_debug(wallet->log, "Loading HTLCs for channel %"PRIu64, chan->id); + log_debug(wallet->log, "Loading HTLCs for channel %"PRIu64, chan->dbid); sqlite3_stmt *stmt = db_query( __func__, wallet->db, "SELECT id, channel_htlc_id, msatoshi, cltv_expiry, hstate, " "payment_hash, shared_secret, payment_key, routing_onion FROM channel_htlcs WHERE " "direction=%d AND channel_id=%" PRIu64 " AND hstate != %d", - DIRECTION_INCOMING, chan->id, SENT_REMOVE_ACK_REVOCATION); + DIRECTION_INCOMING, chan->dbid, SENT_REMOVE_ACK_REVOCATION); if (!stmt) { log_broken(wallet->log, "Could not select htlc_ins"); @@ -1146,7 +1161,7 @@ bool wallet_htlcs_load_for_channel(struct wallet *wallet, "SELECT id, channel_htlc_id, msatoshi, cltv_expiry, hstate, " "payment_hash, origin_htlc, payment_key, routing_onion FROM channel_htlcs WHERE " "direction=%d AND channel_id=%" PRIu64 " AND hstate != %d", - DIRECTION_OUTGOING, chan->id, RCVD_REMOVE_ACK_REVOCATION); + DIRECTION_OUTGOING, chan->dbid, RCVD_REMOVE_ACK_REVOCATION); if (!stmt) { log_broken(wallet->log, "Could not select htlc_outs"); @@ -1264,7 +1279,7 @@ void wallet_invoice_waitone(const tal_t *ctx, struct htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, - struct wallet_channel *chan) + struct channel *chan) { struct htlc_stub *stubs; struct sha256 payment_hash; @@ -1272,7 +1287,7 @@ struct htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, "SELECT channel_id, direction, cltv_expiry, payment_hash " "FROM channel_htlcs WHERE channel_id = ?;"); - sqlite3_bind_int64(stmt, 1, chan->id); + sqlite3_bind_int64(stmt, 1, chan->dbid); stubs = tal_arr(ctx, struct htlc_stub, 0); @@ -1280,7 +1295,7 @@ struct htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, int n = tal_count(stubs); tal_resize(&stubs, n+1); - assert(sqlite3_column_int64(stmt, 0) == chan->id); + assert(sqlite3_column_int64(stmt, 0) == chan->dbid); /* FIXME: merge these two enums */ stubs[n].owner = sqlite3_column_int(stmt, 1)==DIRECTION_INCOMING?REMOTE:LOCAL; diff --git a/wallet/wallet.h b/wallet/wallet.h index 25f20bf88..9d37fcc4d 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -15,6 +15,7 @@ #include struct invoices; +struct channel; struct lightningd; struct oneshot; struct pubkey; @@ -62,17 +63,6 @@ struct wallet_shachain { struct shachain chain; }; -/* A database backed peer struct. Like wallet_shachain, it is writethrough. */ -/* TODO(cdecker) Separate peer from channel */ -struct wallet_channel { - u64 id; - struct peer *peer; - - /* Blockheight at creation, scans for funding confirmations - * will start here */ - u64 first_blocknum; -}; - /* Possible states for a wallet_payment. Payments start in * `PENDING`. Outgoing payments are set to `PAYMENT_COMPLETE` once we * get the preimage matching the rhash, or to @@ -221,7 +211,7 @@ bool wallet_shachain_load(struct wallet *wallet, u64 id, * @chan: the instance to store (not const so we can update the unique_id upon * insert) */ -void wallet_channel_save(struct wallet *w, struct wallet_channel *chan); +void wallet_channel_save(struct wallet *w, struct channel *chan); /** * wallet_channel_delete -- After resolving a channel, forget about it @@ -259,13 +249,11 @@ bool wallet_peer_by_nodeid(struct wallet *w, const struct pubkey *nodeid, * * @ctx: context to allocate peers from * @w: wallet to load from - * @peers: list_head to load channels/peers into * * Be sure to call this only once on startup since it'll append peers * loaded from the database to the list without checking. */ -bool wallet_channels_load_active(const tal_t *ctx, - struct wallet *w, struct list_head *peers); +bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w); /** * wallet_channels_first_blocknum - get first block we're interested in. @@ -286,7 +274,7 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, * wallet_htlc_save_in - store an htlc_in in the database * * @wallet: wallet to store the htlc into - * @chan: the `wallet_channel` this HTLC is associated with + * @chan: the channel this HTLC is associated with * @in: the htlc_in to store * * This will store the contents of the `struct htlc_in` in the @@ -298,7 +286,7 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, * HTLCs. */ void wallet_htlc_save_in(struct wallet *wallet, - const struct wallet_channel *chan, struct htlc_in *in); + const struct channel *chan, struct htlc_in *in); /** * wallet_htlc_save_out - store an htlc_out in the database @@ -306,7 +294,7 @@ void wallet_htlc_save_in(struct wallet *wallet, * See comment for wallet_htlc_save_in. */ void wallet_htlc_save_out(struct wallet *wallet, - const struct wallet_channel *chan, + const struct channel *chan, struct htlc_out *out); /** @@ -347,7 +335,7 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, * corresponding htlc_in after loading all channels. */ bool wallet_htlcs_load_for_channel(struct wallet *wallet, - struct wallet_channel *chan, + struct channel *chan, struct htlc_in_map *htlcs_in, struct htlc_out_map *htlcs_out); @@ -555,7 +543,7 @@ void wallet_invoice_waitone(const tal_t *ctx, * @chan: Channel to fetch stubs for */ struct htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, - struct wallet_channel *chan); + struct channel *chan); /** * wallet_payment_setup - Remember this payment for later committing. diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index e3b34bc77..96fc50074 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -414,21 +414,26 @@ static void json_listfunds(struct command *cmd, const char *buffer UNUSED, /* Add funds that are allocated to channels */ json_array_start(response, "channels"); list_for_each(&cmd->ld->peers, p, list) { - if (!p->our_msatoshi || !p->funding_txid) - continue; - - json_object_start(response, NULL); - json_add_pubkey(response, "peer_id", &p->id); - if (p->scid) - json_add_short_channel_id(response, "short_channel_id", - p->scid); - - /* Poor man's rounding to satoshis to match the unit for outputs */ - json_add_u64(response, "channel_sat", (*p->our_msatoshi + 500)/1000); - json_add_u64(response, "channel_total_sat", - p->funding_satoshi); - json_add_txid(response, "funding_txid", p->funding_txid); - json_object_end(response); + struct channel *c; + list_for_each(&p->channels, c, list) { + if (!c->our_msatoshi || !c->funding_txid) + continue; + + json_object_start(response, NULL); + json_add_pubkey(response, "peer_id", &p->id); + if (c->scid) + json_add_short_channel_id(response, + "short_channel_id", + c->scid); + + /* Poor man's rounding to satoshis to match the unit for outputs */ + json_add_u64(response, "channel_sat", + (*c->our_msatoshi + 500)/1000); + json_add_u64(response, "channel_total_sat", + c->funding_satoshi); + json_add_txid(response, "funding_txid", c->funding_txid); + json_object_end(response); + } } json_array_end(response); json_object_end(response);