Browse Source

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 <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
32411de90e
  1. 1
      lightningd/Makefile
  2. 14
      lightningd/dev_ping.c
  3. 31
      lightningd/lightningd.c
  4. 17
      lightningd/lightningd.h
  5. 789
      lightningd/peer_control.c
  6. 137
      lightningd/peer_control.h
  7. 153
      lightningd/peer_htlcs.c
  8. 1
      lightningd/peer_state.h
  9. 4
      lightningd/subd.c
  10. 8
      lightningd/test/run-find_my_path.c
  11. 2
      tests/test_lightningd.py
  12. 655
      wallet/test/run-wallet.c
  13. 317
      wallet/wallet.c
  14. 28
      wallet/wallet.h
  15. 19
      wallet/walletrpc.c

1
lightningd/Makefile

@ -49,6 +49,7 @@ LIGHTNINGD_SRC := \
lightningd/bitcoind.c \ lightningd/bitcoind.c \
lightningd/build_utxos.c \ lightningd/build_utxos.c \
lightningd/chaintopology.c \ lightningd/chaintopology.c \
lightningd/channel.c \
lightningd/gossip_control.c \ lightningd/gossip_control.c \
lightningd/gossip_msg.c \ lightningd/gossip_msg.c \
lightningd/hsm_control.c \ lightningd/hsm_control.c \

14
lightningd/dev_ping.c

@ -79,15 +79,19 @@ static void json_dev_ping(struct command *cmd,
/* First, see if it's in channeld. */ /* First, see if it's in channeld. */
peer = peer_by_id(cmd->ld, &id); peer = peer_by_id(cmd->ld, &id);
if (peer) { if (peer) {
if (!peer->owner || struct channel *channel = peer_active_channel(peer);
!streq(peer->owner->name, "lightning_channeld")) {
if (!channel
|| !channel->owner
|| !streq(channel->owner->name, "lightning_channeld")) {
command_fail(cmd, "Peer in %s", command_fail(cmd, "Peer in %s",
peer->owner channel && channel->owner
? peer->owner->name : "unattached"); ? channel->owner->name
: "unattached");
return; return;
} }
msg = towire_channel_ping(cmd, pongbytes, len); msg = towire_channel_ping(cmd, pongbytes, len);
owner = peer->owner; owner = channel->owner;
} else { } else {
/* We assume it's in gossipd. */ /* We assume it's in gossipd. */
msg = towire_gossip_ping(cmd, &id, pongbytes, len); msg = towire_gossip_ping(cmd, &id, pongbytes, len);

31
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)); 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) static void shutdown_subdaemons(struct lightningd *ld)
{ {
struct peer *p; struct peer *p;
@ -306,20 +292,23 @@ int main(int argc, char *argv[])
gossip_init(ld); gossip_init(ld);
/* Load peers from database */ /* 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 */ /* TODO(cdecker) Move this into common location for initialization */
struct peer *peer; struct peer *peer;
list_for_each(&ld->peers, peer, list) { list_for_each(&ld->peers, peer, list) {
populate_peer(ld, peer); struct channel *channel;
peer->seed = tal(peer, struct privkey);
derive_peer_seed(ld, peer->seed, &peer->id, peer->channel->id); list_for_each(&peer->channels, channel, list) {
peer->owner = NULL; if (!wallet_htlcs_load_for_channel(ld->wallet,
if (!wallet_htlcs_load_for_channel(ld->wallet, peer->channel, channel,
&ld->htlcs_in, &ld->htlcs_out)) { &ld->htlcs_in,
&ld->htlcs_out)) {
fatal("could not load htlcs for channel"); fatal("could not load htlcs for channel");
} }
} }
}
if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out)) if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out))
fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent."); fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent.");

17
lightningd/lightningd.h

@ -162,23 +162,6 @@ struct lightningd {
#endif /* DEVELOPER */ #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); struct chainparams *get_chainparams(const struct lightningd *ld);
/* State for performing backtraces. */ /* State for performing backtraces. */

789
lightningd/peer_control.c

File diff suppressed because it is too large

137
lightningd/peer_control.h

@ -8,6 +8,7 @@
#include <common/htlc.h> #include <common/htlc.h>
#include <common/json.h> #include <common/json.h>
#include <common/wireaddr.h> #include <common/wireaddr.h>
#include <lightningd/channel.h>
#include <lightningd/peer_state.h> #include <lightningd/peer_state.h>
#include <stdbool.h> #include <stdbool.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
@ -30,133 +31,27 @@ struct peer {
/* ID of peer */ /* ID of peer */
struct pubkey id; struct pubkey id;
/* Error message (iff in error state) */ /* Our channels */
u8 *error; struct list_head channels;
/* 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;
/* History */ /* History */
struct log_book *log_book; struct log_book *log_book;
struct log *log;
/* Channel flags from opening message. */ /* FIXME: Remove in favor of channel->log */
u8 channel_flags; struct log *log;
/* Where we connected to, or it connected from. */ /* Where we connected to, or it connected from. */
struct wireaddr addr; 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 */ /* If we open a channel our direction will be this */
u8 direction; u8 direction;
}; };
static inline bool peer_can_add_htlc(const struct peer *peer) struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid);
{
return peer->state == CHANNELD_NORMAL; struct peer *new_peer(struct lightningd *ld, u64 dbid,
} const struct pubkey *id,
const struct wireaddr *addr);
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 *peer_by_id(struct lightningd *ld, const struct pubkey *id); struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id);
struct peer *peer_from_json(struct lightningd *ld, 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, int peer_fd, int gossip_fd,
const u8 *in_msg); 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. */ /* Could be configurable. */
#define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL #define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL

153
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); htlc_in_update_state(hin->key.peer, hin, SENT_REMOVE_HTLC);
/* Tell peer, if we can. */ /* Tell peer, if we can. */
if (!hin->key.peer->owner) if (!peer2channel(hin->key.peer)->owner)
return; return;
subd_send_msg(hin->key.peer->owner, subd_send_msg(peer2channel(hin->key.peer)->owner,
take(towire_channel_fail_htlc(hin, take(towire_channel_fail_htlc(hin,
hin->key.id, hin->key.id,
hin->failuremsg, hin->failuremsg,
@ -127,7 +127,7 @@ static void fail_out_htlc(struct htlc_out *hout, const char *localfail)
assert(hout->failcode || hout->failuremsg); assert(hout->failcode || hout->failuremsg);
if (hout->in) { if (hout->in) {
fail_in_htlc(hout->in, hout->failcode, hout->failuremsg, fail_in_htlc(hout->in, hout->failcode, hout->failuremsg,
hout->key.peer->scid); peer2channel(hout->key.peer)->scid);
} else { } else {
payment_failed(hout->key.peer->ld, hout, localfail); 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 /* No owner? We'll either send to channeld in peer_htlcs, or
* onchaind in onchaind_tell_fulfill. */ * 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."); log_debug(hin->key.peer->log, "HTLC fulfilled, but no owner.");
return; return;
} }
if (peer_state_on_chain(hin->key.peer->state)) { if (peer_on_chain(hin->key.peer)) {
msg = towire_onchain_known_preimage(hin, preimage); msg = towire_onchain_known_preimage(hin, preimage);
} else { } else {
msg = towire_channel_fulfill_htlc(hin, hin->key.id, preimage); 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, 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); payment_failed(hout->key.peer->ld, hout, localfail);
} else } else
local_fail_htlc(hout->in, failure_code, local_fail_htlc(hout->in, failure_code,
hout->key.peer->scid); peer2channel(hout->key.peer)->scid);
/* Prevent hout from being failed twice. */ /* Prevent hout from being failed twice. */
tal_del_destructor(hout, hout_subd_died); tal_del_destructor(hout, hout_subd_died);
tal_free(hout); 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 **houtp)
{ {
struct htlc_out *hout; struct htlc_out *hout;
struct channel *channel = peer2channel(out);
u8 *msg; u8 *msg;
if (!peer_can_add_htlc(out)) { if (!peer_can_add_htlc(out)) {
log_info(out->log, "Attempt to send HTLC but not ready (%s)", 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; return WIRE_UNKNOWN_NEXT_PEER;
} }
if (!out->owner) { if (!channel->owner) {
log_info(out->log, "Attempt to send HTLC but unowned (%s)", 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; return WIRE_TEMPORARY_CHANNEL_FAILURE;
} }
/* Make peer's daemon own it, catch if it dies. */ /* 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); payment_hash, onion_routing_packet, in);
tal_add_destructor(hout, hout_subd_died); tal_add_destructor(hout, hout_subd_died);
msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash, msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash,
onion_routing_packet); 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) if (houtp)
*houtp = hout; *houtp = hout;
@ -420,7 +421,7 @@ static void forward_htlc(struct htlc_in *hin,
struct peer *next = peer_by_id(ld, next_hop); struct peer *next = peer_by_id(ld, next_hop);
/* Unknown peer, or peer not ready. */ /* Unknown peer, or peer not ready. */
if (!next || !next->scid) { if (!next || !peer2channel(next)->scid) {
local_fail_htlc(hin, WIRE_UNKNOWN_NEXT_PEER, NULL); local_fail_htlc(hin, WIRE_UNKNOWN_NEXT_PEER, NULL);
return; return;
} }
@ -491,7 +492,7 @@ static void forward_htlc(struct htlc_in *hin,
return; return;
fail: fail:
local_fail_htlc(hin, failcode, next->scid); local_fail_htlc(hin, failcode, peer2channel(next)->scid);
} }
/* Temporary information, while we resolve the next hop */ /* 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 * A sending node SHOULD fail to route any HTLC added after it
* sent `shutdown`. */ * sent `shutdown`. */
if (peer->state == CHANNELD_SHUTTING_DOWN) { if (peer2channel(peer)->state == CHANNELD_SHUTTING_DOWN) {
*failcode = WIRE_PERMANENT_CHANNEL_FAILURE; *failcode = WIRE_PERMANENT_CHANNEL_FAILURE;
goto out; 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); 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) const struct fulfilled_htlc *fulfilled)
{ {
struct htlc_out *hout; struct htlc_out *hout;
struct peer *peer = channel2peer(channel);
hout = find_htlc_out(&peer->ld->htlcs_out, peer, fulfilled->id); hout = find_htlc_out(&peer->ld->htlcs_out, peer, fulfilled->id);
if (!hout) { 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) const struct failed_htlc *failed)
{ {
struct htlc_out *hout; struct htlc_out *hout;
struct peer *peer = channel2peer(channel);
hout = find_htlc_out(&peer->ld->htlcs_out, peer, failed->id); hout = find_htlc_out(&peer->ld->htlcs_out, peer, failed->id);
if (!hout) { if (!hout) {
@ -784,7 +787,7 @@ void onchain_failed_our_htlc(const struct peer *peer,
tal_free(localfail); tal_free(localfail);
} else } else
local_fail_htlc(hout->in, WIRE_PERMANENT_CHANNEL_FAILURE, 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) 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 we fulfilled their HTLC, credit us. */
if (hin->preimage) { if (hin->preimage) {
log_debug(peer->log, "Balance %"PRIu64" -> %"PRIu64, log_debug(peer->log, "Balance %"PRIu64" -> %"PRIu64,
*peer->our_msatoshi, *peer2channel(peer)->our_msatoshi,
*peer->our_msatoshi + hin->msatoshi); *peer2channel(peer)->our_msatoshi + hin->msatoshi);
*peer->our_msatoshi += hin->msatoshi; *peer2channel(peer)->our_msatoshi += hin->msatoshi;
} }
tal_free(hin); tal_free(hin);
@ -825,9 +828,9 @@ static void remove_htlc_out(struct peer *peer, struct htlc_out *hout)
} else { } else {
/* We paid for this HTLC, so deduct balance. */ /* We paid for this HTLC, so deduct balance. */
log_debug(peer->log, "Balance %"PRIu64" -> %"PRIu64, log_debug(peer->log, "Balance %"PRIu64" -> %"PRIu64,
*peer->our_msatoshi, *peer2channel(peer)->our_msatoshi,
*peer->our_msatoshi - hout->msatoshi); *peer2channel(peer)->our_msatoshi - hout->msatoshi);
*peer->our_msatoshi -= hout->msatoshi; *peer2channel(peer)->our_msatoshi -= hout->msatoshi;
} }
tal_free(hout); tal_free(hout);
@ -863,7 +866,7 @@ static bool update_out_htlc(struct peer *peer, u64 id, enum htlc_state newstate)
} }
if (!hout->dbid) { 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 */ /* For our own HTLCs, we commit payment to db lazily */
if (hout->origin_htlc_id == 0) 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, struct bitcoin_tx *tx,
const secp256k1_ecdsa_signature *commit_sig) const secp256k1_ecdsa_signature *commit_sig)
{ {
if (commitnum != peer->next_index[LOCAL]) { if (commitnum != peer2channel(peer)->next_index[LOCAL]) {
peer_internal_error(peer, peer_internal_error(peer,
"channel_got_commitsig: expected commitnum %"PRIu64 "channel_got_commitsig: expected commitnum %"PRIu64
" got %"PRIu64, " got %"PRIu64,
peer->next_index[LOCAL], commitnum); peer2channel(peer)->next_index[LOCAL], commitnum);
return false; return false;
} }
peer->next_index[LOCAL]++; peer2channel(peer)->next_index[LOCAL]++;
/* Update peer->last_sig and peer->last_tx before saving to db */ /* Update peer->last_sig and peer->last_tx before saving to db */
peer_last_tx(peer, tx, commit_sig); 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) 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, peer_internal_error(peer,
"channel_sent_commitsig: expected commitnum %"PRIu64 "channel_sent_commitsig: expected commitnum %"PRIu64
" got %"PRIu64, " got %"PRIu64,
peer->next_index[REMOTE], commitnum); peer2channel(peer)->next_index[REMOTE], commitnum);
return false; return false;
} }
peer->next_index[REMOTE]++; peer2channel(peer)->next_index[REMOTE]++;
/* FIXME: Save to database, with sig and HTLCs. */ /* 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; return true;
} }
@ -967,35 +970,35 @@ void peer_sending_commitsig(struct peer *peer, const u8 *msg)
} }
if (num_local_added != 0) { 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, peer_internal_error(peer,
"channel_sending_commitsig:" "channel_sending_commitsig:"
" Added %"PRIu64", maxid now %"PRIu64 " Added %"PRIu64", maxid now %"PRIu64
" from %"PRIu64, " from %"PRIu64,
num_local_added, maxid, peer->next_htlc_id); num_local_added, maxid, peer2channel(peer)->next_htlc_id);
return; return;
} }
peer->next_htlc_id += num_local_added; peer2channel(peer)->next_htlc_id += num_local_added;
} }
/* Update their feerate. */ /* 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)) if (!peer_save_commitsig_sent(peer, commitnum))
return; return;
/* Last was commit. */ /* Last was commit. */
peer->last_was_revoke = false; peer2channel(peer)->last_was_revoke = false;
tal_free(peer->last_sent_commit); tal_free(peer2channel(peer)->last_sent_commit);
peer->last_sent_commit = tal_steal(peer, changed_htlcs); peer2channel(peer)->last_sent_commit = tal_steal(peer, changed_htlcs);
wallet_channel_save(peer->ld->wallet, peer->channel); wallet_channel_save(peer->ld->wallet, peer2channel(peer));
/* Tell it we've got it, and to go ahead with commitment_signed. */ /* 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))); take(towire_channel_sending_commitsig_reply(msg)));
} }
static bool peer_added_their_htlc(struct peer *peer, static bool channel_added_their_htlc(struct channel *channel,
const struct added_htlc *added, const struct added_htlc *added,
const struct secret *shared_secret) const struct secret *shared_secret)
{ {
@ -1007,37 +1010,38 @@ static bool peer_added_their_htlc(struct peer *peer,
* - SHOULD fail the channel. * - SHOULD fail the channel.
*/ */
if (added->amount_msat == 0 if (added->amount_msat == 0
|| added->amount_msat < peer->our_config.htlc_minimum_msat) { || added->amount_msat < channel->our_config.htlc_minimum_msat) {
peer_internal_error(peer, peer_internal_error(channel2peer(channel),
"trying to add HTLC msat %"PRIu64 "trying to add HTLC msat %"PRIu64
" but minimum is %"PRIu64, " but minimum is %"PRIu64,
added->amount_msat, added->amount_msat,
peer->our_config.htlc_minimum_msat); channel->our_config.htlc_minimum_msat);
return false; return false;
} }
/* This stays around even if we fail it immediately: it *is* /* This stays around even if we fail it immediately: it *is*
* part of the current commitment. */ * 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, added->cltv_expiry, &added->payment_hash,
shared_secret, added->onion_routing_packet); shared_secret, added->onion_routing_packet);
/* Save an incoming htlc to the wallet */ /* 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); log_debug(channel->log, "Adding their HTLC %"PRIu64, added->id);
connect_htlc_in(&peer->ld->htlcs_in, hin); connect_htlc_in(&channel->peer->ld->htlcs_in, hin);
return true; return true;
} }
/* The peer doesn't tell us this separately, but logically it's a separate /* The peer doesn't tell us this separately, but logically it's a separate
* step to receiving commitsig */ * 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 added_htlc *added,
struct fulfilled_htlc *fulfilled, struct fulfilled_htlc *fulfilled,
struct failed_htlc **failed, struct failed_htlc **failed,
struct changed_htlc *changed) struct changed_htlc *changed)
{ {
struct peer *peer = channel2peer(channel);
size_t i; size_t i;
for (i = 0; i < tal_count(added); 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; return true;
} }
@ -1083,6 +1087,7 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg)
struct changed_htlc *changed; struct changed_htlc *changed;
struct bitcoin_tx *tx; struct bitcoin_tx *tx;
size_t i; size_t i;
struct channel *channel = peer2channel(peer);
if (!fromwire_channel_got_commitsig(msg, msg, NULL, if (!fromwire_channel_got_commitsig(msg, msg, NULL,
&commitnum, &commitnum,
@ -1109,18 +1114,18 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg)
/* New HTLCs */ /* New HTLCs */
for (i = 0; i < tal_count(added); i++) { 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; return;
} }
/* Save information now for fulfilled & failed HTLCs */ /* Save information now for fulfilled & failed HTLCs */
for (i = 0; i < tal_count(fulfilled); i++) { 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; return;
} }
for (i = 0; i < tal_count(failed); i++) { 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; 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 /* Update both feerates: if we're funder, REMOTE should already be
* that feerate, if we're not, we're about to ACK anyway. */ * that feerate, if we're not, we're about to ACK anyway. */
peer->channel_info->feerate_per_kw[LOCAL] channel->channel_info->feerate_per_kw[LOCAL]
= peer->channel_info->feerate_per_kw[REMOTE] = channel->channel_info->feerate_per_kw[REMOTE]
= feerate; = feerate;
/* Since we're about to send revoke, bump state again. */ /* 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; return;
if (!peer_save_commitsig_received(peer, commitnum, tx, &commit_sig)) if (!peer_save_commitsig_received(peer, commitnum, tx, &commit_sig))
return; return;
wallet_channel_save(peer->ld->wallet, peer->channel); wallet_channel_save(peer->ld->wallet, channel);
tal_free(peer->last_htlc_sigs); tal_free(channel->last_htlc_sigs);
peer->last_htlc_sigs = tal_steal(peer, htlc_sigs); channel->last_htlc_sigs = tal_steal(channel, htlc_sigs);
wallet_htlc_sigs_save(peer->ld->wallet, peer->channel->id, wallet_htlc_sigs_save(peer->ld->wallet, channel->dbid,
peer->last_htlc_sigs); channel->last_htlc_sigs);
/* Tell it we've committed, and to go ahead with revoke. */ /* Tell it we've committed, and to go ahead with revoke. */
msg = towire_channel_got_commitsig_reply(msg); 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. */ /* Shuffle them over, forgetting the ancient one. */
void update_per_commit_point(struct peer *peer, void update_per_commit_point(struct peer *peer,
const struct pubkey *per_commitment_point) 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->old_remote_per_commit = ci->remote_per_commit;
ci->remote_per_commit = *per_commitment_point; 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 pubkey next_per_commitment_point;
struct changed_htlc *changed; struct changed_htlc *changed;
enum onion_type *failcodes; enum onion_type *failcodes;
struct channel *channel = peer2channel(peer);
size_t i; size_t i;
if (!fromwire_channel_got_revoke(msg, msg, NULL, if (!fromwire_channel_got_revoke(msg, msg, NULL,
@ -1211,10 +1217,10 @@ void peer_got_revoke(struct peer *peer, const u8 *msg)
return; 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 peer_internal_error(peer, "got_revoke: expected %"PRIu64
" got %"PRIu64, " got %"PRIu64,
revocations_received(&peer->their_shachain.chain), revokenum); revocations_received(&channel->their_shachain.chain), revokenum);
return; 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 * A receiving node MAY fail if the `per_commitment_secret` was not
* generated by the protocol in [BOLT #3] * 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), shachain_index(revokenum),
&per_commitment_secret)) { &per_commitment_secret)) {
peer_fail_permanent(peer, 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. */ /* Tell it we've committed, and to go ahead with revoke. */
msg = towire_channel_got_revoke_reply(msg); 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? */ /* Now, any HTLCs we need to immediately fail? */
for (i = 0; i < tal_count(changed); i++) { 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); hin = find_htlc_in(&peer->ld->htlcs_in, peer, changed[i].id);
local_fail_htlc(hin, failcodes[i], NULL); 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) static void *tal_arr_append_(void **p, size_t size)
@ -1438,7 +1445,7 @@ void notify_new_block(struct lightningd *ld, u32 height)
continue; continue;
/* Peer already failed, or we hit it? */ /* Peer already failed, or we hit it? */
if (hout->key.peer->error) if (peer2channel(hout->key.peer)->error)
continue; continue;
peer_fail_permanent(hout->key.peer, peer_fail_permanent(hout->key.peer,
@ -1482,7 +1489,7 @@ void notify_new_block(struct lightningd *ld, u32 height)
continue; continue;
/* Peer already failed, or we hit it? */ /* Peer already failed, or we hit it? */
if (hin->key.peer->error) if (peer2channel(hin->key.peer)->error)
continue; continue;
peer_fail_permanent(hin->key.peer, 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 /* FIXME: We choose not to drop to chain if we can't contact
* peer. We *could* do so, however. */ * peer. We *could* do so, however. */
if (!peer->owner) if (!peer2channel(peer)->owner)
continue; continue;
msg = towire_channel_feerates(peer, msg = towire_channel_feerates(peer,
@ -1519,6 +1526,6 @@ void notify_feerate_change(struct lightningd *ld)
FEERATE_IMMEDIATE), FEERATE_IMMEDIATE),
feerate_min(ld), feerate_min(ld),
feerate_max(ld)); feerate_max(ld));
subd_send_msg(peer->owner, take(msg)); subd_send_msg(peer2channel(peer)->owner, take(msg));
} }
} }

1
lightningd/peer_state.h

@ -2,6 +2,7 @@
#define LIGHTNING_LIGHTNINGD_PEER_STATE_H #define LIGHTNING_LIGHTNINGD_PEER_STATE_H
#include "config.h" #include "config.h"
/* FIXME: rename channel_state! */
enum peer_state { enum peer_state {
UNINITIALIZED, UNINITIALIZED,

4
lightningd/subd.c

@ -416,8 +416,8 @@ static bool handle_sent_errmsg(struct subd *sd, const u8 *msg)
return false; return false;
/* FIXME: if not all channels failed, hand back to gossipd! */ /* FIXME: if not all channels failed, hand back to gossipd! */
if (!sd->peer->error) if (!peer2channel(sd->peer)->error)
sd->peer->error = tal_steal(sd->peer, errmsg); peer2channel(sd->peer)->error = tal_steal(sd->peer, errmsg);
/* Don't free sd; we're may be about to free peer. */ /* Don't free sd; we're may be about to free peer. */
sd->peer = NULL; sd->peer = NULL;

8
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 */ /* Generated stub for new_topology */
struct chain_topology *new_topology(struct lightningd *ld UNNEEDED, struct log *log UNNEEDED) struct chain_topology *new_topology(struct lightningd *ld UNNEEDED, struct log *log UNNEEDED)
{ fprintf(stderr, "new_topology called!\n"); abort(); } { 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 */ /* Generated stub for register_opts */
void register_opts(struct lightningd *ld UNNEEDED) void register_opts(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "register_opts called!\n"); abort(); } { fprintf(stderr, "register_opts called!\n"); abort(); }
@ -94,12 +91,11 @@ const char *version(void)
u32 wallet_channels_first_blocknum(struct wallet *w UNNEEDED) u32 wallet_channels_first_blocknum(struct wallet *w UNNEEDED)
{ fprintf(stderr, "wallet_channels_first_blocknum called!\n"); abort(); } { fprintf(stderr, "wallet_channels_first_blocknum called!\n"); abort(); }
/* Generated stub for wallet_channels_load_active */ /* Generated stub for wallet_channels_load_active */
bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED)
struct wallet *w UNNEEDED, struct list_head *peers UNNEEDED)
{ fprintf(stderr, "wallet_channels_load_active called!\n"); abort(); } { fprintf(stderr, "wallet_channels_load_active called!\n"); abort(); }
/* Generated stub for wallet_htlcs_load_for_channel */ /* Generated stub for wallet_htlcs_load_for_channel */
bool wallet_htlcs_load_for_channel(struct wallet *wallet UNNEEDED, 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_in_map *htlcs_in UNNEEDED,
struct htlc_out_map *htlcs_out UNNEEDED) struct htlc_out_map *htlcs_out UNNEEDED)
{ fprintf(stderr, "wallet_htlcs_load_for_channel called!\n"); abort(); } { fprintf(stderr, "wallet_htlcs_load_for_channel called!\n"); abort(); }

2
tests/test_lightningd.py

@ -2876,7 +2876,7 @@ class LightningDTests(BaseLightningDTests):
# Wait for l1 to notice # Wait for l1 to notice
wait_for(lambda: not 'connected' in l1.rpc.listpeers()['peers'][0]['channels'][0]) 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() l2.daemon.start()
wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 1) wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 1)

