mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-22 00:24:19 +01:00
bitcoind: detect when it's still syncing, add field to getinfo.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
be8ebf2667
commit
faded9a9cf
@@ -997,6 +997,103 @@ void bitcoind_getclientversion(struct bitcoind *bitcoind)
|
|||||||
"getnetworkinfo", NULL);
|
"getnetworkinfo", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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)
|
static void destroy_bitcoind(struct bitcoind *bitcoind)
|
||||||
{
|
{
|
||||||
/* Suppresses the callbacks from bcli_finished as we free conns. */
|
/* Suppresses the callbacks from bcli_finished as we free conns. */
|
||||||
@@ -1073,6 +1170,7 @@ static char* check_blockchain_from_bitcoincli(const tal_t *ctx,
|
|||||||
" Should be: %s",
|
" Should be: %s",
|
||||||
bitcoind->chainparams->bip70_name);
|
bitcoind->chainparams->bip70_name);
|
||||||
|
|
||||||
|
is_bitcoind_synced_yet(bitcoind, output, output_bytes, tokens, true);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ struct bitcoind {
|
|||||||
/* Main lightningd structure */
|
/* Main lightningd structure */
|
||||||
struct lightningd *ld;
|
struct lightningd *ld;
|
||||||
|
|
||||||
|
/* Is bitcoind synced? If not, we retry. */
|
||||||
|
bool synced;
|
||||||
|
|
||||||
/* How many high/low prio requests are we running (it's ratelimited) */
|
/* How many high/low prio requests are we running (it's ratelimited) */
|
||||||
size_t num_requests[BITCOIND_NUM_PRIO];
|
size_t num_requests[BITCOIND_NUM_PRIO];
|
||||||
|
|
||||||
|
|||||||
@@ -1553,6 +1553,11 @@ static struct command_result *json_getinfo(struct command *cmd,
|
|||||||
wallet_total_forward_fees(cmd->ld->wallet),
|
wallet_total_forward_fees(cmd->ld->wallet),
|
||||||
"msatoshi_fees_collected",
|
"msatoshi_fees_collected",
|
||||||
"fees_collected_msat");
|
"fees_collected_msat");
|
||||||
|
|
||||||
|
if (!cmd->ld->topology->bitcoind->synced)
|
||||||
|
json_add_string(response, "warning_bitcoind_sync",
|
||||||
|
"Bitcoind is not up-to-date with network.");
|
||||||
|
|
||||||
return command_success(cmd, response);
|
return command_success(cmd, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,27 @@ def test_bitcoin_failure(node_factory, bitcoind):
|
|||||||
sync_blockheight(bitcoind, [l1])
|
sync_blockheight(bitcoind, [l1])
|
||||||
|
|
||||||
|
|
||||||
|
def test_bitcoin_ibd(node_factory, bitcoind):
|
||||||
|
"""Test that we recognize bitcoin in initial download mode"""
|
||||||
|
info = bitcoind.rpc.getblockchaininfo()
|
||||||
|
info['initialblockdownload'] = True
|
||||||
|
|
||||||
|
l1 = node_factory.get_node(start=False)
|
||||||
|
l1.daemon.rpcproxy.mock_rpc('getblockchaininfo', info)
|
||||||
|
|
||||||
|
l1.start()
|
||||||
|
|
||||||
|
# This happens before the Starting message start() waits for.
|
||||||
|
assert l1.daemon.is_in_log('Waiting for initial block download')
|
||||||
|
assert 'warning_bitcoind_sync' in l1.rpc.getinfo()
|
||||||
|
|
||||||
|
# "Finish" IDB.
|
||||||
|
l1.daemon.rpcproxy.mock_rpc('getblockchaininfo', None)
|
||||||
|
|
||||||
|
l1.daemon.wait_for_log('Bitcoind now synced')
|
||||||
|
assert 'warning_bitcoind_sync' not in l1.rpc.getinfo()
|
||||||
|
|
||||||
|
|
||||||
def test_ping(node_factory):
|
def test_ping(node_factory):
|
||||||
l1, l2 = node_factory.line_graph(2, fundchannel=False)
|
l1, l2 = node_factory.line_graph(2, fundchannel=False)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user