Author

Topic: How can I manually verify the proof of work? (Read 833 times)

jr. member
Activity: 52
Merit: 53
October 05, 2016, 02:15:35 PM
#6

You should get:
Code:
SHA256(blockheader.step1)= d972e55cdcfef7665dc28c7b6942d04f1065723efcb87d040000000000000000

Since Bitcoin uses little endian byte order, you'll need to reverse the order of the bytes in that:
Code:
Split up the bytes:
d9 72 e5 5c dc fe f7 66 5d c2 8c 7b 69 42 d0 4f 10 65 72 3e fc b8 7d 04 00 00 00 00 00 00 00 00

Reverse the order of the bytes:
00 00 00 00 00 00 00 00 04 7d b8 fc 3e 72 65 10 4f d0 42 69 7b 8c c2 5d 66 f7 fe dc 5c e5 72 d9

There you go.  All done.


Thank you!

I actually found a very easy way to do it with the help of an online tool...

With the help of https://anyhash.com/sha256 I was able to produce the following:

First 80 bytes from block #432564:
000000208a20ce009629c8212d074a4f3e009401136e5e15eb0775030000000000000000661125a 47e385fcf4ba1aea7cfd7f90a3e73ce3ee662a6d5e8fc58c9d1150ea2625ff157d48e04189f0ff7 d6

Can directly be turned in to the first hash:
be7df6a863420c1ba92315fbc04b6bb30eda27479c64ce918c10b30aa2def684

And the first hash can directly be turned into the second hash:
d972e55cdcfef7665dc28c7b6942d04f1065723efcb87d040000000000000000

Split up the bytes:
d9 72 e5 5c dc fe f7 66 5d c2 8c 7b 69 42 d0 4f 10 65 72 3e fc b8 7d 04 00 00 00 00 00 00 00 00

Reverse the order of the bytes:
00 00 00 00 00 00 00 00 04 7d b8 fc 3e 72 65 10 4f d0 42 69 7b 8c c2 5d 66 f7 fe dc 5c e5 72 d9

Remove spaces:
0000000000000000047db8fc3e7265104fd042697b8cc25d66f7fedc5ce572d9
legendary
Activity: 3472
Merit: 4801
First of all, you have to hash it as byte data. You have hashed it as string. Secondly, the hash is actually SHA256 Double, so you need to hash it, then take that hash and hash it again, both times as byte data. The result should be the block hash in reverse byte order (it's one of the endians, I can't remember which).

As an example of how to do this if you are at a command line interface on a Apple or Linux computer:

First create a txt file that has the block data in format that you would get if you ran xxd on a file containing the 80 bytes:
Code:
0000000: 0000 0020 8a20 ce00 9629 c821 2d07 4a4f  ................
0000010: 3e00 9401 136e 5e15 eb07 7503 0000 0000  ................
0000020: 0000 0000 6611 25a4 7e38 5fcf 4ba1 aea7  ................
0000030: cfd7 f90a 3e73 ce3e e662 a6d5 e8fc 58c9  ................
0000040: d115 0ea2 625f f157 d48e 0418 9f0f f7d6  ................

In my case, I saved this in a file named "blockheader.txt".

Then use the "reverse" functionality of xxd to convert this ascii txt file into 80 bytes ( a 640 bit binary value ).  Using the command below, I saved the binary value in a file named "blockheader.binary"

Code:
xxd -r blockhaeder.txt > blockheader.binary

Now, you can hash this 80 byte file:

Code:
openssl dgst -sha256 blockheader.binary

You should get:
Code:
SHA256(blockheader.binary)= be7df6a863420c1ba92315fbc04b6bb30eda27479c64ce918c10b30aa2def684

However, we don't want a 160 character ascii representation of the hash, we want the actual 256 bit binary value.  "openssl dgst" has a -binary option to output the binary value.  We'll capture this in a file that we'll call "blockheader.step1":

Code:
openssl dgst -sha256 -binary blockheader.binary > blockheader.step1

Now you can calculate the hash of blockheader.step1 to get the final blockhash value that Bitcoin uses:

Code:
openssl dgst -sha256 blockheader.step1

