lightningd: move all chainheight logic into setup_topology.

Handling half in main() and half here was a mess.  And the name
"max_blockheight" was poor: it was the max in the db, or UINT32_MAX,
but then we changed it depending on what height we wanted to start at.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-06-23 00:39:33 +09:30
parent ff15b943fe
commit f2b033d7e1
6 changed files with 55 additions and 52 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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(); }

View file

@ -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);

View file

@ -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