I am trying to understand the contents, their meaning and their volatility of the job we receive from Monero pool. For example

data from pool: {"id":1,"jsonrpc":"2.0","error":null,"result":{"id":"300955505552701","job": {"blob":"0202b4d88cd005723910a7844c6cf04bb10af456fdf6e4b352e1839747d3e971117b7550da82550000000028b751d55f1b5c591ef82e4ec90a621a32f48044e8e112fa8ff4be5b3b046a6a04","job_id":"129359229584224","target":"9bc42000"},"status":"OK"}}

Now I can understand things like Id, jobid, target, status etc. The question I have is, in blob is the length always 76 bytes? can it change from 76 to something and if it does when and why?

Also what does exactly the blob represent? I know the first 39 bytes are something and then 4 bytes are nonce then remaining 33 bytes are something. Those 39 and 33 bytes are what?


1 Answer 1


Mining Blob

The mining blob is the block header + merkle root + number of TX-es. It's similar to block identifier as defined in CNS003:

  1. Calculation of Block Identifier

    The identifier of a block is the result of hashing the following data with Keccak:

    • size of [block_header, Merkle root hash, and the number of transactions] in bytes (varint)

    • block_header,

    • Merkle root hash,

    • number of transactions (varint).

    The goal of the Merkle root hash is to "attach" the transactions referred to in the list to the block header: once the Merkle root hash is fixed, the transactions cannot be modified.

Note that the block identifier is the result of hashing the blob with Keccak and it is not the same as PoW hash. The PoW hash is obtained by hashing the blob with CryptoNight, and it doesn't contain the "size of [block header, ..." which is used exclusively for the block identifier.

See get_block_hashing_blob implementation in Monero source code for details.

  blobdata get_block_hashing_blob(const block& b)
    blobdata blob = t_serializable_object_to_blob(static_cast<block_header>(b));
    crypto::hash tree_root_hash = get_tx_tree_hash(b);
    blob.append(reinterpret_cast<const char*>(&tree_root_hash), sizeof(tree_root_hash));
    return blob;

As you can see, it retrieves the block header blob, and appends Merkle tree root and number of transactions to the blob.

Block Header

Block header is also defined in CNS003:

4.1 Block Header

Each block starts with a block header. The major version defines the block header parsing rules (i.e. block header format) and is incremented with each block header format update. The table below describes version 1 of the block header format. The minor version defines the interpretation details that are not related to block header parsing.

It is always safe to parse the block header of a particular major version with a parsing procedure suitable for said version, even if the minor version is unknown. Parsing the block header with an unknown major version is not safe as the content of the block header may be misinterpreted.

   |     Field     |       Type       |            Content             |
   | major_version | varint           | Major block header version     |
   |               |                  | (always 1)                     |
   | minor_version | varint           | Minor block header version     |
   |               |                  |                                |
   | timestamp     | varint           | Block creation time            |
   |               |                  | (UNIX timestamp)               |
   | prev_id       | hash             | Identifier of the previous     |
   |               |                  | block                          |
   | nonce         | 4 bytes          | Any value which is used in the |
   |               |                  | network consensus algorithm    |

             Table 4.1: Block header structure description 

The definition of block header is found in Monero source code as well.

  struct block_header
    uint8_t major_version;
    uint8_t minor_version;  // now used as a voting mechanism, rather than how this particular block is built
    uint64_t timestamp;
    crypto::hash  prev_id;
    uint32_t nonce;

Note that major version is used for hard-fork upgrade counting, as seen in Monero source code (1, 2). Looks like it's not exactly following the CN specification, where it was supposed to be changed only if the header parsing scheme changes.

Block PoW Hashing

For actual hashing, see get_block_longhash implementation in Monero source code and explanation of the "block 202612 bug workaround": What happened at block 202612?

  • Great, thanks again JollyMort. Seems like you come to save me all the time :-) Anyway, I went through the specification and it says major version always 1, though in my pool job response I see major and minor version always 2. I guess its just relevant to which concurrency it is? Also I just realized that I can find much of info on cryptonote.org as well.
    – Rahul
    Commented Nov 9, 2017 at 17:02
  • My pleasure :) See the updated answer with more detail. Spec. might not always be accurate since Monero diverged from original CryptoNote implementation long time ago. Better look at the source code.
    – JollyMort
    Commented Nov 9, 2017 at 19:40
  • Oh and if the pool is giving major.minor versions 2.2, then it must be behind (or another CN coin). Recent Monero blocks show 6.6: xmrchain.net/block/1439347
    – JollyMort
    Commented Nov 9, 2017 at 19:42
  • Yes, actually I am using Monero thread so that I can get answers quicker, though I am working on Sumokoin. Both coins use same algo and same miner. It is much easier to find answers for Monero which are applicable to Sumo as well, Sumo is not famous yet !!
    – Rahul
    Commented Nov 10, 2017 at 19:34

Your Answer

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

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