stratum – How should I order the block header data in messages with the pool?


First i am creating this post to benefit all of you who are really into understanding and building your own miner from the scratch. There is so many materials but rarely have anything in common.

I need help validating if the order of matters is correct in my Block header for mining. I am building my own miner as a challenge and still struggle with the proper formats. There are many examples on the web but really even the pool doesn’t state in which order the data is being sent out for the clients. So just for an absolute clarity i thought we could have a definitive answer on the question here.

Some of the developers reverse the pool hash and even flip the bytes:

hex2byte(ph, bp);
 revFlip(bp);

Others just simply copy paste Bitcoin wiki solution, without noticing that the prev hash for example is reversed to what the mining pool provides.

 $prevBlockHash = SwapOrder('00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81');
  $rootHash = SwapOrder('2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3');
  $

Some tell, that we should reverse the nbits,ntime, version – but this is already reversed from the pool right?

So the question is :

When talking with the pool, how should i arrange my data for the block header, to be ready for comparison with the target after hashing?

This is so crucial, that any mistake made here will lead miner(s) to compute hashes for things that are irrelevant thus never finding a valid ‘nonce’ – its so wasteful and should really be clarified.

Since i am talking about pool here, i will base this on the use of solo.ckpool.org example.

So let’s start from the beginning by connecting to the pool, and retrieving data that should be used to compose a block header.

Here we go, the data being sent to me from solo.ckpool.org is:

{"result":[[["mining.notify","71ae8ae6"]],"5324fa6e",8],"id":1,"error":null}

{"params":["64851638000ea04d","6a2be50e9bfb43f4973d1b2a84fc5fa27a11730b000209b00000000000000000","01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3503a9d20c0004b8852666047a773e130c","0a636b706f6f6c112f736f6c6f2e636b706f6f6c2e6f72672fffffffff03c432eb1b000000001976a914c987a18977a2139835193b3df2eea097f834966888ac76dc91000000000016001451ed61d2f6aa260cc72cdf743e4e436a82c010270000000000000000266a24aa21a9ed5c2c1c347c20b2c0818daeda78f4d407f55b405e5652265bbc0b5ab948c615cb00000000",["3d14cb3882afe1cdb6121b77a1c6fe1ace1cfb4f56796875c0e5dc7475d794e5","90107e0ab73bfb0cb540cf129823a3fdd4d2df2d1cfb8a50f2ec4f10da6e4e3f","ce46e565beea4882ea532dfaecb83cc879a60c36a298ab40ec2a3c4e5ae42d65","afbead8f037a81818082f0d276e4a438a3456f0dfcce87255c349264a77ffdf1","67dcbd833c2676450e1f388da5781f902c6c4ca423a88fac6cf2a16827ebd567","7ffff8567be6efa8acd37a27b3c60bd194ca990bca74c9e71dd673d3e0c3f621","53514468979f077ace9ba497d3fa44e5091150188d29ed3dcb80a89f36662839","ff0c843842dde895d2ee8e698d35240517de66bdd839ec3f88d7c3a2b2337724","81a08847bb764ec45481a3e491640d5557fc78276091b69534af71267d1610a5","fb60c793ec790c71bb5b54e93cd8db5f134d9730754ec7c88f71862e07151d7f","bcd9c2f483e5a422e735f23610a40d07790f0ef47bea1218a4fbc1489865202c","b9a275e502fab0f76cb10e9d791a16ef18cf8addbf2ebdc92ede9a07a62dee84"],"20000000","17034219","662685b8",true],"id":null,"method":"mining.notify"}

The pool is sending prev hash as 6a2be50e9bfb43f4973d1b2a84fc5fa27a11730b000209b00000000000000000 so some parts are already reversed (but it doesn’t state anywhere, what is reversed and could be used as is).

So based on the details above, let’s head to my way of thinking about how to properly construct the header.