655
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 "wallet/wallet.c"
#include "lightningd/htlc_end.c" #include "lightningd/htlc_end.c"
#include "lightningd/peer_control.c"
#include "lightningd/channel.c"
#include "wallet/db.c" #include "wallet/db.c"
@ -23,7 +25,167 @@ static void db_log_(struct log *log, enum log_level level, const char *fmt, ...)
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
bool deprecated_apis = true;
/* AUTOGENERATED MOCKS START */ /* 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 */ /* Generated stub for invoices_create */
const struct invoice *invoices_create(struct invoices *invoices UNNEEDED, const struct invoice *invoices_create(struct invoices *invoices UNNEEDED,
u64 *msatoshi TAKES 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 (*cb)(const struct invoice * UNNEEDED, void*) UNNEEDED,
void *cbarg UNNEEDED) void *cbarg UNNEEDED)
{ fprintf(stderr, "invoices_waitone called!\n"); abort(); } { 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 */ /* 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 char *wallet_err;
static void wallet_fatal(const char *fmt, ...) static void wallet_fatal(const char *fmt, ...)
{ {
@ -95,6 +541,40 @@ static void wallet_fatal(const char *fmt, ...)
#define transaction_wrap(db, ...) \ #define transaction_wrap(db, ...) \
(db_begin_transaction(db), __VA_ARGS__, db_commit_transaction(db), wallet_err == NULL) (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 * mempat -- Set the memory to a pattern
* *
@ -109,7 +589,7 @@ static void mempat(void *dst, size_t len)
p[i] = n % 251; /* Prime */ 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"; char filename[] = "/tmp/ldb-XXXXXX";
int fd = mkstemp(filename); int fd = mkstemp(filename);
@ -121,6 +601,7 @@ static struct wallet *create_test_wallet(const tal_t *ctx)
ltmp = tal_tmpctx(ctx); ltmp = tal_tmpctx(ctx);
list_head_init(&w->unstored_payments); list_head_init(&w->unstored_payments);
w->ld = ld;
CHECK_MSG(w->db, "Failed opening the db"); CHECK_MSG(w->db, "Failed opening the db");
db_migrate(w->db, w->log); db_migrate(w->db, w->log);
@ -272,29 +753,30 @@ static bool bitcoin_tx_eq(const struct bitcoin_tx *tx1,
return eq; 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 peer *p1 = c1->peer, *p2 = c2->peer;
struct channel_info *ci1 = p1->channel_info, *ci2 = p2->channel_info; struct channel_info *ci1 = c1->channel_info, *ci2 = c2->channel_info;
struct changed_htlc *lc1 = p1->last_sent_commit, *lc2 = p2->last_sent_commit; struct changed_htlc *lc1 = c1->last_sent_commit, *lc2 = c2->last_sent_commit;
CHECK(c1->id == c2->id); CHECK(c1->dbid == c2->dbid);
CHECK(c1->first_blocknum == c2->first_blocknum); CHECK(c1->first_blocknum == c2->first_blocknum);
CHECK(c1->peer->dbid == c2->peer->dbid); 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_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((c1->scid == NULL && c2->scid == NULL) || short_channel_id_eq(c1->scid, c2->scid));
CHECK((p1->our_msatoshi == NULL) == (p2->our_msatoshi == NULL)); CHECK((c1->our_msatoshi == NULL) == (c2->our_msatoshi == NULL));
if (p1->our_msatoshi) if (c1->our_msatoshi)
CHECK(*p1->our_msatoshi == *p2->our_msatoshi); CHECK(*c1->our_msatoshi == *c2->our_msatoshi);
CHECK((p1->remote_shutdown_scriptpubkey == NULL && p2->remote_shutdown_scriptpubkey == NULL) || memeq( CHECK((c1->remote_shutdown_scriptpubkey == NULL && c2->remote_shutdown_scriptpubkey == NULL) || memeq(
p1->remote_shutdown_scriptpubkey, c1->remote_shutdown_scriptpubkey,
tal_len(p1->remote_shutdown_scriptpubkey), tal_len(c1->remote_shutdown_scriptpubkey),
p2->remote_shutdown_scriptpubkey, c2->remote_shutdown_scriptpubkey,
tal_len(p2->remote_shutdown_scriptpubkey))); tal_len(c2->remote_shutdown_scriptpubkey)));
CHECK((p1->funding_txid == NULL && p2->funding_txid == NULL) || memeq( CHECK((c1->funding_txid == NULL && c2->funding_txid == NULL) || memeq(
p1->funding_txid, c1->funding_txid,
sizeof(struct sha256_double), sizeof(struct sha256_double),
p2->funding_txid, c2->funding_txid,
sizeof(struct sha256_double))); sizeof(struct sha256_double)));
CHECK((ci1 != NULL) == (ci2 != NULL)); CHECK((ci1 != NULL) == (ci2 != NULL));
if(ci1) { 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(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)); CHECK((lc1 != NULL) == (lc2 != NULL));
if(lc1) { if(lc1) {
CHECK(lc1->newstate == lc2->newstate); CHECK(lc1->newstate == lc2->newstate);
CHECK(lc1->id == lc2->id); CHECK(lc1->id == lc2->id);
} }
CHECK((p1->last_tx != NULL) == (p2->last_tx != NULL)); CHECK((c1->last_tx != NULL) == (c2->last_tx != NULL));
if(p1->last_tx) { if(c1->last_tx) {
CHECK(bitcoin_tx_eq(p1->last_tx, p2->last_tx)); CHECK(bitcoin_tx_eq(c1->last_tx, c2->last_tx));
} }
CHECK((p1->last_sig != NULL) == (p2->last_sig != NULL)); CHECK((c1->last_sig != NULL) == (c2->last_sig != NULL));
if(p1->last_sig) { if(c1->last_sig) {
CHECK(memeq(p1->last_sig, sizeof(*p1->last_sig), CHECK(memeq(c1->last_sig, sizeof(*c1->last_sig),
p2->last_sig, sizeof(*p2->last_sig))); c2->last_sig, sizeof(*c2->last_sig)));
} }
if (p1->remote_shutdown_scriptpubkey) { if (c1->remote_shutdown_scriptpubkey) {
CHECK(p2->remote_shutdown_scriptpubkey); CHECK(c2->remote_shutdown_scriptpubkey);
CHECK(p1->local_shutdown_idx == p2->local_shutdown_idx); 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; 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; struct peer *peer;
struct channel *channel;
list_head_init(&peers);
/* We expect only one peer, but reuse same code */ /* 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; return NULL;
peer = list_top(&peers, struct peer, list); peer = list_top(&w->ld->peers, struct peer, list);
CHECK(peer); 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 *w = create_test_wallet(ld, ctx);
struct wallet_channel c1, *c2 = tal(w, struct wallet_channel); struct channel c1, *c2 = tal(w, struct channel);
struct peer p; struct peer *p;
struct channel_info ci; struct channel_info ci;
struct bitcoin_txid *hash = tal(w, struct bitcoin_txid); struct bitcoin_txid *hash = tal(w, struct bitcoin_txid);
struct pubkey pk; struct pubkey pk;
@ -366,21 +849,19 @@ static bool test_channel_crud(const tal_t *ctx)
memset(&c1, 0, sizeof(c1)); memset(&c1, 0, sizeof(c1));
memset(c2, 0, sizeof(*c2)); memset(c2, 0, sizeof(*c2));
memset(&p, 0, sizeof(p));
memset(&ci, 3, sizeof(ci)); memset(&ci, 3, sizeof(ci));
mempat(hash, sizeof(*hash)); mempat(hash, sizeof(*hash));
mempat(sig, sizeof(*sig)); mempat(sig, sizeof(*sig));
mempat(&last_commit, sizeof(last_commit)); mempat(&last_commit, sizeof(last_commit));
pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk); pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk);
ci.feerate_per_kw[LOCAL] = ci.feerate_per_kw[REMOTE] = 31337; ci.feerate_per_kw[LOCAL] = ci.feerate_per_kw[REMOTE] = 31337;
mempat(&p.id, sizeof(p.id));
mempat(scriptpubkey, tal_len(scriptpubkey)); mempat(scriptpubkey, tal_len(scriptpubkey));
c1.first_blocknum = 1; c1.first_blocknum = 1;
c1.peer = &p; p = new_peer(ld, 0, &pk, NULL);
p.id = pk; c1.peer = p;
p.our_msatoshi = NULL; c1.our_msatoshi = NULL;
p.last_tx = NULL; c1.last_tx = NULL;
p.state = CHANNELD_NORMAL; c1.state = CHANNELD_NORMAL;
memset(&ci.their_config, 0, sizeof(struct channel_config)); memset(&ci.their_config, 0, sizeof(struct channel_config));
ci.remote_fundingkey = pk; ci.remote_fundingkey = pk;
ci.theirbase.revocation = pk; ci.theirbase.revocation = pk;
@ -397,85 +878,85 @@ static bool test_channel_crud(const tal_t *ctx)
wallet_channel_save(w, &c1); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Load from DB: %s", wallet_err)); tal_fmt(w, "Load from DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v1)"); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v1)");
/* We just inserted them into an empty DB so this must be 1 */ /* 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->dbid == 1);
CHECK(c1.peer->their_shachain.id == 1); CHECK(c1.their_shachain.id == 1);
/* Variant 2: update with scid set */ /* 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); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err)); tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v2)"); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v2)");
/* Updates should not result in new ids */ /* Updates should not result in new ids */
CHECK(c1.id == 1); CHECK(c1.dbid == 1);
CHECK(c1.peer->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 */ /* Variant 3: update with our_satoshi set */
c1.peer->our_msatoshi = &msat; c1.our_msatoshi = &msat;
c1.peer->last_was_revoke = !c1.peer->last_was_revoke; c1.last_was_revoke = !c1.last_was_revoke;
wallet_channel_save(w, &c1); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err)); tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v3)"); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v3)");
/* Variant 4: update with funding_tx_id */ /* Variant 4: update with funding_tx_id */
c1.peer->funding_txid = hash; c1.funding_txid = hash;
wallet_channel_save(w, &c1); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err)); tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v4)"); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v4)");
/* Variant 5: update with channel_info */ /* Variant 5: update with channel_info */
p.channel_info = &ci; c1.channel_info = &ci;
wallet_channel_save(w, &c1); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err)); tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v5)"); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v5)");
/* Variant 6: update with last_commit_sent */ /* Variant 6: update with last_commit_sent */
p.last_sent_commit = &last_commit; c1.last_sent_commit = &last_commit;
wallet_channel_save(w, &c1); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err)); tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v6)"); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v6)");
/* Variant 7: update with last_tx (taken from BOLT #3) */ /* Variant 7: update with last_tx (taken from BOLT #3) */
p.last_tx = bitcoin_tx_from_hex(w, "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", strlen("02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220")); c1.last_tx = bitcoin_tx_from_hex(w, "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", strlen("02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220"));
p.last_sig = sig; c1.last_sig = sig;
wallet_channel_save(w, &c1); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err)); tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v7)"); CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v7)");
/* Variant 8: update and add remote_shutdown_scriptpubkey */ /* Variant 8: update and add remote_shutdown_scriptpubkey */
p.remote_shutdown_scriptpubkey = scriptpubkey; c1.remote_shutdown_scriptpubkey = scriptpubkey;
p.local_shutdown_idx = 1337; c1.local_shutdown_idx = 1337;
wallet_channel_save(w, &c1); wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); 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, CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err)); tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v8)"); 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; 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), struct channel_config *cc1 = talz(ctx, struct channel_config),
*cc2 = 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); CHECK(w);
cc1->dust_limit_satoshis = 1; cc1->dust_limit_satoshis = 1;
@ -510,21 +991,21 @@ static bool test_channel_config_crud(const tal_t *ctx)
return true; 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_in in, *hin;
struct htlc_out out, *hout; struct htlc_out out, *hout;
struct preimage payment_key; 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 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_in_map *htlcs_in = tal(ctx, struct htlc_in_map);
struct htlc_out_map *htlcs_out = tal(ctx, struct htlc_out_map); struct htlc_out_map *htlcs_out = tal(ctx, struct htlc_out_map);
/* Make sure we have our references correct */ /* Make sure we have our references correct */
CHECK(transaction_wrap(w->db, CHECK(transaction_wrap(w->db,
db_exec(__func__, w->db, "INSERT INTO channels (id) VALUES (1);"))); db_exec(__func__, w->db, "INSERT INTO channels (id) VALUES (1);")));
chan->id = 1; chan->dbid = 1;
chan->peer = peer; chan->peer = peer;
memset(&in, 0, sizeof(in)); memset(&in, 0, sizeof(in));
@ -598,10 +1079,10 @@ static bool test_htlc_crud(const tal_t *ctx)
return true; 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_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)); mempat(t, sizeof(*t));
memset(&t->destination, 1, sizeof(t->destination)); memset(&t->destination, 1, sizeof(t->destination));
@ -642,13 +1123,21 @@ int main(void)
{ {
bool ok = true; bool ok = true;
tal_t *tmpctx = tal_tmpctx(NULL); 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_wallet_outputs();
ok &= test_shachain_crud(); ok &= test_shachain_crud();
ok &= test_channel_crud(tmpctx); ok &= test_channel_crud(ld, tmpctx);
ok &= test_channel_config_crud(tmpctx); ok &= test_channel_config_crud(ld, tmpctx);
ok &= test_htlc_crud(tmpctx); ok &= test_htlc_crud(ld, tmpctx);
ok &= test_payment_crud(tmpctx); ok &= test_payment_crud(ld, tmpctx);
tal_free(tmpctx); tal_free(tmpctx);
return !ok; return !ok;

317
wallet/wallet.c

@ -410,29 +410,41 @@ bool wallet_shachain_load(struct wallet *wallet, u64 id,
return true; 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; const unsigned char *addrstr;
struct peer *peer;
struct pubkey id;
struct wireaddr *addrp, addr;
sqlite3_stmt *stmt = sqlite3_stmt *stmt =
db_query(__func__, w->db, 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) { if (!stmt || sqlite3_step(stmt) != SQLITE_ROW) {
sqlite3_finalize(stmt); 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); 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) peer = new_peer(w->ld, sqlite3_column_int64(stmt, 0),
parse_wireaddr((const char*)addrstr, &peer->addr, DEFAULT_PORT); &id, addrp);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return ok; return peer;
} }
bool wallet_peer_by_nodeid(struct wallet *w, const struct pubkey *nodeid, 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 * 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, static struct channel *wallet_stmt2channel(const tal_t *ctx, struct wallet *w, sqlite3_stmt *stmt)
struct wallet_channel *chan)
{ {
bool ok = true; bool ok = true;
struct channel_info *channel_info; struct channel_info *channel_info;
u64 remote_config_id; u64 remote_config_id;
struct channel *chan;
if (!chan->peer) { u64 peer_dbid;
chan->peer = talz(ctx, struct peer); 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 = new_channel(peer, sqlite3_column_int64(stmt, 0),
chan->peer->dbid = sqlite3_column_int64(stmt, 1); sqlite3_column_int64(stmt, 35));
wallet_peer_load(w, chan->peer->dbid, chan->peer);
if (sqlite3_column_type(stmt, 2) != SQLITE_NULL) { if (sqlite3_column_type(stmt, 2) != SQLITE_NULL) {
chan->peer->scid = tal(chan->peer, struct short_channel_id); chan->scid = tal(chan->peer, struct short_channel_id);
sqlite3_column_short_channel_id(stmt, 2, chan->peer->scid); sqlite3_column_short_channel_id(stmt, 2, chan->scid);
} else { } else {
chan->peer->scid = NULL; chan->scid = NULL;
} }
chan->peer->our_config.id = sqlite3_column_int64(stmt, 3); chan->our_config.id = sqlite3_column_int64(stmt, 3);
wallet_channel_config_load(w, chan->peer->our_config.id, &chan->peer->our_config); wallet_channel_config_load(w, chan->our_config.id, &chan->our_config);
remote_config_id = sqlite3_column_int64(stmt, 4); remote_config_id = sqlite3_column_int64(stmt, 4);
chan->peer->state = sqlite3_column_int(stmt, 5); chan->state = sqlite3_column_int(stmt, 5);
chan->peer->funder = sqlite3_column_int(stmt, 6); chan->funder = sqlite3_column_int(stmt, 6);
chan->peer->channel_flags = sqlite3_column_int(stmt, 7); chan->channel_flags = sqlite3_column_int(stmt, 7);
chan->peer->minimum_depth = sqlite3_column_int(stmt, 8); chan->minimum_depth = sqlite3_column_int(stmt, 8);
chan->peer->next_index[LOCAL] = sqlite3_column_int64(stmt, 9); chan->next_index[LOCAL] = sqlite3_column_int64(stmt, 9);
chan->peer->next_index[REMOTE] = sqlite3_column_int64(stmt, 10); chan->next_index[REMOTE] = sqlite3_column_int64(stmt, 10);
chan->peer->next_htlc_id = sqlite3_column_int64(stmt, 11); chan->next_htlc_id = sqlite3_column_int64(stmt, 11);
if (sqlite3_column_type(stmt, 12) != SQLITE_NULL) { if (sqlite3_column_type(stmt, 12) != SQLITE_NULL) {
assert(sqlite3_column_bytes(stmt, 12) == 32); assert(sqlite3_column_bytes(stmt, 12) == 32);
chan->peer->funding_txid = tal(chan->peer, struct bitcoin_txid); chan->funding_txid = tal(chan->peer, struct bitcoin_txid);
memcpy(chan->peer->funding_txid, sqlite3_column_blob(stmt, 12), 32); memcpy(chan->funding_txid, sqlite3_column_blob(stmt, 12), 32);
} else { } else {
chan->peer->funding_txid = NULL; chan->funding_txid = NULL;
} }
chan->peer->funding_outnum = sqlite3_column_int(stmt, 13); chan->funding_outnum = sqlite3_column_int(stmt, 13);
chan->peer->funding_satoshi = sqlite3_column_int64(stmt, 14); chan->funding_satoshi = sqlite3_column_int64(stmt, 14);
chan->peer->remote_funding_locked = chan->remote_funding_locked =
sqlite3_column_int(stmt, 15) != 0; 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) { if (sqlite3_column_type(stmt, 17) != SQLITE_NULL) {
chan->peer->our_msatoshi = tal(chan->peer, u64); chan->our_msatoshi = tal(chan->peer, u64);
*chan->peer->our_msatoshi = sqlite3_column_int64(stmt, 17); *chan->our_msatoshi = sqlite3_column_int64(stmt, 17);
}else { }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 /* 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) { if (sqlite3_column_type(stmt, 18) != SQLITE_NULL) {
/* OK, so we have a valid sig, instantiate and/or fill /* OK, so we have a valid sig, instantiate and/or fill
* in channel_info */ * in channel_info */
if (!chan->peer->channel_info) if (!chan->channel_info)
chan->peer->channel_info = tal(chan->peer, struct channel_info); chan->channel_info = tal(chan, struct channel_info);
channel_info = chan->peer->channel_info; channel_info = chan->channel_info;
/* Populate 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, 19, &channel_info->theirbase.revocation);
ok &= sqlite3_column_pubkey(stmt, 20, &channel_info->theirbase.payment); ok &= sqlite3_column_pubkey(stmt, 20, &channel_info->theirbase.payment);
ok &= sqlite3_column_pubkey(stmt, 21, &channel_info->theirbase.htlc); 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); 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[LOCAL] = sqlite3_column_int(stmt, 25);
channel_info->feerate_per_kw[REMOTE] = sqlite3_column_int(stmt, 26); 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 */ /* Load shachain */
u64 shachain_id = sqlite3_column_int64(stmt, 27); 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? */ /* Do we have a non-null remote_shutdown_scriptpubkey? */
if (sqlite3_column_type(stmt, 28) != SQLITE_NULL) { if (sqlite3_column_type(stmt, 28) != SQLITE_NULL) {
chan->peer->remote_shutdown_scriptpubkey = tal_arr(chan->peer, u8, sqlite3_column_bytes(stmt, 28)); chan->remote_shutdown_scriptpubkey = tal_arr(chan, u8, sqlite3_column_bytes(stmt, 28));
memcpy(chan->peer->remote_shutdown_scriptpubkey, sqlite3_column_blob(stmt, 28), sqlite3_column_bytes(stmt, 28)); memcpy(chan->remote_shutdown_scriptpubkey, sqlite3_column_blob(stmt, 28), sqlite3_column_bytes(stmt, 28));
chan->peer->local_shutdown_idx = sqlite3_column_int64(stmt, 29); chan->local_shutdown_idx = sqlite3_column_int64(stmt, 29);
} else { } else {
chan->peer->remote_shutdown_scriptpubkey = tal_free(chan->peer->remote_shutdown_scriptpubkey); chan->remote_shutdown_scriptpubkey = tal_free(chan->remote_shutdown_scriptpubkey);
chan->peer->local_shutdown_idx = -1; chan->local_shutdown_idx = -1;
} }
/* Do we have a last_sent_commit, if yes, populate */ /* Do we have a last_sent_commit, if yes, populate */
if (sqlite3_column_type(stmt, 30) != SQLITE_NULL) { if (sqlite3_column_type(stmt, 30) != SQLITE_NULL) {
if (!chan->peer->last_sent_commit) { if (!chan->last_sent_commit) {
chan->peer->last_sent_commit = tal(chan->peer, struct changed_htlc); chan->last_sent_commit = tal(chan, struct changed_htlc);
} }
chan->peer->last_sent_commit->newstate = sqlite3_column_int64(stmt, 30); chan->last_sent_commit->newstate = sqlite3_column_int64(stmt, 30);
chan->peer->last_sent_commit->id = sqlite3_column_int64(stmt, 31); chan->last_sent_commit->id = sqlite3_column_int64(stmt, 31);
} else { } 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. */ /* Do we have last_tx? If so, populate. */
if (sqlite3_column_type(stmt, 32) != SQLITE_NULL) { if (sqlite3_column_type(stmt, 32) != SQLITE_NULL) {
chan->peer->last_tx = sqlite3_column_tx(chan->peer, stmt, 32); chan->last_tx = sqlite3_column_tx(chan, stmt, 32);
chan->peer->last_sig = tal(chan->peer, secp256k1_ecdsa_signature); chan->last_sig = tal(chan, secp256k1_ecdsa_signature);
sqlite3_column_signature(stmt, 33, chan->peer->last_sig); sqlite3_column_signature(stmt, 33, chan->last_sig);
} else { } else {
chan->peer->last_tx = tal_free(chan->peer->last_tx); chan->last_tx = tal_free(chan->last_tx);
chan->peer->last_sig = tal_free(chan->peer->last_sig); chan->last_sig = tal_free(chan->last_sig);
} }
chan->peer->last_was_revoke = sqlite3_column_int(stmt, 34) != 0; chan->last_was_revoke = sqlite3_column_int(stmt, 34) != 0;
chan->first_blocknum = sqlite3_column_int64(stmt, 35);
chan->peer->channel = chan;
/* Load any htlc_sigs */ /* 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 /* 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_sent_commit_state, last_sent_commit_id, "
"last_tx, last_sig, last_was_revoke, first_blocknum"; "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; bool ok = true;
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
@ -641,11 +655,11 @@ bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w, struct list
int count = 0; int count = 0;
while (ok && stmt && sqlite3_step(stmt) == SQLITE_ROW) { while (ok && stmt && sqlite3_step(stmt) == SQLITE_ROW) {
struct wallet_channel *c = talz(w, struct wallet_channel); struct channel *c = wallet_stmt2channel(ctx, w, stmt);
ok &= wallet_stmt2channel(ctx, w, stmt, c); if (!c) {
list_add(peers, &c->peer->list); ok = false;
/* Peer owns channel. FIXME delete from db if peer freed! */ break;
tal_steal(c->peer, c); }
count++; count++;
} }
log_debug(w->log, "Loaded %d channels from DB", 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; 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); tal_t *tmpctx = tal_tmpctx(w);
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
assert(chan->first_blocknum); assert(chan->first_blocknum);
if (p->dbid == 0) { if (chan->peer->dbid == 0) {
/* Need to store the peer first */ /* Need to store the peer first */
stmt = db_prepare(w->db, "INSERT INTO peers (node_id, address) VALUES (?, ?);"); stmt = db_prepare(w->db, "INSERT INTO peers (node_id, address) VALUES (?, ?);");
sqlite3_bind_pubkey(stmt, 1, &chan->peer->id); 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), type_to_string(tmpctx, struct wireaddr, &chan->peer->addr),
-1, SQLITE_TRANSIENT); -1, SQLITE_TRANSIENT);
db_exec_prepared(w->db, stmt); 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 */ /* 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 (" stmt = db_prepare(w->db, "INSERT INTO channels ("
"peer_id, first_blocknum) VALUES (?, ?);"); "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); sqlite3_bind_int(stmt, 2, chan->first_blocknum);
db_exec_prepared(w->db, stmt); 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 */ /* Need to initialize the shachain first so we get an id */
if (p->their_shachain.id == 0) { if (chan->their_shachain.id == 0) {
wallet_shachain_init(w, &p->their_shachain); 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 */ /* Now do the real update */
stmt = db_prepare(w->db, "UPDATE channels SET" 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_tx=?, last_sig=?,"
" last_was_revoke=?" " last_was_revoke=?"
" WHERE id=?"); " WHERE id=?");
sqlite3_bind_int64(stmt, 1, p->their_shachain.id); sqlite3_bind_int64(stmt, 1, chan->their_shachain.id);
if (p->scid) if (chan->scid)
sqlite3_bind_short_channel_id(stmt, 2, p->scid); sqlite3_bind_short_channel_id(stmt, 2, chan->scid);
sqlite3_bind_int(stmt, 3, p->state); sqlite3_bind_int(stmt, 3, chan->state);
sqlite3_bind_int(stmt, 4, p->funder); sqlite3_bind_int(stmt, 4, chan->funder);
sqlite3_bind_int(stmt, 5, p->channel_flags); sqlite3_bind_int(stmt, 5, chan->channel_flags);
sqlite3_bind_int(stmt, 6, p->minimum_depth); sqlite3_bind_int(stmt, 6, chan->minimum_depth);
sqlite3_bind_int64(stmt, 7, p->next_index[LOCAL]); sqlite3_bind_int64(stmt, 7, chan->next_index[LOCAL]);
sqlite3_bind_int64(stmt, 8, p->next_index[REMOTE]); sqlite3_bind_int64(stmt, 8, chan->next_index[REMOTE]);
sqlite3_bind_int64(stmt, 9, p->next_htlc_id); sqlite3_bind_int64(stmt, 9, chan->next_htlc_id);
if (p->funding_txid) if (chan->funding_txid)
sqlite3_bind_blob(stmt, 10, p->funding_txid, sizeof(*p->funding_txid), SQLITE_TRANSIENT); sqlite3_bind_blob(stmt, 10, chan->funding_txid, sizeof(*chan->funding_txid), SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 11, p->funding_outnum); sqlite3_bind_int(stmt, 11, chan->funding_outnum);
sqlite3_bind_int64(stmt, 12, p->funding_satoshi); sqlite3_bind_int64(stmt, 12, chan->funding_satoshi);
sqlite3_bind_int(stmt, 13, p->remote_funding_locked); sqlite3_bind_int(stmt, 13, chan->remote_funding_locked);
sqlite3_bind_int64(stmt, 14, p->push_msat); sqlite3_bind_int64(stmt, 14, chan->push_msat);
if (p->our_msatoshi) if (chan->our_msatoshi)
sqlite3_bind_int64(stmt, 15, *p->our_msatoshi); sqlite3_bind_int64(stmt, 15, *chan->our_msatoshi);
if (p->remote_shutdown_scriptpubkey) if (chan->remote_shutdown_scriptpubkey)
sqlite3_bind_blob(stmt, 16, p->remote_shutdown_scriptpubkey, sqlite3_bind_blob(stmt, 16, chan->remote_shutdown_scriptpubkey,
tal_len(p->remote_shutdown_scriptpubkey), tal_len(chan->remote_shutdown_scriptpubkey),
SQLITE_TRANSIENT); SQLITE_TRANSIENT);
sqlite3_bind_int64(stmt, 17, p->local_shutdown_idx); sqlite3_bind_int64(stmt, 17, chan->local_shutdown_idx);
sqlite3_bind_int64(stmt, 18, p->our_config.id); sqlite3_bind_int64(stmt, 18, chan->our_config.id);
if (p->last_tx) if (chan->last_tx)
sqlite3_bind_tx(stmt, 19, p->last_tx); sqlite3_bind_tx(stmt, 19, chan->last_tx);
if (p->last_sig) if (chan->last_sig)
sqlite3_bind_signature(stmt, 20, p->last_sig); sqlite3_bind_signature(stmt, 20, chan->last_sig);
sqlite3_bind_int(stmt, 21, p->last_was_revoke); sqlite3_bind_int(stmt, 21, chan->last_was_revoke);
sqlite3_bind_int64(stmt, 22, chan->id); sqlite3_bind_int64(stmt, 22, chan->dbid);
db_exec_prepared(w->db, stmt); db_exec_prepared(w->db, stmt);
if (chan->peer->channel_info) { if (chan->channel_info) {
wallet_channel_config_save(w, &p->channel_info->their_config); wallet_channel_config_save(w, &chan->channel_info->their_config);
stmt = db_prepare(w->db, "UPDATE channels SET" stmt = db_prepare(w->db, "UPDATE channels SET"
" fundingkey_remote=?," " fundingkey_remote=?,"
" revocation_basepoint_remote=?," " revocation_basepoint_remote=?,"
@ -839,30 +854,30 @@ void wallet_channel_save(struct wallet *w, struct wallet_channel *chan)
" remote_feerate_per_kw=?," " remote_feerate_per_kw=?,"
" channel_config_remote=?" " channel_config_remote=?"
" WHERE id=?"); " WHERE id=?");
sqlite3_bind_pubkey(stmt, 1, &p->channel_info->remote_fundingkey); sqlite3_bind_pubkey(stmt, 1, &chan->channel_info->remote_fundingkey);
sqlite3_bind_pubkey(stmt, 2, &p->channel_info->theirbase.revocation); sqlite3_bind_pubkey(stmt, 2, &chan->channel_info->theirbase.revocation);
sqlite3_bind_pubkey(stmt, 3, &p->channel_info->theirbase.payment); sqlite3_bind_pubkey(stmt, 3, &chan->channel_info->theirbase.payment);
sqlite3_bind_pubkey(stmt, 4, &p->channel_info->theirbase.htlc); sqlite3_bind_pubkey(stmt, 4, &chan->channel_info->theirbase.htlc);
sqlite3_bind_pubkey(stmt, 5, &p->channel_info->theirbase.delayed_payment); sqlite3_bind_pubkey(stmt, 5, &chan->channel_info->theirbase.delayed_payment);
sqlite3_bind_pubkey(stmt, 6, &p->channel_info->remote_per_commit); sqlite3_bind_pubkey(stmt, 6, &chan->channel_info->remote_per_commit);
sqlite3_bind_pubkey(stmt, 7, &p->channel_info->old_remote_per_commit); sqlite3_bind_pubkey(stmt, 7, &chan->channel_info->old_remote_per_commit);
sqlite3_bind_int(stmt, 8, p->channel_info->feerate_per_kw[LOCAL]); sqlite3_bind_int(stmt, 8, chan->channel_info->feerate_per_kw[LOCAL]);
sqlite3_bind_int(stmt, 9, p->channel_info->feerate_per_kw[REMOTE]); sqlite3_bind_int(stmt, 9, chan->channel_info->feerate_per_kw[REMOTE]);
sqlite3_bind_int64(stmt, 10, p->channel_info->their_config.id); sqlite3_bind_int64(stmt, 10, chan->channel_info->their_config.id);
sqlite3_bind_int64(stmt, 11, chan->id); sqlite3_bind_int64(stmt, 11, chan->dbid);
db_exec_prepared(w->db, stmt); db_exec_prepared(w->db, stmt);
} }
/* If we have a last_sent_commit, store it */ /* 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, stmt = db_prepare(w->db,
"UPDATE channels SET" "UPDATE channels SET"
" last_sent_commit_state=?," " last_sent_commit_state=?,"
" last_sent_commit_id=?" " last_sent_commit_id=?"
" WHERE id=?"); " WHERE id=?");
sqlite3_bind_int(stmt, 1, p->last_sent_commit->newstate); sqlite3_bind_int(stmt, 1, chan->last_sent_commit->newstate);
sqlite3_bind_int64(stmt, 2, p->last_sent_commit->id); sqlite3_bind_int64(stmt, 2, chan->last_sent_commit->id);
sqlite3_bind_int64(stmt, 3, chan->id); sqlite3_bind_int64(stmt, 3, chan->dbid);
db_exec_prepared(w->db, stmt); 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, 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); tal_t *tmpctx = tal_tmpctx(wallet);
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
@ -946,7 +961,7 @@ void wallet_htlc_save_in(struct wallet *wallet,
" routing_onion) VALUES " " 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_int64(stmt, 2, in->key.id);
sqlite3_bind_int(stmt, 3, DIRECTION_INCOMING); sqlite3_bind_int(stmt, 3, DIRECTION_INCOMING);
sqlite3_bind_int64(stmt, 4, in->msatoshi); 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, void wallet_htlc_save_out(struct wallet *wallet,
const struct wallet_channel *chan, const struct channel *chan,
struct htlc_out *out) struct htlc_out *out)
{ {
tal_t *tmpctx = tal_tmpctx(wallet); tal_t *tmpctx = tal_tmpctx(wallet);
@ -994,7 +1009,7 @@ void wallet_htlc_save_out(struct wallet *wallet,
" hstate," " hstate,"
" routing_onion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); " 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_int64(stmt, 2, out->key.id);
sqlite3_bind_int(stmt, 3, DIRECTION_OUTGOING); sqlite3_bind_int(stmt, 3, DIRECTION_OUTGOING);
if (out->in) if (out->in)
@ -1038,13 +1053,13 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid,
db_exec_prepared(wallet->db, stmt); 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) sqlite3_stmt *stmt, struct htlc_in *in)
{ {
bool ok = true; bool ok = true;
in->dbid = sqlite3_column_int64(stmt, 0); in->dbid = sqlite3_column_int64(stmt, 0);
in->key.id = sqlite3_column_int64(stmt, 1); 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->msatoshi = sqlite3_column_int64(stmt, 2);
in->cltv_expiry = sqlite3_column_int(stmt, 3); in->cltv_expiry = sqlite3_column_int(stmt, 3);
in->hstate = sqlite3_column_int(stmt, 4); in->hstate = sqlite3_column_int(stmt, 4);
@ -1072,13 +1087,13 @@ static bool wallet_stmt2htlc_in(const struct wallet_channel *channel,
return ok; 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) sqlite3_stmt *stmt, struct htlc_out *out)
{ {
bool ok = true; bool ok = true;
out->dbid = sqlite3_column_int64(stmt, 0); out->dbid = sqlite3_column_int64(stmt, 0);
out->key.id = sqlite3_column_int64(stmt, 1); 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->msatoshi = sqlite3_column_int64(stmt, 2);
out->cltv_expiry = sqlite3_column_int(stmt, 3); out->cltv_expiry = sqlite3_column_int(stmt, 3);
out->hstate = sqlite3_column_int(stmt, 4); 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, bool wallet_htlcs_load_for_channel(struct wallet *wallet,
struct wallet_channel *chan, struct channel *chan,
struct htlc_in_map *htlcs_in, struct htlc_in_map *htlcs_in,
struct htlc_out_map *htlcs_out) struct htlc_out_map *htlcs_out)
{ {
bool ok = true; bool ok = true;
int incount = 0, outcount = 0; 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( sqlite3_stmt *stmt = db_query(
__func__, wallet->db, __func__, wallet->db,
"SELECT id, channel_htlc_id, msatoshi, cltv_expiry, hstate, " "SELECT id, channel_htlc_id, msatoshi, cltv_expiry, hstate, "
"payment_hash, shared_secret, payment_key, routing_onion FROM channel_htlcs WHERE " "payment_hash, shared_secret, payment_key, routing_onion FROM channel_htlcs WHERE "
"direction=%d AND channel_id=%" PRIu64 " AND hstate != %d", "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) { if (!stmt) {
log_broken(wallet->log, "Could not select htlc_ins"); 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, " "SELECT id, channel_htlc_id, msatoshi, cltv_expiry, hstate, "
"payment_hash, origin_htlc, payment_key, routing_onion FROM channel_htlcs WHERE " "payment_hash, origin_htlc, payment_key, routing_onion FROM channel_htlcs WHERE "
"direction=%d AND channel_id=%" PRIu64 " AND hstate != %d", "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) { if (!stmt) {
log_broken(wallet->log, "Could not select htlc_outs"); 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 htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet,
struct wallet_channel *chan) struct channel *chan)
{ {
struct htlc_stub *stubs; struct htlc_stub *stubs;
struct sha256 payment_hash; 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 " "SELECT channel_id, direction, cltv_expiry, payment_hash "
"FROM channel_htlcs WHERE channel_id = ?;"); "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); 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); int n = tal_count(stubs);
tal_resize(&stubs, n+1); 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 */ /* FIXME: merge these two enums */
stubs[n].owner = sqlite3_column_int(stmt, 1)==DIRECTION_INCOMING?REMOTE:LOCAL; stubs[n].owner = sqlite3_column_int(stmt, 1)==DIRECTION_INCOMING?REMOTE:LOCAL;

28
wallet/wallet.h

@ -15,6 +15,7 @@
#include <wally_bip32.h> #include <wally_bip32.h>
struct invoices; struct invoices;
struct channel;
struct lightningd; struct lightningd;
struct oneshot; struct oneshot;
struct pubkey; struct pubkey;
@ -62,17 +63,6 @@ struct wallet_shachain {
struct shachain chain; 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 /* Possible states for a wallet_payment. Payments start in
* `PENDING`. Outgoing payments are set to `PAYMENT_COMPLETE` once we * `PENDING`. Outgoing payments are set to `PAYMENT_COMPLETE` once we
* get the preimage matching the rhash, or to * 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 * @chan: the instance to store (not const so we can update the unique_id upon
* insert) * 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 * 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 * @ctx: context to allocate peers from
* @w: wallet to load 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 * Be sure to call this only once on startup since it'll append peers
* loaded from the database to the list without checking. * loaded from the database to the list without checking.
*/ */
bool wallet_channels_load_active(const tal_t *ctx, bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w);
struct wallet *w, struct list_head *peers);
/** /**
* wallet_channels_first_blocknum - get first block we're interested in. * 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_htlc_save_in - store an htlc_in in the database
* *
* @wallet: wallet to store the htlc into * @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 * @in: the htlc_in to store
* *
* This will store the contents of the `struct htlc_in` in the * 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. * HTLCs.
*/ */
void wallet_htlc_save_in(struct wallet *wallet, 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 * 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. * See comment for wallet_htlc_save_in.
*/ */
void wallet_htlc_save_out(struct wallet *wallet, void wallet_htlc_save_out(struct wallet *wallet,
const struct wallet_channel *chan, const struct channel *chan,
struct htlc_out *out); 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. * corresponding htlc_in after loading all channels.
*/ */
bool wallet_htlcs_load_for_channel(struct wallet *wallet, bool wallet_htlcs_load_for_channel(struct wallet *wallet,
struct wallet_channel *chan, struct channel *chan,
struct htlc_in_map *htlcs_in, struct htlc_in_map *htlcs_in,
struct htlc_out_map *htlcs_out); struct htlc_out_map *htlcs_out);
@ -555,7 +543,7 @@ void wallet_invoice_waitone(const tal_t *ctx,
* @chan: Channel to fetch stubs for * @chan: Channel to fetch stubs for
*/ */
struct htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, 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. * wallet_payment_setup - Remember this payment for later committing.

19
wallet/walletrpc.c

@ -414,22 +414,27 @@ static void json_listfunds(struct command *cmd, const char *buffer UNUSED,
/* Add funds that are allocated to channels */ /* Add funds that are allocated to channels */
json_array_start(response, "channels"); json_array_start(response, "channels");
list_for_each(&cmd->ld->peers, p, list) { list_for_each(&cmd->ld->peers, p, list) {
if (!p->our_msatoshi || !p->funding_txid) struct channel *c;
list_for_each(&p->channels, c, list) {
if (!c->our_msatoshi || !c->funding_txid)
continue; continue;
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_pubkey(response, "peer_id", &p->id); json_add_pubkey(response, "peer_id", &p->id);
if (p->scid) if (c->scid)
json_add_short_channel_id(response, "short_channel_id", json_add_short_channel_id(response,
p->scid); "short_channel_id",
c->scid);
/* Poor man's rounding to satoshis to match the unit for outputs */ /* 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_sat",
(*c->our_msatoshi + 500)/1000);
json_add_u64(response, "channel_total_sat", json_add_u64(response, "channel_total_sat",
p->funding_satoshi); c->funding_satoshi);
json_add_txid(response, "funding_txid", p->funding_txid); json_add_txid(response, "funding_txid", c->funding_txid);
json_object_end(response); json_object_end(response);
} }
}
json_array_end(response); json_array_end(response);
json_object_end(response); json_object_end(response);

Loading…
Cancel
Save