Browse Source

Generate the merkle root for gbt work generation.

Con Kolivas 13 years ago
parent
commit
cbc246eace
2 changed files with 78 additions and 3 deletions
  1. 76 3
      cgminer.c
  2. 2 0
      miner.h

+ 76 - 3
cgminer.c

@@ -1366,8 +1366,9 @@ static void __build_gbt_coinbase(struct pool *pool)
 	int cbt_len;
 	int cbt_len;
 
 
 	cbt_len = strlen(pool->coinbasetxn) / 2;
 	cbt_len = strlen(pool->coinbasetxn) / 2;
+	pool->coinbase_len = cbt_len + 4;
 	/* We add 4 bytes of extra data corresponding to nonce2 of stratum */
 	/* We add 4 bytes of extra data corresponding to nonce2 of stratum */
-	coinbase = calloc(cbt_len + 4, 1);
+	coinbase = calloc(pool->coinbase_len, 1);
 	hex2bin(coinbase, pool->coinbasetxn, 42);
 	hex2bin(coinbase, pool->coinbasetxn, 42);
 	extra_len = (uint8_t *)(coinbase + 41);
 	extra_len = (uint8_t *)(coinbase + 41);
 	*extra_len += 4;
 	*extra_len += 4;
@@ -1407,7 +1408,11 @@ static bool __build_gbt_txns(struct pool *pool, json_t *res_val)
 		goto out;
 		goto out;
 
 
 	txn0 = json_string_value(json_object_get(json_array_get(txn_array, 0), "data"));
 	txn0 = json_string_value(json_object_get(json_array_get(txn_array, 0), "data"));
-	if (!hex2bin(pool->txn0, txn0, strlen(txn0) / 2))
+	pool->txn0_len = strlen(txn0) / 2;
+	pool->txn0 = calloc(pool->txn0_len , 1);;
+	if (unlikely(!pool->txn0))
+		quit(1, "Failed to calloc pool->txn0");
+	if (!hex2bin(pool->txn0, txn0, pool->txn0_len))
 		quit(1, "Failed to hex2bin txn0");
 		quit(1, "Failed to hex2bin txn0");
 	pool->txn_hashes = calloc(32 * pool->gbt_txns, 1);
 	pool->txn_hashes = calloc(32 * pool->gbt_txns, 1);
 	if (unlikely(!pool->txn_hashes))
 	if (unlikely(!pool->txn_hashes))
@@ -1433,6 +1438,63 @@ out:
 	return ret;
 	return ret;
 }
 }
 
 
+static unsigned char *__gbt_merkleroot(struct pool *pool)
+{
+	unsigned char *merkles, *txn0, *merkle_hash;
+	int i, txns;
+
+	if (!pool->gbt_txns) {
+		pool->txn0 = (unsigned char *)strdup((const char *)pool->gbt_coinbase);
+		pool->txn0_len = pool->coinbase_len;
+	}
+
+	txn0 = calloc(pool->coinbase_len + pool->txn0_len, 1);
+	if (unlikely(!txn0))
+		quit(1, "Failed to calloc txn0hash");
+
+	memcpy(txn0, pool->gbt_coinbase, pool->coinbase_len);
+	memcpy(txn0 + pool->coinbase_len, pool->txn0, pool->txn0_len);
+
+	merkles = calloc(32 + (32 * pool->gbt_txns), 1);
+	if (unlikely(!merkles))
+		quit(1, "Failed to calloc merkles in __gbt_merkleroot");
+
+	gen_hash(txn0, merkles, pool->coinbase_len + pool->txn0_len);
+	free(txn0);
+
+	if (pool->gbt_txns > 1)
+		memcpy(merkles + 32, pool->txn_hashes, (pool->gbt_txns - 1) * 32);
+
+	merkle_hash = calloc((pool->gbt_txns + 1) * 32, 1);
+	if (unlikely(!merkle_hash))
+		quit(1, "Failed to calloc merkle_hash in __gbt_merkleroot");
+
+	txns = pool->gbt_txns + 1;
+	for (i = 0; i < txns; i++){
+		unsigned char tohash[64];
+
+		memcpy(tohash, &merkles[i * 32], 32);
+		if (i + 1 < txns)
+			memcpy(tohash + 32, &merkles[(i + 1) * 32], 32);
+		else
+			memcpy(tohash + 32, &merkles[i * 32], 32);
+		gen_hash(tohash, merkle_hash + (i * 32), 64);
+	}
+	return merkle_hash;
+}
+	
+static void gen_gbt_work(struct pool *pool, struct work *work)
+{
+	unsigned char *merkleroot;
+
+	mutex_lock(&pool->gbt_lock);
+	__build_gbt_coinbase(pool);
+	merkleroot = __gbt_merkleroot(pool);
+	mutex_unlock(&pool->gbt_lock);
+
+	free(merkleroot);
+}
+
 static bool gbt_decode(struct pool *pool, json_t *res_val)
 static bool gbt_decode(struct pool *pool, json_t *res_val)
 {
 {
 	const char *previousblockhash;
 	const char *previousblockhash;
@@ -1486,7 +1548,6 @@ static bool gbt_decode(struct pool *pool, json_t *res_val)
 	pool->curtime = htobe32(curtime);
 	pool->curtime = htobe32(curtime);
 	pool->gbt_submitold = submitold;
 	pool->gbt_submitold = submitold;
 	pool->gbt_bits = strdup(bits);
 	pool->gbt_bits = strdup(bits);
-	__build_gbt_coinbase(pool);
 	__build_gbt_txns(pool, res_val);
 	__build_gbt_txns(pool, res_val);
 	mutex_unlock(&pool->gbt_lock);
 	mutex_unlock(&pool->gbt_lock);
 
 
@@ -2919,6 +2980,18 @@ retry:
 		goto out;
 		goto out;
 	}
 	}
 
 
+	if (pool->has_gbt) {
+		ret_work = make_work();
+		gen_gbt_work(pool, ret_work);
+		if (unlikely(!stage_work(ret_work))) {
+			applog(LOG_ERR, "Failed to stage gbt work in get_work_thread");
+			kill_work();
+			free(ret_work);
+		}
+		dec_queued(pool);
+		goto out;
+	}
+
 	if (clone_available()) {
 	if (clone_available()) {
 		dec_queued(pool);
 		dec_queued(pool);
 		goto out;
 		goto out;

+ 2 - 0
miner.h

@@ -900,6 +900,8 @@ struct pool {
 	unsigned char *txn0;
 	unsigned char *txn0;
 	unsigned char *txn_hashes;
 	unsigned char *txn_hashes;
 	int gbt_txns;
 	int gbt_txns;
+	int txn0_len;
+	int coinbase_len;
 };
 };
 
 
 #define GETWORK_MODE_TESTPOOL 'T'
 #define GETWORK_MODE_TESTPOOL 'T'