2

I need some help trying to verify that my implementation is correct or not. I'm trying to make a Stratum mining client.

All byte orders are as is directly received from the server, without endian swapping

Here's the data:

{"result": [[["mining.notify", "108fa002000000001"], ["mining.set_difficulty", "108fa002000000002"]], "108fa00200000000", 4], "id": 1, "error": null}
{"params": ["1369818357 489", "56d14795eadabe52464b0c6410f8c1f70c0af2c5444379160000002400000000", "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff51039aa3030d00456c69676975730051a5c4f5fabe6d6d28db22e01b9dceb2e0dc8d7cc01bfc4dcdbce7f7a49c57020c827389efdcea970200000000000000002f7373302f00", "ffffffff3ed2f0af0c000000001976a914ad9261f01eae43c949ecaaa375759f9fcbcb3dc288acda8bae0c000000001976a914df4ad46ed8ac51d73e17f8bd7a203f07e932294e88ac0914f809000000001976a91479257603444e9e8b6796d17646ecae881376128388ac2d535509000000001976a914a804274391cb1a6f157a500cf8df2b4141bae42588ac88a61107000000001976a914c8459142759347c481684590dabf11d9f91e143f88acd1c76e06000000001976a914da9d41c79ca85ce0c68057b8adfb753424e7f07a88ac5f874c06000000001976a914bc98f0de5c77080eae5142e11a884e6e0b793d3888acb36b4c06000000001976a914b5945df721fd42b339737c07c24ab36ee3e7c1ac88ac44963606000000001976a91499b4fb6f4d29cfd2ccd200ce9df24c61e2491da188acfb86b605000000001976a914195344563ecbfc06eb183d330437fddd53b2635288acd7659902000000001976a914bf7d251592efa8397598e08960b22c434464d23288acc8418f02000000001976a9145dfae39b14a09e9493fc6f95019fc1d8d1c9258088ac023c3d02000000001976a91453d0290a46f94887b3f5a552e7ffcce5f1202d9b88ac76bf2d02000000001976a9141623fbaf4d6b6ba8af9183c41760adadaef34bab88ac04b4f501000000001976a91435244a9cdc90997ff5536bdfbf909b2b6165d67a88ac24fad101000000001976a914fc169f6235cbfd5a1f9f7f080b60e3599f1d677388ac9d94cb01000000001976a914647dffe1e73cdffe0c763fb677f938dcd2d616a988ac3a0a9f01000000001976a914b3056b29332c33e84c97ab2f61dd648cc6c8f75588ac01649301000000001976a914a2df6ff0702ac2889cfff340df476af8adbcc8b688acb4838501000000001976a914f5aab50a274a24857d8745f2e3aeee18c28b513288accd188501000000001976a914c17e44923f07ddd95b030cee63e94bea7a28550288ac48f88301000000001976a9141fc352bd6c1db3f461bc41af113701f6e28256ea88aceed28101000000001976a914a72cab69d8a1748729a2798834dc3408c0e0f5a288ac29ff4a01000000001976a914eb2715703c77f1b334e8c68010682a58aa011be188ac48234201000000001976a914cce45595065ed827562e901ce831d6274222753288ac58254001000000001976a9147d702b3c6d922699b9d2509d9db40c2915aa54e488ac711f3b01000000001976a9149465fdac29b5c47b99c8d17379d0fc6d99c1e4a688ac46313a01000000001976a91455d28f71541dcb0a5848f3a15218da960182512b88ac80be3701000000001976a9147f960729bfd6684569d58e13674d877552069d8288ac4fed3401000000001976a914720b13f90cfb675568b99ae88bdc41e0b9612f4c88ac59643401000000001976a914a07d0ff15ad9d770a8f4ce336ccfd038436a51e588ac61532f01000000001976a914768acf953a1d3b1eddbe225291290d55d067a18e88ac9adf2d01000000001976a91404ba740ae19208ecc3f6505dc8dbcf0b692a6c6e88ac82a62c01000000001976a914da39d920f0f15c9d99978992517efcc3429dd62088ac066e2701000000001976a9149193af5c84dea0a2fc0b7e52087c7c96bfbcf44088acaade2501000000001976a914247bf801ffd4afb506e71b027eb2ed647fdc69d488ac458e2401000000001976a914952dea3415effa2c0b8544fb7fc0a602a92fe84288ac10662401000000001976a9143d192a354cee6d1ddbddb7df03ad4229d3095bb788ac07e92201000000001976a9144ae00300aaad08ee3a219fe772ec1f3a73a8c94788ac413b2101000000001976a914540d04e4f2a7281a2a2b60e90ebd5c46074dc00e88acb56c2001000000001976a914172205d324c0d902ab9e4330e7fbdef128b71b7f88ac22361f01000000001976a9145c90a505a74f6c3c10d71c9b089b9cd0b919bdb988acc9d11d01000000001976a9148fdf745b2aca7f918bf2a4f54526653e3466e54388ac404a1b01000000001976a914e54f005cdc5405459f22a0588bae51940deaad1988ac8b3f1b01000000001976a914d39d22a99da41e94b3a866822a3e482b09e3d73088ac21ec1a01000000001976a9145f5473211ff432a7a65df04d5ea1f05d183368c288aca6521a01000000001976a9146b1af4b5e35b061381cb75505edec009caa8566f88aca7111901000000001976a9145ab1860a6059e4ec5e82a733132ef678fdd4abcf88ac383f1701000000001976a91447e803b8dc72e6a3bdad26f0e623e66f5c46c77e88ac84221701000000001976a914bb5db3069f74f1a7775e238c7361ee1ca37279ea88ac18951601000000001976a9141fed5b3bffd76ecc742257286befccf4a561ac6788ac0a7d1601000000001976a914b6aae63d35235aa5742db64bf41983feb55c1fd188ac09e91501000000001976a9148ace0f9a55cfb3f119bb8b40344eaadd2f83932d88ac24fd1301000000001976a91498bc3bd4ef9f301985a73042a41e307bbc21b2b388ac04e21301000000001976a9142ac79cc463b3bf2a67c28a0a71d54cb7def691ca88ac31581301000000001976a9146790d62962472fbdd81bc7552a23a4fb0a07c17088accac61201000000001976a914235e7b503fd47e908b4ea7d11237003e18e4833e88acff761201000000001976a914915c5363289cef9e4b05eaf13608d955717bf5fb88ac7b681201000000001976a914db2f9af40204e79f9c2316c043df0abc2121879388acaaed1101000000001976a914d2744af774b66c595b753af38c88b8948a99827188ac56780b00000000001976a91467123b0c6577d7932ddb7045567eed2c488773c488ac01000000000000001976a9145399c3093d31e4b0af4be1215d59b857b861ad5d88ac00000000", ["d8481cf9050990f425c82fd0f4b0d1dcd3166435cd56eb8f00c76244704812d8", "815bb21cfd4bf9d26b8b85937390bfb6c39f84a81f8580ba0028c935543cfeec", "1450b5fe41462f25ca2b8f1f8df1fc08732532ec5b72039f5ad1ad1bd0a3546c", "af94c2da313d385e2c0c8812c70f8e86809e90f95e79f25e6cdf6c98eac1232a", "53276d253bee618e675e32b0367e3a786e717bc7e766b165caa8d5de84ef1bf8", "b0e99cef9b6a55684b8a399a54842a5123163c2fe324a9c563f4d5314ff50684", "1b559b9b59306deb2d23716fecd213852efe519cbf297c9b10178be71c1013e9"], "00000002", "1a016164", "51a5c4f5", false], "id": null, "method": "mining.notify"}
{"params": ["redacted", "1369818357 489", "12000000", "51a5c4f5", "41f20233"], "id": 2, "method": "mining.submit"}

I've obtained this from running bfgminer and dumped the share logs and tcpdumped the connection to the pool.

bfgminer has logged the block header as (with padding):

0000000256d14795eadabe52464b0c6410f8c1f70c0af2c5444379160000002400000000751b1aba
ddefb3e3e74c3ac8bbe49787a5ae21703b873e0958a9441a0871d2dc51a5c4f51a01616441f20233
00000080000000000000000000000000000000000000000000000000000000000000000000000000
0000000080020000

Hashing the data as it appears in the usual fashion, ie., sha256(sha256(data)), doesn't yield the hash that it says it obtained, which is d8b5ed97e69707dc17cae1c23e672818a18b75fd362bb698fad4433b00000000.

I thought I could calculate the merkle root by the usual fashion, with the nonces obtained from the above subscription and the submission message:

>>> coinbase = coinbase1 + extranonce1 + extranonce2 + coinbase2
>>> coinbase_bin = binascii.unhexlify(coinbase)
>>> root = coinbase_bin
>>> for h in merkle_branch:
...   root = hashlib.sha256(hashlib.sha256(root + binascii.unhexlify(h)).digest()).digest()
>>> binascii.hexlify(root)
'eed07afc76bc7b15dc5871581a2460c7473ed68573082a0e5864140db0d11803'

which is wrong too.

Can someone tell me what's going on here? What do I need to swap and what do I need to keep as-is? Or can someone give me a subscription message, a work notification, and a submission message, and show me how to perform all the validation steps?

1

The block output you're seeing from bfgminer ("0000000256d14795...") is the wrong thing to be hashing; it looks like it isn't swabbing the fields when it logs. The first four bytes of a block are a little endian format version number, and I do not think block format version 33554432 will be released for some time.

Compare the example given on bitcoin.it (https://en.bitcoin.it/wiki/Block_hashing_algorithm): the initial bytes are "01000000" (format version 1 as a little-endian uint32_t).

  • Thanks. Just for the record, the version field, prevhash, time, and difficulty fields require swabbing. The merkle root doesn't appear to need swabbing, and my error above is failing to hash the coinbase before calculating the root. – zeta May 30 '13 at 8:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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