Your first payment, step by step#
We will give Alice 100 imaginary units, have her pay Bob 25, and check the result. You need basic Python, but no prior cryptography knowledge. Read Start here: a blockchain without the jargon first if blocks, keys, or signatures are unfamiliar.
Install#
With Python 3.10 or newer, in a virtual environment:
python -m venv .venv
source .venv/bin/activate # on Windows: .venv\Scripts\activate
python -m pip install blockchainkit jupyterlab
The virtual environment keeps this project’s dependencies together, and
JupyterLab runs the notebooks. To work on the package itself, clone the
repository and install it in editable mode with pip install -e ".[dev]"
instead.
Create a chain and mine the payment#
The initial allocation is a shared simulation input. This model has no coinbase rewards, issuance schedule, transaction fees, or mempool.
>>> initial = bk.structures.Ledger({alice: 100})
>>> genesis = bk.consensus.mine(bk.structures.Block(difficulty=5)).block
>>> chain = bk.structures.Blockchain(genesis, initial)
>>> candidate = bk.structures.Block(
... previous_hash=genesis.hash, transactions=(tx,), height=1,
... timestamp=1, difficulty=5,
... )
>>> mined = bk.consensus.mine(candidate).block
>>> chain.add(mined)
True
>>> chain.state.balances[alice], chain.state.balances[bob]
(75, 25)
>>> chain.state.nonces[alice]
1
The genesis block is the starting block, at height 0. Our new block is at
height 1 and points to genesis using its hash. (tx,) is Python’s notation
for a tuple containing one payment. The timestamp is a simulation number,
not real clock time. Difficulty 5 requires about 32 attempts on average;
individual searches can take fewer or more attempts.
mine searches for a suitable block hash. chain.add checks the block
and payments before accepting them. The result is Alice with 75 and Bob with
25. Alice’s next payment number is 1, so replaying this payment with number 0
will be rejected.
Verify inclusion independently#
A Merkle proof answers “is this exact payment in this block?” The index 0
means the first payment. to_bytes() converts the payment to a consistent
byte representation, and merkle_root is the block’s batch fingerprint.
>>> tree = bk.structures.MerkleTree(t.to_bytes() for t in mined.transactions)
>>> bk.structures.verify_proof(tx.to_bytes(), tree.proof(0), mined.merkle_root)
True
The proof establishes membership in that block. It does not establish that the block is on the selected chain or that it will remain there. Explore this distinction in Nakamoto consensus: a payment, a fork, and a reorganization (2008).
Continue the course#
Every experiment in the Examples has a Download Jupyter
notebook link at the bottom of its page. Open a downloaded notebook with
jupyter lab, read it from top to bottom, and run its cells in that order.
The HTML pages contain the same explanations and figures without requiring a
running Python environment. To begin, notebooks/quickstart.ipynb takes one
payment from a signature to a mined block. Each experiment ends with an exercise.
If Python says ModuleNotFoundError, check that your terminal or notebook
kernel uses the environment where you installed the package. If you get a
payment sequence error after rerunning only part of an experiment, restart
with a fresh ledger and run all cells in order.
Direct script execution creates figures without waiting for a GUI window.
For interactive inspection, use python -i examples/crypto/hashing/plot_04_sha256_avalanche.py and
then call matplotlib.pyplot.show(). Documentation build instructions and
developer tools are covered in Developing blockchainkit.