Blockchain Mechanics — Proof of Work

Explaining the Mechanics of Proof of Work Mining With Python

Ciaran Mcveigh
blockchaintechnologies
7 min readApr 1, 2018

--

This article will look into the process of mining within blockchain technologies. We will look specifically at “Proof of Work” mining and will attempt to help readers understand the “Work” that the miners complete. The article will use simple examples in python to highlight the underlying mechanics of the system. A basic understanding of blockchains and block structures are assumed.

Bitcoin Mining

We’ll use bitcoin mining as our case study for this article, given it is the original cryptocurrency and a successful implementation of mining and proof of work. In this article we’ll ask ourselves what mining is? Why do we need it? And how does it work?

What is Mining?

Mining is a process on decentralised networks to maintain and validate data on the blockchain ledger. The miners collaborate to reach consensus on the state of the blockchain. They ensure the transactions on the blockchain contain the correct digital signatures, process those transactions and ensure that blocks created by other miners are also valid.

This Mining process also mints new coins with every new block and pays these coins as a block reward to the miner who mined the block. This acts as a way to steadily distribute the currency into the ecosystem while also acting as an incentive for miners.

The block reward started at 50 bitcoin and halves every 210,000 blocks or roughly every 4 years. This means the currency has a fixed supply of 21 million bitcoin which should be reached around the year 2140. Once this limit is reached there will be no block reward for mining new blocks. Currently, the block rewards stands at 12.5 bitcoin.

Miners also receive transaction fees from all the transactions included in a block. While currently these transaction fees represent a small portion of the total reward in the future transaction fees helps solve the question of what incentive is there when the block reward goes to 0.

These transaction fees and block rewards incentivise the miner to act honestly, any incorrect information in a block will be rejected by other miners and essentially takes you out of the running of being the miner who mines the next block and receives the reward.

Miner are required to solve a computation problem. The network works on the principle of 1CPu 1 vote (or 1CPu 1 Ticket as mining is essentially a lottery). This means the more CPU's you have dedicated to mining the more likely you will mine a block (win the lottery).

The winner is the miner who solves the computation problem first, once he solves the problem he sends his solution to the other miners who then validate it and begin mining the next block.

Why do we Need Miners?

Miners maintain the data on the blockchain holding complete copies of the ledger to ensure all transactions are valid. They provide the decentralisation aspect of blockchains and protection against individual bad actors as they decide on the correct version of the truth based on consensus.

Since miners receive a reward of new minted bitcoin it is in their best interest to be honest and ensure all signatures are valid and that there are no double spend transactions in their block. If I solve the computational puzzle and send my block out to other miners with invalid transactions they will reject it. In this situation, if I had been honest and only used valid transactions the miners would have accepted it and I would have received a reward of new minted bitcoin. As a result, it’s in my best individual interests that I stay honest to earn the most that I can.

How does Mining work?

The computational problem involves guessing a number referred to as a nonce. This number when hashed (in actuality it is double hashed) with the rest of the block header yields a block hash that is less than the difficulty number. As the difficulty number decreases the amount of possible correct hashes also decreases thus making it harder to find the correct hash.

Consider a random number generator. Let's say the generator gives us a number between 1 and 10 and I give you a target (difficulty) of 9. In this case if you need to match or get lower than that number you have a 90% chance of success as 1, 2, 3, 4, 5, 6, 7, 8, 9 will all satisfy our requirements. If I change the target to 3 you now have a 30% chance of success with the numbers 1, 2, 3. This reduction in potential success represents an increase in difficulty.

To understand how this hash which is hexadecimal correlates to a number have a look at this. Another albeit inaccurate way to look at this is requiring a hash to start with a number of 0’s. In this analogy the difficulty of the mining process is correlated to how many prepended 0’s the network requires.

Note the nonce is allocated 4 bytes or 32 bits of data. As a result the nonce must be an integer between 0 and 4,294,967,295.

There may be several nonces that produce the desired result, or there may be none (in which case the miners keep trying, but with a different block configuration).

The proof of work system acts as a random selector of the winning miner, with people who are more heavily invested in the technology having a greater chance of winning. This randomness is necessary to prevent certain attack vectors. The “work” part of the mining is required to ensure the miners, the people who maintain the integrity of the network are invested in the technology through buying compute resources and dedicating those resources to mining.

The code below shows how the computational problem in mining works programmatically. While the finer details of this process are missed the program gives users a better understanding and enables users to tinker with the code to explore further.

Please read the comments in the code snippet below and run it in python3. Some print statements have been left in to help show you what is happening.

The print statements show the hash of the block and the nonce used to produce that block. We can see from the output that the correct nonce was 119 yielding a hash of 0093d3f90374dbaf3b26eca3e4147d1e156d9ef1b7883650d984863fc661a736. This means it took 119 guesses to get a correct nonce.

A final print statement of the winning miner shows us who mined the block. Since the miners are randomly shuffled in the array any of the participants could win when you run the code with their odds reflected by their CPUs.

If we change the difficultly_hash from 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF to 0x000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF (ie require three 0's at the start of hash) we can see it significantly increases the amount of guesses we have to make, from 119 to 1500.

Additional Details

Below are some details regarding the block rate and the block size. The block rate determines how often a block is mined and influences the difficulty of the “proof of work”. The block size determines how many transactions can fit inside of a block and subsequently the amount of transaction fees a miner can receive.

Let's start with the block rate. Blocks are mined at a predefined rate, in bitcoins case it’s 1 block every 10 minutes. This means only 1 miner gets to mine a block roughly every 10 minutes (Some blocks are mined quicker, some are mined slower).

The difficulty is adjusted every 2016 blocks, it will look at the average block time and determine whether the difficulty needs to go up, down or remain the same. If the average block rate for the last 2016 blocks is 8 minutes the difficulty needs to increase to ensure an average time of 10 minutes is maintained. This ensures that as more compute power comes onto the network the block rate remains constant. This set rate is to provide a compromise between wasted work, limiting forks and speed of payment.

The size of a block is programmed at 1MB, limiting the number of transactions included in each block. There are a few reasons for this limit when it was originally implemented. These included the fact that at the time, the average block size was orders of magnitude smaller than 1MB. That from a coding perspective it was a simple change to the code to increase the block size at a later date. Finally, there would have been far more technical challenges for larger block sizes. For more details see this article.

CHALLENGEAs a challenge see if you can update the python code to continuously mine. Let's say we want a block time of 30 seconds and that we want to retarget the difficulty every 10 blocks.Therefore every 10 blocks we need to find the average block time and update the difficulty as necessary.Difficultly is updated using the following equationNew Target = Old Target * (Time of previous 10 Blocks / 300 seconds)Where target is the difficultly and the 300 seconds represents the 10 blocks * 30 seconds or our targeted combined block time. Also an additional rule states that each difficulty retargeting cannot be adjusted by more than a factor of 4. This is to avoid extreme volatility in the difficulty.Therefore if New Target > (Old Target * 4) or < (Old Target / 4), then New Target = (Old Target * or / 4).Solution: Coming Soon

Feel free to offer improvements and corrections, they are always welcome.

--

--