Title: Q: Converting diff to hash Post by: joblo on August 23, 2019, 04:10:41 AM 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? Title: Re: Q: Converting diff to hash Post by: odolvlobo on August 24, 2019, 10:56:43 PM 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.
Title: Re: Q: Converting diff to hash Post by: joblo on August 25, 2019, 01:12:11 AM 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. Title: Re: Q: Converting diff to hash Post by: joblo on August 25, 2019, 07:07:49 PM 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 Hash is as accepted by the pool, therefore correct. Target is calculated from the 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 = 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 |