4

please note I have made this question previously (link) and I was indicated to visit here.

I am writing a program using GoLang to mine bitcoins. It's part of my college conclusion project and likely won't be used to mine bitcoins since it's not gonna be efficient enough running on regular PC's (facing a race against those huge chinese mining pools). Though it's not originally intended for real usage, my college expects nothing less than a flawless piece of software to mine real bitcoins (in parallel).

So far, I have implemented quite an extensive code, therefore, you guys may assume I already have means to achieve:

  1. Get pending transactions to fill my block (from https://blockchain.info)
  2. Build the merkle tree over the transactions data retrieved
  3. Calculate a sha256 of a given data input (I also understand the concepts behind such hash functions)

I have organized my questions regarding this subject below:

Question 1) I can't precisely tell how to build a block header which would be appended to the block chain. I know it has fields like the root of our merkle tree (which I already know how to calculate) or a version field, but if I was to produce a block header as an array of bytes, how would I do it ? I'd like to see how to calculate each field we need to build the header and how our byte array (representing the header) would look like.

Any dummy data may be used for this example, my focus stays on understanding the process and the data structure.

Please, note I have already read this: https://bitcoin.org/en/developer-reference#block-headers

I have studied quite a lot regarding how the bitcoin protocol works to achieve the code I currently have, but I feel extremely limited on the information I can find online regarding the internal details of the bitcoin protocol:

Question 2) Is there any online technical information you guys would consider useful for me to read regarding the headers subject and/or anything else in bitcoin? Keep in mid that I still have quite some code to write, therefore, I'm taking all the information I can get : )

1 Answer 1

7

As an example of how to build a block header, here's a short Python program that calculates this block header's hash:

#!/usr/bin/env python3
import urllib.request 
import json
import binascii
import struct
import hashlib
ux = binascii.unhexlify
hx = lambda bin: binascii.hexlify(bin).decode('ascii')

# Load testing data in json format from blockchain.info
url = "https://blockchain.info/block-index/1114939/000000000000000003e6d3647001d1f455d585cdd3c298093902fe52ea4529ba?format=json"
block = json.loads(urllib.request.urlopen(url).read().decode('ascii'))
print("Original block hash: " + block["hash"])

version = block["ver"]
# 4 bytes, little endian
version = struct.pack("<I", version)

print("Version: " + hx(version))

prev_block = block["prev_block"]
# Reverse hash to go from display format to internal format
prev_block = ux(prev_block)[::-1]

print("prev_block: " + hx(prev_block))

merkle_root = block["mrkl_root"]
# Reverse hash to go from display format to internal format
merkle_root = ux(merkle_root)[::-1]

print("Merkle root: " + hx(merkle_root))

timestamp = block["time"]
# 4 bytes, little endian
timestamp = struct.pack("<I", timestamp)

print("Timestamp: " + hx(timestamp))

target = block["bits"]
# 4 bytes, little endian
target = struct.pack("<I", target)

print("Encoded target: ", hx(target))

nonce = block["nonce"]
# 4 bytes, little endian
nonce = struct.pack("<I", nonce)

print("Nonce: ", hx(nonce))

combined = version + prev_block + merkle_root + timestamp + target + nonce

print("Block header: " + hx(combined))

sha256 = lambda x: hashlib.sha256(x).digest()
sha256d = lambda x: sha256(sha256(x))
computed_hash = sha256d(combined)

# Reverse hash to go from internal format to display format
computed_hash = computed_hash[::-1]

print("computed_hash: " + hx(computed_hash))

Here's the output.

Original block hash: 000000000000000003e6d3647001d1f455d585cdd3c298093902fe52ea4529ba
Version: 01000030
prev_block: cd0594ebccfe15b205125165cc3b66986ed5b2a311cd88050000000000000000
Merkle root: 37022f7a3b9a2b199d53fbf1552be32c141892319966c3ef999d348d74cfb582
Timestamp: 7f476357
Encoded target:  a09b0518
Nonce:  ae5ae1c1
Block header: 01000030cd0594ebccfe15b205125165cc3b66986ed5b2a311cd8805000000000000000037022f7a3b9a2b199d53fbf1552be32c141892319966c3ef999d348d74cfb5827f476357a09b0518ae5ae1c1
computed_hash: 000000000000000003e6d3647001d1f455d585cdd3c298093902fe52ea4529ba
1
  • I hereby show my deepest appreciation Mr. ODell. You were extremely helpful and your code works nice and smooth. Due to your example now I'm able to understand how these underlying bytes are organized to build the header.
    – G Oliveira
    Jun 22, 2016 at 13:15

Your Answer

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

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