Mining the Genesis Block
What you'll learn
We'll write a short Python3 script to re-mine Bitcoin's first block, the Genesis Block. In doing so, you'll learn about the six fields that make up a Bitcoin block header.
The Block Header
In the previous tutorial, you got a look at the Genesis Block. Now let's learn more about the first part of that block, the block header.
Each Bitcoin block header is exactly 80 bytes long and is composed of the following fields.
|4||version||Which set of block validation rules to follow.|
|32||Previous block header hash||The previous block’s header|
|32||Merkle root hash||A hash derived from hashes of all transactions included in this block|
|4||Time||The approximate time the block was created.|
|4||nBits||The target threshold this block’s header hash must be less than or equal to.|
|4||Nonce||An arbitrary number miners change during mining|
Let's start our script by importing some modules and defining the header
fields. Use the
nano text editor to open a file named
Paste in the following code:
## Objective: mine the Bitcoin genesis block from struct import pack from hashlib import sha256 from codecs import decode from binascii import hexlify
Bitcoin uses the SHA256-double (sha256d) hash function. It also does some weird byte reversals, so let's add a couple of helper functions:
## Bitcoin uses the SHA256d hash function, which is the SHA256 function ## run twice (double). def sha256d(data): return sha256(sha256(data).digest()).digest() ## We want to display our results as hex in RPC Byte Order, so ## we need to reverse the byte order def internal2rpc(hash): return hexlify(hash[::-1])
The first field in the block header is the version field, which indicates what block validation rules should be followed for this block. Blocks started with version 1 (0x01000000) and are currently on version 3. Since we're mining the Genesis Block, we'll add the same version 1 it used to our code:
## The version number 1 as a little-endian (<) unsigned-long (L) version = pack("<L", 0x01)
The Previous Block Hash
The block header always contains a hash pointer to the hash of the previous block header linking the new block to all previous blocks in the chain. In the unique case of the Genesis Block, there was no previous block, so Nakamoto filled this field with zero bits.
## The previous block header hash is 32-bit zero previous_header_hash = decode("0000000000000000000000000000000000000000000000000000000000000000", 'hex')
The merkle root
Bitcoin block headers include a merkle root, which is the final hash in a merkle tree that connects all of the transactions in a block to the block header using a cryptographic hash that can prove that none of the transactions have been modified.
The merkle tree is created by looking at all of the transactions in the block in the order they appear. The rules for creating a Bitcoin merkle root are mildly complex for most blocks, but for the genesis block they're easy—the merkle root is the same as the hash of the first (and only) transaction in the Genesis Block. Let's add that hash to our script:
## Merkle root (in this case, also a txid). We have to reverse it ## into Internal Byte Order merkle_root = decode("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", 'hex')[::-1]
Bitcoin block headers use Unix epoch time, often simply called Unix time or epoch time. This is the number of seconds elapsed since midnight 1 January 1970 UTC. As you might suspect, it’s easy to get that time on a Unix-like system:
## Get the current Unix time date +%s
You can also get the Unix time for an arbitrary date, such as the date Nakamoto used when mining the Genesis Block:
## Get the corresponding Unix time for the provided date date +%s -d '3 Jan 2009 18:15:05 UTC'
Let's add that time to our mining script:
## Date in Unix time format date = pack("<L", 1231006505)
nBits: encoding the target
In the Hashcash tutorial, you learned that Hashcash allowed you to increase your Proof Of Work (POW) security by increasing the number of leading zero bits, but that for each additional bit, you had to do twice as much work. Bitcoin also has a way of increasing the amount of POW security when miners are producing blocks too fast, but more fine-grained control was needed than simply waiting until miners were producing blocks twice as fast. So Nakamoto created the target number.
Bitcoin block header hashes are interpreted as numbers that must be less than the target value, which provides more granularity than whole bits do. To help keep track of the current target, a field in the block header stores the current 256-bit target compressed into just 32 bits (reducing granularity somewhat). To do this, the base-256 form of scientific notation is used.
The lowest allowed target in Bitcoin is called difficulty 1. In nBits, it’s 1d00ffff. The Genesis Block was officially mined at that difficulty, although the amount of proof of work in the Genesis Block is much higher than a typical difficulty-1 block.
Let's add the difficulty to our block:
## nBits is stored as a little-endian (>) unsigned-long (L) nbits = pack("<L", 0x1d00ffff)
Let's also add some code to convert nBits into the target threshold so that we can determine when we've found a difficulty-1 block later:
## Convert current nbits into a big-endian string nbits_calc = hexlify(nbits[::-1]) ## The nbits calculation is base-256 base = 256 ## The nbits exponent is the the first byte of the nBits exponent = int(nbits_calc[0:2], 16) - 3 ## The nbits significand is the other three bytes significand = int(nbits_calc[2:8], 16) ## Do the nbits calculation target = significand * ( base ** exponent )
When trying to create successful Proof Of Work (POW) for blocks, miners need to create many different hash results with minimal changes to the hashed data. Nakamoto gave them an easy way to do that by including a Number used Once (nonce) field in the block header. Mining software can change just the number in that field without affecting the other fields.
Typically miners start with a nonce of zero and iterate up to its maximum value, 0xffffffff. If none of those values work and it took them more than a second to search all possible nonces, they can simply update the time field to the new current time. If they were able to search all the fields in less than a second, they can change one of the transactions in the block to get a different merkle root. After either change, they can start searching nonces again.
In our case, we don't want to spend all day searching nonces, so we're going to enter a pre-computed nonce that is very close to the nonce we need to generate the Genesis Block header hash. Add this to your mining script:
nonce = 0x7c2bac10
Mining the Genesis Block on a CPU
Now you have all the pieces in place, let's use a simple loop to check header hashes until we find a block header hash with a sufficient amount of proof of work. Add the following code to the end of your script:
while nonce < 0x7c2bac1e: header = ( version + previous_header_hash + merkle_root + date + nbits + pack("<L", nonce) ) ## Get the header hash corresponding to the header header_hash = sha256d(header) ## If the header hash is less than the target, print the results and ## break the loop if int(hexlify(header_hash[::-1]), 16) < target: print("Nonce Header Hash") print(nonce, internal2rpc(header_hash)) break ## Increment the nonce nonce += 1
Save and exit the file using the instructions that
nano prints on
the bottom of the screen. The ^ character means press-and-hold the
Ctrl key. Then run your code like this:
In case you copied and pasted anything wrong, you can also download a copy of miner.py like this, and then run it the same as above:
When the script finishes running after a second or two, it should print the header hash of the Genesis Block. Notice the leading zeroes demonstrating proof of work. Congratulations, you mined the Genesis Block using a CPU just like Satoshi Nakamoto did (although he had to run his code much longer because he didn't know what nonce to start with).