I'm looking at nodejs-pool and this is what I extracted from it to verify the hash sent by the miner:

     // All the variables are self explanatory
     const cnUtil = require("cryptonote-util");
     const cryptoNight = require("cryptonight-hashing")['cryptonight'];

     let template = new Buffer(blockTemplateBlob,'hex');
     let poolNonce = new Buffer(_poolNonce,'hex');

     let shareBuffer = cnUtil.construct_block_blob(template, new Buffer(nonce, 'hex'));

     let convertedBlob = cnUtil.convert_blob(shareBuffer);
     let hash = cryptoNight(convertedBlob, 13, blockHeightWhenJobWasIssued);
     if (hash.toString('hex') != resultHashFromMiner){
        console.log("hashes don't match");
        return false;
    } else {
       console.log("hashes match");

It always prints hashes don't match. I've checked every variable is correct. Also I have verified that the algorithm being used on the miner side is CryptonightR, but still can't figure out what's wrong. Can anybody help here?

2 Answers 2


Recall from this answer, the pool adds various data to the reserved space and it stores/caches the block template it used to create the hashing blob it sends to the miner.

Therefore, your lines:

 let template = new Buffer(blockTemplateBlob,'hex');
 let poolNonce = new Buffer(_poolNonce,'hex');

Look rather suspect.

First, blockTemplateBlob, where are you getting this from?? This would need to be the pools cached template, and I suspect you have not obtained this. Ref.

Second, in nodejs-pool, the variable they call "poolNonce" is only used for proxy jobs, not standard miner jobs. Ref.

Third, you are writing "poolNonce" to the start of the reserved space, which is not where this pool adds the "poolNonce" - they add it at job.clientPoolLocation. Ref.

Forth, you are not adding the miner specific nonce (what they call "extraNonce") into the reserved space (which should be at the beginning of the reserved space). Ref.

Given all this, I'm not surprised at all your hashes don't match.

UPDATE (for completeness):

Through the comments below, it turns out you were not supplying the correct height parameter to the hash function and job. The height has to match exactly the height of the block template and that which is supplied to the miner (and in your case, it turns out you never actually supplied the height to the miner). The pool has to of course use the same height it told the miner to use when hashing. If the heights mismatch, the hashes won't match. If you don't provide a height to the miner but do in the pool, the hashes won't match.

  • 1. I've abstracted the code to make it easier to read. I've checked twice and thrice that all the variables I have correct values by console logging them. 2. I'm only adding miner specific nonce. This is one only nonce that I'm using. So I named it poolNonce. 3. Since there is only one nonce I'm writing it to the start of the reserve space just like I did when creating the job 4. #2 explains it My suspect is the cryptoNight hash function. why does it need the other two parameters. what does 13 mean and why are we passing it job height as an argument as well. Also I'm running testnet
    – Shiva Teja
    Jun 8, 2019 at 1:52
  • 1
    Recall, the pool adds data to the reserved space in a block template. It then creates and sends the miner a hashing blob. The miner then this hashes and returns a result hash and nonce. The pool takes the previously modified template, adds the miner supplied nonce (not in the reserved space), creates a new hashing blob, hashes and compares. Now to your Q about cryptoNight hash function. 13 is an algorithm switch.
    – jtgrassie
    Jun 8, 2019 at 2:16
  • 1
    And your Q on passing it height, CN/R hashing function requires a height parameter. This must be the exact same height of your template and the same height passed to the miner in the job.
    – jtgrassie
    Jun 8, 2019 at 2:27
  • 1
    No. This won't affect anything. Testnet,. stagenet and mainnet all using the same CN variant right now.
    – jtgrassie
    Jun 8, 2019 at 3:48
  • 1
    I just found the issue, you said we need block height as a parameter for the cnV4 hash function right? I just connected to supportxmr.com pool and it appears to be sending the block height as a part of the job. I included the height in the job and now the hashes match.
    – Shiva Teja
    Jun 8, 2019 at 4:03

cryptonight V4 ( AKA Cryptonight-R ) requires block height that the job is for, to be sent to miner as a part of getjob jsonrpc method. Not including it won't show any error messages or warnings but the hash will be completely different.

Below is an example response to the jsonrpc method getjob :

      id: exact_id_as_sent_by_miner_request,
      error: null,
      result: {
         id: some_id,
         job: {
            target: target_hex,
            algo: "cn/r",
            height // this is important. this is the block height that the miner is supposed to be working on
         status: "OK"

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.