diff --git a/.travis.yml b/.travis.yml index 2f2391a8f55c..0cb8b19258aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ env: - NO_VALGRIND=1 ARCH=32 DEVELOPER=1 COMPILER=gcc TEST_GROUP=1 TEST_GROUP_COUNT=2 SOURCE_CHECK_ONLY=false - NO_VALGRIND=1 ARCH=32 DEVELOPER=1 COMPILER=gcc TEST_GROUP=2 TEST_GROUP_COUNT=2 SOURCE_CHECK_ONLY=false - NO_VALGRIND=1 ARCH=64 DEVELOPER=1 COMPILER=gcc SOURCE_CHECK_ONLY=false + - NO_VALGRIND=1 ARCH=64 DEVELOPER=0 COMPILER=gcc NO_COMPAT=1 SOURCE_CHECK_ONLY=false - NO_VALGRIND=0 ARCH=64 DEVELOPER=0 COMPILER=gcc TEST_GROUP=1 TEST_GROUP_COUNT=3 SOURCE_CHECK_ONLY=false - NO_VALGRIND=0 ARCH=64 DEVELOPER=0 COMPILER=gcc TEST_GROUP=2 TEST_GROUP_COUNT=3 SOURCE_CHECK_ONLY=false - NO_VALGRIND=0 ARCH=64 DEVELOPER=0 COMPILER=gcc TEST_GROUP=3 TEST_GROUP_COUNT=3 SOURCE_CHECK_ONLY=false @@ -25,7 +26,7 @@ env: script: - docker pull cdecker/lightning-ci:${ARCH}bit | tee - env | grep -E '^[A-Z_]+\=' | tee /tmp/envlist - - $SOURCE_CHECK_ONLY || docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make -j3 CC=${COMPILER} DEVELOPER=${DEVELOPER} + - $SOURCE_CHECK_ONLY || docker run --rm=true --env-file=/tmp/envlist -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make -j3 CC=${COMPILER} DEVELOPER=${DEVELOPER} - $SOURCE_CHECK_ONLY || docker run --rm=true --env-file=/tmp/envlist -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make CC=${COMPILER} check DEVELOPER=${DEVELOPER} # - (! $SOURCE_CHECK_ONLY) || git clone https://github.com/lightningnetwork/lightning-rfc.git # - (! $SOURCE_CHECK_ONLY) || docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make check-source BOLTDIR=lightning-rfc diff --git a/Makefile b/Makefile index 440885b8e31f..a8a17e61348b 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,11 @@ PIE_CFLAGS=-fPIE -fPIC PIE_LDFLAGS=-pie endif +ifneq ($(NO_COMPAT),1) +# We support compatibility with pre-0.6. +COMPAT_CFLAGS=-DCOMPAT_V052=1 +endif + PYTEST := $(shell command -v pytest 2> /dev/null) PYTEST_OPTS := -v -x ifeq ($(TRAVIS),true) @@ -161,7 +166,7 @@ ALL_PROGRAMS = CPPFLAGS = -DBINTOPKGLIBEXECDIR='"'$(shell sh tools/rel.sh $(bindir) $(pkglibexecdir))'"' CWARNFLAGS := -Werror -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition CDEBUGFLAGS := -std=gnu11 -g -fstack-protector -CFLAGS = $(CPPFLAGS) $(CWARNFLAGS) $(CDEBUGFLAGS) -I $(CCANDIR) $(EXTERNAL_INCLUDE_FLAGS) -I . -I/usr/local/include $(FEATURES) $(COVFLAGS) $(DEV_CFLAGS) -DSHACHAIN_BITS=48 -DJSMN_PARENT_LINKS $(PIE_CFLAGS) +CFLAGS = $(CPPFLAGS) $(CWARNFLAGS) $(CDEBUGFLAGS) -I $(CCANDIR) $(EXTERNAL_INCLUDE_FLAGS) -I . -I/usr/local/include $(FEATURES) $(COVFLAGS) $(DEV_CFLAGS) -DSHACHAIN_BITS=48 -DJSMN_PARENT_LINKS $(PIE_CFLAGS) $(COMPAT_CFLAGS) # We can get configurator to run a different compile cmd to cross-configure. CONFIGURATOR_CC := $(CC) diff --git a/bitcoin/script.c b/bitcoin/script.c index f540f3440d1b..8295cfe0c3c5 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -22,6 +22,7 @@ #define OP_NOTIF 0x64 #define OP_ELSE 0x67 #define OP_ENDIF 0x68 +#define OP_RETURN 0x6a #define OP_2DROP 0x6d #define OP_DEPTH 0x74 #define OP_DROP 0x75 @@ -214,6 +215,14 @@ u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct bitcoin_address *addr) return script; } +u8 *scriptpubkey_opreturn(const tal_t *ctx) +{ + u8 *script = tal_arr(ctx, u8, 0); + + add_op(&script, OP_RETURN); + return script; +} + /* Create an input script which spends p2pkh */ u8 *bitcoin_redeem_p2pkh(const tal_t *ctx, const struct pubkey *pubkey, const secp256k1_ecdsa_signature *sig) diff --git a/bitcoin/script.h b/bitcoin/script.h index fd0e89a5ecff..53a4425e72b4 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -29,6 +29,9 @@ u8 *scriptpubkey_p2sh_hash(const tal_t *ctx, const struct ripemd160 *redeemhash) /* Create an output script using p2pkh */ u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct bitcoin_address *addr); +/* Create a prunable output script */ +u8 *scriptpubkey_opreturn(const tal_t *ctx); + /* Create an input script which spends p2pkh */ u8 *bitcoin_redeem_p2pkh(const tal_t *ctx, const struct pubkey *pubkey, const secp256k1_ecdsa_signature *sig); diff --git a/channeld/channel.c b/channeld/channel.c index 14d639c5d4f3..8b1d979f94b3 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -146,9 +146,12 @@ struct peer { /* We save calculated commit sigs while waiting for master approval */ struct commit_sigs *next_commit_sigs; - /* If master told us to shut down, this contains scriptpubkey until - * we're ready to send it. */ - u8 *unsent_shutdown_scriptpubkey; + /* The scriptpubkey to use for shutting down. */ + u8 *final_scriptpubkey; + + /* If master told us to shut down */ + bool send_shutdown; + /* Has shutdown been sent by each side? */ bool shutdown_sent[NUM_SIDES]; /* Information used for reestablishment. */ @@ -769,7 +772,7 @@ static void maybe_send_shutdown(struct peer *peer) { u8 *msg; - if (!peer->unsent_shutdown_scriptpubkey) + if (!peer->send_shutdown) return; /* Send a disable channel_update so others don't try to route @@ -778,11 +781,9 @@ static void maybe_send_shutdown(struct peer *peer) wire_sync_write(GOSSIP_FD, msg); enqueue_peer_msg(peer, take(msg)); - msg = towire_shutdown(peer, &peer->channel_id, - peer->unsent_shutdown_scriptpubkey); + msg = towire_shutdown(peer, &peer->channel_id, peer->final_scriptpubkey); enqueue_peer_msg(peer, take(msg)); - peer->unsent_shutdown_scriptpubkey - = tal_free(peer->unsent_shutdown_scriptpubkey); + peer->send_shutdown = false; peer->shutdown_sent[LOCAL] = true; billboard_update(peer); } @@ -1589,11 +1590,24 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) &peer->channel_id, "Bad shutdown %s", tal_hex(peer, shutdown)); - /* Tell master, it will tell us what to send (if any). */ + /* Tell master: we don't have to wait because on reconnect other end + * will re-send anyway. */ wire_sync_write(MASTER_FD, take(towire_channel_got_shutdown(peer, scriptpubkey))); peer->shutdown_sent[REMOTE] = true; + /* BOLT #2: + * + * A receiving node: + * ... + * - once there are no outstanding updates on the peer, UNLESS + * it has already sent a `shutdown`: + * - MUST reply to a `shutdown` message with a `shutdown` + */ + if (!peer->shutdown_sent[LOCAL]) { + peer->send_shutdown = true; + start_commit_timer(peer); + } billboard_update(peer); } @@ -2377,13 +2391,11 @@ static void handle_ping_cmd(struct peer *peer, const u8 *inmsg) static void handle_shutdown_cmd(struct peer *peer, const u8 *inmsg) { - u8 *scriptpubkey; - - if (!fromwire_channel_send_shutdown(peer, inmsg, &scriptpubkey)) + if (!fromwire_channel_send_shutdown(inmsg)) master_badmsg(WIRE_CHANNEL_SEND_SHUTDOWN, inmsg); - /* We can't send this until commit (if any) is done, so start timer<. */ - peer->unsent_shutdown_scriptpubkey = scriptpubkey; + /* We can't send this until commit (if any) is done, so start timer. */ + peer->send_shutdown = true; start_commit_timer(peer); } @@ -2537,8 +2549,9 @@ static void init_channel(struct peer *peer) &peer->funding_locked[REMOTE], &peer->short_channel_ids[LOCAL], &reconnected, - &peer->unsent_shutdown_scriptpubkey, + &peer->send_shutdown, &peer->shutdown_sent[REMOTE], + &peer->final_scriptpubkey, &peer->channel_flags, &funding_signed)) master_badmsg(WIRE_CHANNEL_INIT, msg); diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index cd255b3ad14b..da809d30e037 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -55,9 +55,10 @@ channel_init,,local_funding_locked,bool channel_init,,remote_funding_locked,bool channel_init,,funding_short_id,struct short_channel_id channel_init,,reestablish,bool -channel_init,,shutdown_scriptpubkey_len,u16 -channel_init,,shutdown_scriptpubkey,shutdown_scriptpubkey_len*u8 +channel_init,,send_shutdown,bool channel_init,,remote_shutdown_received,bool +channel_init,,final_scriptpubkey_len,u16 +channel_init,,final_scriptpubkey,final_scriptpubkey_len*u8 channel_init,,flags,u8 channel_init,,init_peer_pkt_len,u16 channel_init,,init_peer_pkt,init_peer_pkt_len*u8 @@ -164,10 +165,8 @@ channel_got_revoke,,changed,num_changed*struct changed_htlc # (eg. if we sent another commitment_signed, that would implicitly ack). channel_got_revoke_reply,1122 -# Tell peer that channel is shutting down +# Tell peer to shut down channel. channel_send_shutdown,1023 -channel_send_shutdown,,scriptpubkey_len,u16 -channel_send_shutdown,,scriptpubkey,scriptpubkey_len*u8 # Peer told us that channel is shutting down channel_got_shutdown,1024 diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 11683d870ed7..385675142e38 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -483,6 +483,10 @@ static void init_topo(struct bitcoind *bitcoind UNUSED, block_map_add(&topo->block_map, topo->root); topo->tip = topo->prev_tip = topo->root; + /* In case we don't get all the way to updates_complete */ + db_set_intvar(topo->bitcoind->ld->wallet->db, + "last_processed_block", topo->tip->height); + io_break(topo); } diff --git a/lightningd/channel.c b/lightningd/channel.c index b89b638040ed..775821386107 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -145,8 +146,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, const struct channel_info *channel_info, /* NULL or stolen */ u8 *remote_shutdown_scriptpubkey, - /* (-1 if not chosen yet) */ - s64 local_shutdown_idx, + u64 final_key_idx, bool last_was_revoke, /* NULL or stolen */ struct changed_htlc *last_sent_commit, @@ -199,7 +199,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->channel_info = *channel_info; channel->remote_shutdown_scriptpubkey = tal_steal(channel, remote_shutdown_scriptpubkey); - channel->local_shutdown_idx = local_shutdown_idx; + channel->final_key_idx = final_key_idx; channel->last_was_revoke = last_was_revoke; channel->last_sent_commit = tal_steal(channel, last_sent_commit); channel->first_blocknum = first_blocknum; @@ -208,6 +208,11 @@ struct channel *new_channel(struct peer *peer, u64 dbid, list_add_tail(&peer->channels, &channel->list); tal_add_destructor(channel, destroy_channel); + /* Make sure we see any spends using this key */ + txfilter_add_scriptpubkey(peer->ld->owned_txfilter, + take(p2wpkh_for_keyidx(NULL, peer->ld, + channel->final_key_idx))); + return channel; } diff --git a/lightningd/channel.h b/lightningd/channel.h index 01ff66f4e3ed..0a46ac2f0cae 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -80,8 +80,8 @@ struct channel { /* Their scriptpubkey if they sent shutdown. */ u8 *remote_shutdown_scriptpubkey; - /* Our key for shutdown (-1 if not chosen yet) */ - s64 local_shutdown_idx; + /* Address for any final outputs */ + u64 final_key_idx; /* Reestablishment stuff: last sent commit and revocation details. */ bool last_was_revoke; @@ -122,8 +122,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, const struct channel_info *channel_info, /* NULL or stolen */ u8 *remote_shutdown_scriptpubkey, - /* (-1 if not chosen yet) */ - s64 local_shutdown_idx, + u64 final_key_idx, bool last_was_revoke, /* NULL or stolen */ struct changed_htlc *last_sent_commit, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index c4f65b7a9b16..a00946f31f9a 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -76,48 +76,11 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg) return; } - if (channel->local_shutdown_idx == -1) { - u8 *scriptpubkey; - - channel->local_shutdown_idx = wallet_get_newindex(ld); - if (channel->local_shutdown_idx == -1) { - channel_internal_error(channel, - "Can't get local shutdown index"); - return; - } - + /* If we weren't already shutting down, we are now */ + if (channel->state == CHANNELD_NORMAL) channel_set_state(channel, CHANNELD_NORMAL, CHANNELD_SHUTTING_DOWN); - /* BOLT #2: - * - * A sending node MUST set `scriptpubkey` to one of the - * following forms: - * - * ...3. `OP_0` `20` 20-bytes (version 0 pay to witness pubkey), - */ - scriptpubkey = p2wpkh_for_keyidx(msg, ld, - channel->local_shutdown_idx); - if (!scriptpubkey) { - channel_internal_error(channel, - "Can't get shutdown script %"PRIu64, - channel->local_shutdown_idx); - return; - } - - txfilter_add_scriptpubkey(ld->owned_txfilter, scriptpubkey); - - /* BOLT #2: - * - * A receiving node MUST reply to a `shutdown` message with a - * `shutdown` once there are no outstanding updates on the - * peer, unless it has already sent a `shutdown`. - */ - subd_send_msg(channel->owner, - take(towire_channel_send_shutdown(channel, - scriptpubkey))); - } - /* TODO(cdecker) Selectively save updated fields to DB */ wallet_channel_save(ld->wallet, channel); } @@ -215,7 +178,6 @@ bool peer_start_channeld(struct channel *channel, const struct failed_htlc **failed_htlcs; enum side *failed_sides; struct short_channel_id funding_channel_id; - const u8 *shutdown_scriptpubkey; u64 num_revocations; struct lightningd *ld = channel->peer->ld; const struct config *cfg = &ld->config; @@ -262,13 +224,6 @@ bool peer_start_channeld(struct channel *channel, memset(&funding_channel_id, 0, sizeof(funding_channel_id)); } - if (channel->local_shutdown_idx != -1) { - shutdown_scriptpubkey - = p2wpkh_for_keyidx(tmpctx, ld, - channel->local_shutdown_idx); - } else - shutdown_scriptpubkey = NULL; - num_revocations = revocations_received(&channel->their_shachain.chain); /* Warn once. */ @@ -316,8 +271,10 @@ bool peer_start_channeld(struct channel *channel, channel->remote_funding_locked, &funding_channel_id, reconnected, - shutdown_scriptpubkey, + channel->state == CHANNELD_SHUTTING_DOWN, channel->remote_shutdown_scriptpubkey != NULL, + p2wpkh_for_keyidx(tmpctx, ld, + channel->final_key_idx), channel->channel_flags, funding_signed); diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 9ce9ce7f1e64..30af84f9afc2 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -140,20 +141,15 @@ void peer_start_closingd(struct channel *channel, bool reconnected) { const tal_t *tmpctx = tal_tmpctx(channel); - u8 *initmsg, *local_scriptpubkey; + u8 *initmsg; u64 minfee, startfee, feelimit; u64 num_revocations; u64 funding_msatoshi, our_msatoshi, their_msatoshi; struct lightningd *ld = channel->peer->ld; - if (channel->local_shutdown_idx == -1 - || !channel->remote_shutdown_scriptpubkey) { + if (!channel->remote_shutdown_scriptpubkey) { channel_internal_error(channel, - "Can't start closing: local %s remote %s", - channel->local_shutdown_idx == -1 - ? "not shutdown" : "shutdown", - channel->remote_shutdown_scriptpubkey - ? "shutdown" : "not shutdown"); + "Can't start closing: no remote info"); tal_free(tmpctx); return; } @@ -174,15 +170,6 @@ void peer_start_closingd(struct channel *channel, return; } - local_scriptpubkey = p2wpkh_for_keyidx(tmpctx, ld, - channel->local_shutdown_idx); - if (!local_scriptpubkey) { - channel_internal_error(channel, - "Can't generate local shutdown scriptpubkey"); - tal_free(tmpctx); - return; - } - /* BOLT #2: * * A sending node MUST set `fee_satoshis` lower than or equal @@ -227,7 +214,8 @@ void peer_start_closingd(struct channel *channel, their_msatoshi / 1000, /* Rounds down */ channel->our_config.dust_limit_satoshis, minfee, feelimit, startfee, - local_scriptpubkey, + p2wpkh_for_keyidx(tmpctx, ld, + channel->final_key_idx), channel->remote_shutdown_scriptpubkey, reconnected, channel->next_index[LOCAL], diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index fd8cf3ec833d..7208a5c993a9 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -217,10 +217,9 @@ static void shutdown_subdaemons(struct lightningd *ld) db_commit_transaction(ld->wallet->db); } -struct chainparams *get_chainparams(const struct lightningd *ld) +const struct chainparams *get_chainparams(const struct lightningd *ld) { - return cast_const(struct chainparams *, - ld->topology->bitcoind->chainparams); + return ld->topology->bitcoind->chainparams; } static void init_txfilter(struct wallet *w, struct txfilter *filter) diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index f738920b0e8a..8ac352514983 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -169,7 +169,7 @@ struct lightningd { #endif /* DEVELOPER */ }; -struct chainparams *get_chainparams(const struct lightningd *ld); +const struct chainparams *get_chainparams(const struct lightningd *ld); /* State for performing backtraces. */ struct backtrace_state *backtrace_state; diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index c2cbad27061e..30926a3162f1 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -343,13 +344,12 @@ enum watch_result funding_spent(struct channel *channel, size_t input_num, const struct block *block) { - u8 *msg, *scriptpubkey; + u8 *msg; struct bitcoin_txid our_last_txid; - s64 keyindex; - struct pubkey ourkey; struct htlc_stub *stubs; const tal_t *tmpctx = tal_tmpctx(channel); struct lightningd *ld = channel->peer->ld; + struct pubkey final_key; channel_fail_permanent(channel, "Funding transaction spent"); @@ -380,35 +380,13 @@ enum watch_result funding_spent(struct channel *channel, return KEEP_WATCHING; } - /* We re-use this key to send other outputs to. */ - if (channel->local_shutdown_idx >= 0) - keyindex = channel->local_shutdown_idx; - else { - keyindex = wallet_get_newindex(ld); - if (keyindex < 0) { - log_broken(channel->log, "Could not get keyindex"); - tal_free(tmpctx); - return KEEP_WATCHING; - } - } - scriptpubkey = p2wpkh_for_keyidx(tmpctx, ld, keyindex); - if (!scriptpubkey) { - channel_internal_error(channel, - "Can't get shutdown script %"PRIu64, - keyindex); + if (!bip32_pubkey(ld->wallet->bip32_base, &final_key, + channel->final_key_idx)) { + log_broken(channel->log, "Could not derive onchain key %"PRIu64, + channel->final_key_idx); tal_free(tmpctx); - return DELETE_WATCH; - } - txfilter_add_scriptpubkey(ld->owned_txfilter, scriptpubkey); - - if (!bip32_pubkey(ld->wallet->bip32_base, &ourkey, keyindex)) { - channel_internal_error(channel, - "Can't get shutdown key %"PRIu64, - keyindex); - tal_free(tmpctx); - return DELETE_WATCH; + return KEEP_WATCHING; } - /* This could be a mutual close, but it doesn't matter. */ bitcoin_txid(channel->last_tx, &our_last_txid); @@ -429,9 +407,10 @@ enum watch_result funding_spent(struct channel *channel, channel->our_config.dust_limit_satoshis, &channel->channel_info.theirbase.revocation, &our_last_txid, - scriptpubkey, + p2wpkh_for_keyidx(tmpctx, ld, + channel->final_key_idx), channel->remote_shutdown_scriptpubkey, - &ourkey, + &final_key, channel->funder, &channel->channel_info.theirbase.payment, &channel->channel_info.theirbase.htlc, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 6b9f81d1296e..79c8af92d4e5 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -146,7 +146,8 @@ void json_add_uncommitted_channel(struct json_result *response, json_object_end(response); } -/* Steals fields from uncommitted_channel */ +/* Steals fields from uncommitted_channel: returns NULL if can't generate a + * key for this channel (shouldn't happen!). */ static struct channel * wallet_commit_channel(struct lightningd *ld, struct uncommitted_channel *uc, @@ -162,6 +163,14 @@ wallet_commit_channel(struct lightningd *ld, { struct channel *channel; u64 our_msatoshi; + s64 final_key_idx; + + /* Get a key to use for closing outputs from this tx */ + final_key_idx = wallet_get_newindex(ld); + if (final_key_idx == -1) { + log_broken(uc->log, "Can't get final key index"); + return NULL; + } if (uc->fc) our_msatoshi = funding_satoshi * 1000 - push_msat; @@ -198,7 +207,7 @@ wallet_commit_channel(struct lightningd *ld, NULL, /* No HTLC sigs yet */ channel_info, NULL, /* No remote_shutdown_scriptpubkey yet */ - -1, false, + final_key_idx, false, NULL, /* No commit sent yet */ uc->first_blocknum); @@ -335,6 +344,10 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, fc->channel_flags, &channel_info, feerate); + if (!channel) { + command_fail(fc->cmd, "Key generation failure"); + goto failed; + } /* Get HSM to sign the funding tx. */ log_debug(channel->log, "Getting HSM to sign funding tx"); @@ -450,6 +463,10 @@ static void opening_fundee_finished(struct subd *openingd, channel_flags, &channel_info, feerate); + if (!channel) { + tal_free(uc); + return; + } log_debug(channel->log, "Watching funding tx %s", type_to_string(reply, struct bitcoin_txid, diff --git a/lightningd/pay.c b/lightningd/pay.c index ea13f9145ad2..47433a34d3db 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -382,6 +382,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, payment = wallet_payment_by_hash(tmpctx, ld->wallet, &hout->payment_hash); +#ifdef COMPAT_V052 /* FIXME: Prior to 299b280f7, we didn't put route_nodes and * route_channels in db. If this happens, it's an old payment, * so we can simply mark it failed in db and return. */ @@ -396,6 +397,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, tal_free(tmpctx); return; } +#endif /* This gives more details than a generic failure message */ if (localfail) { diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 73bb9774ae5e..cefc4499445a 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -808,28 +808,12 @@ static void json_close(struct command *cmd, /* Normal case. */ if (channel->state == CHANNELD_NORMAL) { - u8 *shutdown_scriptpubkey; - - channel->local_shutdown_idx = wallet_get_newindex(cmd->ld); - if (channel->local_shutdown_idx == -1) { - command_fail(cmd, "Failed to get new key for shutdown"); - return; - } - shutdown_scriptpubkey = p2wpkh_for_keyidx(cmd, cmd->ld, - channel->local_shutdown_idx); - if (!shutdown_scriptpubkey) { - command_fail(cmd, "Failed to get script for shutdown"); - return; - } - - channel_set_state(channel, CHANNELD_NORMAL, CHANNELD_SHUTTING_DOWN); - - txfilter_add_scriptpubkey(cmd->ld->owned_txfilter, shutdown_scriptpubkey); + channel_set_state(channel, + CHANNELD_NORMAL, CHANNELD_SHUTTING_DOWN); if (channel->owner) subd_send_msg(channel->owner, - take(towire_channel_send_shutdown(channel, - shutdown_scriptpubkey))); + take(towire_channel_send_shutdown(channel))); command_success(cmd, null_response(cmd)); } else diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index a5b30752d775..288db2eb0786 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -84,7 +84,8 @@ void subd_shutdown(struct subd *subd UNNEEDED, unsigned int seconds UNNEEDED) void timer_expired(tal_t *ctx UNNEEDED, struct timer *timer UNNEEDED) { fprintf(stderr, "timer_expired called!\n"); abort(); } /* Generated stub for txfilter_add_derkey */ -void txfilter_add_derkey(struct txfilter *filter UNNEEDED, u8 derkey[PUBKEY_DER_LEN]) +void txfilter_add_derkey(struct txfilter *filter UNNEEDED, + const u8 derkey[PUBKEY_DER_LEN]) { fprintf(stderr, "txfilter_add_derkey called!\n"); abort(); } /* Generated stub for txfilter_new */ struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED) diff --git a/onchaind/onchain.c b/onchaind/onchain.c index c95d4948028b..303291059df8 100644 --- a/onchaind/onchain.c +++ b/onchaind/onchain.c @@ -213,6 +213,8 @@ static const char *output_type_name(enum output_type output_type) * 3. the their-commitment, our HTLC redeem case (` `) * 4. the their-revoked-commitment, to-local (` 1`) * 5. the their-revoked-commitment, htlc (` `) + * + * Overrides *tx_type if it all turns to dust. */ static struct bitcoin_tx *tx_to_us(const tal_t *ctx, struct tracked_output *out, @@ -221,7 +223,8 @@ static struct bitcoin_tx *tx_to_us(const tal_t *ctx, const void *elem, size_t elemsize, const u8 *wscript, const struct privkey *privkey, - const struct pubkey *pubkey) + const struct pubkey *pubkey, + enum tx_type *tx_type) { struct bitcoin_tx *tx; u64 fee; @@ -243,10 +246,12 @@ static struct bitcoin_tx *tx_to_us(const tal_t *ctx, + 1 + 3 + 73 + 0 + tal_len(wscript)) / 1000; - /* Result is trivial? Just eliminate output. */ - if (tx->output[0].amount < dust_limit_satoshis + fee) - tal_resize(&tx->output, 0); - else + /* Result is trivial? Spent to OP_RETURN to avoid leaving dust. */ + if (tx->output[0].amount < dust_limit_satoshis + fee) { + tx->output[0].amount = 0; + tx->output[0].script = scriptpubkey_opreturn(tx->output); + *tx_type = DONATING_TO_MINERS; + } else tx->output[0].amount -= fee; sign_tx_input(tx, 0, NULL, wscript, privkey, pubkey, &sig); @@ -336,7 +341,7 @@ static void propose_resolution(struct tracked_output *out, unsigned int depth_required, enum tx_type tx_type) { - status_trace("Propose handling %s/%s by %s (%s) in %u blocks", + status_trace("Propose handling %s/%s by %s (%s) after %u blocks", tx_type_name(out->tx_type), output_type_name(out->output_type), tx_type_name(tx_type), @@ -362,35 +367,85 @@ static void propose_resolution_at_block(struct tracked_output *out, /* Expiry could be in the past! */ if (block_required < out->tx_blockheight) depth = 0; - else - depth = block_required - out->tx_blockheight; + else /* Note that out->tx_blockheight is already at depth 1 */ + depth = block_required - out->tx_blockheight + 1; propose_resolution(out, tx, depth, tx_type); } +static bool is_valid_sig(const u8 *e) +{ + secp256k1_ecdsa_signature sig; + size_t len = tal_len(e); + + /* Last byte is sighash flags */ + if (len < 1) + return false; + + return signature_from_der(e, len-1, &sig); +} + +/* We ignore things which look like signatures. */ +static bool input_similar(const struct bitcoin_tx_input *i1, + const struct bitcoin_tx_input *i2) +{ + if (!structeq(&i1->txid, &i2->txid)) + return false; + + if (i1->index != i2->index) + return false; + + if (!scripteq(i1->script, i2->script)) + return false; + + if (i1->sequence_number != i2->sequence_number) + return false; + + if (tal_count(i1->witness) != tal_count(i2->witness)) + return false; + + for (size_t i = 0; i < tal_count(i1->witness); i++) { + if (scripteq(i1->witness[i], i2->witness[i])) + continue; + + if (is_valid_sig(i1->witness[i]) && is_valid_sig(i2->witness[i])) + continue; + return false; + } + + return true; +} + /* This simple case: true if this was resolved by our proposal. */ static bool resolved_by_proposal(struct tracked_output *out, - const struct bitcoin_txid *txid) + const struct bitcoin_tx *tx) { /* If there's no TX associated, it's not us. */ if (!out->proposal->tx) return false; out->resolved = tal(out, struct resolution); - bitcoin_txid(out->proposal->tx, &out->resolved->txid); - /* Not the same as what we proposed? */ - if (!structeq(&out->resolved->txid, txid)) { - out->resolved = tal_free(out->resolved); - /* Don't need proposal any more */ - out->proposal = tal_free(out->proposal); + /* Our proposal can change as feerates change. Input + * comparison (ignoring signatures) works pretty well. + * + * FIXME: Better would be to compare outputs, but they weren't + * saved to db correctly until now. (COMPAT_V052) + */ + if (tal_count(tx->input) != tal_count(out->proposal->tx->input)) return false; + + for (size_t i = 0; i < tal_count(tx->input); i++) { + if (!input_similar(tx->input + i, out->proposal->tx->input + i)) + return false; } + bitcoin_txid(tx, &out->resolved->txid); status_trace("Resolved %s/%s by our proposal %s (%s)", tx_type_name(out->tx_type), output_type_name(out->output_type), tx_type_name(out->proposal->tx_type), - type_to_string(trc, struct bitcoin_tx, out->proposal->tx)); + type_to_string(trc, struct bitcoin_txid, + &out->resolved->txid)); out->resolved->depth = 0; out->resolved->tx_type = out->proposal->tx_type; @@ -672,6 +727,7 @@ static void resolve_htlc_tx(struct tracked_output ***outs, { struct tracked_output *out; struct bitcoin_tx *tx; + enum tx_type tx_type = OUR_DELAYED_RETURN_TO_WALLET; u8 *wscript = bitcoin_wscript_htlc_tx(htlc_tx, to_self_delay[LOCAL], &keyset->self_revocation_key, &keyset->self_delayed_payment_key); @@ -705,10 +761,10 @@ static void resolve_htlc_tx(struct tracked_output ***outs, tx = tx_to_us(*outs, out, to_self_delay[LOCAL], 0, NULL, 0, wscript, &delayed_payment_privkey, - &keyset->self_delayed_payment_key); + &keyset->self_delayed_payment_key, + &tx_type); - propose_resolution(out, tx, to_self_delay[LOCAL], - OUR_DELAYED_RETURN_TO_WALLET); + propose_resolution(out, tx, to_self_delay[LOCAL], tx_type); } /* BOLT #5: @@ -726,6 +782,7 @@ static void resolve_htlc_tx(struct tracked_output ***outs, static void steal_htlc_tx(struct tracked_output *out) { struct bitcoin_tx *tx; + enum tx_type tx_type = OUR_PENALTY_TX; /* BOLT #3: * @@ -736,8 +793,9 @@ static void steal_htlc_tx(struct tracked_output *out) &ONE, sizeof(ONE), out->wscript, revocation_privkey, - &keyset->self_revocation_key); - propose_resolution(out, tx, 0, OUR_PENALTY_TX); + &keyset->self_revocation_key, + &tx_type); + propose_resolution(out, tx, 0, tx_type); } /* An output has been spent: see if it resolves something we care about. */ @@ -761,7 +819,7 @@ static void output_spent(struct tracked_output ***outs, continue; /* Was this our resolution? */ - if (resolved_by_proposal(out, &txid)) { + if (resolved_by_proposal(out, tx)) { /* If it's our htlc tx, we need to resolve that, too. */ if (out->resolved->tx_type == OUR_HTLC_SUCCESS_TX || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX) @@ -995,6 +1053,8 @@ static void handle_preimage(struct tracked_output **outs, outs[i]->wscript); propose_resolution(outs[i], tx, 0, OUR_HTLC_SUCCESS_TX); } else { + enum tx_type tx_type = THEIR_HTLC_FULFILL_TO_US; + /* BOLT #5: * * otherwise, it MUST spend the output to a convenient @@ -1004,9 +1064,9 @@ static void handle_preimage(struct tracked_output **outs, preimage, sizeof(*preimage), outs[i]->wscript, &htlc_privkey, - &keyset->other_htlc_key); - propose_resolution(outs[i], tx, 0, - THEIR_HTLC_FULFILL_TO_US); + &keyset->other_htlc_key, + &tx_type); + propose_resolution(outs[i], tx, 0, tx_type); } } } @@ -1155,6 +1215,7 @@ static void resolve_our_htlc_ourcommit(struct tracked_output *out) static void resolve_our_htlc_theircommit(struct tracked_output *out) { struct bitcoin_tx *tx; + enum tx_type tx_type = OUR_HTLC_TIMEOUT_TO_US; /* BOLT #5: * @@ -1171,10 +1232,10 @@ static void resolve_our_htlc_theircommit(struct tracked_output *out) tx = tx_to_us(out, out, 0, out->htlc->cltv_expiry, NULL, 0, out->wscript, &htlc_privkey, - &keyset->other_htlc_key); + &keyset->other_htlc_key, + &tx_type); - propose_resolution_at_block(out, tx, out->htlc->cltv_expiry, - OUR_HTLC_TIMEOUT_TO_US); + propose_resolution_at_block(out, tx, out->htlc->cltv_expiry, tx_type); } static void resolve_their_htlc(struct tracked_output *out) @@ -1388,6 +1449,8 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx, if (script[LOCAL] && scripteq(tx->output[i].script, script[LOCAL])) { struct bitcoin_tx *to_us; + enum tx_type tx_type = OUR_DELAYED_RETURN_TO_WALLET; + /* BOLT #5: * * 1. _A's main output_: A node SHOULD spend this @@ -1410,14 +1473,15 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx, NULL, 0, local_wscript, &delayed_payment_privkey, - &keyset->self_delayed_payment_key); + &keyset->self_delayed_payment_key, + &tx_type); /* BOLT #5: * * If the output is spent (as recommended), the output * is *resolved* by the spending transaction */ propose_resolution(out, to_us, to_self_delay[LOCAL], - OUR_DELAYED_RETURN_TO_WALLET); + tx_type); script[LOCAL] = NULL; continue; @@ -1496,6 +1560,7 @@ static void steal_to_them_output(struct tracked_output *out) const tal_t *tmpctx = tal_tmpctx(NULL); u8 *wscript; struct bitcoin_tx *tx; + enum tx_type tx_type = OUR_PENALTY_TX; /* BOLT #3: * @@ -1512,15 +1577,17 @@ static void steal_to_them_output(struct tracked_output *out) &ONE, sizeof(ONE), wscript, revocation_privkey, - &keyset->self_revocation_key); + &keyset->self_revocation_key, + &tx_type); - propose_resolution(out, tx, 0, OUR_PENALTY_TX); + propose_resolution(out, tx, 0, tx_type); tal_free(tmpctx); } static void steal_htlc(struct tracked_output *out) { struct bitcoin_tx *tx; + enum tx_type tx_type = OUR_PENALTY_TX; u8 der[PUBKEY_DER_LEN]; /* BOLT #3: @@ -1535,9 +1602,10 @@ static void steal_htlc(struct tracked_output *out) der, sizeof(der), out->wscript, revocation_privkey, - &keyset->self_revocation_key); + &keyset->self_revocation_key, + &tx_type); - propose_resolution(out, tx, 0, OUR_PENALTY_TX); + propose_resolution(out, tx, 0, tx_type); } /* BOLT #5: diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index d2cf2ed41542..5164c3613abb 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -35,6 +35,9 @@ enum tx_type { /* When we use revocation key to take output. */ OUR_PENALTY_TX, + /* Amount too small, we're just spending it to close UTXO */ + DONATING_TO_MINERS, + /* Special type for marking outputs as resolved by self. */ SELF, diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index d7c03a845441..6b358769c7fd 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -1225,7 +1225,7 @@ def test_permfail(self): l1.daemon.wait_for_log('Their unilateral tx, old commit point') l1.daemon.wait_for_log(' to ONCHAIN') l2.daemon.wait_for_log(' to ONCHAIN') - l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET (.*) in 5 blocks') + l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET (.*) after 5 blocks') wait_for(lambda: l1.rpc.listpeers(l2.info['id'])['peers'][0]['channels'][0]['status'] == ['CHANNELD_NORMAL:Received error from peer: channel ALL: Internal error: Failing due to dev-fail command', @@ -1430,11 +1430,13 @@ def test_onchain_timeout(self): l2.daemon.wait_for_log(' to ONCHAIN') # Wait for timeout. - l1.daemon.wait_for_log('Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* in 5 blocks') - bitcoind.generate_block(5) + l1.daemon.wait_for_logs(['Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks', + 'Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX .* after 6 blocks']) + bitcoind.generate_block(4) - # (l1 will also collect its to-self payment.) l1.daemon.wait_for_log('sendrawtx exit 0') + + bitcoind.generate_block(1) l1.daemon.wait_for_log('sendrawtx exit 0') # We use 3 blocks for "reasonable depth" @@ -1456,6 +1458,7 @@ def test_onchain_timeout(self): # Now, 100 blocks and l1 should be done. bitcoind.generate_block(10) + sync_blockheight([l1]) assert not l1.daemon.is_in_log('onchaind complete, forgetting peer') bitcoind.generate_block(1) l1.daemon.wait_for_log('onchaind complete, forgetting peer') @@ -1510,7 +1513,7 @@ def try_pay(): l2.daemon.wait_for_log('OUR_UNILATERAL/THEIR_HTLC') # l2 should fulfill HTLC onchain, and spend to-us (any order) - l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks') + l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks') l2.daemon.wait_for_log('sendrawtx exit 0') # Payment should succeed. @@ -1587,9 +1590,9 @@ def test_penalty_inhtlc(self): # l2 should spend all of the outputs (except to-us). # Could happen in any order, depending on commitment tx. - l2.daemon.wait_for_logs(['Propose handling THEIR_REVOKED_UNILATERAL/DELAYED_OUTPUT_TO_THEM by OUR_PENALTY_TX .* in 0 blocks', + l2.daemon.wait_for_logs(['Propose handling THEIR_REVOKED_UNILATERAL/DELAYED_OUTPUT_TO_THEM by OUR_PENALTY_TX .* after 0 blocks', 'sendrawtx exit 0', - 'Propose handling THEIR_REVOKED_UNILATERAL/THEIR_HTLC by OUR_PENALTY_TX .* in 0 blocks', + 'Propose handling THEIR_REVOKED_UNILATERAL/THEIR_HTLC by OUR_PENALTY_TX .* after 0 blocks', 'sendrawtx exit 0']) # FIXME: test HTLC tx race! @@ -1650,9 +1653,9 @@ def test_penalty_outhtlc(self): # l2 should spend all of the outputs (except to-us). # Could happen in any order, depending on commitment tx. l2.daemon.wait_for_logs(['Ignoring output.*: THEIR_REVOKED_UNILATERAL/OUTPUT_TO_US', - 'Propose handling THEIR_REVOKED_UNILATERAL/DELAYED_OUTPUT_TO_THEM by OUR_PENALTY_TX .* in 0 blocks', + 'Propose handling THEIR_REVOKED_UNILATERAL/DELAYED_OUTPUT_TO_THEM by OUR_PENALTY_TX .* after 0 blocks', 'sendrawtx exit 0', - 'Propose handling THEIR_REVOKED_UNILATERAL/OUR_HTLC by OUR_PENALTY_TX .* in 0 blocks', + 'Propose handling THEIR_REVOKED_UNILATERAL/OUR_HTLC by OUR_PENALTY_TX .* after 0 blocks', 'sendrawtx exit 0']) # FIXME: test HTLC tx race! @@ -1663,6 +1666,138 @@ def test_penalty_outhtlc(self): # FIXME: Test wallet balance... wait_forget_channels(l2) + @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1") + def test_onchain_feechange(self): + """Onchain handling when we restart with different fees""" + # HTLC 1->2, 2 fails just after they're both irrevocably committed + # We need 2 to drop to chain, because then 1's HTLC timeout tx + # is generated on-the-fly, and is thus feerate sensitive. + disconnects = ['-WIRE_UPDATE_FAIL_HTLC', 'permfail'] + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) + + l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port']) + self.fund_channel(l1, l2, 10**6) + + rhash = l2.rpc.invoice(10**8, 'onchain_timeout', 'desc')['payment_hash'] + # We underpay, so it fails. + routestep = { + 'msatoshi': 10**8 - 1, + 'id': l2.info['id'], + 'delay': 5, + 'channel': '1:1:1' + } + + self.executor.submit(l1.rpc.sendpay, to_json([routestep]), rhash) + + # l2 will drop to chain. + l2.daemon.wait_for_log('permfail') + l2.daemon.wait_for_log('sendrawtx exit 0') + bitcoind.generate_block(1) + l1.daemon.wait_for_log(' to ONCHAIN') + l2.daemon.wait_for_log(' to ONCHAIN') + + # Wait for timeout. + l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US .* after 6 blocks') + bitcoind.generate_block(6) + + l1.daemon.wait_for_log('sendrawtx exit 0') + + # Make sure that gets included. + + bitcoind.generate_block(1) + # Now we restart with different feerates. + l1.stop() + + l1.daemon.cmd_line.append('--override-fee-rates=20000/9000/2000') + l1.daemon.start() + + # We recognize different proposal as ours. + l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US') + + # We use 3 blocks for "reasonable depth", so add two more + bitcoind.generate_block(2) + + # Note that the very similar test_onchain_timeout looks for a + # different string: that's because it sees the JSONRPC response, + # and due to the l1 restart, there is none here. + l1.daemon.wait_for_log('WIRE_PERMANENT_CHANNEL_FAILURE') + + # 90 later, l2 is done + bitcoind.generate_block(89) + sync_blockheight([l2]) + assert not l2.daemon.is_in_log('onchaind complete, forgetting peer') + bitcoind.generate_block(1) + l2.daemon.wait_for_log('onchaind complete, forgetting peer') + + # Now, 7 blocks and l1 should be done. + bitcoind.generate_block(6) + sync_blockheight([l1]) + assert not l1.daemon.is_in_log('onchaind complete, forgetting peer') + bitcoind.generate_block(1) + l1.daemon.wait_for_log('onchaind complete, forgetting peer') + + # Payment failed, BTW + assert l2.rpc.listinvoices('onchain_timeout')['invoices'][0]['status'] == 'unpaid' + + @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for dev-set-fees") + def test_onchain_all_dust(self): + """Onchain handling when we reduce output to all dust""" + # HTLC 1->2, 2 fails just after they're both irrevocably committed + # We need 2 to drop to chain, because then 1's HTLC timeout tx + # is generated on-the-fly, and is thus feerate sensitive. + disconnects = ['-WIRE_UPDATE_FAIL_HTLC', 'permfail'] + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) + + l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port']) + self.fund_channel(l1, l2, 10**6) + + rhash = l2.rpc.invoice(10**8, 'onchain_timeout', 'desc')['payment_hash'] + # We underpay, so it fails. + routestep = { + 'msatoshi': 10**7 - 1, + 'id': l2.info['id'], + 'delay': 5, + 'channel': '1:1:1' + } + + self.executor.submit(l1.rpc.sendpay, to_json([routestep]), rhash) + + # l2 will drop to chain. + l2.daemon.wait_for_log('permfail') + l2.daemon.wait_for_log('sendrawtx exit 0') + + # Make l1's fees really high. + l1.rpc.dev_setfees('100000', '100000', '100000') + + bitcoind.generate_block(1) + l1.daemon.wait_for_log(' to ONCHAIN') + l2.daemon.wait_for_log(' to ONCHAIN') + + # Wait for timeout. + l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by DONATING_TO_MINERS .* after 6 blocks') + bitcoind.generate_block(6) + + l1.daemon.wait_for_log('sendrawtx exit 0') + bitcoind.generate_block(1) + + l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal DONATING_TO_MINERS') + + # 100 deep and l2 forgets. + bitcoind.generate_block(91) + sync_blockheight([l2]) + assert not l2.daemon.is_in_log('onchaind complete, forgetting peer') + bitcoind.generate_block(1) + l2.daemon.wait_for_log('onchaind complete, forgetting peer') + + # l1 forgets 100 blocks after DONATING_TO_MINERS. + bitcoind.generate_block(6) + sync_blockheight([l1]) + assert not l1.daemon.is_in_log('onchaind complete, forgetting peer') + bitcoind.generate_block(1) + l1.daemon.wait_for_log('onchaind complete, forgetting peer') + @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1") def test_permfail_new_commit(self): # Test case where we have two possible commits: it will use new one. @@ -1682,8 +1817,8 @@ def test_permfail_new_commit(self): l1.daemon.wait_for_log('Their unilateral tx, new commit point') l1.daemon.wait_for_log(' to ONCHAIN') l2.daemon.wait_for_log(' to ONCHAIN') - l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) in 5 blocks') - l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) in 5 blocks') + l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) after 6 blocks') + l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) after 6 blocks') # OK, time out HTLC. bitcoind.generate_block(5) @@ -1718,17 +1853,17 @@ def test_permfail_htlc_in(self): l1.daemon.wait_for_log('Their unilateral tx, old commit point') l1.daemon.wait_for_log(' to ONCHAIN') l2.daemon.wait_for_log(' to ONCHAIN') - l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) in 5 blocks') - l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) in 5 blocks') + l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) after 6 blocks') + l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) after 6 blocks') # l2 then gets preimage, uses it instead of ignoring - l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks') + l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks') l2.daemon.wait_for_log('sendrawtx exit 0') bitcoind.generate_block(1) # OK, l1 sees l2 fulfill htlc. l1.daemon.wait_for_log('THEIR_UNILATERAL/OUR_HTLC gave us preimage') - l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* in 5 blocks') - bitcoind.generate_block(5) + l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks') + bitcoind.generate_block(6) l2.daemon.wait_for_log('sendrawtx exit 0') @@ -1760,12 +1895,12 @@ def test_permfail_htlc_out(self): l1.daemon.wait_for_log('Their unilateral tx, old commit point') l1.daemon.wait_for_log(' to ONCHAIN') l2.daemon.wait_for_log(' to ONCHAIN') - l2.daemon.wait_for_logs(['Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX \\(.*\\) in 5 blocks', - 'Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* in 5 blocks']) + l2.daemon.wait_for_logs(['Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX \\(.*\\) after 6 blocks', + 'Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks']) - l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) in 5 blocks') + l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) after 6 blocks') # l1 then gets preimage, uses it instead of ignoring - l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_FULFILL_TO_US .* in 0 blocks') + l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_FULFILL_TO_US .* after 0 blocks') l1.daemon.wait_for_log('sendrawtx exit 0') # l2 sees l1 fulfill tx. @@ -1774,19 +1909,22 @@ def test_permfail_htlc_out(self): l2.daemon.wait_for_log('OUR_UNILATERAL/OUR_HTLC gave us preimage') t.cancel() - # l2 can send OUR_DELAYED_RETURN_TO_WALLET after 4 more blocks. - bitcoind.generate_block(4) + # l2 can send OUR_DELAYED_RETURN_TO_WALLET after 3 more blocks. + bitcoind.generate_block(3) l2.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET .* to resolve OUR_UNILATERAL/DELAYED_OUTPUT_TO_US') l2.daemon.wait_for_log('sendrawtx exit 0') # Now, 100 blocks they should be done. - bitcoind.generate_block(94) + bitcoind.generate_block(95) + sync_blockheight([l1, l2]) assert not l1.daemon.is_in_log('onchaind complete, forgetting peer') assert not l2.daemon.is_in_log('onchaind complete, forgetting peer') bitcoind.generate_block(1) l1.daemon.wait_for_log('onchaind complete, forgetting peer') + sync_blockheight([l2]) assert not l2.daemon.is_in_log('onchaind complete, forgetting peer') - bitcoind.generate_block(5) + bitcoind.generate_block(3) + sync_blockheight([l2]) assert not l2.daemon.is_in_log('onchaind complete, forgetting peer') bitcoind.generate_block(1) wait_forget_channels(l2) @@ -2337,14 +2475,14 @@ def test_htlc_out_timeout(self): l2.daemon.wait_for_log(' to ONCHAIN') # L1 will timeout HTLC immediately - l1.daemon.wait_for_logs(['Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX .* in 0 blocks', - 'Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* in 5 blocks']) + l1.daemon.wait_for_logs(['Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX .* after 0 blocks', + 'Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks']) l1.daemon.wait_for_log('sendrawtx exit 0') bitcoind.generate_block(1) - l1.daemon.wait_for_log('Propose handling OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* in 5 blocks') - bitcoind.generate_block(5) + l1.daemon.wait_for_log('Propose handling OUR_HTLC_TIMEOUT_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks') + bitcoind.generate_block(4) # It should now claim both the to-local and htlc-timeout-tx outputs. l1.daemon.wait_for_logs(['Broadcasting OUR_DELAYED_RETURN_TO_WALLET', 'Broadcasting OUR_DELAYED_RETURN_TO_WALLET', @@ -2392,11 +2530,11 @@ def test_htlc_in_timeout(self): l1.daemon.wait_for_log(' to ONCHAIN') # L2 will collect HTLC - l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks') + l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* after 0 blocks') l2.daemon.wait_for_log('sendrawtx exit 0') bitcoind.generate_block(1) - l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* in 5 blocks') - bitcoind.generate_block(5) + l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks') + bitcoind.generate_block(4) l2.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET') l2.daemon.wait_for_log('sendrawtx exit 0') diff --git a/wallet/Makefile b/wallet/Makefile index a12988e31e3e..4c82a78db2e4 100644 --- a/wallet/Makefile +++ b/wallet/Makefile @@ -14,7 +14,13 @@ WALLET_LIB_SRC := \ WALLET_LIB_OBJS := $(WALLET_LIB_SRC:.c=.o) WALLET_LIB_HEADERS := $(WALLET_LIB_SRC:.c=.h) +# Make sure these depend on everything. +ALL_OBJS += $(LIGHTNINGD_OBJS) + check-whitespace: $(WALLET_LIB_SRC:%=check-whitespace/%) $(WALLET_LIB_HEADERS:%=check-whitespace/%) +check-source: $(WALLET_LIB_SRC:%=check-src-include-order/%) +check-source: $(WALLET_LIB_HEADERS:%=check-hdr-include-order/%) +check-source-bolt: $(WALLET_LIB_SRC:%=bolt-check/%) $(WALLET_LIB_HEADERS:%=bolt-check/%) clean: wallet-clean diff --git a/wallet/db.c b/wallet/db.c index 9ccc2d029c61..9e86226fe03c 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -230,6 +230,9 @@ char *dbmigrations[] = { /* Necessary index for long rollbacks of the blockchain, otherwise we're * doing table scans for every block removed. */ "CREATE INDEX utxoset_spend ON utxoset (spendheight)", + /* Assign key 0 to unassigned shutdown_keyidx_local. */ + "UPDATE channels SET shutdown_keyidx_local=0 WHERE shutdown_keyidx_local = -1;", + /* FIXME: We should rename shutdown_keyidx_local to final_key_index */ NULL, }; diff --git a/wallet/db.h b/wallet/db.h index 7514cd7b72f0..62b466a6bcba 100644 --- a/wallet/db.h +++ b/wallet/db.h @@ -1,14 +1,13 @@ #ifndef WALLET_DB_H #define WALLET_DB_H - #include "config.h" -#include + #include +#include #include #include #include #include - #include #include #include diff --git a/wallet/invoices.c b/wallet/invoices.c index 8cc43e47756c..4d46665ce968 100644 --- a/wallet/invoices.c +++ b/wallet/invoices.c @@ -7,13 +7,13 @@ #include #include #include +#include +#include #include #include #include #include #include -#include -#include struct invoice_waiter { /* Is this waiter already triggered? */ diff --git a/wallet/invoices.h b/wallet/invoices.h index 05ccba482154..8fbf196d89fe 100644 --- a/wallet/invoices.h +++ b/wallet/invoices.h @@ -1,10 +1,10 @@ #ifndef LIGHTNING_WALLET_INVOICES_H #define LIGHTNING_WALLET_INVOICES_H #include "config.h" +#include #include -#include #include -#include +#include struct db; struct invoice; diff --git a/wallet/test/Makefile b/wallet/test/Makefile index e7d0284282bd..64a88be6f00b 100644 --- a/wallet/test/Makefile +++ b/wallet/test/Makefile @@ -6,6 +6,7 @@ WALLET_TEST_COMMON_OBJS := \ common/htlc_state.o \ common/type_to_string.o \ common/memleak.o \ + common/key_derive.o \ common/pseudorand.o \ common/timeout.o \ common/utils.o \ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index ff3e39ed5dca..035eec2294a5 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -28,10 +28,6 @@ static void db_log_(struct log *log UNUSED, enum log_level level UNUSED, const c bool deprecated_apis = true; /* AUTOGENERATED MOCKS START */ -/* Generated stub for bip32_pubkey */ -bool bip32_pubkey(const struct ext_key *bip32_base UNNEEDED, - struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED) -{ fprintf(stderr, "bip32_pubkey called!\n"); abort(); } /* Generated stub for bitcoind_gettxout */ void bitcoind_gettxout(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_txid *txid UNNEEDED, const u32 outnum UNNEEDED, @@ -73,8 +69,14 @@ bool derive_basepoints(const struct privkey *seed UNNEEDED, /* 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 fromwire_gossipctl_peer_disconnect_reply */ +bool fromwire_gossipctl_peer_disconnect_reply(const void *p UNNEEDED) +{ fprintf(stderr, "fromwire_gossipctl_peer_disconnect_reply called!\n"); abort(); } +/* Generated stub for fromwire_gossipctl_peer_disconnect_replyfail */ +bool fromwire_gossipctl_peer_disconnect_replyfail(const void *p UNNEEDED, bool *isconnected UNNEEDED) +{ fprintf(stderr, "fromwire_gossipctl_peer_disconnect_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, struct pubkey **id UNNEEDED, struct wireaddr **addr UNNEEDED, struct gossip_getnodes_entry ***nodes UNNEEDED) +bool fromwire_gossip_getpeers_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey **id UNNEEDED, struct wireaddr **addr UNNEEDED, struct gossip_getnodes_entry ***nodes UNNEEDED) { fprintf(stderr, "fromwire_gossip_getpeers_reply called!\n"); abort(); } /* Generated stub for fromwire_gossip_peer_connected */ bool fromwire_gossip_peer_connected(const tal_t *ctx UNNEEDED, const void *p 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) @@ -191,6 +193,10 @@ void json_add_short_channel_id(struct json_result *response UNNEEDED, /* 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_string_escape */ +void json_add_string_escape(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, + const char *value UNNEEDED) +{ fprintf(stderr, "json_add_string_escape 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) @@ -322,7 +328,7 @@ u8 *towire_channel_funding_announce_depth(const tal_t *ctx UNNEEDED) 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_send_shutdown */ -u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *scriptpubkey UNNEEDED) +u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channel_send_shutdown 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) @@ -338,6 +344,9 @@ u8 *towire_gossipctl_hand_back_peer(const tal_t *ctx UNNEEDED, const struct pubk /* 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_peer_disconnect */ +u8 *towire_gossipctl_peer_disconnect(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) +{ fprintf(stderr, "towire_gossipctl_peer_disconnect 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(); } @@ -347,9 +356,6 @@ u8 *towire_gossip_disable_channel(const tal_t *ctx UNNEEDED, const struct short_ /* 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 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(); } @@ -373,18 +379,6 @@ struct txowatch *watch_txo(const tal_t *ctx UNNEEDED, size_t input_num UNNEEDED, const struct block *block)) { fprintf(stderr, "watch_txo called!\n"); abort(); } -/* Generated stub for json_add_string_escape */ -void json_add_string_escape(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, const char *value UNNEEDED) -{ fprintf(stderr, "json_add_string_escape called!\n"); abort(); } -/* Generated stub for towire_gossipctl_peer_disconnect */ -u8 *towire_gossipctl_peer_disconnect(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) -{ fprintf(stderr, "towire_gossipctl_peer_disconnect called!\n"); abort(); } -/* Generated stub for fromwire_gossipctl_peer_disconnect_reply */ -bool fromwire_gossipctl_peer_disconnect_reply(const void *p UNNEEDED) -{ fprintf(stderr, "fromwire_gossipctl_peer_disconnect_reply called!\n"); abort(); } -/* Generated stub for fromwire_gossipctl_peer_disconnect_replyfail*/ -bool fromwire_gossipctl_peer_disconnect_replyfail(const void *p UNNEEDED, bool *isconnected UNNEEDED) -{ fprintf(stderr, "fromwire_gossipctl_peer_disconnect_replyfail called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ #if DEVELOPER @@ -444,6 +438,12 @@ const char *log_prefix(const struct log *log UNNEEDED) return ""; } +void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES) +{ + if (taken(script)) + tal_free(script); +} + /** * mempat -- Set the memory to a pattern * @@ -463,6 +463,7 @@ static struct wallet *create_test_wallet(struct lightningd *ld, const tal_t *ctx char filename[] = "/tmp/ldb-XXXXXX"; int fd = mkstemp(filename); struct wallet *w = tal(ctx, struct wallet); + static unsigned char badseed[BIP32_ENTROPY_LEN_128]; CHECK_MSG(fd != -1, "Unable to generate temp filename"); close(fd); @@ -471,6 +472,12 @@ static struct wallet *create_test_wallet(struct lightningd *ld, const tal_t *ctx ltmp = tal_tmpctx(ctx); list_head_init(&w->unstored_payments); w->ld = ld; + ld->wallet = w; + + w->bip32_base = tal(w, struct ext_key); + CHECK(bip32_key_from_seed(badseed, sizeof(badseed), + BIP32_VER_TEST_PRIVATE, 0, + w->bip32_base) == WALLY_OK); CHECK_MSG(w->db, "Failed opening the db"); db_migrate(w->db, w->log); @@ -667,10 +674,11 @@ static bool channelseq(struct channel *c1, struct channel *c2) CHECK(memeq(&c1->last_sig, sizeof(c1->last_sig), &c2->last_sig, sizeof(c2->last_sig))); - if (c1->remote_shutdown_scriptpubkey) { - CHECK(c2->remote_shutdown_scriptpubkey); - CHECK(c1->local_shutdown_idx == c2->local_shutdown_idx); - } + CHECK(c1->final_key_idx == c2->final_key_idx); + CHECK(memeq(c1->remote_shutdown_scriptpubkey, + tal_len(c1->remote_shutdown_scriptpubkey), + c2->remote_shutdown_scriptpubkey, + tal_len(c2->remote_shutdown_scriptpubkey))); CHECK(c1->last_was_revoke == c2->last_was_revoke); @@ -716,6 +724,7 @@ static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx) ci->feerate_per_kw[LOCAL] = ci->feerate_per_kw[REMOTE] = 31337; mempat(scriptpubkey, tal_len(scriptpubkey)); c1.first_blocknum = 1; + c1.final_key_idx = 1337; p = new_peer(ld, 0, &pk, NULL); c1.peer = p; c1.dbid = wallet_get_channel_dbid(w); @@ -781,7 +790,6 @@ static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx) /* Variant 4: update and add remote_shutdown_scriptpubkey */ c1.remote_shutdown_scriptpubkey = scriptpubkey; - c1.local_shutdown_idx = 1337; wallet_channel_save(w, &c1); CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err)); CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB")); @@ -971,6 +979,13 @@ int main(void) ok &= test_htlc_crud(ld, tmpctx); ok &= test_payment_crud(ld, tmpctx); + take_cleanup(); tal_free(tmpctx); + + /* FIXME! https://github.com/ElementsProject/libwally-core/issues/26 */ + { + secp256k1_context *secp_ctx(void); + secp256k1_context_destroy(secp_ctx()); + } return !ok; } diff --git a/wallet/txfilter.c b/wallet/txfilter.c index d74bef0bdd7a..ec0f25d91a88 100644 --- a/wallet/txfilter.c +++ b/wallet/txfilter.c @@ -3,15 +3,15 @@ #include #include #include -#include #include +#include #include #include #include #include struct txfilter { - u8 **scriptpubkeys; + const u8 **scriptpubkeys; }; struct outpointfilter_entry { @@ -49,18 +49,19 @@ struct outpointfilter { struct txfilter *txfilter_new(const tal_t *ctx) { struct txfilter *filter = tal(ctx, struct txfilter); - filter->scriptpubkeys = tal_arr(filter, u8*, 0); + filter->scriptpubkeys = tal_arr(filter, const u8 *, 0); return filter; } -void txfilter_add_scriptpubkey(struct txfilter *filter, u8 *script) +void txfilter_add_scriptpubkey(struct txfilter *filter, const u8 *script TAKES) { size_t count = tal_count(filter->scriptpubkeys); tal_resize(&filter->scriptpubkeys, count + 1); filter->scriptpubkeys[count] = tal_dup_arr(filter, u8, script, tal_len(script), 0); } -void txfilter_add_derkey(struct txfilter *filter, u8 derkey[PUBKEY_DER_LEN]) +void txfilter_add_derkey(struct txfilter *filter, + const u8 derkey[PUBKEY_DER_LEN]) { tal_t *tmpctx = tal_tmpctx(filter); u8 *skp, *p2sh; diff --git a/wallet/txfilter.h b/wallet/txfilter.h index fb8db02f811f..397631300723 100644 --- a/wallet/txfilter.h +++ b/wallet/txfilter.h @@ -26,7 +26,8 @@ struct txfilter *txfilter_new(const tal_t *ctx); * scriptpubkey then the transaction is marked as a match. Adds * scriptpubkey for both raw p2wpkh and p2wpkh wrapped in p2sh. */ -void txfilter_add_derkey(struct txfilter *filter, u8 derkey[PUBKEY_DER_LEN]); +void txfilter_add_derkey(struct txfilter *filter, + const u8 derkey[PUBKEY_DER_LEN]); /** * txfilter_match -- Check whether the tx matches the filter @@ -36,7 +37,7 @@ bool txfilter_match(const struct txfilter *filter, const struct bitcoin_tx *tx); /** * txfilter_add_scriptpubkey -- Add a serialized scriptpubkey to the filter */ -void txfilter_add_scriptpubkey(struct txfilter *filter, u8 *script); +void txfilter_add_scriptpubkey(struct txfilter *filter, const u8 *script TAKES); /** * outpointfilter_new -- Create a new outpointfilter diff --git a/wallet/wallet.c b/wallet/wallet.c index 8a0378e973ac..e98dfcc5a638 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -4,10 +4,11 @@ #include #include #include +#include +#include #include #include #include -#include #include #include #include @@ -584,6 +585,7 @@ static struct channel *wallet_stmt2channel(const tal_t *ctx, struct wallet *w, s u8 *remote_shutdown_scriptpubkey; struct changed_htlc *last_sent_commit; const tal_t *tmpctx = tal_tmpctx(ctx); + s64 final_key_idx; peer_dbid = sqlite3_column_int64(stmt, 1); peer = find_peer_by_dbid(w->ld, peer_dbid); @@ -640,6 +642,12 @@ static struct channel *wallet_stmt2channel(const tal_t *ctx, struct wallet *w, s return NULL; } + final_key_idx = sqlite3_column_int64(stmt, 29); + if (final_key_idx < 0) { + log_broken(w->log, "%s: Final key < 0", __func__); + tal_free(tmpctx); + return NULL; + } chan = new_channel(peer, sqlite3_column_int64(stmt, 0), &wshachain, sqlite3_column_int(stmt, 5), @@ -665,8 +673,7 @@ static struct channel *wallet_stmt2channel(const tal_t *ctx, struct wallet *w, s sqlite3_column_int64(stmt, 0)), &channel_info, remote_shutdown_scriptpubkey, - remote_shutdown_scriptpubkey - ? sqlite3_column_int64(stmt, 29) : -1, + final_key_idx, sqlite3_column_int(stmt, 34) != 0, last_sent_commit, sqlite3_column_int64(stmt, 35)); @@ -720,6 +727,7 @@ bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w) return ok; } +#ifdef COMPAT_V052 /* Upgrade of db (or initial create): do we have anything to scan for? */ static bool wallet_ever_used(struct wallet *w) { @@ -740,6 +748,7 @@ static bool wallet_ever_used(struct wallet *w) return channel_utxos; } +#endif /* We want the earlier of either: * 1. The first channel we're still watching (it might have closed), @@ -764,6 +773,8 @@ u32 wallet_first_blocknum(struct wallet *w, u32 first_possible) first_channel = UINT32_MAX; sqlite3_finalize(stmt); +#ifdef COMPAT_V052 + /* This field was missing in older databases. */ first_utxo = db_get_intvar(w->db, "last_processed_block", 0); if (first_utxo == 0) { /* Don't know? New db, or upgraded. */ @@ -773,6 +784,9 @@ u32 wallet_first_blocknum(struct wallet *w, u32 first_possible) else first_utxo = UINT32_MAX; } +#else + first_utxo = db_get_intvar(w->db, "last_processed_block", UINT32_MAX); +#endif if (first_utxo < first_channel) return first_utxo; @@ -902,7 +916,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) tal_len(chan->remote_shutdown_scriptpubkey), SQLITE_TRANSIENT); - sqlite3_bind_int64(stmt, 17, chan->local_shutdown_idx); + sqlite3_bind_int64(stmt, 17, chan->final_key_idx); sqlite3_bind_int64(stmt, 18, chan->our_config.id); sqlite3_bind_tx(stmt, 19, chan->last_tx); sqlite3_bind_signature(stmt, 20, &chan->last_sig);