3

I'm trying to dig into the monero codebase and understand how hashes are validated to be the solution for the current block. The below code returns true if the hash is valid, but I'm trying to understand why. I can tell it does a quick check on the highest word, but the rest I cannot fully grasp.

What I'd like to accomplish is to determine if the hash was close to the solution, even though it was not valid. What I did try was to make a copy of this function, removing the initial high word check, and reducing the difficulty variable that was passed (divide by 4) which returns true more often than when a block has actually been found.

I've also tried looking into the xmr-stak code, as what I'm really trying to accomplish is to get a list similar to the "Top 10 best results found".

bool check_hash(const crypto::hash &hash, difficulty_type difficulty) {
  uint64_t low, high, top, cur;
  // First check the highest word, this will most likely fail for a random hash.                                             
  mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, top, high);
  if (high != 0) {
    return false;
  }
  mul(swap64le(((const uint64_t *) &hash)[0]), difficulty, low, cur);
  mul(swap64le(((const uint64_t *) &hash)[1]), difficulty, low, high);
  bool carry = cadd(cur, low);
  cur = high;
  mul(swap64le(((const uint64_t *) &hash)[2]), difficulty, low, high);
  carry = cadc(cur, low, carry);
  carry = cadc(high, top, carry);
  return !carry;
}

Edit: With the help from glv, this is what I have:

uint64_t get_result(const crypto::hash &hash, difficulty_type difficulty) {
  uint64_t low, high;
  mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, low, high);
  return high;
}

To my understanding, this is returning the highest word when multiplying the hash and the difficulty. So, in order to find a block, this value must be zero, but to find a close enough hash, I am checking that this value is below 4 in miner.cpp:

result = get_result(h, local_diff);

if(result < 4) {
  // we have a close answer
}

1 Answer 1

2

The check_hash function returns true if hash * difficulty < 2^256 and false otherwise.

From src/cryptonote_basic/difficulty.h:

/**
 * @brief checks if a hash fits the given difficulty
 *
 * The hash passes if (hash * difficulty) < 2^256.
 * Phrased differently, if (hash * difficulty) fits without overflow into
 * the least significant 256 bits of the 320 bit multiplication result.
 *
 * @param hash the hash to check
 * @param difficulty the difficulty to check against
 *
 * @return true if valid, else false
 */
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
1
  • Thank you, the solution was right there in the comments. So, if I wanted to get results that were close, but not valid, I could check if (hash * difficulty) < 2^258, or as the comment puts it in other words, the product of the hash and difficulty fits within the first 258 bits without overflow.
    – jtnw
    Feb 19, 2018 at 17:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.