Browse Source

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 d0398fed4a.

Reinstate for merge.
master
Con Kolivas 9 years ago
parent
commit
3a7ea5b504
  1. 112
      src/bitcoin.c
  2. 2
      src/bitcoin.h
  3. 112
      src/stratifier.c

112
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:

2
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

112
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);

Loading…
Cancel
Save