A basic implementation of the Proof of Work (PoW) algorithm used as Sybil prevention by Bitcoin and other PoW networks. A deeper comparison between PoW and Proof of Stake (PoS) can be found in our article PoW vs PoS: The Next Industrial Revolution.
Method & Python Script
Install VS Code: https://code.visualstudio.com or similar application.
In VS Code open a new terminal window by navigating to Terminal > New Terminal.
Install Homebrew by pasting the following code into the terminal and pressing Enter:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Install Python in the same way:
brew install pythonThere are no dependencies to install. The script uses only hashlib and datetime, both of which are part of the Python standard library and are already available once Python is installed. Do not try to
pip installthem: the packages published on PyPI under those names are an obsolete Python 2 backport ofhashliband an unrelated Zope date type, so the command will either fail to build or shadow the standard library.Now, create a project folder and navigate to it in VS Code via File > Open Folder.
Create a new Python file in VS Code via File > New File. Name it something like pow.py
This script calculates the hash for the text “hello” with five leading zeros. Copy and paste it into pow.py and save it.
# v.0.1
from hashlib import sha256
from datetime import datetime
def pow(data, zeros, nonce):
data = str(data).encode("utf-8")
zeros = zeros * "0"
t1 = datetime.now()
while True:
combo = data + f"{nonce}".encode("utf-8")
hash_ = sha256(combo).hexdigest()
if hash_.startswith(zeros):
t2 = datetime.now()
return nonce, hash_, t2-t1
else:
nonce += 1
output = pow("hello", 5, 0) # 5 = ~ 1 second
print(output)Run the script from the terminal with:
python3 pow.pyHow long it takes
Each additional leading zero multiplies the expected work by sixteen. A hexadecimal digit carries four bits, so a hash with z leading zeros turns up once in 16z attempts on average – about 1.05 million at five zeros, 16.8 million at six, 268 million at seven. This loop sustains roughly 1.8 million hashes per second on a single core of a 2026 laptop under CPython 3.13, which puts five zeros at about 0.6 seconds, six at about ten seconds and seven at two and a half minutes. Slower hardware, an older interpreter or a longer input shift those numbers but not the factor of sixteen between them.
Individual runs scatter much further than the averages suggest, because the search is memoryless: every nonce is an independent trial with probability 16−z of succeeding, so the number of attempts is geometrically distributed and its standard deviation is essentially equal to its mean. Two runs of the script above make the point – five zeros finished at nonce 156,056, a seventh of the expected work, while six zeros needed 33,290,382, about twice it. A single fast or slow run says nothing about the difficulty.
That spread is why proof of work is a rate limiter rather than a clock, and why Bitcoin only averages it out at network scale: the protocol recalculates the target every 2,016 blocks from the time those blocks actually took, against an ideal of 1,209,600 seconds – two weeks, or ten minutes a block – so the difficulty tracks whatever hash rate the network is currently pointing at it. The same arithmetic sits behind the energy comparison in PoW vs PoS: raising the zero count costs nothing to verify and everything to produce.