CONSTRUCTING (CONCATENATING)

  1. Do not reverse Version from the pool 20000000
  2. Do not reverse the prev hash (looks reversed when compared to https://en.bitcoin.it/wiki/Block_hashing_algorithm) 6a2be50e9bfb43f4973d1b2a84fc5fa27a11730b000209b00000000000000000
  3. Dhash the merkle and reverse it
  4. Do not reverse ntime from the pool 662685b8
  5. Do not reverse nbits from the pool 17034219
  6. Generate a random nonce and do not reverse it (because we’re working on Little Endian machine)

Append all as usual:
version+prev_block_hash+merkle_hash+ntime+nbits+nonce

For clarity: version+prev_block_hash+reverse(merkle_hash)+ntime+nbits+nonce

And the output i generate is:

Coinbase1           : 01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3503a9d20c0004b8852666047a773e130c
Coinbase2           : 0a636b706f6f6c112f736f6c6f2e636b706f6f6c2e6f72672fffffffff03c432eb1b000000001976a914c987a18977a2139835193b3df2eea097f834966888ac76dc91000000000016001451ed61d2f6aa260cc72cdf743e4e436a82c010270000000000000000266a24aa21a9ed5c2c1c347c20b2c0818daeda78f4d407f55b405e5652265bbc0b5ab948c615cb00000000
Extranonce1         : 5324fa6e
Extranonce2         : 000000008f6bc892
Extranonce2 size    : 8
Merkle 0            :3d14cb3882afe1cdb6121b77a1c6fe1ace1cfb4f56796875c0e5dc7475d794e5
Merkle 1            :90107e0ab73bfb0cb540cf129823a3fdd4d2df2d1cfb8a50f2ec4f10da6e4e3f
Merkle 2            :ce46e565beea4882ea532dfaecb83cc879a60c36a298ab40ec2a3c4e5ae42d65
Merkle 3            :afbead8f037a81818082f0d276e4a438a3456f0dfcce87255c349264a77ffdf1
Merkle 4            :67dcbd833c2676450e1f388da5781f902c6c4ca423a88fac6cf2a16827ebd567
Merkle 5            :7ffff8567be6efa8acd37a27b3c60bd194ca990bca74c9e71dd673d3e0c3f621
Merkle 6            :53514468979f077ace9ba497d3fa44e5091150188d29ed3dcb80a89f36662839
Merkle 7            :ff0c843842dde895d2ee8e698d35240517de66bdd839ec3f88d7c3a2b2337724
Merkle 8            :81a08847bb764ec45481a3e491640d5557fc78276091b69534af71267d1610a5
Merkle 9            :fb60c793ec790c71bb5b54e93cd8db5f134d9730754ec7c88f71862e07151d7f
Merkle 10            :bcd9c2f483e5a422e735f23610a40d07790f0ef47bea1218a4fbc1489865202c
Merkle 11            :b9a275e502fab0f76cb10e9d791a16ef18cf8addbf2ebdc92ede9a07a62dee84
Version             : 536870912 / 20000000
Merklehash          : bc65e13b5f7c69e9ce91adbb063d46b9be2445805e6a2498e13863708d57392c
ntime               : 662685b8 / 662685b8
nbits               : 17034219 / 17034219
Nonce               : 00
Block prevhash      : 6a2be50e9bfb43f4973d1b2a84fc5fa27a11730b000209b00000000000000000
Block Header        : 000000206a2be50e9bfb43f4973d1b2a84fc5fa27a11730b000209b000000000000000002c39578d706338e198246a5e804524beb9463d06bbad91cee9697c5f3be165bcb88526661942031700000000
Block hash(reversed): 03752b55669564dccb91e47cb1d5fe421fac014e1e9fb2d563d1bd8fe44c86f2
Target(reversed)    : 0000000000000000000000000000000000000000194203000000000000000000

Then we need to double hash merkle and block header with SHA256, and as far as i know SHA256 is always represented BE, so we have to reverse the hash after completing the double hash.

HASHING

  1. Calculate merkle, double hash it and reverse (because we are doing SHA256)

  2. After DHashing the header, reverse it (because we are doing SHA256)

COMPARE
But that is a different story.

Thanks in advance, any help here is appreciated since i’ve seen many implementations of different miners, and seriously majority of them do things differently – even if working with the same pool.



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *