diff --git a/lightningd/bitcoind.c b/lightningd/bitcoind.c index 72c09c496..f1bf7b7fe 100644 --- a/lightningd/bitcoind.c +++ b/lightningd/bitcoind.c @@ -556,34 +556,211 @@ void bitcoind_getrawblock_(struct bitcoind *bitcoind, "getblock", hex, "false", NULL); } -static bool process_getblockcount(struct bitcoin_cli *bcli) +/* Our Bitcoin backend plugin gave us a bad response. We can't recover. */ +static void bitcoin_plugin_error(struct bitcoind *bitcoind, const char *buf, + const jsmntok_t *toks, const char *method, + const char *reason) { - u32 blockcount; - char *p, *end; + struct plugin *p = strmap_get(&bitcoind->pluginsmap, method); + fatal("%s error: bad response to %s (%s), response was %.*s", + p->cmd, method, reason, + toks->end - toks->start, buf + toks->start); +} + +/* `getrawblockbyheight` + * + * If no block were found at that height, will set each field to `null`. + * Plugin response: + * { + * "blockhash": "", + * "block": "rawblock" + * } + */ + +struct getrawblockbyheight_call { + struct bitcoind *bitcoind; void (*cb)(struct bitcoind *bitcoind, - u32 blockcount, - void *arg) = bcli->cb; + struct bitcoin_blkid *blkid, + struct bitcoin_block *block, + void *); + void *cb_arg; +}; + +static void +getrawblockbyheight_callback(const char *buf, const jsmntok_t *toks, + const jsmntok_t *idtok, + struct getrawblockbyheight_call *call) +{ + const jsmntok_t *resulttok, *blockhashtok, *blocktok; + const char *block_str, *blockhash_str; + struct bitcoin_blkid blkid; + struct bitcoin_block *blk; - p = tal_strndup(bcli, bcli->output, bcli->output_bytes); - blockcount = strtol(p, &end, 10); - if (end == p || *end != '\n') - fatal("%s: gave non-numeric blockcount %s", - bcli_args(tmpctx, bcli), p); + resulttok = json_get_member(buf, toks, "result"); + if (!resulttok) + bitcoin_plugin_error(call->bitcoind, buf, toks, + "getrawblockbyheight", + "bad 'result' field"); + + blockhashtok = json_get_member(buf, resulttok, "blockhash"); + if (!blockhashtok) + bitcoin_plugin_error(call->bitcoind, buf, toks, + "getrawblockbyheight", + "bad 'blockhash' field"); + /* If block hash is `null`, this means not found! Call the callback + * with NULL values. */ + if (json_tok_is_null(buf, blockhashtok)) { + db_begin_transaction(call->bitcoind->ld->wallet->db); + call->cb(call->bitcoind, NULL, NULL, call->cb_arg); + db_commit_transaction(call->bitcoind->ld->wallet->db); + goto clean; + } + blockhash_str = json_strdup(tmpctx, buf, blockhashtok); + if (!bitcoin_blkid_from_hex(blockhash_str, strlen(blockhash_str), &blkid)) + bitcoin_plugin_error(call->bitcoind, buf, toks, + "getrawblockbyheight", + "bad block hash"); + + blocktok = json_get_member(buf, resulttok, "block"); + if (!blocktok) + bitcoin_plugin_error(call->bitcoind, buf, toks, + "getrawblockbyheight", + "bad 'block' field"); + block_str = json_strdup(tmpctx, buf, blocktok); + blk = bitcoin_block_from_hex(tmpctx, chainparams, block_str, + strlen(block_str)); + if (!blk) + bitcoin_plugin_error(call->bitcoind, buf, toks, + "getrawblockbyheight", + "bad block"); - cb(bcli->bitcoind, blockcount, bcli->cb_arg); - return true; + db_begin_transaction(call->bitcoind->ld->wallet->db); + call->cb(call->bitcoind, &blkid, blk, call->cb_arg); + db_commit_transaction(call->bitcoind->ld->wallet->db); + +clean: + tal_free(call); } -void bitcoind_getblockcount_(struct bitcoind *bitcoind, - void (*cb)(struct bitcoind *bitcoind, - u32 blockcount, - void *arg), - void *arg) +void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind, + u32 height, + void (*cb)(struct bitcoind *bitcoind, + struct bitcoin_blkid *blkid, + struct bitcoin_block *blk, + void *arg), + void *cb_arg) { - start_bitcoin_cli(bitcoind, NULL, process_getblockcount, false, - BITCOIND_HIGH_PRIO, - cb, arg, - "getblockcount", NULL); + struct jsonrpc_request *req; + struct getrawblockbyheight_call *call = tal(NULL, + struct getrawblockbyheight_call); + + call->bitcoind = bitcoind; + call->cb = cb; + call->cb_arg = cb_arg; + + req = jsonrpc_request_start(bitcoind, "getrawblockbyheight", + bitcoind->log, getrawblockbyheight_callback, + /* Freed in cb. */ + notleak(call)); + json_add_num(req->stream, "height", height); + jsonrpc_request_end(req); + plugin_request_send(strmap_get(&bitcoind->pluginsmap, + "getrawblockbyheight"), req); +} + +/* `getchaininfo` + * + * Called at startup to check the network we are operating on, and to check + * if the Bitcoin backend is synced to the network tip. This also allows to + * get the current block count. + * { + * "chain": "", + * "headercount": , + * "blockcount": , + * "ibd": + * } + */ + +struct getchaininfo_call { + struct bitcoind *bitcoind; + /* Should we log verbosely? */ + bool first_call; + void (*cb)(struct bitcoind *bitcoind, + const char *chain, + u32 headercount, + u32 blockcount, + const bool ibd, + const bool first_call, + void *); + void *cb_arg; +}; + +static void getchaininfo_callback(const char *buf, const jsmntok_t *toks, + const jsmntok_t *idtok, + struct getchaininfo_call *call) +{ + const jsmntok_t *resulttok, *chaintok, *headerstok, *blktok, *ibdtok; + u32 headers = 0; + u32 blocks = 0; + bool ibd = false; + + resulttok = json_get_member(buf, toks, "result"); + if (!resulttok) + bitcoin_plugin_error(call->bitcoind, buf, toks, "getchaininfo", + "bad 'result' field"); + + chaintok = json_get_member(buf, resulttok, "chain"); + if (!chaintok) + bitcoin_plugin_error(call->bitcoind, buf, toks, "getchaininfo", + "bad 'chain' field"); + + headerstok = json_get_member(buf, resulttok, "headercount"); + if (!headerstok || !json_to_number(buf, headerstok, &headers)) + bitcoin_plugin_error(call->bitcoind, buf, toks, "getchaininfo", + "bad 'headercount' field"); + + blktok = json_get_member(buf, resulttok, "blockcount"); + if (!blktok || !json_to_number(buf, blktok, &blocks)) + bitcoin_plugin_error(call->bitcoind, buf, toks, "getchaininfo", + "bad 'blockcount' field"); + + ibdtok = json_get_member(buf, resulttok, "ibd"); + if (!ibdtok || !json_to_bool(buf, ibdtok, &ibd)) + bitcoin_plugin_error(call->bitcoind, buf, toks, "getchaininfo", + "bad 'ibd' field"); + + db_begin_transaction(call->bitcoind->ld->wallet->db); + call->cb(call->bitcoind, json_strdup(tmpctx, buf, chaintok), headers, + blocks, ibd, call->first_call, call->cb_arg); + db_commit_transaction(call->bitcoind->ld->wallet->db); + + tal_free(call); +} + +void bitcoind_getchaininfo_(struct bitcoind *bitcoind, + const bool first_call, + void (*cb)(struct bitcoind *bitcoind, + const char *chain, + u32 headercount, + u32 blockcount, + const bool ibd, + const bool first_call, + void *), + void *cb_arg) +{ + struct jsonrpc_request *req; + struct getchaininfo_call *call = tal(bitcoind, struct getchaininfo_call); + + call->bitcoind = bitcoind; + call->cb = cb; + call->cb_arg = cb_arg; + call->first_call = first_call; + + req = jsonrpc_request_start(bitcoind, "getchaininfo", bitcoind->log, + getchaininfo_callback, call); + jsonrpc_request_end(req); + plugin_request_send(strmap_get(&bitcoind->pluginsmap, "getchaininfo"), + req); } struct get_output { @@ -890,103 +1067,6 @@ void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height, bitcoind_getblockhash(bitcoind, height, process_getfilteredblock_step1, call); } -/* Mutual recursion */ -static bool process_getblockchaininfo(struct bitcoin_cli *bcli); - -static void retry_getblockchaininfo(struct bitcoind *bitcoind) -{ - assert(!bitcoind->synced); - start_bitcoin_cli(bitcoind, NULL, - process_getblockchaininfo, - false, BITCOIND_LOW_PRIO, NULL, NULL, - "getblockchaininfo", NULL); -} - -/* Given JSON object from getblockchaininfo, are we synced? Poll if not. */ -static void is_bitcoind_synced_yet(struct bitcoind *bitcoind, - const char *output, size_t output_len, - const jsmntok_t *obj, - bool initial) -{ - const jsmntok_t *t; - unsigned int headers, blocks; - bool ibd; - - t = json_get_member(output, obj, "headers"); - if (!t || !json_to_number(output, t, &headers)) - fatal("Invalid 'headers' field in getblockchaininfo '%.*s'", - (int)output_len, output); - - t = json_get_member(output, obj, "blocks"); - if (!t || !json_to_number(output, t, &blocks)) - fatal("Invalid 'blocks' field in getblockchaininfo '%.*s'", - (int)output_len, output); - - t = json_get_member(output, obj, "initialblockdownload"); - if (!t || !json_to_bool(output, t, &ibd)) - fatal("Invalid 'initialblockdownload' field in getblockchaininfo '%.*s'", - (int)output_len, output); - - if (ibd) { - if (initial) - log_unusual(bitcoind->log, - "Waiting for initial block download" - " (this can take a while!)"); - else - log_debug(bitcoind->log, - "Still waiting for initial block download"); - } else if (headers != blocks) { - if (initial) - log_unusual(bitcoind->log, - "Waiting for bitcoind to catch up" - " (%u blocks of %u)", - blocks, headers); - else - log_debug(bitcoind->log, - "Waiting for bitcoind to catch up" - " (%u blocks of %u)", - blocks, headers); - } else { - if (!initial) - log_info(bitcoind->log, "Bitcoind now synced."); - bitcoind->synced = true; - return; - } - - bitcoind->synced = false; - notleak(new_reltimer(bitcoind->ld->timers, bitcoind, - /* Be 4x more aggressive in this case. */ - time_divide(time_from_sec(bitcoind->ld->topology - ->poll_seconds), 4), - retry_getblockchaininfo, bitcoind)); -} - -static bool process_getblockchaininfo(struct bitcoin_cli *bcli) -{ - const jsmntok_t *tokens; - bool valid; - - tokens = json_parse_input(bcli, bcli->output, bcli->output_bytes, - &valid); - if (!tokens) - fatal("%s: %s response (%.*s)", - bcli_args(tmpctx, bcli), - valid ? "partial" : "invalid", - (int)bcli->output_bytes, bcli->output); - - if (tokens[0].type != JSMN_OBJECT) { - log_unusual(bcli->bitcoind->log, - "%s: gave non-object (%.*s)?", - bcli_args(tmpctx, bcli), - (int)bcli->output_bytes, bcli->output); - return false; - } - - is_bitcoind_synced_yet(bcli->bitcoind, bcli->output, bcli->output_bytes, - tokens, false); - return true; -} - static void destroy_bitcoind(struct bitcoind *bitcoind) { strmap_clear(&bitcoind->pluginsmap); @@ -994,131 +1074,6 @@ static void destroy_bitcoind(struct bitcoind *bitcoind) bitcoind->shutdown = true; } -static const char **cmdarr(const tal_t *ctx, const struct bitcoind *bitcoind, - const char *cmd, ...) -{ - va_list ap; - const char **args; - - va_start(ap, cmd); - args = gather_args(bitcoind, ctx, cmd, ap); - va_end(ap); - return args; -} - -static void fatal_bitcoind_failure(struct bitcoind *bitcoind, const char *error_message) -{ - const char **cmd = cmdarr(bitcoind, bitcoind, "echo", NULL); - - fprintf(stderr, "%s\n\n", error_message); - fprintf(stderr, "Make sure you have bitcoind running and that bitcoin-cli is able to connect to bitcoind.\n\n"); - fprintf(stderr, "You can verify that your Bitcoin Core installation is ready for use by running:\n\n"); - fprintf(stderr, " $ %s 'hello world'\n", args_string(cmd, cmd)); - tal_free(cmd); - exit(1); -} - -/* This function is used to check "chain" field from - * bitcoin-cli "getblockchaininfo" API */ -static char* check_blockchain_from_bitcoincli(const tal_t *ctx, - struct bitcoind *bitcoind, - char* output, const char **cmd) -{ - size_t output_bytes; - const jsmntok_t *tokens, *valuetok; - bool valid; - - if (!output) - return tal_fmt(ctx, "Reading from %s failed: %s", - args_string(tmpctx, cmd), strerror(errno)); - - output_bytes = tal_count(output); - - tokens = json_parse_input(cmd, output, output_bytes, - &valid); - - if (!tokens) - return tal_fmt(ctx, "%s: %s response", - args_string(tmpctx, cmd), - valid ? "partial" : "invalid"); - - if (tokens[0].type != JSMN_OBJECT) - return tal_fmt(ctx, "%s: gave non-object (%.*s)?", - args_string(tmpctx, cmd), - (int)output_bytes, output); - - valuetok = json_get_member(output, tokens, "chain"); - if (!valuetok) - return tal_fmt(ctx, "%s: had no chain member (%.*s)?", - args_string(tmpctx, cmd), - (int)output_bytes, output); - - if (!json_tok_streq(output, valuetok, - chainparams->bip70_name)) - return tal_fmt(ctx, "Error blockchain for bitcoin-cli?" - " Should be: %s", - chainparams->bip70_name); - - is_bitcoind_synced_yet(bitcoind, output, output_bytes, tokens, true); - return NULL; -} - -void wait_for_bitcoind(struct bitcoind *bitcoind) -{ - int from, status, ret; - pid_t child; - const char **cmd = cmdarr(bitcoind, bitcoind, "getblockchaininfo", NULL); - bool printed = false; - char *errstr; - - for (;;) { - child = pipecmdarr(NULL, &from, &from, cast_const2(char **,cmd)); - if (child < 0) { - if (errno == ENOENT) { - fatal_bitcoind_failure(bitcoind, "bitcoin-cli not found. Is bitcoin-cli (part of Bitcoin Core) available in your PATH?"); - } - fatal("%s exec failed: %s", cmd[0], strerror(errno)); - } - - char *output = grab_fd(cmd, from); - - while ((ret = waitpid(child, &status, 0)) < 0 && errno == EINTR); - if (ret != child) - fatal("Waiting for %s: %s", cmd[0], strerror(errno)); - if (!WIFEXITED(status)) - fatal("Death of %s: signal %i", - cmd[0], WTERMSIG(status)); - - if (WEXITSTATUS(status) == 0) { - /* If succeeded, so check answer it gave. */ - errstr = check_blockchain_from_bitcoincli(tmpctx, bitcoind, output, cmd); - if (errstr) - fatal("%s", errstr); - - break; - } - - /* bitcoin/src/rpc/protocol.h: - * RPC_IN_WARMUP = -28, //!< Client still warming up - */ - if (WEXITSTATUS(status) != 28) { - if (WEXITSTATUS(status) == 1) { - fatal_bitcoind_failure(bitcoind, "Could not connect to bitcoind using bitcoin-cli. Is bitcoind running?"); - } - fatal("%s exited with code %i: %s", - cmd[0], WEXITSTATUS(status), output); - } - - if (!printed) { - log_unusual(bitcoind->log, - "Waiting for bitcoind to warm up..."); - printed = true; - } - sleep(1); - } - tal_free(cmd); -} - struct bitcoind *new_bitcoind(const tal_t *ctx, struct lightningd *ld, struct log *log) @@ -1143,6 +1098,7 @@ struct bitcoind *new_bitcoind(const tal_t *ctx, bitcoind->rpcconnect = NULL; bitcoind->rpcport = NULL; tal_add_destructor(bitcoind, destroy_bitcoind); + bitcoind->synced = false; return bitcoind; } diff --git a/lightningd/bitcoind.h b/lightningd/bitcoind.h index f39af0b7c..7ccb8141b 100644 --- a/lightningd/bitcoind.h +++ b/lightningd/bitcoind.h @@ -89,8 +89,6 @@ struct bitcoind *new_bitcoind(const tal_t *ctx, struct lightningd *ld, struct log *log); -void wait_for_bitcoind(struct bitcoind *bitcoind); - void bitcoind_estimate_fees_(struct bitcoind *bitcoind, const u32 blocks[], const char *estmode[], size_t num_estimates, @@ -120,20 +118,6 @@ void bitcoind_sendrawtx_(struct bitcoind *bitcoind, int, const char *), \ (arg)) -void bitcoind_getblockcount_(struct bitcoind *bitcoind, - void (*cb)(struct bitcoind *bitcoind, - u32 blockcount, - void *arg), - void *arg); - -#define bitcoind_getblockcount(bitcoind_, cb, arg) \ - bitcoind_getblockcount_((bitcoind_), \ - typesafe_cb_preargs(void, void *, \ - (cb), (arg), \ - struct bitcoind *, \ - u32 blockcount), \ - (arg)) - /* blkid is NULL if call fails. */ void bitcoind_getblockhash_(struct bitcoind *bitcoind, u32 height, @@ -178,6 +162,40 @@ void bitcoind_getrawblock_(struct bitcoind *bitcoind, struct bitcoin_block *), \ (arg)) +void bitcoind_getchaininfo_(struct bitcoind *bitcoind, + const bool first_call, + void (*cb)(struct bitcoind *bitcoind, + const char *chain, + u32 headercount, + u32 blockcount, + const bool ibd, + const bool first_call, void *), + void *cb_arg); +#define bitcoind_getchaininfo(bitcoind_, first_call_, cb, arg) \ + bitcoind_getchaininfo_((bitcoind_), (first_call_), \ + typesafe_cb_preargs(void, void *, \ + (cb), (arg), \ + struct bitcoind *, \ + const char *, u32, u32, \ + const bool, const bool), \ + (arg)) + +void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind, + u32 height, + void (*cb)(struct bitcoind *bitcoind, + struct bitcoin_blkid *blkid, + struct bitcoin_block *blk, + void *arg), + void *arg); +#define bitcoind_getrawblockbyheight(bitcoind_, height_, cb, arg) \ + bitcoind_getrawblockbyheight_((bitcoind_), (height_), \ + typesafe_cb_preargs(void, void *, \ + (cb), (arg), \ + struct bitcoind *, \ + struct bitcoin_blkid *, \ + struct bitcoin_block *),\ + (arg)) + void bitcoind_gettxout(struct bitcoind *bitcoind, const struct bitcoin_txid *txid, const u32 outnum, void (*cb)(struct bitcoind *bitcoind, diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index a9bdb4854..2ca6b1e65 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -28,7 +28,7 @@ /* Mutual recursion via timer. */ static void try_extend_tip(struct chain_topology *topo); -/* get_init_blockhash sets topo->root, start_fee_estimate clears +/* init_topo sets topo->root, start_fee_estimate clears * feerate_uninitialized (even if unsuccessful) */ static void maybe_completed_init(struct chain_topology *topo) { @@ -780,6 +780,7 @@ static void try_extend_tip(struct chain_topology *topo) } static void init_topo(struct bitcoind *bitcoind UNUSED, + struct bitcoin_blkid *blkid UNUSED, struct bitcoin_block *blk, struct chain_topology *topo) { @@ -795,45 +796,6 @@ static void init_topo(struct bitcoind *bitcoind UNUSED, maybe_completed_init(topo); } -static void get_init_block(struct bitcoind *bitcoind, - const struct bitcoin_blkid *blkid, - struct chain_topology *topo) -{ - bitcoind_getrawblock(bitcoind, blkid, init_topo, topo); -} - -static void get_init_blockhash(struct bitcoind *bitcoind, u32 blockcount, - struct chain_topology *topo) -{ - /* 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 (blockcount < topo->max_blockheight) { - /* UINT32_MAX == no blocks in database */ - if (topo->max_blockheight == UINT32_MAX) { - /* Relative rescan, but we didn't know the blockheight */ - /* Protect against underflow in subtraction. - * Possible in regtest mode. */ - if (blockcount < bitcoind->ld->config.rescan) - topo->max_blockheight = 0; - else - topo->max_blockheight = blockcount - bitcoind->ld->config.rescan; - } else - fatal("bitcoind has gone backwards from %u to %u blocks!", - topo->max_blockheight, blockcount); - } - - /* Rollback to the given blockheight, so we start track - * correctly again */ - wallet_blocks_rollback(topo->ld->wallet, topo->max_blockheight); - /* This may have unconfirmed txs: reconfirm as we add blocks. */ - watch_for_utxo_reconfirmation(topo, topo->ld->wallet); - - /* Get up to speed with topology. */ - bitcoind_getblockhash(bitcoind, topo->max_blockheight, - get_init_block, topo); -} - u32 get_block_height(const struct chain_topology *topo) { return topo->tip->height; @@ -942,9 +904,95 @@ struct chain_topology *new_topology(struct lightningd *ld, struct log *log) topo->root = NULL; topo->sync_waiters = tal(topo, struct list_head); list_head_init(topo->sync_waiters); + return topo; } +static void check_blockcount(struct chain_topology *topo, u32 blockcount) +{ + /* 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 (blockcount < topo->max_blockheight) { + /* UINT32_MAX == no blocks in database */ + if (topo->max_blockheight == UINT32_MAX) { + /* Relative rescan, but we didn't know the blockheight */ + /* Protect against underflow in subtraction. + * Possible in regtest mode. */ + if (blockcount < topo->bitcoind->ld->config.rescan) + topo->max_blockheight = 0; + else + topo->max_blockheight = blockcount - topo->bitcoind->ld->config.rescan; + } else + fatal("bitcoind has gone backwards from %u to %u blocks!", + topo->max_blockheight, blockcount); + } + + /* Rollback to the given blockheight, so we start track + * correctly again */ + wallet_blocks_rollback(topo->ld->wallet, topo->max_blockheight); + /* This may have unconfirmed txs: reconfirm as we add blocks. */ + watch_for_utxo_reconfirmation(topo, topo->ld->wallet); +} + +static void retry_check_chain(struct chain_topology *topo); + +static void +check_chain(struct bitcoind *bitcoind, const char *chain, + const u32 headercount, const u32 blockcount, const bool ibd, + const bool first_call, struct chain_topology *topo) +{ + if (!streq(chain, chainparams->bip70_name)) + fatal("Wrong network! Our Bitcoin backend is running on '%s'," + " but we expect '%s'.", chain, chainparams->bip70_name); + + if (first_call) { + /* Has the Bitcoin backend gone backward ? */ + check_blockcount(topo, blockcount); + /* Get up to speed with topology. */ + bitcoind_getrawblockbyheight(topo->bitcoind, topo->max_blockheight, + init_topo, topo); + } + + if (ibd) { + if (first_call) + log_unusual(bitcoind->log, + "Waiting for initial block download (this can take" + " a while!)"); + else + log_debug(bitcoind->log, + "Still waiting for initial block download"); + } else if (headercount != blockcount) { + if (first_call) + log_unusual(bitcoind->log, + "Waiting for bitcoind to catch up" + " (%u blocks of %u)", + blockcount, headercount); + else + log_debug(bitcoind->log, + "Waiting for bitcoind to catch up" + " (%u blocks of %u)", + blockcount, headercount); + } else { + if (!first_call) + log_unusual(bitcoind->log, + "Bitcoin backend now synced."); + bitcoind->synced = true; + return; + } + + notleak(new_reltimer(bitcoind->ld->timers, bitcoind, + /* Be 4x more aggressive in this case. */ + time_divide(time_from_sec(bitcoind->ld->topology + ->poll_seconds), 4), + retry_check_chain, bitcoind->ld->topology)); + } + +static void retry_check_chain(struct chain_topology *topo) +{ + bitcoind_getchaininfo(topo->bitcoind, true, check_chain, topo); +} + void setup_topology(struct chain_topology *topo, struct timers *timers, u32 min_blockheight, u32 max_blockheight) @@ -958,10 +1006,8 @@ void setup_topology(struct chain_topology *topo, /* This waits for bitcoind. */ bitcoind_check_commands(topo->bitcoind); - /* Make sure bitcoind is started, and ready */ - wait_for_bitcoind(topo->bitcoind); - - bitcoind_getblockcount(topo->bitcoind, get_init_blockhash, topo); + /* Sanity checks, then topology initialization. */ + bitcoind_getchaininfo(topo->bitcoind, true, check_chain, topo); tal_add_destructor(topo, destroy_chain_topology);