You should get:
Code:
SHA256(blockheader.step1)= d972e55cdcfef7665dc28c7b6942d04f1065723efcb87d040000000000000000

Since Bitcoin uses little endian byte order, you'll need to reverse the order of the bytes in that:
Code:
Split up the bytes:
d9 72 e5 5c dc fe f7 66 5d c2 8c 7b 69 42 d0 4f 10 65 72 3e fc b8 7d 04 00 00 00 00 00 00 00 00

Reverse the order of the bytes:
00 00 00 00 00 00 00 00 04 7d b8 fc 3e 72 65 10 4f d0 42 69 7b 8c c2 5d 66 f7 fe dc 5c e5 72 d9

There you go.  All done.
staff
Activity: 3458
Merit: 6793
Just writing some code
When calculating SHA256 on the first 80 bytes I get:
a2cca229c9e96b9b71b1507e8f71631da7840c750a94c3c199a0ce371f51caa0

But the “proof of work hash” that I want to generate is:
0000000000000000047db8fc3e7265104fd042697b8cc25d66f7fedc5ce572d9

What am I doing wrong?
First of all, you have to hash it as byte data. You have hashed it as string. Secondly, the hash is actually SHA256 Double, so you need to hash it, then take that hash and hash it again, both times as byte data. The result should be the block hash in reverse byte order (it's one of the endians, I can't remember which).
jr. member
Activity: 52
Merit: 53

The block header is the first 80 bytes of the block. You can get it by getting the hexdump of a block. In Bitcoin Core, you run
Code:
getblock false
where is the block hash. This will get you the hex of the block. Just take the first 80 bytes and you will have the block header.


Thank you for responding to my post!

I have been doing tests on block #432564, but so far I have not been successful..

I run the following in Bitcoin Core:

getblock 0000000000000000047db8fc3e7265104fd042697b8cc25d66f7fedc5ce572d9 false

I get the hex dump and the first 80 bytes is:

000000208a20ce009629c8212d074a4f3e009401136e5e15eb0775030000000000000000661125a 47e385fcf4ba1aea7cfd7f90a3e73ce3ee662a6d5e8fc58c9d1150ea2625ff157d48e04189f0ff7 d6

If I understand correctly this can be broken down to:

00000020  =  Block version

8a20ce009629c8212d074a4f3e009401136e5e15eb0775030000000000000000 = Hash of previous block's header

661125a47e385fcf4ba1aea7cfd7f90a3e73ce3ee662a6d5e8fc58c9d1150ea2 = Merkle root

625ff157 = Time

d48e0418 = Target

9f0ff7d6 = Nonce

When calculating SHA256 on the first 80 bytes I get:
a2cca229c9e96b9b71b1507e8f71631da7840c750a94c3c199a0ce371f51caa0

But the “proof of work hash” that I want to generate is:
0000000000000000047db8fc3e7265104fd042697b8cc25d66f7fedc5ce572d9

What am I doing wrong?
staff
Activity: 3458
Merit: 6793
Just writing some code
It is a common misconception that the hash has to start with a number of zeroes. It actually doesn't. The hash has to be a number less than the target, and it just so happens that hash will have a lot of zeroes, but the zeroes aren't actually counted or anything like that.

The block header is the first 80 bytes of the block. You can get it by getting the hexdump of a block. In Bitcoin Core, you run
Code:
getblock false
where is the block hash. This will get you the hex of the block. Just take the first 80 bytes and you will have the block header.

There is a field in the header called nBits. This is a compact form of the target. Follow the instructions at https://bitcoin.org/en/developer-reference#target-nbits to convert that into the target. Then just check that the block hash is less than that target. If it is, then that hash satisfies the proof of work.
jr. member
Activity: 52
Merit: 53
How can I manually verify the proof of work?

My understanding is that the proof of work is a SHA256 hash of the block header.

This hash needs to start with a number of zeros to prove that a lot of work have been performed.

As an example the hash belonging to block #432548 is
00000000000000000205d1c504bc67918fcb7a61af857607c1a6ceb95a0a069a

But how can I manually check that this is correct?

I want to be able to copy-paste the header of a block into my SHA256 calculator and to see that the resulting hash matches the "proof of work hash"

But how can I find the block header in the correct format?
Jump to: