From 3a7ea5b504583a1f59a1348cf734681cec744d07 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 4 Feb 2016 09:55:41 +1100 Subject: [PATCH] Revert "Revert "Move merkle tree generation to the stratifier along with all transaction data to allow transaction data to be used directly in future code"" This reverts commit d0398fed4a67c5295453aedb27bc80f8f3ff7dd0. Reinstate for merge. --- src/bitcoin.c | 112 ++--------------------------------------------- src/bitcoin.h | 2 +- src/stratifier.c | 112 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 96 insertions(+), 130 deletions(-) diff --git a/src/bitcoin.c b/src/bitcoin.c index 92bb7919..016a543f 100644 --- a/src/bitcoin.c +++ b/src/bitcoin.c @@ -79,99 +79,6 @@ 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; - json_t *arr_val; - uchar *hashbin; - - dealloc(gbt->txn_data); - dealloc(gbt->txn_hashes); - gbt->txns = 0; - gbt->merkles = 0; - gbt->txns = json_array_size(transaction_arr); - binlen = gbt->txns * 32 + 32; - hashbin = alloca(binlen + 32); - memset(hashbin, 0, 32); - binleft = binlen / 32; - if (gbt->txns) { - int len = 1, ofs = 0; - const char *txn; - - for (i = 0; i < gbt->txns; i++) { - arr_val = json_array_get(transaction_arr, i); - txn = json_string_value(json_object_get(arr_val, "data")); - if (!txn) { - LOGWARNING("json_string_value fail - cannot find transaction data"); - return false; - } - len += strlen(txn); - } - - gbt->txn_data = ckzalloc(len + 1); - gbt->txn_hashes = ckzalloc(gbt->txns * 65 + 1); - memset(gbt->txn_hashes, 0x20, gbt->txns * 65); // Spaces - - for (i = 0; i < gbt->txns; i++) { - char binswap[32]; - const char *hash; - - arr_val = json_array_get(transaction_arr, i); - hash = json_string_value(json_object_get(arr_val, "hash")); - txn = json_string_value(json_object_get(arr_val, "data")); - len = strlen(txn); - memcpy(gbt->txn_data + ofs, txn, len); - ofs += len; -#if 0 - /* In case we ever want to be a gbt poolproxy */ - if (!hash) { - char *txn_bin; - int txn_len; - - txn_len = len / 2; - txn_bin = ckalloc(txn_len); - hex2bin(txn_bin, txn, txn_len); - /* This is needed for pooled mining since only - * transaction data and not hashes are sent */ - gen_hash(txn_bin, hashbin + 32 + 32 * i, txn_len); - continue; - } -#endif - if (!hex2bin(binswap, hash, 32)) { - LOGERR("Failed to hex2bin hash in gbt_merkle_bins"); - return false; - } - memcpy(gbt->txn_hashes + i * 65, hash, 64); - bswap_256(hashbin + 32 + 32 * i, binswap); - } - } - if (binleft > 1) { - while (42) { - uchar merklebin[32]; - - if (binleft == 1) - break; - memcpy(merklebin, hashbin + 32, 32); - __bin2hex(&gbt->merklehash[gbt->merkles][0], merklebin, 32); - LOGDEBUG("MH%d %s",gbt->merkles, &gbt->merklehash[gbt->merkles][0]); - gbt->merkles++; - if (binleft % 2) { - memcpy(hashbin + binlen, hashbin + binlen - 32, 32); - binlen += 32; - binleft++; - } - for (i = 32, j = 64; j < binlen; i += 32, j += 64) - gen_hash(hashbin + j, hashbin + i, 64); - binleft /= 2; - binlen = binleft * 32; - } - } - LOGINFO("Stored %d transactions", gbt->txns); - return true; -} - static const char *gbt_req = "{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": [\"coinbasetxn\", \"workid\", \"coinbase/append\"]}]}\n"; /* Request getblocktemplate from bitcoind already connected with a connsock_t @@ -179,7 +86,7 @@ static const char *gbt_req = "{\"method\": \"getblocktemplate\", \"params\": [{\ * 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, *array; + json_t *txn_array, *coinbase_aux, *res_val, *val; const char *previousblockhash; char hash_swap[32], tmp[32]; uint64_t coinbasevalue; @@ -189,7 +96,6 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) int version; int curtime; int height; - int i; bool ret = false; val = json_rpc_call(cs, gbt_req); @@ -205,7 +111,7 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) previousblockhash = json_string_value(json_object_get(res_val, "previousblockhash")); target = json_string_value(json_object_get(res_val, "target")); - transaction_arr = json_object_get(res_val, "transactions"); + txn_array = json_object_get(res_val, "transactions"); version = json_integer_value(json_object_get(res_val, "version")); curtime = json_integer_value(json_object_get(res_val, "curtime")); bits = json_string_value(json_object_get(res_val, "bits")); @@ -258,19 +164,7 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) gbt->flags = strdup(flags); json_object_set_new_nocheck(gbt->json, "flags", json_string_nocheck(gbt->flags)); - gbt_merkle_bins(gbt, transaction_arr); - json_object_set_new_nocheck(gbt->json, "txns", json_integer(gbt->txns)); - if (gbt->txns) { - json_object_set_new_nocheck(gbt->json, "txn_data", json_string_nocheck(gbt->txn_data)); - json_object_set_new_nocheck(gbt->json, "txn_hashes", json_string_nocheck(gbt->txn_hashes)); - } - json_object_set_new_nocheck(gbt->json, "merkles", json_integer(gbt->merkles)); - if (gbt->merkles) { - array = json_array(); - for (i = 0; i < gbt->merkles; i++) - json_array_append_new(array, json_string_nocheck(&gbt->merklehash[i][0])); - json_object_set_new_nocheck(gbt->json, "merklehash", array); - } + json_object_set_new_nocheck(gbt->json, "transactions", json_deep_copy(txn_array)); ret = true; out: diff --git a/src/bitcoin.h b/src/bitcoin.h index 1404c538..9ba4534d 100644 --- a/src/bitcoin.h +++ b/src/bitcoin.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Con Kolivas + * Copyright 2014-2016 Con Kolivas * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/stratifier.c b/src/stratifier.c index 80f28c3a..acc139ab 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1104,6 +1104,95 @@ struct update_req { static void broadcast_ping(sdata_t *sdata); +/* Distill down a set of transactions into an efficient tree arrangement for + * stratum messages and fast work assembly. */ +static void wb_merkle_bins(workbase_t *wb, json_t *txn_array) +{ + int i, j, binleft, binlen; + json_t *arr_val; + uchar *hashbin; + + wb->txns = json_array_size(txn_array); + wb->merkles = 0; + binlen = wb->txns * 32 + 32; + hashbin = alloca(binlen + 32); + memset(hashbin, 0, 32); + binleft = binlen / 32; + if (wb->txns) { + int len = 1, ofs = 0; + const char *txn; + + for (i = 0; i < wb->txns; i++) { + arr_val = json_array_get(txn_array, i); + txn = json_string_value(json_object_get(arr_val, "data")); + if (!txn) { + LOGWARNING("json_string_value fail - cannot find transaction data"); + return; + } + len += strlen(txn); + } + + wb->txn_data = ckzalloc(len + 1); + wb->txn_hashes = ckzalloc(wb->txns * 65 + 1); + memset(wb->txn_hashes, 0x20, wb->txns * 65); // Spaces + + for (i = 0; i < wb->txns; i++) { + char binswap[32]; + const char *hash; + + arr_val = json_array_get(txn_array, i); + hash = json_string_value(json_object_get(arr_val, "hash")); + txn = json_string_value(json_object_get(arr_val, "data")); + len = strlen(txn); + memcpy(wb->txn_data + ofs, txn, len); + ofs += len; +#if 0 + /* In case we ever want to be a gbt poolproxy */ + if (!hash) { + char *txn_bin; + int txn_len; + + txn_len = len / 2; + txn_bin = ckalloc(txn_len); + hex2bin(txn_bin, txn, txn_len); + /* This is needed for pooled mining since only + * transaction data and not hashes are sent */ + gen_hash(txn_bin, hashbin + 32 + 32 * i, txn_len); + continue; + } +#endif + if (!hex2bin(binswap, hash, 32)) { + LOGERR("Failed to hex2bin hash in gbt_merkle_bins"); + return; + } + memcpy(wb->txn_hashes + i * 65, hash, 64); + bswap_256(hashbin + 32 + 32 * i, binswap); + } + } else + wb->txn_hashes = ckzalloc(1); + if (binleft > 1) { + while (42) { + uchar merklebin[32]; + + if (binleft == 1) + break; + memcpy(merklebin, hashbin + 32, 32); + __bin2hex(&wb->merklehash[wb->merkles][0], merklebin, 32); + LOGDEBUG("MH%d %s",wb->merkles, &wb->merklehash[wb->merkles][0]); + wb->merkles++; + if (binleft % 2) { + memcpy(hashbin + binlen, hashbin + binlen - 32, 32); + binlen += 32; + binleft++; + } + for (i = 32, j = 64; j < binlen; i += 32, j += 64) + gen_hash(hashbin + j, hashbin + i, 64); + binleft /= 2; + binlen = binleft * 32; + } + } +} + /* This function assumes it will only receive a valid json gbt base template * since checking should have been done earlier, and creates the base template * for generating work templates. */ @@ -1113,11 +1202,11 @@ static void *do_update(void *arg) int prio = ur->prio, retries = 0; ckpool_t *ckp = ur->ckp; sdata_t *sdata = ckp->data; + json_t *val, *txn_array; bool new_block = false; bool ret = false; workbase_t *wb; time_t now_t; - json_t *val; char *buf; pthread_detach(pthread_self()); @@ -1158,25 +1247,8 @@ retry: json_uint64cpy(&wb->coinbasevalue, val, "coinbasevalue"); json_intcpy(&wb->height, val, "height"); json_strdup(&wb->flags, val, "flags"); - json_intcpy(&wb->txns, val, "txns"); - if (wb->txns) { - json_strdup(&wb->txn_data, val, "txn_data"); - json_strdup(&wb->txn_hashes, val, "txn_hashes"); - } else - wb->txn_hashes = ckzalloc(1); - json_intcpy(&wb->merkles, val, "merkles"); - wb->merkle_array = json_array(); - if (wb->merkles) { - json_t *arr; - int i; - - arr = json_object_get(val, "merklehash"); - for (i = 0; i < wb->merkles; i++) { - strcpy(&wb->merklehash[i][0], json_string_value(json_array_get(arr, i))); - hex2bin(&wb->merklebin[i][0], &wb->merklehash[i][0], 32); - json_array_append_new(wb->merkle_array, json_string(&wb->merklehash[i][0])); - } - } + txn_array = json_object_get(val, "transactions"); + wb_merkle_bins(wb, txn_array); json_decref(val); generate_coinbase(ckp, wb);