I'm trying to calculate the hash of transactions in bitcoin blocks, but I'm not getting the right answers.

For example, the genesis block has a single transaction.

Here's how I'm attempting to calculate its hash...

Transactions are encoded as:

  • a 32 bit 'nVersion'
  • a list of input transactions, vin
  • a list of output transactions, vout
  • a 32 bit 'nLockTime'

For the transaction in the genesis block, these are:

  • nVersion: 01000000
  • inputs
    • count: 01
    • 1st input:
      • prevout_hash: 0000000000000000000000000000000000000000000000000000000000000000
      • prevout_n: ffffffff
      • scriptSig: 4d:04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73
      • sequence: ffffffff
  • outputs
    • count: 01
    • 1st output:
      • value: 00f2052a01000000 (hex(50*10^8) is 0000012a05f200, and bitcoin puts the bytes in reverse order)
      • scriptPubKey: 43:4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac
  • nLockTime: 00000000

If I string all those together end to end, I get 204 bytes: 01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000

Taking the sha256 hash of this gives 27362e66e032c731c1c8519f43063fe0e5d070db1c0c3552bb04afa18a31c6bf.

Taking the sha256 hash of that hash gives 3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a.

But the real transaction hash according to blockexplorer.com is 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b.

What am I doing wrong? How can I get to the correct transaction hash?

Here's my working in Python:

>>> import Crypto.Hash.SHA256 as hash, binascii
>>> tx = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'
>>> len(binascii.unhexlify(tx))
>>> hash.new(binascii.unhexlify(tx)).digest().encode('hex_codec')
>>> hash.new(hash.new(binascii.unhexlify(tx)).digest()).digest().encode('hex_codec')

Taking the sha256 hash of that hash gives

3b a3 ed fd 7a 7b ..............

But the real transaction hash according to blockexplorer.com is

.............. 7b 7a fd ed a3 3b

The answer I was getting was correct, but bytewise reversed. I need to get used to Bitcoin using little-endian storage.

  • 1
    I found the answer to my own question shortly after asking it. Should I delete the question and the answer or leave them both? – Chris Moore Feb 6 '12 at 6:31
  • 4
    It's a valid question, it's a correct answer and you did the work to find it. I'd give it a few days to make sure someone doesn't post a more complete (or awesome) answer and then just accept your own answer. Ideally it's not the way StackExchange works, but it's perfectly valid to self-answer - trust me you're not a trend-setter on this one ;) – David Perry Feb 6 '12 at 8:27
  • 1
    Actually, it is encouraged to post and share your own answer, when applicable. stackoverflow.com/help/self-answer – random65537 Mar 8 '14 at 22:25
  • 1
    You just saved me so many hours of research . i was facing exactly the same issue. cheers – blockwala May 23 '18 at 18:15

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.