Skip to content

Commit 98cfb40

Browse files
committed
Merge branch 'rpccookie'
2 parents 9bfb2f6 + d3b061e commit 98cfb40

File tree

7 files changed

+88
-12
lines changed

7 files changed

+88
-12
lines changed

src/datum_blocktemplates.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ void *datum_gateway_fallback_notifier(void *args) {
349349

350350
while(1) {
351351
snprintf(req, sizeof(req), "{\"jsonrpc\":\"1.0\",\"id\":\"%"PRIu64"\",\"method\":\"getbestblockhash\",\"params\":[]}", current_time_millis());
352-
gbbh = json_rpc_call(tcurl, datum_config.bitcoind_rpcurl, datum_config.bitcoind_rpcuserpass, req);
352+
gbbh = bitcoind_json_rpc_call(tcurl, &datum_config, req);
353353
if (gbbh) {
354354
res_val = json_object_get(gbbh, "result");
355355
if (!res_val) {
@@ -415,7 +415,7 @@ void *datum_gateway_template_thread(void *args) {
415415

416416
// fetch latest template
417417
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));
418-
gbt = json_rpc_call(tcurl, datum_config.bitcoind_rpcurl, datum_config.bitcoind_rpcuserpass, gbt_req);
418+
gbt = bitcoind_json_rpc_call(tcurl, &datum_config, gbt_req);
419419

420420
if (!gbt) {
421421
DLOG_ERROR("Could not fetch new template from %s!", datum_config.bitcoind_rpcurl);

src/datum_conf.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <jansson.h>
4444

4545
#include "datum_conf.h"
46+
#include "datum_jsonrpc.h"
4647
#include "datum_utils.h"
4748
#include "datum_sockets.h"
4849

@@ -52,10 +53,12 @@ const char *datum_conf_var_type_text[] = { "N/A", "boolean", "integer", "string"
5253

5354
const T_DATUM_CONFIG_ITEM datum_config_options[] = {
5455
// Bitcoind configs
56+
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpccookiefile", .description = "Path to file to read RPC cookie from, for communication with local bitcoind.",
57+
.required = false, .ptr = datum_config.bitcoind_rpccookiefile, .default_string[0] = "", .max_string_len = sizeof(datum_config.bitcoind_rpccookiefile) },
5558
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpcuser", .description = "RPC username for communication with local bitcoind.",
56-
.required = true, .ptr = datum_config.bitcoind_rpcuser, .max_string_len = sizeof(datum_config.bitcoind_rpcuser) },
59+
.required = false, .ptr = datum_config.bitcoind_rpcuser, .default_string[0] = "", .max_string_len = sizeof(datum_config.bitcoind_rpcuser) },
5760
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpcpassword", .description = "RPC password for communication with local bitcoind.",
58-
.required = true, .ptr = datum_config.bitcoind_rpcpassword, .max_string_len = sizeof(datum_config.bitcoind_rpcpassword) },
61+
.required = false, .ptr = datum_config.bitcoind_rpcpassword, .default_string[0] = "", .max_string_len = sizeof(datum_config.bitcoind_rpcpassword) },
5962
{ .var_type = DATUM_CONF_STRING, .category = "bitcoind", .name = "rpcurl", .description = "RPC URL for communication with local bitcoind. (GBT Template Source)",
6063
.required = true, .ptr = datum_config.bitcoind_rpcurl, .max_string_len = sizeof(datum_config.bitcoind_rpcurl) },
6164
{ .var_type = DATUM_CONF_INT, .category = "bitcoind", .name = "work_update_seconds", .description = "How many seconds between normal work updates? (5-120, 40 suggested)",
@@ -150,6 +153,21 @@ const T_DATUM_CONFIG_ITEM datum_config_options[] = {
150153

151154
#define NUM_CONFIG_ITEMS (sizeof(datum_config_options) / sizeof(datum_config_options[0]))
152155

156+
const T_DATUM_CONFIG_ITEM *datum_config_get_option_info(const char * const category, const size_t category_len, const char * const name, const size_t name_len) {
157+
for (size_t i = 0; i < NUM_CONFIG_ITEMS; ++i) {
158+
if (strncmp(category, datum_config_options[i].category, category_len)) continue;
159+
if (datum_config_options[i].category[category_len]) continue;
160+
if (strncmp(name, datum_config_options[i].name, name_len)) continue;
161+
if (datum_config_options[i].name[name_len]) continue;
162+
return &datum_config_options[i];
163+
}
164+
return NULL;
165+
}
166+
167+
const T_DATUM_CONFIG_ITEM *datum_config_get_option_info2(const char * const category, const char * const name) {
168+
return datum_config_get_option_info(category, strlen(category), name, strlen(name));
169+
}
170+
153171
json_t *load_json_from_file(const char *file_path) {
154172
json_error_t error;
155173
json_t *root = json_load_file(file_path, 0, &error);
@@ -254,6 +272,11 @@ int datum_config_parse_value(const T_DATUM_CONFIG_ITEM *c, json_t *item) {
254272
return -1;
255273
}
256274

275+
static void datum_config_opt_missing_error(const T_DATUM_CONFIG_ITEM * const opt) {
276+
DLOG_ERROR("Required configuration option (%s.%s) not found in config file:", opt->category, opt->name);
277+
DLOG_ERROR("--- Config description: \"%s\"", opt->description);
278+
}
279+
257280
int datum_read_config(const char *conffile) {
258281
json_t *config = NULL;
259282
json_t *cat, *item;
@@ -278,8 +301,7 @@ int datum_read_config(const char *conffile) {
278301
}
279302
if ((!item) || json_is_null(item)) {
280303
if (datum_config_options[i].required) {
281-
DLOG_ERROR("Required configuration option (%s.%s) not found in config file:", datum_config_options[i].category, datum_config_options[i].name);
282-
DLOG_ERROR("--- Config description: \"%s\"", datum_config_options[i].description);
304+
datum_config_opt_missing_error(&datum_config_options[i]);
283305
return 0;
284306
} else {
285307
datum_config_set_default(&datum_config_options[i]);
@@ -321,6 +343,24 @@ int datum_read_config(const char *conffile) {
321343
datum_config.bitcoind_work_update_seconds = 120;
322344
}
323345

346+
if (datum_config.bitcoind_rpcuser[0]) {
347+
if (!datum_config.bitcoind_rpcpassword[0]) {
348+
datum_config_opt_missing_error(datum_config_get_option_info2("bitcoind", "rpcpassword"));
349+
return 0;
350+
}
351+
snprintf(datum_config.bitcoind_rpcuserpass, sizeof(datum_config.bitcoind_rpcuserpass), "%s:%s", datum_config.bitcoind_rpcuser, datum_config.bitcoind_rpcpassword);
352+
} else if (datum_config.bitcoind_rpccookiefile[0]) {
353+
update_rpc_cookie(&datum_config);
354+
} else {
355+
const T_DATUM_CONFIG_ITEM *opt;
356+
DLOG_ERROR("Either bitcoind.rpcuser (and bitcoind.rpcpassword) or bitcoind.rpccookiefile is required.");
357+
opt = datum_config_get_option_info2("bitcoind", "rpcuser");
358+
DLOG_ERROR("--- Config description for %s.%s: \"%s\"", opt->category, opt->name, opt->description);
359+
opt = datum_config_get_option_info2("bitcoind", "rpccookiefile");
360+
DLOG_ERROR("--- Config description for %s.%s: \"%s\"", opt->category, opt->name, opt->description);
361+
return 0;
362+
}
363+
324364
if (datum_config.stratum_v1_max_threads > MAX_THREADS) {
325365
DLOG_FATAL("Maximum threads must be less than %d.", MAX_THREADS);
326366
return 0;

src/datum_conf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,13 @@ typedef struct {
6565
bool required;
6666
} T_DATUM_CONFIG_ITEM;
6767

68+
const T_DATUM_CONFIG_ITEM *datum_config_get_option_info(const char *category, size_t category_len, const char *name, size_t name_len);
69+
const T_DATUM_CONFIG_ITEM *datum_config_get_option_info2(const char *category, const char *name);
70+
6871
// Globally accessable config options
6972
typedef struct {
7073
char bitcoind_rpcuserpass[256];
74+
char bitcoind_rpccookiefile[1024];
7175
char bitcoind_rpcuser[128];
7276
char bitcoind_rpcpassword[128];
7377
char bitcoind_rpcurl[256];

src/datum_jsonrpc.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
*
3434
*/
3535

36+
#include <assert.h>
3637
#include <stdint.h>
3738
#include <stdio.h>
3839
#include <stdlib.h>
@@ -41,6 +42,7 @@
4142
#include <jansson.h>
4243
#include <stdbool.h>
4344

45+
#include "datum_conf.h"
4446
#include "datum_jsonrpc.h"
4547
#include "datum_utils.h"
4648

@@ -137,7 +139,7 @@ char *basic_http_call(CURL *curl, const char *url) {
137139
return NULL;
138140
}
139141

140-
json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, const char *rpc_req, const char *extra_header) {
142+
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) {
141143
json_t *val, *err_val, *res_val;
142144
CURLcode rc;
143145
struct data_buffer all_data = { };
@@ -185,6 +187,7 @@ json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, co
185187

186188
rc = curl_easy_perform(curl);
187189
if (rc) {
190+
if (http_resp_code_out) curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_resp_code_out);
188191
DLOG_DEBUG("json_rpc_call: HTTP request failed: %s", curl_err_str);
189192
DLOG_DEBUG("json_rpc_call: Request was: %s",rpc_req);
190193
goto err_out;
@@ -230,5 +233,31 @@ json_t *json_rpc_call_full(CURL *curl, const char *url, const char *userpass, co
230233
}
231234

232235
json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req) {
233-
return json_rpc_call_full(curl, url, userpass, rpc_req, NULL);
236+
return json_rpc_call_full(curl, url, userpass, rpc_req, NULL, NULL);
237+
}
238+
239+
bool update_rpc_cookie(global_config_t * const cfg) {
240+
assert(!cfg->bitcoind_rpcuser[0]);
241+
FILE * const F = fopen(cfg->bitcoind_rpccookiefile, "r");
242+
if (!F) {
243+
DLOG_ERROR("Cannot %s cookie file %s", "open", datum_config.bitcoind_rpccookiefile);
244+
return false;
245+
}
246+
if (!(fgets(cfg->bitcoind_rpcuserpass, sizeof(cfg->bitcoind_rpcuserpass), F) && cfg->bitcoind_rpcuserpass[0])) {
247+
DLOG_ERROR("Cannot %s cookie file %s", "read", datum_config.bitcoind_rpccookiefile);
248+
return false;
249+
}
250+
return true;
251+
}
252+
253+
json_t *bitcoind_json_rpc_call(CURL * const curl, global_config_t * const cfg, const char * const rpc_req) {
254+
long http_resp_code = -1;
255+
json_t *j = json_rpc_call_full(curl, cfg->bitcoind_rpcurl, cfg->bitcoind_rpcuserpass, rpc_req, NULL, &http_resp_code);
256+
if (j) return j;
257+
if (cfg->bitcoind_rpcuser[0]) return NULL;
258+
if (http_resp_code != 401) return NULL;
259+
260+
// Authentication failure using cookie; reload cookie file and try again
261+
if (!update_rpc_cookie(cfg)) return NULL;
262+
return json_rpc_call(curl, cfg->bitcoind_rpcurl, cfg->bitcoind_rpcuserpass, rpc_req);
234263
}

src/datum_jsonrpc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include <curl/curl.h>
4040
#include <jansson.h>
4141

42+
#include "datum_conf.h"
43+
4244
#ifndef JSON_INTEGER_IS_LONG_LONG
4345
# error "Jansson 2.0 with long long support required!"
4446
#endif
@@ -63,5 +65,7 @@ struct upload_buffer {
6365

6466
json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req);
6567
char *basic_http_call(CURL *curl, const char *url);
68+
bool update_rpc_cookie(global_config_t *cfg);
69+
json_t *bitcoind_json_rpc_call(CURL *curl, global_config_t *cfg, const char *rpc_req);
6670

6771
#endif

src/datum_stratum.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2183,7 +2183,7 @@ int assembleBlockAndSubmit(uint8_t *block_header, uint8_t *coinbase_txn, size_t
21832183
}
21842184

21852185
// make the call!
2186-
r = json_rpc_call(tcurl, datum_config.bitcoind_rpcurl, datum_config.bitcoind_rpcuserpass, submitblock_req);
2186+
r = bitcoind_json_rpc_call(tcurl, &datum_config, submitblock_req);
21872187
curl_easy_cleanup(tcurl);
21882188
if (!r) {
21892189
// oddly, this means success here.

src/datum_submitblock.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ void preciousblock(CURL *curl, char *blockhash) {
5353
json_t *json;
5454
char rpc_data[384];
5555

56-
// TODO: Move these types of things to the conf file
5756
snprintf(rpc_data, sizeof(rpc_data), "{\"method\":\"preciousblock\",\"params\":[\"%s\"],\"id\":1}", blockhash);
58-
json = json_rpc_call(curl, datum_config.bitcoind_rpcurl, datum_config.bitcoind_rpcuserpass, rpc_data);
57+
json = bitcoind_json_rpc_call(curl, &datum_config, rpc_data);
5958
if (!json) return;
6059

6160
json_decref(json);
@@ -67,7 +66,7 @@ void datum_submitblock_doit(CURL *tcurl, char *url, const char *submitblock_req,
6766
char *s = NULL;
6867
// TODO: Move these types of things to the conf file
6968
if (!url) {
70-
r = json_rpc_call(tcurl, datum_config.bitcoind_rpcurl, datum_config.bitcoind_rpcuserpass, submitblock_req);
69+
r = bitcoind_json_rpc_call(tcurl, &datum_config, submitblock_req);
7170
} else {
7271
r = json_rpc_call(tcurl, url, NULL, submitblock_req);
7372
}

0 commit comments

Comments
 (0)