Bitcoin Forum
December 14, 2024, 08:08:06 AM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Q: Converting diff to hash  (Read 188 times)
joblo (OP)
Legendary
*
Offline Offline

Activity: 1470
Merit: 1114


View Profile
August 23, 2019, 04:10:41 AM
 #1

I'm an altcoin guy but this question applies to bitcoin.

The formula for converting share difficulty to an equivalent number of hashes
is documented on the bitcoin wiki: https://en.bitcoin.it/wiki/Difficulty

However, in my testing this formula produced incorrect results for altcoin algos.
I couldn't test sha256d as I don't have HW capable of supporting the extremely
high stratum diff. But since most altcoins were cloned from bitcoin I see no reason
why sha256d/bitcoin would be an exception.

Following are the comments I added to my code to explain my modification.
I arrived at the value through trial and error. Averaging over 100 shares the results
converged nicely to the miner's calculated hash rate for a cross section of algos.

Code:
// Bitcoin formula for converting a share's difficulty to an equivalent
// number of hashes.
//
//   https://en.bitcoin.it/wiki/Difficulty
//
//   H = D * 2**48 / 0xffff
//     = D * 2**32
//
// That formula doesn't seem to be accurate but an adjustment to the
// constant produces correct results.
//
// The formula used is:
//
//   hash = sharediff * 2**48 / 0x3fff
//        = sharediff * 2**30
//        = sharediff * diff2hash

const uint64_t diff2hash = 0x40000000ULL;

Although the numbers work I have no explanation for the discrepency with the documented
formula. I chose to decrease the denominator by a factor of 4 but increasing the numerator
would have the same effect so I don't know which one is "in error".

Is it simply a documentation error or am I missing something?

AKA JayDDee, cpuminer-opt developer. https://github.com/JayDDee/cpuminer-opt
https://bitcointalk.org/index.php?topic=5226770.msg53865575#msg53865575
BTC: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT,
odolvlobo
Legendary
*
Offline Offline

Activity: 4522
Merit: 3426



View Profile
August 24, 2019, 10:56:43 PM
 #2

Perhaps, sharediff is off by a factor of 4. Also, hashes are 256-bit values and using 64 bit values might be causing an overflow somewhere.

Join an anti-signature campaign: Click ignore on the members of signature campaigns.
PGP Fingerprint: 6B6BC26599EC24EF7E29A405EAF050539D0B2925 Signing address: 13GAVJo8YaAuenj6keiEykwxWUZ7jMoSLt
joblo (OP)
Legendary
*
Offline Offline

Activity: 1470
Merit: 1114


View Profile
August 25, 2019, 01:12:11 AM
 #3

Thanks for refocussing my thinking. Your suggestion presumes a pre-existing bug
causing incorrect sharediff and my fix was the second wrong that made things right.

The more I think about it the more plausible it seems. I had assumed the sharediff was correct,
but it's never used except for user info so an error would have no side effects.

I've got some work to do.


AKA JayDDee, cpuminer-opt developer. https://github.com/JayDDee/cpuminer-opt
https://bitcointalk.org/index.php?topic=5226770.msg53865575#msg53865575
BTC: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT,
joblo (OP)
Legendary
*
Offline Offline

Activity: 1470
Merit: 1114


View Profile
August 25, 2019, 07:07:49 PM
Last edit: August 26, 2019, 01:55:20 AM by joblo
 #4

TLDR: sharediff error was a bust, back to square 1.

I analyzed the code and did some testing to verify sharediff and the variables
used to calculate it.

The 256 bit arithmetic is done by converting the hash and target to double
using a simple polynomial:
Code:
const double base = (const double)(1<<32) * (const double)(1<<32);  // 2**64
 double dhash = hash[0] + hash[1]*base + hash[2]*base**2 + hash[3]*base**3;

This will introduce some loss of precision but not a 4x error. The resulting precision
matches the precision of the networkstratum diff which is also double.

NetworkStratum diff is obtained from the pool and matches, therefore correct.

Hash is as accepted by the pool, therefore correct.

Target is calculated from the networkstratum diff. If the target was too low if would produce
occasional low diff rejected shares, which isn't happening.

If the target was too high there would be no errors but the miner would neglect to
submit shares that would be accepted, resulting in a lower hashrate at the pool.
That was not observed.

In addition, I did some testing by raising the difficulty by 4x and low difficulty shares
were produced. 2x higher also produced low diff shares proving the original target
was neither too low nor too high.

The formula used:

sharediff = networkstratumdiff * target / hash

I can find nothing wrong with the sharediff calculation. It points back to the constant divisor
in the wiki arcticle being in error.

I'm willing ro accept it's simply a documentation error. My confidence in my code has increased
by doing a detailed analysis, however, it's still a hack without a proper explanation.

Edit: corrected references to stratum diff instead of network diff

AKA JayDDee, cpuminer-opt developer. https://github.com/JayDDee/cpuminer-opt
https://bitcointalk.org/index.php?topic=5226770.msg53865575#msg53865575
BTC: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT,
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!