Bismuth is a proof-of-work cryptocurrency and smart-contract platform written in Python. A node validates blocks, maintains the ledger, talks to peers, mines, and serves wallets and explorers.
Status — modernization fork. This tree is an in-progress modernization of the Bismuth node. The guiding rule is that consensus does not change: the same blocks must produce the same hashes and validate identically. Every change is replay-verified (the chain is re-hashed end-to-end through a frozen serialization boundary) and gated by the test suite, so storage, networking and APIs can be modernized safely behind a fixed consensus layer. See the Roadmap and
doc/16.For production, use a tagged release —
mainmay be ahead of what's network-validated.
Requires Python 3.8+ (developed/tested on 3.12).
# 1. install dependencies
pip3 install -r requirements-node.txt
# 2. run a node (mainnet)
python3 node.py
# 3. stop it cleanly
python3 node_stop.pyDon't babysit a screen/nohup. Install the node as a systemd service — it survives reboots, restarts
on failure, and stops gracefully (systemd sends SIGTERM, the node finishes its in-flight block and
drains db_lock, so ledger.db/hyper.db stay consistent):
sudo bash scripts/install-node-service.shThe installer auto-detects the repo dir, python3, and user; gracefully stops any node already running
on :5658; writes /etc/systemd/system/bismuth-node.service; and enables + starts it. After that:
systemctl status bismuth-node # up / synced?
systemctl stop bismuth-node # graceful stop
systemctl restart bismuth-node # graceful restart
journalctl -u bismuth-node -f # follow the logsThe service sets BISMUTH_IGNORE_CONFIG_CUSTOM=1 so it always boots mainnet even if a leftover
regnet config_custom.txt is present.
regnet is a private, instantly-mineable chain for development — no peers, no real PoW. The test
suite spins one up automatically:
# run the full test suite (launches a throwaway regnet node, ~90 tests)
python3 -m pytest
# or run a regnet node yourself (REST API on :3031, socket on :3030)
cp tests/config_custom.txt config_custom.txt
python3 node.py regnet2Configuration lives in config.txt (see doc/11); regnet/test overrides
are in tests/config_custom.txt.
A modern, read-only HTTP API runs alongside the legacy socket protocol (opt in with rest_api=True;
default port 5659, regnet 3031). It is self-describing — GET /api (or the bare root /) lists
every method:
| Endpoint | Purpose |
|---|---|
GET /api/status |
node height, peers, difficulty, consensus |
GET /api/capabilities |
REST/transport capabilities for peer sync (reachable = capable) |
GET /api/block/height/{n} · GET /api/block/hash/{h} |
a single block |
GET /api/blocks/since/{h} · GET /api/blocks/range/{a}/{b} |
block ranges, for parallel sync |
GET /api/balance/{address} |
confirmed balance |
GET /api/transaction/{txid} |
a transaction |
GET /api/address/{address}/transactions |
recent txs (?limit=N) |
GET /api/mempool · GET /api/peers |
pending txs · known peers |
Transport compression is applied at the HTTP layer: responses are gzip/br compressed for any
client that sends Accept-Encoding (browsers, and the bundled rest_client.py). Add ?compress=none
to read plaintext, or ?compress=gzip|br to force a codec.
rest_client.py is the parallel block-fetch client: it discovers a peer (GET /api/capabilities) and
pulls /api/blocks/range in concurrent, compressed chunks — the modern alternative to the serial
socket sync. Full REST API reference: doc/15.
| Concern | Where | Notes |
|---|---|---|
| Consensus serialization | bismuth_serialize.py |
frozen signing/block-hash byte forms; the boundary everything hides behind |
| Block processing | digest.py |
validates and applies blocks |
| PoW / difficulty | mining_heavy3.py, difficulty |
Heavy3 hashing |
| Ledger / storage | dbhandler.py, amounts.py, SQLite |
integer atomic-unit storage behind the frozen boundary (opt-in) |
| Schema migrations | db_migrations.py |
ordered, PRAGMA user_version-tracked |
| Mempool | mempool.py |
pending transactions |
| Networking (legacy) | node.py, connections.py |
length-prefixed JSON over sockets |
| Networking (modern) | rest_api.py, rest_client.py, transport.py |
HTTP API + parallel fetch + compression |
| Crypto / keys | polysign/ |
RSA / ECDSA / ed25519 signers |
Full design docs are in doc/ — start with doc/01-overview.md and the
file reference.
Detailed plan: doc/17-roadmap.md. Database deep-dive: doc/16.
✅ Done
- Frozen consensus boundary — signing-buffer and block-hash byte forms extracted into
bismuth_serialize.pyand characterization-locked, so storage/transport can change without touching consensus. - Schema versioning & migrations — ordered,
user_version-tracked (db_migrations.py). - Integer atomic-unit storage — exact integer amounts behind the frozen boundary, replay-verified
(every block hash byte-identical), live on regnet behind
ledger_integer_amounts(default off). - Modern HTTP layer — read-only REST API; capability discovery (reachable = capable); parallel,
gzip/br-compressed block fetch client (
rest_client.py);mainnet0023capability signal.
◑ In progress / next
- Wire the parallel REST fetch into the actual sync path, so nodes catch up over the HTTP API instead of the serial, blocking socket loop.
- Incremental balance index — O(1) maintained credit/debit, bit-matching the authoritative sum.
- Explicit reward & pruning model — replace negative-height "mirror" rows and
Hyperblockstring rows with real columns/tables.
🗺️ Planned
- Consensus hard fork — sign/hash native integer units + a binary tx encoding (deleting the
'%.8f'/'%.2f'string conversions, all tagged# HARDFORK (doc/16)), and adopt a bounded, content-derived txid (nado-style BLAKE2b, the signature signs the txid). - Deprecate the blocking socket protocol in favour of the HTTP API for node-to-node traffic.
- Storage-engine evaluation — modernize SQLite usage, benchmark, and consider a KV store (LMDB/RocksDB) for block bodies while keeping SQLite for queryable indexes — decided on data.
- Repository reorganization — group modules, retire dead files.
- Website: https://bismuth.cz · Explorers: https://bismuth.im
- Hypernodes: https://hypernodes.bismuth.live · https://bismuth.world
- Wallets: download from bismuth.cz · BIS Paper Wallet · Android
- Exchanges: CoinGecko · CoinMarketCap
- Social: Discord · Reddit · Telegram · Blog
- Source: https://github.com/hclivess/Bismuth
GNU General Public License — see LICENSE.