From 82812682329561867539271f7995d6e567779104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Haf?= Date: Wed, 2 Jul 2025 12:45:37 +0000 Subject: [PATCH] warn if bitcoind is still in IBD --- src/datum_blocktemplates.c | 18 ++++++++++++++++-- src/datum_jsonrpc.c | 19 ++++++++++++------- src/datum_jsonrpc.h | 2 +- src/datum_stratum.c | 2 +- src/datum_submitblock.c | 4 ++-- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/datum_blocktemplates.c b/src/datum_blocktemplates.c index f135215..5642818 100644 --- a/src/datum_blocktemplates.c +++ b/src/datum_blocktemplates.c @@ -351,7 +351,7 @@ void *datum_gateway_fallback_notifier(void *args) { while(1) { snprintf(req, sizeof(req), "{\"jsonrpc\":\"1.0\",\"id\":\"%"PRIu64"\",\"method\":\"getbestblockhash\",\"params\":[]}", current_time_millis()); - gbbh = bitcoind_json_rpc_call(tcurl, &datum_config, req); + gbbh = bitcoind_json_rpc_call(tcurl, &datum_config, req, /*failonerror=*/true); if (gbbh) { res_val = json_object_get(gbbh, "result"); if (!res_val) { @@ -432,7 +432,7 @@ void *datum_gateway_template_thread(void *args) { // fetch latest template snprintf(gbt_req, sizeof(gbt_req), "{\"method\":\"getblocktemplate\",\"params\":[{\"rules\":[\"segwit\"]}],\"id\":%"PRIu64"}",(uint64_t)((uint64_t)time(NULL)<<(uint64_t)8)|(uint64_t)(i&255)); - gbt = bitcoind_json_rpc_call(tcurl, &datum_config, gbt_req); + gbt = bitcoind_json_rpc_call(tcurl, &datum_config, gbt_req, /*failonerror=*/false); if (!gbt) { datum_blocktemplates_error = "Could not fetch new template!"; @@ -440,7 +440,21 @@ void *datum_gateway_template_thread(void *args) { sleep(1); continue; } else { + json_t *error_obj = json_object_get(gbt, "error"); res_val = json_object_get(gbt, "result"); + + if (json_is_object(error_obj)) { + json_t *code_val = json_object_get(error_obj, "code"); + if (code_val && json_is_integer(code_val)) { + if ((int)json_integer_value(code_val) == -10) { + DLOG_ERROR("bitcoind still syncing"); + datum_blocktemplates_error = "Could not fetch new template!"; + sleep(1); + continue; + } + } + } + if (!res_val) { datum_blocktemplates_error = "Could not decode GBT result!"; DLOG_ERROR("%s", datum_blocktemplates_error); diff --git a/src/datum_jsonrpc.c b/src/datum_jsonrpc.c index be099f8..2acb392 100644 --- a/src/datum_jsonrpc.c +++ b/src/datum_jsonrpc.c @@ -139,7 +139,7 @@ char *basic_http_call(CURL *curl, const char *url) { return NULL; } -json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, const char *rpc_req, const char *extra_header, long * const http_resp_code_out) { +json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, const char *rpc_req, const char *extra_header, long * const http_resp_code_out, bool failonerror) { json_t *val, *err_val, *res_val; CURLcode rc; struct data_buffer all_data = { }; @@ -152,7 +152,7 @@ json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, co curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_ENCODING, ""); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(curl, CURLOPT_FAILONERROR, failonerror); curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data); @@ -186,11 +186,12 @@ json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, co curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); rc = curl_easy_perform(curl); + if (http_resp_code_out) { + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_resp_code_out); + } if (rc) { - if (http_resp_code_out) curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_resp_code_out); DLOG_DEBUG("json_rpc_call: HTTP request failed: %s", curl_err_str); DLOG_DEBUG("json_rpc_call: Request was: %s",rpc_req); - goto err_out; } val = JSON_LOADS(all_data.buf, &err); @@ -203,6 +204,10 @@ json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, co res_val = json_object_get(val, "result"); err_val = json_object_get(val, "error"); + if (json_integer_value(json_object_get(err_val, "code")) == -10) { + return val; + } + if (!res_val || json_is_null(res_val) || (err_val && !json_is_null(err_val))) { char *s; @@ -233,7 +238,7 @@ json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, co } json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req) { - return json_rpc_call_full(curl, url, userpass, rpc_req, NULL, NULL); + return json_rpc_call_full(curl, url, userpass, rpc_req, NULL, NULL, 1); } bool update_rpc_cookie(global_config_t * const cfg) { @@ -258,9 +263,9 @@ void update_rpc_auth(global_config_t * const cfg) { } } -json_t *bitcoind_json_rpc_call(CURL * const curl, global_config_t * const cfg, const char * const rpc_req) { +json_t *bitcoind_json_rpc_call(CURL * const curl, global_config_t * const cfg, const char * const rpc_req, bool failonerror) { long http_resp_code = -1; - json_t *j = json_rpc_call_full(curl, cfg->bitcoind_rpcurl, cfg->bitcoind_rpcuserpass, rpc_req, NULL, &http_resp_code); + json_t *j = json_rpc_call_full(curl, cfg->bitcoind_rpcurl, cfg->bitcoind_rpcuserpass, rpc_req, NULL, &http_resp_code, failonerror); if (j) return j; if (cfg->bitcoind_rpcuser[0]) return NULL; if (http_resp_code != 401) return NULL; diff --git a/src/datum_jsonrpc.h b/src/datum_jsonrpc.h index ef47a46..feaf8f5 100644 --- a/src/datum_jsonrpc.h +++ b/src/datum_jsonrpc.h @@ -67,6 +67,6 @@ json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const c char *basic_http_call(CURL *curl, const char *url); bool update_rpc_cookie(global_config_t *cfg); void update_rpc_auth(global_config_t *cfg); -json_t *bitcoind_json_rpc_call(CURL *curl, global_config_t *cfg, const char *rpc_req); +json_t *bitcoind_json_rpc_call(CURL *curl, global_config_t *cfg, const char *rpc_req, bool failonerror); #endif diff --git a/src/datum_stratum.c b/src/datum_stratum.c index 0b12629..8a14454 100644 --- a/src/datum_stratum.c +++ b/src/datum_stratum.c @@ -2189,7 +2189,7 @@ int assembleBlockAndSubmit(uint8_t *block_header, uint8_t *coinbase_txn, size_t } // make the call! - r = bitcoind_json_rpc_call(tcurl, &datum_config, submitblock_req); + r = bitcoind_json_rpc_call(tcurl, &datum_config, submitblock_req, /*failonerror=*/true); curl_easy_cleanup(tcurl); if (!r) { // oddly, this means success here. diff --git a/src/datum_submitblock.c b/src/datum_submitblock.c index d076e99..0a6b171 100644 --- a/src/datum_submitblock.c +++ b/src/datum_submitblock.c @@ -54,7 +54,7 @@ void preciousblock(CURL *curl, char *blockhash) { char rpc_data[384]; snprintf(rpc_data, sizeof(rpc_data), "{\"method\":\"preciousblock\",\"params\":[\"%s\"],\"id\":1}", blockhash); - json = bitcoind_json_rpc_call(curl, &datum_config, rpc_data); + json = bitcoind_json_rpc_call(curl, &datum_config, rpc_data, /*failonerror=*/true); if (!json) return; json_decref(json); @@ -66,7 +66,7 @@ void datum_submitblock_doit(CURL *tcurl, char *url, const char *submitblock_req, char *s = NULL; // TODO: Move these types of things to the conf file if (!url) { - r = bitcoind_json_rpc_call(tcurl, &datum_config, submitblock_req); + r = bitcoind_json_rpc_call(tcurl, &datum_config, submitblock_req, /*failonerror=*/true); } else { r = json_rpc_call(tcurl, url, NULL, submitblock_req); }