From 6620305606d94ec0df37c029cb952a073fd8cabf Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 16 Feb 2018 08:39:55 +1030 Subject: [PATCH] wallet: use last_processed_block to determine scan start. With fallback depending on chainparams: this means the first upgrade will be slow, but after that it'll be fast. Fixes: #990 Signed-off-by: Rusty Russell --- bitcoin/chainparams.c | 5 +++++ bitcoin/chainparams.h | 1 + lightningd/chaintopology.c | 18 +++++++++--------- lightningd/lightningd.c | 9 ++++++--- lightningd/test/run-find_my_path.c | 6 +++--- wallet/wallet.c | 18 ++++++++++++------ wallet/wallet.h | 7 +++---- 7 files changed, 39 insertions(+), 25 deletions(-) diff --git a/bitcoin/chainparams.c b/bitcoin/chainparams.c index 5ce516821..800e05594 100644 --- a/bitcoin/chainparams.c +++ b/bitcoin/chainparams.c @@ -12,6 +12,8 @@ const struct chainparams networks[] = { .cli = "bitcoin-cli", .cli_args = NULL, .dust_limit = 546, + /* "Lightning Charge Powers Developers & Blockstream Store" */ + .when_lightning_became_cool = 504500, .testnet = false}, {.index = 1, .network_name = "regtest", @@ -21,6 +23,7 @@ const struct chainparams networks[] = { .cli = "bitcoin-cli", .cli_args = "-regtest", .dust_limit = 546, + .when_lightning_became_cool = 1, .testnet = true}, {.index = 2, .network_name = "testnet", @@ -39,6 +42,7 @@ const struct chainparams networks[] = { .cli = "litecoin-cli", .cli_args = NULL, .dust_limit = 100000, + .when_lightning_became_cool = 1, .testnet = false}, {.index = 4, .network_name = "litecoin-testnet", @@ -48,6 +52,7 @@ const struct chainparams networks[] = { .cli = "litecoin-cli", .cli_args = "-testnet", .dust_limit = 100000, + .when_lightning_became_cool = 1, .testnet = true} }; diff --git a/bitcoin/chainparams.h b/bitcoin/chainparams.h index 3a5d65489..92a0d2d6d 100644 --- a/bitcoin/chainparams.h +++ b/bitcoin/chainparams.h @@ -15,6 +15,7 @@ struct chainparams { const char *cli; const char *cli_args; const u64 dust_limit; + const u32 when_lightning_became_cool; /* Whether this is a test network or not */ const bool testnet; diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index b8cb6a614..3907680f8 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -470,16 +470,16 @@ static void get_init_block(struct bitcoind *bitcoind, static void get_init_blockhash(struct bitcoind *bitcoind, u32 blockcount, struct chain_topology *topo) { - /* This happens if first_blocknum is UINTMAX-1 */ - if (blockcount < topo->first_blocknum) - topo->first_blocknum = blockcount; - /* FIXME: Because we don't handle our root disappearing, we go * 100 blocks back */ - if (topo->first_blocknum < 100) - topo->first_blocknum = 0; + if (blockcount < 100) + blockcount = 0; else - topo->first_blocknum -= 100; + blockcount -= 100; + + /* This happens if first_blocknum is UINTMAX-1 */ + if (blockcount < topo->first_blocknum) + topo->first_blocknum = blockcount; /* Get up to speed with topology. */ bitcoind_getblockhash(bitcoind, topo->first_blocknum, @@ -714,14 +714,14 @@ struct chain_topology *new_topology(struct lightningd *ld, struct log *log) void setup_topology(struct chain_topology *topo, struct timers *timers, - struct timerel poll_time, u32 first_channel_block) + struct timerel poll_time, u32 first_blocknum) { memset(&topo->feerate, 0, sizeof(topo->feerate)); topo->timers = timers; topo->poll_time = poll_time; /* Start one before the block we are interested in (as we won't * get notifications on txs in that block). */ - topo->first_blocknum = first_channel_block - 1; + topo->first_blocknum = first_blocknum - 1; /* Make sure bitcoind is started, and ready */ wait_for_bitcoind(topo->bitcoind); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index adb1dfc00..c4d1d6a22 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -256,7 +256,7 @@ int main(int argc, char *argv[]) struct log_book *log_book; struct lightningd *ld; bool newdir; - u32 peer_first_blocknum; + u32 first_blocknum; err_set_progname(argv[0]); @@ -336,7 +336,10 @@ int main(int argc, char *argv[]) if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out)) fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent."); - peer_first_blocknum = wallet_channels_first_blocknum(ld->wallet); + /* Worst case, scan back to the first lightning deployment */ + first_blocknum = wallet_first_blocknum(ld->wallet, + get_chainparams(ld) + ->when_lightning_became_cool); db_commit_transaction(ld->wallet->db); @@ -344,7 +347,7 @@ int main(int argc, char *argv[]) setup_topology(ld->topology, &ld->timers, ld->config.poll_time, - peer_first_blocknum); + first_blocknum); /* Create RPC socket (if any) */ setup_jsonrpc(ld, ld->rpc_filename); diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index a00fb20f1..9b16093c3 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -87,12 +87,12 @@ struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED) /* Generated stub for version */ const char *version(void) { fprintf(stderr, "version called!\n"); abort(); } -/* Generated stub for wallet_channels_first_blocknum */ -u32 wallet_channels_first_blocknum(struct wallet *w UNNEEDED) -{ fprintf(stderr, "wallet_channels_first_blocknum called!\n"); abort(); } /* Generated stub for wallet_channels_load_active */ bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED) { fprintf(stderr, "wallet_channels_load_active called!\n"); abort(); } +/* Generated stub for wallet_first_blocknum */ +u32 wallet_first_blocknum(struct wallet *w UNNEEDED, u32 first_possible UNNEEDED) +{ fprintf(stderr, "wallet_first_blocknum called!\n"); abort(); } /* Generated stub for wallet_htlcs_load_for_channel */ bool wallet_htlcs_load_for_channel(struct wallet *wallet UNNEEDED, struct channel *chan UNNEEDED, diff --git a/wallet/wallet.c b/wallet/wallet.c index cb2397634..3ee3352c7 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -667,22 +667,28 @@ bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w) return ok; } -u32 wallet_channels_first_blocknum(struct wallet *w) +u32 wallet_first_blocknum(struct wallet *w, u32 first_possible) { int err; - u32 first_blocknum; + u32 first_channel, first_utxo; sqlite3_stmt *stmt = db_query(__func__, w->db, "SELECT MIN(first_blocknum) FROM channels;"); err = sqlite3_step(stmt); if (err == SQLITE_ROW && sqlite3_column_type(stmt, 0) != SQLITE_NULL) - first_blocknum = sqlite3_column_int(stmt, 0); + first_channel = sqlite3_column_int(stmt, 0); else - first_blocknum = UINT32_MAX; - + first_channel = UINT32_MAX; sqlite3_finalize(stmt); - return first_blocknum; + + /* If it's an old database, go back to before c-lightning was cool */ + first_utxo = db_get_intvar(w->db, "last_processed_block", + first_possible); + if (first_utxo < first_channel) + return first_utxo; + else + return first_channel; } void wallet_channel_config_save(struct wallet *w, struct channel_config *cc) diff --git a/wallet/wallet.h b/wallet/wallet.h index 6120852b4..f911065fe 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -260,13 +260,12 @@ bool wallet_peer_by_nodeid(struct wallet *w, const struct pubkey *nodeid, bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w); /** - * wallet_channels_first_blocknum - get first block we're interested in. + * wallet_first_blocknum - get first block we're interested in. * * @w: wallet to load from. - * - * Returns UINT32_MAX if nothing interesting. + * @first_possible: when c-lightning may have been active from */ -u32 wallet_channels_first_blocknum(struct wallet *w); +u32 wallet_first_blocknum(struct wallet *w, u32 first_possible); /** * wallet_extract_owned_outputs - given a tx, extract all of our outputs