Browse Source

Bugfix: Clean up share hashing and target checks, fixing share difficulty calculation for above-target would-be-shares

Luke Dashjr 13 years ago
parent
commit
bfab076d59
4 changed files with 72 additions and 83 deletions
  1. 1 1
      libblkmaker
  2. 9 60
      miner.c
  3. 55 22
      util.c
  4. 7 0
      util.h

+ 1 - 1
libblkmaker

@@ -1 +1 @@
-Subproject commit ca3cf0173806d39d2b3a1400de3fa4bec7ab772a
+Subproject commit 5f3ad2a1edc37ef2745634fea6bfc5b4d9bfdf9a

+ 9 - 60
miner.c

@@ -2355,52 +2355,13 @@ void clear_logwin(void)
 #endif
 
 /* regenerate the full work->hash value and also return true if it's a block */
-bool regeneratehash(const struct work *work)
+bool regeneratehash(struct work *work)
 {
-	uint32_t *data32 = (uint32_t *)(work->data);
-	unsigned char swap[128];
-	uint32_t *swap32 = (uint32_t *)swap;
-	unsigned char hash1[32];
-	uint32_t *hash32 = (uint32_t *)(work->hash);
-	uint32_t difficulty = 0;
-	uint32_t diffbytes = 0;
-	uint32_t diffvalue = 0;
-	uint32_t diffcmp[8];
-	int diffshift = 0;
-	int i;
-
-	swap32yes(swap32, data32, 80 / 4);
-
-	sha2(swap, 80, hash1, false);
-	sha2(hash1, 32, (unsigned char *)(work->hash), false);
-
-	difficulty = be32toh(*((uint32_t *)(work->data + 72)));
-
-	diffbytes = ((difficulty >> 24) & 0xff) - 3;
-	diffvalue = difficulty & 0x00ffffff;
-
-	diffshift = (diffbytes % 4) * 8;
-	if (diffshift == 0) {
-		diffshift = 32;
-		diffbytes--;
-	}
-
-	memset(diffcmp, 0, 32);
-	diffcmp[(diffbytes >> 2) + 1] = diffvalue >> (32 - diffshift);
-	diffcmp[diffbytes >> 2] = diffvalue << diffshift;
+	unsigned char target[32];
 
-	for (i = 7; i >= 0; i--) {
-		uint32_t hash32i = le32toh(hash32[i]);
-		if (hash32i > diffcmp[i])
-			return false;
-		if (hash32i < diffcmp[i])
-			return true;
-	}
-
-	// https://en.bitcoin.it/wiki/Block says: "numerically below"
-	// https://en.bitcoin.it/wiki/Target says: "lower than or equal to"
-	// code in bitcoind 0.3.24 main.cpp CheckWork() says: if (hash > hashTarget) return false;
-	return true;
+	hash_data(work->hash, work->data);
+	real_block_target(target, work->data);
+	return hash_target_check(work->hash, target);
 }
 
 static void enable_pool(struct pool *pool)
@@ -5956,7 +5917,7 @@ static struct work *clone_work(struct work *work)
 	return work;
 }
 
