Add support for rpccookiefile alternative to rpcuser/rpcpassword

This commit is contained in:
Luke Dashjr 2025-01-15 20:26:27 +00:00
commit 14993bbd91
No known key found for this signature in database
GPG Key ID: A291A2C45D0C504A
4 changed files with 58 additions and 7 deletions

View File

@ -43,6 +43,7 @@
#include <jansson.h>
#include "datum_conf.h"
#include "datum_jsonrpc.h"
#include "datum_utils.h"
#include "datum_sockets.h"
@ -52,10 +53,12 @@ const char *datum_conf_var_type_text[] = { "N/A", "boolean", "integer", "string"
const T_DATUM_CONFIG_ITEM datum_config_options[] = {
// Bitcoind configs
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpccookiefile", .description = "Path to file to read RPC cookie from, for communication with local bitcoind.",
.required = false, .ptr = datum_config.bitcoind_rpccookiefile, .default_string[0] = "", .max_string_len = sizeof(datum_config.bitcoind_rpccookiefile) },
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpcuser", .description = "RPC username for communication with local bitcoind.",
.required = true, .ptr = datum_config.bitcoind_rpcuser, .max_string_len = sizeof(datum_config.bitcoind_rpcuser) },
.required = false, .ptr = datum_config.bitcoind_rpcuser, .default_string[0] = "", .max_string_len = sizeof(datum_config.bitcoind_rpcuser) },
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpcpassword", .description = "RPC password for communication with local bitcoind.",
.required = true, .ptr = datum_config.bitcoind_rpcpassword, .max_string_len = sizeof(datum_config.bitcoind_rpcpassword) },
.required = false, .ptr = datum_config.bitcoind_rpcpassword, .default_string[0] = "", .max_string_len = sizeof(datum_config.bitcoind_rpcpassword) },
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpcurl", .description = "RPC URL for communication with local bitcoind. (GBT Template Source)",
.required = true, .ptr = datum_config.bitcoind_rpcurl, .max_string_len = sizeof(datum_config.bitcoind_rpcurl) },
{ .var_type = DATUM_CONF_INT, .category = "bitcoind", .name = "work_update_seconds", .description = "How many seconds between normal work updates? (5-120, 40 suggested)",
@ -269,6 +272,11 @@ int datum_config_parse_value(const T_DATUM_CONFIG_ITEM *c, json_t *item) {
return -1;
}
static void datum_config_opt_missing_error(const T_DATUM_CONFIG_ITEM * const opt) {
DLOG_ERROR("Required configuration option (%s.%s) not found in config file:", opt->category, opt->name);
DLOG_ERROR("--- Config description: \"%s\"", opt->description);
}
int datum_read_config(const char *conffile) {
json_t *config = NULL;
json_t *cat, *item;
@ -293,8 +301,7 @@ int datum_read_config(const char *conffile) {
}
if ((!item) || json_is_null(item)) {
if (datum_config_options[i].required) {
DLOG_ERROR("Required configuration option (%s.%s) not found in config file:", datum_config_options[i].category, datum_config_options[i].name);
DLOG_ERROR("--- Config description: \"%s\"", datum_config_options[i].description);
datum_config_opt_missing_error(&datum_config_options[i]);
return 0;
} else {
datum_config_set_default(&datum_config_options[i]);
@ -336,6 +343,24 @@ int datum_read_config(const char *conffile) {
datum_config.bitcoind_work_update_seconds = 120;
}
if (datum_config.bitcoind_rpcuser[0]) {
if (!datum_config.bitcoind_rpcpassword[0]) {
datum_config_opt_missing_error(datum_config_get_option_info2("bitcoind", "rpcpassword"));
return 0;
}
sprintf(datum_config.bitcoind_rpcuserpass, "%s:%s", datum_config.bitcoind_rpcuser, datum_config.bitcoind_rpcpassword);
} else if (datum_config.bitcoind_rpccookiefile[0]) {
update_rpc_cookie(&datum_config);
} else {
const T_DATUM_CONFIG_ITEM *opt;
DLOG_ERROR("Either bitcoind.rpcuser (and bitcoind.rpcpassword) or bitcoind.rpccookiefile is required.");
opt = datum_config_get_option_info2("bitcoind", "rpcuser");
DLOG_ERROR("--- Config description for %s.%s: \"%s\"", opt->category, opt->name, opt->description);
opt = datum_config_get_option_info2("bitcoind", "rpccookiefile");
DLOG_ERROR("--- Config description for %s.%s: \"%s\"", opt->category, opt->name, opt->description);
return 0;
}
if (datum_config.stratum_v1_max_threads > MAX_THREADS) {
DLOG_FATAL("Maximum threads must be less than %d.", MAX_THREADS);
return 0;

View File

@ -71,6 +71,7 @@ const T_DATUM_CONFIG_ITEM *datum_config_get_option_info2(const char *category, c
// Globally accessable config options
typedef struct {
char bitcoind_rpcuserpass[256];
char bitcoind_rpccookiefile[1024];
char bitcoind_rpcuser[128];
char bitcoind_rpcpassword[128];
char bitcoind_rpcurl[256];

View File

@ -33,6 +33,7 @@
*
*/
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -138,7 +139,7 @@ err_out:
return NULL;
}
json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, const char *rpc_req, const char *extra_header) {
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 *val, *err_val, *res_val;
CURLcode rc;
struct data_buffer all_data = { };
@ -186,6 +187,7 @@ json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, co
rc = curl_easy_perform(curl);
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;
@ -231,9 +233,31 @@ err_out:
}
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);
return json_rpc_call_full(curl, url, userpass, rpc_req, NULL, NULL);
}
bool update_rpc_cookie(global_config_t * const cfg) {
assert(!cfg->bitcoind_rpcuser[0]);
FILE * const F = fopen(cfg->bitcoind_rpccookiefile, "r");
if (!F) {
DLOG_ERROR("Cannot %s cookie file %s", "open", datum_config.bitcoind_rpccookiefile);
return false;
}
if (!(fgets(cfg->bitcoind_rpcuserpass, sizeof(cfg->bitcoind_rpcuserpass), F) && cfg->bitcoind_rpcuserpass[0])) {
DLOG_ERROR("Cannot %s cookie file %s", "read", datum_config.bitcoind_rpccookiefile);
return false;
}
return true;
}
json_t *bitcoind_json_rpc_call(CURL * const curl, global_config_t * const cfg, const char * const rpc_req) {
return json_rpc_call(curl, cfg->bitcoind_rpcurl, datum_config.bitcoind_rpcuserpass, rpc_req);
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);
if (j) return j;
if (cfg->bitcoind_rpcuser[0]) return NULL;
if (http_resp_code != 401) return NULL;
// Authentication failure using cookie; reload cookie file and try again
if (!update_rpc_cookie(cfg)) return NULL;
return json_rpc_call(curl, cfg->bitcoind_rpcurl, cfg->bitcoind_rpcuserpass, rpc_req);
}

View File

@ -65,6 +65,7 @@ struct upload_buffer {
json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req);
char *basic_http_call(CURL *curl, const char *url);
bool update_rpc_cookie(global_config_t *cfg);
json_t *bitcoind_json_rpc_call(CURL *curl, global_config_t *cfg, const char *rpc_req);
#endif