Browse Source

Optimise coinbase check logic by using actual script bytes everywhere possible

Luke Dashjr 11 years ago
parent
commit
150520fe8c
3 changed files with 25 additions and 36 deletions
  1. 7 6
      miner.c
  2. 3 3
      miner.h
  3. 15 27
      util.c

+ 7 - 6
miner.c

@@ -1594,13 +1594,13 @@ static char *set_cbcaddr(char *arg)
 	
 	for (; (addr = strtok_r(arg, ",", &p)); arg = NULL)
 	{
-		struct addr_hash *ah;
+		struct bytes_hashtbl *ah;
 		
 		if (set_b58addr(addr, &target_script))
 			/* No bother to free memory since we are going to exit anyway */
 			return "Invalid address in --coinbase-check-address list";
 		
-		HASH_FIND_STR(pool->cb_param.addr_ht, addr, ah);
+		HASH_FIND(hh, pool->cb_param.scripts, bytes_buf(&target_script), bytes_len(&target_script), ah);
 		if (!ah)
 		{
 			/* Note: for the below allocated memory we have good way to release its memory
@@ -1610,9 +1610,10 @@ static char *set_cbcaddr(char *arg)
 			 * We just hope the remove_pool() would not be called many many times during
 			 * the whole running life of this program.
 			 */
-			ah = malloc(sizeof(struct addr_hash));
-			ah->addr = addr;
-			HASH_ADD_STR(pool->cb_param.addr_ht, addr, ah);
+			ah = malloc(sizeof(*ah));
+			bytes_init(&ah->b);
+			bytes_assimilate(&ah->b, &target_script);
+			HASH_ADD(hh, pool->cb_param.scripts, b.buf, bytes_len(&ah->b), ah);
 		}
 	}
 	bytes_free(&target_script);
@@ -1643,7 +1644,7 @@ static char *set_cbcperc(const char *arg)
 		return "Define pool first, then the --coinbase-check-percent argument";
 	
 	pool = pools[total_pools - 1];
-	if (!pool->cb_param.addr_ht)
+	if (!pool->cb_param.scripts)
 		return "Define --coinbase-check-addr list first, then the --coinbase-check-total argument";
 	
 	pool->cb_param.perc = atof(arg);

+ 3 - 3
miner.h

@@ -1246,14 +1246,14 @@ struct stratum_work {
  * Build an hash table in case there are lots
  * of addresses to check against
  */
-struct addr_hash {
-	char* addr;
+struct bytes_hashtbl {
+	bytes_t b;
 	UT_hash_handle hh;
 };
 
 struct coinbase_param {
 	bool testnet;
-	struct addr_hash *addr_ht;
+	struct bytes_hashtbl *scripts;
 	int64_t total;
 	float perc;
 };

+ 15 - 27
util.c

@@ -2428,8 +2428,6 @@ incomplete_cb:
 	
 	while (len-- > 0)
 	{
-		char addr[35];
-		
 		if (cbsize <= pos + 8)
 			goto incomplete_cb;
 		
@@ -2443,42 +2441,32 @@ incomplete_cb:
 			goto incomplete_cb;
 		pos += i;
 		
-		i = script_to_address(addr, sizeof(addr), coinbase + pos, curr_pk_script_len, cb_param->testnet);
-		if (i && i <= sizeof(addr))
+		struct bytes_hashtbl *ah = NULL;
+		HASH_FIND(hh, cb_param->scripts, &coinbase[pos], curr_pk_script_len, ah);
+		if (ah)
 		{
-			/* So this script is to payout to an valid address */
-			struct addr_hash *ah = NULL;
-			HASH_FIND_STR(cb_param->addr_ht, addr, ah);
-			if (ah)
-			{
-				found_target = true;
-				target += amount;
-			}
-			if (opt_debug)
-				applog(LOG_DEBUG, "Coinbase output: %10"PRIu64" -- %34s%c", amount, addr, ah ? '*' : '\0');
+			found_target = true;
+			target += amount;
 		}
-		else
+		
 		if (opt_debug)
 		{
-			char *hex = addr;
-			if (curr_pk_script_len * 2 >= sizeof(addr))
-				hex = malloc(curr_pk_script_len * 2 + 1);
-			if (hex)
+			char s[(curr_pk_script_len * 2) + 3];
+			i = script_to_address(s, sizeof(s), &coinbase[pos], curr_pk_script_len, cb_param->testnet);
+			if (!(i && i <= sizeof(s)))
 			{
-				bin2hex(hex, coinbase + pos, curr_pk_script_len);
-				applog(LOG_DEBUG, "Coinbase output: %10"PRIu64" PK %34s", amount, hex);
-				if (hex != addr)
-					free(hex);
+				s[0] = '[';
+				bin2hex(&s[1], &coinbase[pos], curr_pk_script_len);
+				strcpy(&s[(curr_pk_script_len * 2) + 1], "]");
 			}
-			else
-				applog(LOG_DEBUG, "Coinbase output: %10"PRIu64" PK (Unknown)", amount);
+			applog(LOG_DEBUG, "Coinbase output: %10"PRIu64" -- %s%s", amount, s, ah ? "*" : "");
 		}
 		
 		pos += curr_pk_script_len;
 	}
 	if (total < cb_param->total)
 		applogr(false, LOG_ERR, "Coinbase check: lopsided total output amount = %"PRIu64", expecting >=%"PRIu64, total, cb_param->total);
-	if (cb_param->addr_ht)
+	if (cb_param->scripts)
 	{
 		if (cb_param->perc && !(total && (float)((double)target / total) >= cb_param->perc))
 			applogr(false, LOG_ERR, "Coinbase check: lopsided target/total = %g(%"PRIu64"/%"PRIu64"), expecting >=%g", (total ? (double)target / total : (double)0), target, total, cb_param->perc);
@@ -2492,7 +2480,7 @@ incomplete_cb:
 	pos += 4;
 	
 	if (opt_debug)
-		applog(LOG_DEBUG, "Coinbase: (size, pos, addr_count, target, total) = (%lu, %lu, %d, %"PRIu64", %"PRIu64")", (unsigned long)cbsize, (unsigned long)pos, (int)(HASH_COUNT(cb_param->addr_ht)), target, total);
+		applog(LOG_DEBUG, "Coinbase: (size, pos, addr_count, target, total) = (%lu, %lu, %d, %"PRIu64", %"PRIu64")", (unsigned long)cbsize, (unsigned long)pos, (int)(HASH_COUNT(cb_param->scripts)), target, total);
 	
 	return true;
 }