From 0b08bbb43e1e7b6df3891ff8085f7f1517c9449e Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 27 Apr 2014 20:51:09 +1000 Subject: [PATCH] Add submission of blocksolves --- src/bitcoin.c | 37 +++++++++++++++++++++++++++ src/bitcoin.h | 1 + src/ckpool.c | 2 +- src/generator.c | 3 +++ src/stratifier.c | 66 +++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/src/bitcoin.c b/src/bitcoin.c index 53c7e7f5..09c5839a 100644 --- a/src/bitcoin.c +++ b/src/bitcoin.c @@ -369,3 +369,40 @@ out: json_decref(val); return ret; } + +bool submit_block(connsock_t *cs, char *params) +{ + json_t *val, *res_val; + const char *res_ret; + bool ret = false; + char *rpc_req; + int len; + char *s; + + len = strlen(params) + 50; + rpc_req = ckalloc(len); + sprintf(rpc_req, "{\"method\": \"submitblock\", \"params\": [\"%s\"]}\n", params); + LOGWARNING("SUBMITTING: %s", rpc_req); + val = json_rpc_call(cs, rpc_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 = true; +out: + s = json_dumps(val, 0); + LOGWARNING("SUBMIT RESULT: %s", s); + free(s); + json_decref(val); + return ret; +} diff --git a/src/bitcoin.h b/src/bitcoin.h index e2585d72..0b3805fb 100644 --- a/src/bitcoin.h +++ b/src/bitcoin.h @@ -37,5 +37,6 @@ void clear_gbtbase(gbtbase_t *gbt); int get_blockcount(connsock_t *cs); bool get_blockhash(connsock_t *cs, int height, char *hash); bool get_bestblockhash(connsock_t *cs, char *hash); +bool submit_block(connsock_t *cs, char *params); #endif /* BITCOIN_H */ diff --git a/src/ckpool.c b/src/ckpool.c index c3202819..dbd4c7ec 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -24,7 +24,7 @@ #include "connector.h" /* Only global variable, to be used only by sighandler */ -static ckpool_t *global_ckp; +ckpool_t *global_ckp; static void *listener(void *arg) { diff --git a/src/generator.c b/src/generator.c index 041d1cb9..c764177a 100644 --- a/src/generator.c +++ b/src/generator.c @@ -81,6 +81,9 @@ retry: LOGDEBUG("Hash: %s", hash); } } + } else if (!strncasecmp(buf, "submitblock:", 12)) { + LOGDEBUG("Submitting block data!"); + submit_block(cs, buf + 12); } close(sockd); goto retry; diff --git a/src/stratifier.c b/src/stratifier.c index a2688ec6..5f285fd2 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -206,14 +206,16 @@ static void generate_coinbase(ckpool_t *ckp, workbase_t *wb) tv_time(&now); ofs += ser_number(wb->coinb1bin + ofs, now.tv_sec); + /* Leave enonce1/2varlen constant at 8 bytes for bitcoind sources */ + wb->enonce1varlen = 8; + wb->enonce2varlen = 8; + wb->coinb1bin[ofs++] = wb->enonce1varlen + wb->enonce2varlen; + wb->coinb1len = ofs; len = wb->coinb1len - 41; - /* Leave enonce1/2varlen constant at 8 bytes for bitcoind sources */ - wb->enonce1varlen = 8; len += wb->enonce1varlen; - wb->enonce2varlen = 8; len += wb->enonce2varlen; memcpy(wb->coinb2bin, "\x0a\x2f\x63\x6b\x70\x6f\x6f\x6c\x34\x32\x2f", 11); @@ -230,7 +232,7 @@ static void generate_coinbase(ckpool_t *ckp, workbase_t *wb) } len += wb->coinb2len; - wb->coinb1bin[41] = len; /* Set the length now */ + wb->coinb1bin[41] = len - 1; /* Set the length now */ __bin2hex(wb->coinb1, wb->coinb1bin, wb->coinb1len); LOGDEBUG("Coinb1: %s", wb->coinb1); /* Coinbase 1 complete */ @@ -738,13 +740,54 @@ static void add_submit_fail(stratum_instance_t *client, int diff) add_submit(client, diff); } +extern ckpool_t *global_ckp; + +/* We should already be holding the workbase_lock */ +static void test_blocksolve(workbase_t *wb, const uchar *data, double diff, const char *coinbase, + int cblen) +{ + int transactions = wb->transactions + 1; + char *gbt_block, varint[12]; + char hexcoinbase[512]; + + /* Submit anything over 95% of the diff in case of rounding errors */ + if (diff < current_workbase->diff * 0.95) + return; + + gbt_block = ckalloc(512); + sprintf(gbt_block, "submitblock:"); + __bin2hex(gbt_block + 12, data, 80); + if (transactions < 0xfd) { + uint8_t val8 = transactions; + + __bin2hex(varint, (const unsigned char *)&val8, 1); + } else if (transactions <= 0xffff) { + uint16_t val16 = htole16(transactions); + + strcat(gbt_block, "fd"); + __bin2hex(varint, (const unsigned char *)&val16, 2); + } else { + uint32_t val32 = htole32(transactions); + + strcat(gbt_block, "fe"); + __bin2hex(varint, (const unsigned char *)&val32, 4); + } + strcat(gbt_block, varint); + __bin2hex(hexcoinbase, coinbase, cblen); + strcat(gbt_block, hexcoinbase); + if (wb->transactions) + realloc_strcat(&gbt_block, wb->txn_data); + send_proc(&global_ckp->generator, gbt_block); + free(gbt_block); +} + static double submission_diff(stratum_instance_t *client, workbase_t *wb, const char *nonce2, uint32_t ntime32, const char *nonce) { - uchar coinbase[256], swap[80], hash[32], hash1[32]; unsigned char merkle_root[32], merkle_sha[64]; + char coinbase[256], data[80], share[68]; + uchar swap[80], hash[32], hash1[32]; uint32_t *data32, *swap32, nonce32; - char data[80], share[68]; int cblen = 0, i; double ret; @@ -757,7 +800,7 @@ static double submission_diff(stratum_instance_t *client, workbase_t *wb, const memcpy(coinbase + cblen, wb->coinb2bin, wb->coinb2len); cblen += wb->coinb2len; - gen_hash(coinbase, merkle_root, cblen); + gen_hash((uchar *)coinbase, merkle_root, cblen); memcpy(merkle_sha, merkle_root, 32); for (i = 0; i < wb->merkles; i++) { memcpy(merkle_sha + 32, &wb->merklebin[i], 32); @@ -788,12 +831,17 @@ static double submission_diff(stratum_instance_t *client, workbase_t *wb, const sha256(swap, 80, hash1); sha256(hash1, 32, hash); + /* Calculate the diff of the share here */ + ret = diff_from_target(hash); + + /* Test we haven't solved a block */ + test_blocksolve(wb, swap, ret, coinbase, cblen); + + /* Generate hex string of hash for logging */ data32 = (uint32_t *)hash1; bswap_256(hash1, hash); __bin2hex(share, hash1, 32); - ret = diff_from_target(hash); - LOGINFO("Client %d share diff %.1f : %s", client->id, ret, share); /* FIXME: Log share here */