-static void gen_hash(unsigned char *data, unsigned char *hash, int len)
+void gen_hash(unsigned char *data, unsigned char *hash, int len)
 {
 	unsigned char hash1[32];
 
@@ -6215,17 +6176,9 @@ err_out:
 
 enum test_nonce2_result hashtest2(struct work *work, bool checktarget)
 {
-	uint32_t *data32 = (uint32_t *)(work->data);
-	unsigned char swap[128];
-	uint32_t *swap32 = (uint32_t *)swap;
-	unsigned char hash1[32];
-	unsigned char hash2[32];
-	uint32_t *hash2_32 = (uint32_t *)hash2;
-
-	swap32yes(swap32, data32, 80 / 4);
+	uint32_t *hash2_32 = (uint32_t *)&work->hash[0];
 
-	sha2(swap, 80, hash1, false);
-	sha2(hash1, 32, hash2, false);
+	hash_data(work->hash, work->data);
 
 	if (hash2_32[7] != 0)
 		return TNR_BAD;
@@ -6233,11 +6186,7 @@ enum test_nonce2_result hashtest2(struct work *work, bool checktarget)
 	if (!checktarget)
 		return TNR_GOOD;
 
-	swap32yes(hash2_32, hash2_32, 32 / 4);
-
-	memcpy((void*)work->hash, hash2, 32);
-
-	if (!fulltest(work->hash, work->target))
+	if (!hash_target_check_v(work->hash, work->target))
 		return TNR_HIGH;
 
 	return TNR_GOOD;

+ 55 - 22
util.c

@@ -571,34 +571,59 @@ bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
 	return ret;
 }
 
-bool fulltest(const unsigned char *hash, const unsigned char *target)
+void hash_data(unsigned char *out_hash, const unsigned char *data)
 {
-	unsigned char hash_swap[32], target_swap[32];
-	uint32_t *hash32 = (uint32_t *) hash_swap;
-	uint32_t *target32 = (uint32_t *) target_swap;
-	char *hash_str, *target_str;
-	bool rc = true;
-	int i;
-
-	swap256(hash_swap, hash);
-	swap256(target_swap, target);
+	unsigned char blkheader[80];
+	
+	// data is past the first SHA256 step (padding and interpreting as big endian on a little endian platform), so we need to flip each 32-bit chunk around to get the original input block header
+	swap32yes(blkheader, data, 80 / 4);
+	
+	// double-SHA256 to get the block hash
+	gen_hash(blkheader, out_hash, 80);
+}
 
-	for (i = 0; i < 32/4; i++) {
-		uint32_t h32tmp = htobe32(hash32[i]);
-		uint32_t t32tmp = htole32(target32[i]);
-		target32[i] = swab32(target32[i]);	/* for printing */
+void real_block_target(unsigned char *target, const unsigned char *data)
+{
+	uint8_t targetshift;
+
+	targetshift = data[72] - 3;
+	memset(target, 0, targetshift);
+	target[targetshift++] = data[75];
+	target[targetshift++] = data[74];
+	target[targetshift++] = data[73];
+	memset(&target[targetshift], 0, 0x20 - targetshift);
+}
 
-		if (h32tmp > t32tmp) {
-			rc = false;
-			break;
-		}
-		if (h32tmp < t32tmp) {
-			rc = true;
-			break;
-		}
+bool hash_target_check(const unsigned char *hash, const unsigned char *target)
+{
+	const uint32_t *h32 = (uint32_t*)&hash[0];
+	const uint32_t *t32 = (uint32_t*)&target[0];
+	for (int i = 7; i >= 0; --i) {
+		uint32_t h32i = le32toh(h32[i]);
+		uint32_t t32i = le32toh(t32[i]);
+		if (h32i > t32i)
+			return false;
+		if (h32i < t32i)
+			return true;
 	}
+	return true;
+}
+
+bool hash_target_check_v(const unsigned char *hash, const unsigned char *target)
+{
+	bool rc;
+
+	rc = hash_target_check(hash, target);
 
 	if (opt_debug) {
+		unsigned char hash_swap[32], target_swap[32];
+		char *hash_str, *target_str;
+
+		for (int i = 0; i < 32; ++i) {
+			hash_swap[i] = hash[31-i];
+			target_swap[i] = target[31-i];
+		}
+
 		hash_str = bin2hex(hash_swap, 32);
 		target_str = bin2hex(target_swap, 32);
 
@@ -615,6 +640,14 @@ bool fulltest(const unsigned char *hash, const unsigned char *target)
 	return rc;
 }
 
+// DEPRECATED: This uses an input hash that has every 4 bytes flipped
+bool fulltest(const unsigned char *hash, const unsigned char *target)
+{
+	unsigned char hash2[32];
+	swap32yes(hash2, hash, 32 / 4);
+	return hash_target_check_v(hash2, target);
+}
+
 struct thread_q *tq_new(void)
 {
 	struct thread_q *tq;

+ 7 - 0
util.h

@@ -45,6 +45,13 @@
 struct pool;
 enum dev_reason;
 struct cgpu_info;
+
+extern void gen_hash(unsigned char *data, unsigned char *hash, int len);
+extern void hash_data(unsigned char *out_hash, const unsigned char *data);
+extern void real_block_target(unsigned char *target, const unsigned char *data);
+extern bool hash_target_check(const unsigned char *hash, const unsigned char *target);
+extern bool hash_target_check_v(const unsigned char *hash, const unsigned char *target);
+
 bool stratum_send(struct pool *pool, char *s, ssize_t len);
 char *recv_line(struct pool *pool);
 bool parse_method(struct pool *pool, char *s);