Make pooled GBT mining use merkle bin optimisations slated for solo mining.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
diff --git a/cgminer.c b/cgminer.c
index 2231626..420587f 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -1873,80 +1873,28 @@ char *workpadding = "00000080000000000000000000000000000000000000000000000000000
* transaction, and the hashes of the remaining transactions since these
* remain constant with an altered coinbase when generating work. Must be
* entered under gbt_lock */
-static bool __build_gbt_txns(struct pool *pool, json_t *res_val)
+static void gbt_merkle_bins(struct pool *pool, json_t *transaction_arr);
+
+static void __build_gbt_txns(struct pool *pool, json_t *res_val)
{
json_t *txn_array;
- bool ret = false;
- size_t cal_len;
- int i;
-
- free(pool->txn_hashes);
- pool->txn_hashes = NULL;
- pool->gbt_txns = 0;
txn_array = json_object_get(res_val, "transactions");
- if (!json_is_array(txn_array))
- goto out;
-
- ret = true;
- pool->gbt_txns = json_array_size(txn_array);
- if (!pool->gbt_txns)
- goto out;
-
- pool->txn_hashes = calloc(32 * (pool->gbt_txns + 1), 1);
- if (unlikely(!pool->txn_hashes))
- quit(1, "Failed to calloc txn_hashes in __build_gbt_txns");
-
- for (i = 0; i < pool->gbt_txns; i++) {
- json_t *txn_val = json_object_get(json_array_get(txn_array, i), "data");
- const char *txn = json_string_value(txn_val);
- int txn_len = strlen(txn);
- unsigned char *txn_bin;
-
- cal_len = txn_len;
- align_len(&cal_len);
- txn_bin = calloc(cal_len, 1);
- if (unlikely(!txn_bin))
- quit(1, "Failed to calloc txn_bin in __build_gbt_txns");
- if (unlikely(!hex2bin(txn_bin, txn, txn_len / 2)))
- quit(1, "Failed to hex2bin txn_bin");
-
- gen_hash(txn_bin, pool->txn_hashes + (32 * i), txn_len / 2);
- free(txn_bin);
- }
-out:
- return ret;
+ gbt_merkle_bins(pool, txn_array);
}
-static unsigned char *__gbt_merkleroot(struct pool *pool)
+static void __gbt_merkleroot(struct pool *pool, unsigned char *merkle_root)
{
- unsigned char *merkle_hash;
- int i, txns;
-
- merkle_hash = calloc(32 * (pool->gbt_txns + 2), 1);
- if (unlikely(!merkle_hash))
- quit(1, "Failed to calloc merkle_hash in __gbt_merkleroot");
-
- gen_hash(pool->coinbase, merkle_hash, pool->coinbase_len);
-
- if (pool->gbt_txns)
- memcpy(merkle_hash + 32, pool->txn_hashes, pool->gbt_txns * 32);
-
- txns = pool->gbt_txns + 1;
- while (txns > 1) {
- if (txns % 2) {
- memcpy(&merkle_hash[txns * 32], &merkle_hash[(txns - 1) * 32], 32);
- txns++;
- }
- for (i = 0; i < txns; i += 2){
- unsigned char hashout[32];
+ unsigned char merkle_sha[64];
+ int i;
- gen_hash(merkle_hash + (i * 32), hashout, 64);
- memcpy(merkle_hash + (i / 2 * 32), hashout, 32);
- }
- txns /= 2;
+ gen_hash(pool->coinbase, merkle_root, pool->coinbase_len);
+ memcpy(merkle_sha, merkle_root, 32);
+ for (i = 0; i < pool->merkles; i++) {
+ memcpy(merkle_sha + 32, pool->merklebin + i * 32, 32);
+ gen_hash(merkle_sha, merkle_root, 64);
+ memcpy(merkle_sha, merkle_root, 32);
}
- return merkle_hash;
}
static bool work_decode(struct pool *pool, struct work *work, json_t *val);
@@ -1991,7 +1939,7 @@ static void update_gbt(struct pool *pool)
static void gen_gbt_work(struct pool *pool, struct work *work)
{
- unsigned char *merkleroot;
+ unsigned char merkleroot[32];
struct timeval now;
uint64_t nonce2le;
@@ -2004,7 +1952,7 @@ static void gen_gbt_work(struct pool *pool, struct work *work)
memcpy(pool->coinbase + pool->nonce2_offset, &nonce2le, pool->n2size);
pool->nonce2++;
cg_dwlock(&pool->gbt_lock);
- merkleroot = __gbt_merkleroot(pool);
+ __gbt_merkleroot(pool, merkleroot);
memcpy(work->data, &pool->gbt_version, 4);
memcpy(work->data + 4, pool->previousblockhash, 32);
@@ -2023,7 +1971,6 @@ static void gen_gbt_work(struct pool *pool, struct work *work)
cg_runlock(&pool->gbt_lock);
flip32(work->data + 4 + 32, merkleroot);
- free(merkleroot);
memset(work->data + 4 + 32 + 32 + 4 + 4, 0, 4); /* nonce */
hex2bin(work->data + 4 + 32 + 32 + 4 + 4 + 4, workpadding, 48);
@@ -2173,7 +2120,7 @@ static bool pool_localgen(struct pool *pool)
static void gbt_merkle_bins(struct pool *pool, json_t *transaction_arr)
{
- json_t *value, *arr_val;
+ json_t *arr_val;
int transactions, i, j;
pool->merkles = 0;
@@ -2190,23 +2137,31 @@ static void gbt_merkle_bins(struct pool *pool, json_t *transaction_arr)
const char *hash;
arr_val = json_array_get(transaction_arr, i);
- if (!arr_val) {
- applog(LOG_ERR, "json_array_get fail of arr_val");
- continue;
- }
- value = json_object_get(arr_val, "hash");
- if (!value) {
- applog(LOG_ERR, "json_object_get fail of value");
- continue;
- }
- hash = json_string_value(value);
+ hash = json_string_value(json_object_get(arr_val, "hash"));
if (!hash) {
- applog(LOG_ERR, "json_string_value fail of hash");
+ /* This is needed for pooled mining since only
+ * transaction data and not hashes are sent */
+ const char *txn = json_string_value(json_object_get(arr_val, "data"));
+ unsigned char *txn_bin;
+ int txn_len;
+
+ if (!txn) {
+ applog(LOG_ERR, "Pool %d json_string_value fail - cannot find transaction hash nor data",
+ pool->pool_no);
+ return;
+ }
+ txn_len = strlen(txn) / 2;
+ txn_bin = malloc(txn_len);
+ if (!txn_bin)
+ quit(1, "Failed to malloc txn_bin in gbt_merkle_bins");
+ hex2bin(txn_bin, txn, txn_len);
+ gen_hash(txn_bin, hashbin + 32 + 32 * i, txn_len);
+ free(txn_bin);
continue;
}
if (!hex2bin(binswap, hash, 32)) {
applog(LOG_ERR, "Failed to hex2bin hash in gbt_merkle_bins");
- continue;
+ return;
}
swab256(hashbin + 32 + 32 * i, binswap);
}
@@ -2233,7 +2188,6 @@ static void gbt_merkle_bins(struct pool *pool, json_t *transaction_arr)
__bin2hex(hashhex, pool->merklebin + i * 32, 32);
applog(LOG_WARNING, "MH%d %s",i, hashhex);
}
- exit(0);
}
}