diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index a6502054f..d57166f40 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -1362,7 +1362,15 @@ static void retry_height_reached(struct wait_for_height *wh) wait_until_height_reached, wh); } -void setup_topology(struct chain_topology *topo, u32 max_blockheight) +/* Subtract, but floored at 0 */ +static u32 blocknum_reduce(u32 blockheight, s32 sub) +{ + if ((u32)sub > blockheight) + return 0; + return blockheight - sub; +} + +void setup_topology(struct chain_topology *topo) { void *ret; /* Since we loop below, we free tmpctx, so we need a local */ @@ -1370,6 +1378,8 @@ void setup_topology(struct chain_topology *topo, u32 max_blockheight) struct chaininfo_once *chaininfo = tal(local_ctx, struct chaininfo_once); struct feerates_once *feerates = tal(local_ctx, struct feerates_once); struct bitcoin_block *blk; + bool blockscan_start_set; + u32 blockscan_start; /* This waits for bitcoind. */ bitcoind_check_commands(topo->bitcoind); @@ -1377,8 +1387,28 @@ void setup_topology(struct chain_topology *topo, u32 max_blockheight) /* For testing.. */ log_debug(topo->ld->log, "All Bitcoin plugin commands registered"); + db_begin_transaction(topo->ld->wallet->db); + + /*~ If we were asked to rescan from an absolute height (--rescan < 0) + * then just go there. Otherwise compute the diff to our current height, + * lowerbounded by 0. */ + if (topo->ld->config.rescan < 0) { + blockscan_start = -topo->ld->config.rescan; + blockscan_start_set = true; + } else { + /* Get the blockheight we are currently at, or 0 */ + blockscan_start = wallet_blocks_maxheight(topo->ld->wallet); + blockscan_start_set = (blockscan_start != 0); + + /* If we don't know blockscan_start, can't do this yet */ + if (blockscan_start_set) + blockscan_start = blocknum_reduce(blockscan_start, topo->ld->config.rescan); + } + + db_commit_transaction(topo->ld->wallet->db); + /* Sanity checks, then topology initialization. */ - bitcoind_getchaininfo(topo->bitcoind, max_blockheight, + bitcoind_getchaininfo(topo->bitcoind, blockscan_start, get_chaininfo_once, chaininfo); bitcoind_estimate_fees(topo->bitcoind, get_feerates_once, feerates); @@ -1393,32 +1423,26 @@ void setup_topology(struct chain_topology *topo, u32 max_blockheight) fatal("Wrong network! Our Bitcoin backend is running on '%s'," " but we expect '%s'.", chaininfo->chain, chainparams->bip70_name); - /* If bitcoind's current blockheight is below the requested - * height, refuse. You can always explicitly request a reindex from - * that block number using --rescan=. */ - if (chaininfo->blockcount < max_blockheight) { - /* UINT32_MAX == no blocks in database */ - if (max_blockheight == UINT32_MAX) { - /* Relative rescan, but we didn't know the blockheight */ - /* Protect against underflow in subtraction. - * Possible in regtest mode. */ - if (chaininfo->blockcount < topo->bitcoind->ld->config.rescan) - max_blockheight = 0; - else - max_blockheight = chaininfo->blockcount - topo->bitcoind->ld->config.rescan; - } else if (chaininfo->headercount < max_blockheight) { + if (!blockscan_start_set) { + blockscan_start = blocknum_reduce(chaininfo->blockcount, topo->ld->config.rescan); + } else { + /* If bitcoind's current blockheight is below the requested + * height, wait, as long as header count is greater. You can + * always explicitly request a reindex from that block number + * using --rescan=. */ + if (chaininfo->headercount < blockscan_start) { fatal("bitcoind has gone backwards from %u to %u blocks!", - max_blockheight, chaininfo->blockcount); - } else { + blockscan_start, chaininfo->blockcount); + } else if (chaininfo->blockcount < blockscan_start) { struct wait_for_height *wh = tal(local_ctx, struct wait_for_height); wh->bitcoind = topo->bitcoind; - wh->minheight = max_blockheight; + wh->minheight = blockscan_start; /* We're not happy, but we'll wait... */ log_broken(topo->ld->log, "bitcoind has gone backwards from %u to %u blocks, waiting...", - max_blockheight, chaininfo->blockcount); - bitcoind_getchaininfo(topo->bitcoind, max_blockheight, + blockscan_start, chaininfo->blockcount); + bitcoind_getchaininfo(topo->bitcoind, blockscan_start, wait_until_height_reached, wh); ret = io_loop_with_timers(topo->ld); assert(ret == wh); @@ -1438,13 +1462,13 @@ void setup_topology(struct chain_topology *topo, u32 max_blockheight) update_feerates(topo->ld, feerates->feerate_floor, feerates->rates, NULL); /* Get the first block, so we can initialize topography. */ - bitcoind_getrawblockbyheight(topo->bitcoind, max_blockheight, + bitcoind_getrawblockbyheight(topo->bitcoind, blockscan_start, get_block_once, &blk); ret = io_loop_with_timers(topo->ld); assert(ret == topo); tal_steal(local_ctx, blk); - topo->root = new_block(topo, blk, max_blockheight); + topo->root = new_block(topo, blk, blockscan_start); block_map_add(topo->block_map, topo->root); topo->tip = topo->root; topo->prev_tip = topo->tip->blkid; @@ -1457,7 +1481,7 @@ void setup_topology(struct chain_topology *topo, u32 max_blockheight) /* Rollback to the given blockheight, so we start track * correctly again */ - wallet_blocks_rollback(topo->ld->wallet, max_blockheight); + wallet_blocks_rollback(topo->ld->wallet, blockscan_start); /* May have unconfirmed txs: reconfirm as we add blocks. */ watch_for_utxo_reconfirmation(topo, topo->ld->wallet); diff --git a/lightningd/chaintopology.h b/lightningd/chaintopology.h index 008d74aea..6b1796ea1 100644 --- a/lightningd/chaintopology.h +++ b/lightningd/chaintopology.h @@ -240,7 +240,7 @@ void broadcast_tx_(const tal_t *ctx, void *cbarg TAKES); struct chain_topology *new_topology(struct lightningd *ld, struct logger *log); -void setup_topology(struct chain_topology *topology, u32 max_blockheight); +void setup_topology(struct chain_topology *topology); void begin_topology(struct chain_topology *topo); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index ac036b300..e3fa06458 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -1153,7 +1153,6 @@ static void setup_fd_limit(struct lightningd *ld, size_t num_channels) int main(int argc, char *argv[]) { struct lightningd *ld; - u32 max_blockheight; int connectd_gossipd_fd; int stop_fd; struct timers *timers; @@ -1333,21 +1332,6 @@ int main(int argc, char *argv[]) init_txfilter(ld->wallet, ld->bip32_base, ld->owned_txfilter); trace_span_end(ld->wallet); - /*~ Get the blockheight we are currently at, UINT32_MAX is used to signal - * an uninitialized wallet and that we should start off of bitcoind's - * current height */ - max_blockheight = wallet_blocks_maxheight(ld->wallet, UINT32_MAX); - - /*~ If we were asked to rescan from an absolute height (--rescan < 0) - * then just go there. Otherwise compute the diff to our current height, - * lowerbounded by 0. */ - if (ld->config.rescan < 0) - max_blockheight = -ld->config.rescan; - else if (max_blockheight < (u32)ld->config.rescan) - max_blockheight = 0; - else if (max_blockheight != UINT32_MAX) - max_blockheight -= ld->config.rescan; - /*~ Finish our runes initialization (includes reading from db) */ runes_finish_init(ld->runes); @@ -1360,7 +1344,7 @@ int main(int argc, char *argv[]) /*~ Initialize block topology. This does its own io_loop to * talk to bitcoind, so does its own db transactions. */ trace_span_start("setup_topology", ld->topology); - setup_topology(ld->topology, max_blockheight); + setup_topology(ld->topology); trace_span_end(ld->topology); db_begin_transaction(ld->wallet->db); diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 095449139..de1449701 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -237,7 +237,7 @@ void setup_color_and_alias(struct lightningd *ld UNNEEDED) void setup_peers(struct lightningd *ld UNNEEDED) { fprintf(stderr, "setup_peers called!\n"); abort(); } /* Generated stub for setup_topology */ -void setup_topology(struct chain_topology *topology UNNEEDED, u32 max_blockheight UNNEEDED) +void setup_topology(struct chain_topology *topology UNNEEDED) { fprintf(stderr, "setup_topology called!\n"); abort(); } /* Generated stub for shutdown_plugins */ void shutdown_plugins(struct lightningd *ld UNNEEDED) @@ -277,9 +277,6 @@ const char *version(void) void waitblockheight_notify_new_block(struct lightningd *ld UNNEEDED, u32 block_height UNNEEDED) { fprintf(stderr, "waitblockheight_notify_new_block called!\n"); abort(); } -/* Generated stub for wallet_blocks_maxheight */ -u32 wallet_blocks_maxheight(struct wallet *w UNNEEDED, u32 def UNNEEDED) -{ fprintf(stderr, "wallet_blocks_maxheight called!\n"); abort(); } /* Generated stub for wallet_new */ struct wallet *wallet_new(struct lightningd *ld UNNEEDED, struct timers *timers UNNEEDED) { fprintf(stderr, "wallet_new called!\n"); abort(); } diff --git a/wallet/wallet.c b/wallet/wallet.c index 96e5e38d7..93eb22fcb 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2120,9 +2120,9 @@ void wallet_channel_stats_load(struct wallet *w, tal_free(stmt); } -u32 wallet_blocks_maxheight(struct wallet *w, u32 def) +u32 wallet_blocks_maxheight(struct wallet *w) { - u32 max; + u32 max = 0; struct db_stmt *stmt = db_prepare_v2(w->db, SQL("SELECT MAX(height) FROM blocks;")); db_query_prepared(stmt); @@ -2132,7 +2132,6 @@ u32 wallet_blocks_maxheight(struct wallet *w, u32 def) max = db_col_int(stmt, "MAX(height)"); } else { db_col_ignore(stmt, "MAX(height)"); - max = def; } } tal_free(stmt); diff --git a/wallet/wallet.h b/wallet/wallet.h index b3db3cee9..0ec63e23a 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -727,12 +727,11 @@ void wallet_channel_stats_load(struct wallet *w, u64 cdbid, struct channel_stats /** * Retrieve the blockheight of the last block processed by lightningd. * - * Will return the default value if the wallet was never used before. + * Will return the 0 if the wallet was never used before. * * @w: wallet to load from. - * @def: the default value to return if we've never used the wallet before */ -u32 wallet_blocks_maxheight(struct wallet *w, u32 def); +u32 wallet_blocks_maxheight(struct wallet *w); /** * wallet_extract_owned_outputs - given a tx, extract all of our outputs