From f2dc9c796f15e1890ebb2181435cf2604950a09a Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Apr 2014 16:12:22 +1000 Subject: [PATCH] Add helper functions for getting best block heights/hashes --- src/bitcoin.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/bitcoin.h | 3 ++ 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/bitcoin.c b/src/bitcoin.c index 4fc8d188..d1863a91 100644 --- a/src/bitcoin.c +++ b/src/bitcoin.c @@ -16,6 +16,8 @@ static const char *b58chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; +/* Take a bitcoin address and do some sanity checks on it, then send it to + * bitcoind to see if it's a valid address */ bool validate_address(connsock_t *cs, const char *address) { json_t *val, *res_val, *valid_val; @@ -76,6 +78,8 @@ out: return ret; } +/* Distill down a set of transactions into an efficient tree arrangement for + * stratum messages and fast work assembly. */ static bool gbt_merkle_bins(gbtbase_t *gbt, json_t *transaction_arr) { int i, j, binleft, binlen; @@ -166,6 +170,9 @@ static bool gbt_merkle_bins(gbtbase_t *gbt, json_t *transaction_arr) static const char *gbt_req = "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": [\"coinbasetxn\", \"workid\", \"coinbase/append\"]}]}\n"; +/* Request getblocktemplate from bitcoind already connected with a connsock_t + * and then summarise the information to the most efficient set of data + * required to assemble a mining template, storing it in a gbtbase_t structure */ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) { json_t *transaction_arr, *coinbase_aux, *res_val, *val; @@ -188,7 +195,7 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) res_val = json_object_get(val, "result"); if (!res_val) { LOGWARNING("Failed to get result in json response to getblocktemplate"); - return ret; + goto out; } previousblockhash = json_string_value(json_object_get(res_val, "previousblockhash")); @@ -224,7 +231,92 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) gbt->height = height; out: - if (res_val) - json_decref(res_val); + json_decref(val); + return ret; +} + +static const char *blockcount_req = "{\"method\": \"getblockcount\"}\n"; + +/* Request getblockcount from bitcoind, returning the count or -1 if the call + * fails. */ +int get_blockcount(connsock_t *cs) +{ + json_t *val, *res_val; + int ret = -1; + + val = json_rpc_call(cs, blockcount_req); + if (!val) { + LOGWARNING("Failed to get valid json response to getblockcount"); + return ret; + } + res_val = json_object_get(val, "result"); + if (!res_val) { + LOGWARNING("Failed to get result in json response to getblockcount"); + goto out; + } + ret = json_integer_value(res_val); +out: + json_decref(val); + return ret; +} + +/* Request getblockhash from bitcoind for height, returning a freshly allocated + * string or NULL if it fails. */ +char *get_blockhash(connsock_t *cs, int height) +{ + char rpc_req[128], *ret = NULL; + json_t *val, *res_val; + const char *res_ret; + + sprintf(rpc_req, "{\"method\": \"getblockhash\", \"params\": [%d]}\n", height); + val = json_rpc_call(cs, rpc_req); + if (!val) { + LOGWARNING("Failed to get valid json response to getblockhash"); + return ret; + } + res_val = json_object_get(val, "result"); + if (!res_val) { + LOGWARNING("Failed to get result in json response to getblockhash"); + goto out; + } + res_ret = json_string_value(res_val); + if (!res_ret || !strlen(res_ret)) { + LOGWARNING("Got null string in result to getblockhash"); + goto out; + } + ret = strdup(res_ret); +out: + json_decref(val); + return ret; +} + +static const char *bestblockhash_req = "{\"method\": \"getbestblockhash\"}\n"; + +/* Request getbestblockhash from bitcoind, returning a freshly allocated + * string or NULL if it fails. bitcoind 0.9+ only */ +char *get_bestblockhash(connsock_t *cs) +{ + json_t *val, *res_val; + const char *res_ret; + char *ret = NULL; + + val = json_rpc_call(cs, bestblockhash_req); + if (!val) { + LOGWARNING("Failed to get valid json response to getbestblockhash"); + return ret; + } + res_val = json_object_get(val, "result"); + if (!res_val) { + LOGWARNING("Failed to get result in json response to getbestblockhash"); + goto out; + } + res_ret = json_string_value(res_val); + if (!res_ret || !strlen(res_ret)) { + LOGWARNING("Got null string in result to getbestblockhash"); + goto out; + } + ret = strdup(res_ret); +out: + json_decref(val); return ret; } diff --git a/src/bitcoin.h b/src/bitcoin.h index 5e5a58b2..37714b90 100644 --- a/src/bitcoin.h +++ b/src/bitcoin.h @@ -12,5 +12,8 @@ bool validate_address(connsock_t *cs, const char *address); bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt); +int get_blockcount(connsock_t *cs); +char *get_blockhash(connsock_t *cs, int height); +char *get_bestblockhash(connsock_t *cs); #endif /* BITCOIN_H */