---
title: "Proof of Work"
url: "https://radix.wiki/contents/resources/python-scripts/proof-of-work"
updated: 2026-08-18
last_verified: 2026-08-28
license: CC-BY-4.0
license_url: "https://creativecommons.org/licenses/by/4.0/"
version: "1.3.2"
---

# Proof of Work

| Proof of Work |  |
| --- | --- |
| Type | Python script · worked example |
| Demonstrates | SHA-256 hash mining as Sybil prevention |
| Language | Python 3 |
| Dependencies | None – [hashlib](https://docs.python.org/3/library/hashlib.html) and [datetime](https://docs.python.org/3/library/datetime.html) ship with Python |
| Difficulty | Tunable via leading-zero count (5 ≈ 1 second) |
| Related | [PoW vs PoS](/blog/pow-vs-pos-the-next-industrial-revolution) · [Delegated Proof of Stake](/contents/tech/core-concepts/delegated-proof-of-stake-dpos) · [DLT Efficiency Metric](/contents/resources/python-scripts/dlt-efficiency-metric) |

A basic implementation of the Proof of Work (PoW) algorithm used as Sybil prevention by [Bitcoin](https://bitcoin.org) 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**](/blog/pow-vs-pos-the-next-industrial-revolution).

## **Method & Python Script**

1. Install VS Code: [**https://code.visualstudio.com**](https://code.visualstudio.com) or similar application.
2. In VS Code open a new terminal window by navigating to Terminal > New Terminal.
3. Install [**Homebrew**](https://brew.sh/) 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)"`
4. Install Python in the same way:`brew install python`
5. There are no dependencies to install. The script uses only [**hashlib**](https://docs.python.org/3/library/hashlib.html) and [**datetime**](https://docs.python.org/3/library/datetime.html), both of which are part of the Python standard library and are already available once Python is installed. Do not try to `pip install` them: the packages published on PyPI under those names are an obsolete Python 2 backport of `hashlib` and an unrelated [Zope date type](https://pypi.org/project/DateTime/), so the command will either fail to build or shadow the standard library.
6. Now, create a project folder and navigate to it in VS Code via File > Open Folder.
7. Create a new Python file in VS Code via File > New File. Name it something like pow.py
8. 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)
```

1. Run the script from the terminal with:

```
python3 pow.py
```

## **How 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 16_z_ 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](https://bitcoin.org) only averages it out at network scale: the protocol [recalculates the target every 2,016 blocks](https://developer.bitcoin.org/devguide/block_chain.html) 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](/blog/pow-vs-pos-the-next-industrial-revolution): raising the zero count costs nothing to verify and everything to produce.
