Blockchain, stripped to its essence in Python.
Project description
██╗ ██╗██████╗ ██╗ ██╗██████╗ ████████╗██╗██╗ ██╗ █████╗ ██║ ██╔╝██╔══██╗╚██╗ ██╔╝██╔══██╗╚══██╔══╝██║██║ ██╔╝██╔══██╗ █████╔╝ ██████╔╝ ╚████╔╝ ██████╔╝ ██║ ██║█████╔╝ ███████║ ██╔═██╗ ██╔══██╗ ╚██╔╝ ██╔═══╝ ██║ ██║██╔═██╗ ██╔══██║ ██║ ██╗██║ ██║ ██║ ██║ ██║ ██║██║ ██╗██║ ██║ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
Blockchain, stripped to its essence in Python.
What is Kryptika?
Kryptika is a complete, working blockchain written entirely in pure Python. It covers the full stack — SHA-256 hashing, Proof of Work mining, ECDSA-signed transactions, live peer-to-peer networking, SQLite persistence, and a thread-safe HTTP node. Every primitive is hand-written and meant to be read.
It's for developers who want to stop wondering how blockchains work and just see it happen. Clone it, run it, break it, read the source.
What's New in v1.2.0
- Streamlit Dashboard — a browser-based GUI covering everything the CLI can do, plus live Plotly charts and a visual chain explorer. Launch with
streamlit run dashboard.py. - Transaction Notes — every transaction now accepts an optional
notefield, stored alongside the transaction and visible in the dashboard, CLI, and history API. - Wallet Import — restore any existing wallet from its PKCS8 DER private key hex using
Wallet.from_private_key(), available in both the dashboard and the CLI. - Node Uptime — the
/statusendpoint now includesuptime_secs, so you can see exactly how long a node has been running. - Persistent Mempool — pending transactions survive a node restart; they are written to the
mempooltable in SQLite and reloaded on startup, filtering out any that were confirmed while the node was offline.
Table of Contents
- Features
- How It Works
- Project Structure
- Installation
- Quick Start
- Running a Node
- Streamlit Dashboard
- Wallet CLI
- Multi-Node Network
- REST API Reference
- Running the Tests
- Architecture Notes
- Security Model
- Known Limitations
- License
1. Features
Kryptika implements the core ideas behind real blockchains — nothing simulated, nothing mocked out.
| Area | What's included |
|---|---|
| Chain | SHA-256 block hashing, tamper-evident linking, deterministic genesis block |
| Mining | Proof of Work with configurable difficulty; 10 KRY base reward plus collected transaction fees |
| Wallets | ECDSA P-256 key pairs, address derivation via SHA-256, wallet import from private key hex |
| Transactions | Cryptographic signatures, replay protection via tx_id, 8-decimal-place precision, optional notes |
| Network | P2P broadcast, longest-chain consensus, mempool sync across peers, full REST API with CORS |
| Dashboard | Streamlit GUI with live Plotly charts, multi-wallet manager, chain explorer, and chain validator |
| Safety | Effective-balance mempool checks, per-batch double-spend tracking in mine_block(), O(1) replay detection |
| Storage | SQLite with atomic BEGIN / COMMIT / ROLLBACK; separate database file per node; schema migration for older databases |
| CI | GitHub Actions pipeline across Python 3.10, 3.11, 3.12, and 3.13 with ruff linting |
2. How It Works
Blocks and the Chain
Every block contains a list of transactions, a timestamp, a nonce, and the hash of the block before it. Change even a single byte anywhere and the block's SHA-256 hash changes — which breaks every chain link that follows it. Tampering is immediately detectable.
Block 0 is the genesis block — always empty, always mined identically. Every block after it locks onto the previous block's hash, forming a chain that can't be quietly rewritten.
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Block 0 │ │ Block 1 │ │ Block 2 │
│ (Genesis) │────→│ │────→│ │
│ prev: 000000 │ │ prev: 000a1b2c │ │ prev: 000f3d9a │
│ hash: 000a1b2c │ │ hash: 000f3d9a │ │ hash: 000c77e1 │
└──────────────────┘ └──────────────────┘ └──────────────────┘
The hash covers five fields — index, transactions, prev_hash, timestamp, and nonce — serialised with json.dumps(..., sort_keys=True) to guarantee determinism across Python versions and platforms.
Proof of Work
To add a block, a miner must find a nonce value that makes the block's SHA-256 hash start with a specific number of leading zeros (the difficulty). There's no shortcut — it requires thousands of hash attempts. That's the point. Rewriting history would mean redoing all that computation for every block that follows, which is what makes the chain trustworthy.
# Simplified — difficulty 3 means the hash must start with "000"
while not block_hash.startswith("000"):
block.nonce += 1
block_hash = sha256(block)
Each extra leading zero requires roughly 16× more hash attempts on average — difficulty scales exponentially.
Wallets and Addresses
A wallet is an ECDSA P-256 key pair. The address is the SHA-256 hash of the uncompressed public key point (65 bytes → 64 hex characters), and it's safe to share with anyone. The private key stays on your machine; it's what proves you authorised a transaction.
Private key ──(ECDSA P-256)──→ Public key (65 bytes) ──(SHA-256)──→ Address (64 hex chars)
SECRET — never share shareable shareable
Signatures are stored as raw r‖s (64 bytes, 128 hex characters). The private key is serialised as PKCS8 DER hex — raw P-256 DER raises a ValueError in the cryptography library.
Transactions
When you send coins, you sign a payload containing the sender, recipient, amount, and fee. That signature is broadcast alongside the transaction. Every node verifies it against your embedded public key — without ever needing your private key.
{ sender, recipient, amount, fee } + private key
│
ECDSA P-256 / SHA-256
│
signature (128 hex chars)
│
broadcast with public_key embedded
│
node verifies with embedded public key ✓
The note field is stored alongside the transaction and visible in history and the dashboard, but it is not part of the signed payload — it is informational metadata.
A tx_id is computed as SHA-256({sender, recipient, amount, fee, signature}) and is unique per transaction because ECDSA signing is randomised, even for identical inputs.
The Mempool
Before a transaction lands on the chain, it waits in the mempool — a queue of unconfirmed transactions persisted to SQLite. Miners bundle the full mempool into the next block. The miner earns the base reward plus every fee in that block, so transactions with higher fees naturally confirm faster.
Mempool: [alice→bob 5.0 | fee: 0.5] [bob→carol 2.0 | fee: 0.5] [carol→dave 1.0 | fee: 0.5]
↓ miner mines
Block confirmed → miner earns 10 KRY base + 1.5 KRY in fees = 11.5 KRY
When a node accepts a new transaction it checks four things in order: reject COINBASE sender → verify ECDSA signature → reject duplicate tx_id (against both mempool and confirmed chain) → effective balance ≥ amount + fee after subtracting all already-pending spend.
Consensus — Longest Chain Wins
Sometimes two nodes mine a block at exactly the same moment. That creates a fork — two valid but competing chains. Kryptika resolves it the same way Bitcoin does: the longest valid chain wins. As soon as any node mines the next block, it broadcasts a chain one block longer. Every other node validates it and switches over automatically. No votes, no manual intervention — forks self-heal in seconds.
Fork:
Node A: [0]──[1]──[2]──[3a] ← tied
Node B: [0]──[1]──[2]──[3b] ← tied
Node A mines next:
Node A: [0]──[1]──[2]──[3a]──[4] ← broadcasts; wins (longer valid chain)
Node B: [0]──[1]──[2]──[3a]──[4] ← drops [3b], adopts A's chain
sync_with_peers() does two things in sequence: first it finds and adopts the longest valid chain across all known peers; then it absorbs any pending transactions from peer mempools, so unconfirmed transactions propagate even when chain heights are equal.
3. Project Structure
kryptika/ ← project root — run all commands from here
│
├── run_node.py ← start a blockchain node
├── wallet_cli.py ← interactive terminal wallet
├── dashboard.py ← Streamlit browser dashboard (new in v1.2.0)
├── pyproject.toml ← package metadata, dependencies, entry points
├── LICENSE ← MIT
│
├── kryptika/ ← main Python package
│ ├── core/
│ │ ├── transaction.py ← Wallet (keygen, sign, import) + Transaction (create, verify)
│ │ ├── block.py ← Block (SHA-256 hash, nonce, serialisation)
│ │ └── blockchain.py ← Blockchain (mine, validate, balance, history)
│ │
│ ├── network/
│ │ ├── node.py ← Node (mempool, broadcast, sync — thread-safe RLock)
│ │ └── server.py ← ThreadingHTTPServer JSON REST API (all 13 endpoints)
│ │
│ ├── storage/
│ │ └── storage.py ← SQLiteStorage (atomic save/load, schema migration)
│ │
│ └── main.py ← standalone demo script
│
└── tests/
├── test_core.py ← 34 unit tests
├── test_storage.py ← 5 storage tests
└── test_network.py ← 13 integration tests (52 total)
4. Installation
You'll need Python 3.10 or newer.
Working inside a virtual environment is strongly recommended so Kryptika's dependencies don't interfere with anything else on your machine.
# Create and activate a virtual environment
python -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows — Command Prompt
.venv\Scripts\activate.bat
# Windows — PowerShell
.venv\Scripts\Activate.ps1
Then install Kryptika and all its dependencies in one step:
pip install -e .
This installs cryptography, requests, streamlit, and plotly automatically, and registers the kryptika-node command on your PATH so you can start nodes without typing python run_node.py every time.
If you'd rather not install as a package, install the dependencies manually and run scripts directly:
pip install "cryptography>=41.0" "requests>=2.31" "streamlit>=1.35" "plotly>=5.20"
python run_node.py
python wallet_cli.py
streamlit run dashboard.py
5. Quick Start
Don't want to spin up a server yet? This single command runs the full blockchain lifecycle — key generation, mining, signed transactions, balance tracking, and tamper detection — entirely in memory:
python -m kryptika.main
It creates wallets for Alice, Bob, and Carol; mines several blocks; sends signed transactions between them; prints final balances; validates the full chain; and then deliberately tampers with a block to show detection in action:
========================================================
Kryptika Demo
========================================================
[1] Creating wallets...
Alice : 3f9a2b1c...
Bob : 7d4e8f0a...
Carol : c2e91f33...
[2] Initialising blockchain (difficulty=2)...
Genesis block mined. Height=1
[3] Mining reward blocks...
Block mined -> Alice earns 10.0 coins. Height=2
Block mined -> Alice earns 10.0 coins. Height=3
[5] Alice sends 7 coins to Bob (fee=0.5)...
[7] Validating chain...
Chain valid : True
[8] Tamper test -- modifying a transaction amount...
Chain valid after tamper : False
Reason : Block #1 has been tampered with — stored hash does not match computed hash.
This is the fastest way to verify everything is working before you run a real node.
6. Running a Node
A node maintains the chain, validates transactions, mines blocks, and communicates with peers over HTTP. Each node writes its chain to a dedicated SQLite file (chain_5000.db, chain_5001.db, etc.), so multiple nodes on the same machine stay completely independent.
python run_node.py # port 5000, difficulty 3
python run_node.py 5001 # port 5001, difficulty 3
python run_node.py 5001 4 # port 5001, difficulty 4
If you installed via pip install -e ., the registered entry point works identically:
kryptika-node # port 5000, difficulty 3
kryptika-node 5001 4 # port 5001, difficulty 4
On startup the node prints its configuration and every available endpoint:
┌─────────────────────────────────────────────────┐
│ │
│ Kryptika Node │
│ │
├─────────────────────────────────────────────────┤
│ Port : 5000 │
│ Difficulty : 3 │
│ Database : chain_5000.db │
├─────────────────────────────────────────────────┤
│ GET /chain /status /peers /peers/sync │
│ GET /mine?address=<addr> │
│ GET /balance/<addr> /history/<addr> │
│ GET /transactions/pending /wallet/new │
│ POST /peers/add /peers/receive │
│ POST /transactions/new /transactions/receive│
└─────────────────────────────────────────────────┘
Press Ctrl+C to stop.
If a chain_<port>.db file already exists, the node resumes from it and prints the current height. If not, it mines the genesis block and saves it before accepting any connections.
7. Streamlit Dashboard
The dashboard is a browser-based GUI that connects to any running node over HTTP. It covers everything the CLI can do — wallets, sending, mining, peer management — plus live Plotly charts and a full block explorer.
Starting
You need at least one node running first. Then open a second terminal:
# Terminal 1 — the node
python run_node.py 5000
# Terminal 2 — the dashboard
streamlit run dashboard.py
Streamlit opens http://localhost:8501 in your browser automatically.
Switching nodes
The sidebar has a Connected Node selector with presets for ports 5000, 5001, and 5002. Choose custom... to type any host and port — the dashboard verifies the connection before switching. Chain height, mempool count, and peer count update live beneath the selector.
Pages
| Page | What you can do |
|---|---|
| Overview | Live stats (height, mempool, peers, uptime) and Plotly charts showing transactions per block and time between blocks. Scroll down for a live activity feed. |
| Chain Explorer | Browse every block on the chain. Search by block index or hash fragment. Expand any block to inspect its hashes, nonce, timestamp, and every transaction including notes. |
| Mempool | View all unconfirmed transactions waiting to be mined, with total pending volume and fee totals. |
| Wallet | Create a new keypair, import an existing wallet by private key hex, check balances, set a default wallet, and view a full transaction history with running balance for any address. |
| Send | Build and broadcast a transaction. Pick a sending wallet, enter a recipient address, amount, fee, and an optional note. A live summary panel updates your remaining balance as you type. |
| Mine | Choose which wallet receives the mining reward, then start mining. The result panel shows the block index, the winning nonce, how many transactions were confirmed, and the total reward earned. |
| Peers | See all connected nodes, add a new peer (the dashboard attempts a mutual handshake automatically), or trigger a sync to pull the longest chain from all peers. |
| Chain Validator | Fetch the full chain from the node and verify every block — hash linkage, Proof of Work compliance, and transaction signatures. Any tampered block is flagged with a specific error. |
Auto-refresh
Toggle Auto in the sidebar to reload the dashboard every 5 seconds — useful for monitoring a live network or watching blocks arrive during a mining session.
⚠️
wallets.jsonstores private keys as plain hex on disk. The dashboard and the CLI share this same file, so wallets created in one are immediately available in the other. Never commit this file to version control or share it with anyone.
8. Wallet CLI
The wallet CLI is the terminal alternative to the dashboard. It connects directly to a running node and provides a menu-driven interface for every operation.
Connecting
python wallet_cli.py # auto-scans ports 5000–5010, shows found nodes
python wallet_cli.py 5001 # connect directly to localhost:5001
python wallet_cli.py 192.168.1.5:5000 # connect to a node on another machine
If you don't pass a port, the CLI scans localhost automatically and presents whatever nodes it finds:
══════════════════════════════════════════════════════════
Kryptika Wallet CLI -- Node Selection
══════════════════════════════════════════════════════════
Scanning for running nodes...
[1] localhost:5000 height=4 peers=1 mempool=0
[2] localhost:5001 height=4 peers=1 mempool=2
[c] Enter a custom address
Select node (Enter for [1]):
Main menu
════════════════════════════════════════
Kryptika Wallet
════════════════════════════════════════
1. Create / load wallet
2. Show balance
3. Send coins
4. Transaction history
5. Mine a block
6. View pending transactions
7. View the full chain
8. Node status
9. Manage peers / multi-node
0. Exit
════════════════════════════════════════
Wallets are saved to wallets.json and persist between sessions. When you choose Send (option 3), you'll be prompted for an optional note — if you skip it, the field is stored as an empty string.
9. Multi-Node Network
Running multiple nodes lets you watch Kryptika's P2P broadcast and consensus resolve in real time. Blocks mined on one node propagate to all peers immediately; forks self-heal automatically.
Setting up three nodes
# Terminal 1
python run_node.py 5000
# Terminal 2
python run_node.py 5001
# Terminal 3
python run_node.py 5002
Peering them together
Use the CLI or the dashboard Peers page. From the CLI, connect to node 5000 and add the other two:
python wallet_cli.py 5000
# option 9 → Add a peer → localhost:5001 (mutual handshake registered automatically)
# option 9 → Add a peer → localhost:5002
Then link 5001 to 5002:
python wallet_cli.py 5001
# option 9 → Add peer → localhost:5002
All three nodes now know each other. Mine on any one of them and every other node receives the new block instantly.
Suggested exploration workflow
- Mine a few blocks on port 5000 to put some coins into circulation.
- Peer all three nodes as described above.
- Submit transactions from any node — they appear in every node's mempool automatically via P2P broadcast.
- Mine from any node — the block propagates and is accepted by all peers.
- Watch all nodes converge on the same chain height via
GET /statusor the dashboard Overview page.
How forks resolve
If two nodes mine a block at the same height simultaneously, each broadcasts its version and both chains are temporarily tied. As soon as either node mines the next block, it broadcasts a chain one block longer. Every other node validates it, drops the shorter fork, and switches over. The process takes seconds and requires no human intervention.
A transaction broadcast to one node's mempool immediately reaches all connected peers. If a peer was offline during the broadcast, it picks up the transaction during the next
sync_with_peers()call via the mempool-sync step.
10. REST API Reference
Every endpoint responds with JSON. Errors always include an "error" key with a plain-English explanation. All responses include Access-Control-Allow-Origin: *. Request bodies are hard-capped at 10 MB.
GET endpoints
| Endpoint | What it returns |
|---|---|
GET /status |
{status, height, difficulty, peers, mempool, uptime_secs, last_block} |
GET /chain |
Full blockchain as a JSON array of block objects |
GET /peers |
{peers: ["localhost:5001", ...]} |
GET /peers/sync |
Pulls chains + mempools from all peers; adopts longest valid chain → {replaced, height, message} |
GET /mine?address=<addr> |
Mines the mempool into a new block → {message, index, transactions, nonce, hash, miner_reward} |
GET /balance/<address> |
{address, balance} — confirmed balance, 8 decimal places |
GET /history/<address> |
{address, count, history} — all confirmed transactions, oldest first |
GET /transactions/pending |
{count, transactions} — current mempool |
GET /wallet/new |
Generates a fresh key pair on the node → {address, warning} (private key is not stored server-side) |
POST endpoints
| Endpoint | Body | What it does |
|---|---|---|
POST /peers/add |
{"address": "localhost:5001"} |
Registers a peer |
POST /peers/receive |
[{block}, ...] |
Accepts a chain broadcast; replaces local chain if longer and valid |
POST /transactions/new |
Transaction object (see below) | Validates, adds to mempool, broadcasts to all peers → HTTP 201 |
POST /transactions/receive |
Transaction object | Silently accepts a transaction forwarded by a peer → HTTP 200 |
Transaction object
{
"sender": "<64-char hex address>",
"recipient": "<64-char hex address>",
"amount": 5.0,
"fee": 0.5,
"note": "optional label",
"signature": "<128 hex chars — raw r‖s, ECDSA P-256 / SHA-256>",
"public_key": "<130 hex chars — uncompressed EC point>",
"tx_id": "<64 hex chars — SHA-256 fingerprint>"
}
curl examples
# Node status
curl http://localhost:5000/status
# Check balance
curl http://localhost:5000/balance/<address>
# Mine a block
curl "http://localhost:5000/mine?address=<your_address>"
# View pending mempool
curl http://localhost:5000/transactions/pending
# Submit a signed transaction
curl -X POST http://localhost:5000/transactions/new \
-H "Content-Type: application/json" \
-d '{
"sender": "...",
"recipient": "...",
"amount": 5.0,
"fee": 0.5,
"note": "payment",
"signature": "...",
"public_key": "...",
"tx_id": "..."
}'
# Add a peer
curl -X POST http://localhost:5000/peers/add \
-H "Content-Type: application/json" \
-d '{"address": "localhost:5001"}'
# Sync with all peers
curl http://localhost:5000/peers/sync
11. Running the Tests
Make sure your virtual environment is active and you're in the project root:
# Install test dependencies
pip install pytest pytest-timeout ruff
# Run all 52 tests
pytest
# Run suites individually
pytest tests/test_core.py # 34 unit tests — core primitives
pytest tests/test_storage.py # 5 unit tests — SQLite persistence
pytest tests/test_network.py # 13 integration tests — live HTTP servers
The network tests spin up real HTTP servers on ports 5100–5114 and tear them down cleanly after each test, so they won't interfere with any nodes you have running. A 60-second per-test timeout is applied automatically.
What's covered
Core — 34 tests
Transaction creation, signing, and ECDSA verification. Tamper detection (test_tampered_transaction_is_invalid). Coinbase creation and validation. Block hash determinism (test_block_hash_is_deterministic, test_nonce_changes_hash). Proof of Work enforcement. Chain validation across tampered data, broken links, wrong prev_hash, and insufficient PoW. Balance calculation with fee accounting. tx_id uniqueness and round-trip serialisation. Batch double-spend rejection inside mine_block() (test_batch_double_spend_rejected_by_mine_block, test_batch_double_spend_same_sender_different_recipients). Fee collection by the miner. Fake coinbase rejection.
Storage — 5 tests
Save/load round-trip with chain integrity verified after reload. Hash preservation through serialise/deserialise cycles. Empty database raises ValueError. Atomic overwrite — a new save fully replaces old data.
Network — 13 tests
All HTTP GET endpoints: chain, status, wallet generation, mine, balance, pending transactions, peers. P2P broadcast — mine on one node, confirm the block appears on a connected peer. Chain sync — a shorter-chain node adopts a longer chain from a peer. Error cases — missing address query param returns 400, unknown endpoint returns 404, fake coinbase transaction rejected. Concurrent requests — /status stays responsive while /mine is running.
12. Architecture Notes
A handful of design decisions in the source that might seem subtle at first — each has a concrete reason.
Why Proof of Work runs outside the node lock
When /mine is called, the entire hash-grinding loop runs before acquiring the RLock. Only the final step — appending the block to self.blockchain.chain and writing to disk — is done inside the lock. This keeps /status, /balance, /history, and all other read endpoints fully responsive during mining.
There's a second benefit: if a peer broadcasts a longer chain while PoW is in progress, mine() checks self.blockchain.height != prev_height after acquiring the lock and discards the stale candidate cleanly, without any conflict.
Why coin amounts use Decimal arithmetic
Python's native float accumulates rounding errors. After enough transactions, a comparison like balance == expected can silently return False even when the math is correct. Kryptika avoids this by rounding every coin value to exactly 8 decimal places using decimal.Decimal with ROUND_HALF_UP — the same precision model Bitcoin uses for satoshis.
Why the tx_id confirmed-set grows incrementally
Node._confirmed_ids is a set that gains new tx_id values as each block is mined (_index_block()), rather than scanning the full chain on every incoming transaction. When a longer chain is adopted via sync, the set is rebuilt once from scratch (_rebuild_confirmed_ids()). This keeps replay-attack checks at O(1) cost instead of O(chain length × mempool size) on every submission.
Why the mempool is persisted to SQLite
Pending transactions are written to the mempool table after every add_transaction() call and on every mine. When a node restarts, it reloads the mempool and silently drops any transactions whose tx_id is already in _confirmed_ids — transactions that were confirmed while the node was offline are discarded automatically, with no risk of double-processing.
Why notes are not part of the ECDSA signature
The _signable_bytes() method covers only the four economic fields — sender, recipient, amount, and fee. Notes are optional metadata attached to the transaction for human readability. They are stored in the database, returned by /history, and displayed in the dashboard and CLI, but they are not cryptographically bound to the signature. Changing a note on a stored transaction would not invalidate the signature.
13. Security Model
| What's protected | How |
|---|---|
| Signature forgery | ECDSA P-256 — a transaction cannot be signed without the sender's private key |
| Tamper detection | SHA-256 chain hashing — altering any byte in any block invalidates every hash that follows |
| Replay attacks | Every tx_id is checked against both the confirmed-chain cache and the live mempool before a transaction is accepted |
| Mempool double-spend | Effective balance = confirmed balance − all pending outgoing amounts for that sender |
| Block double-spend | mine_block() tracks cumulative spend per sender within a single call, rejecting any transaction that would exceed the remaining balance |
| Thread safety | An RLock protects all state mutations; PoW runs outside the lock so read endpoints never block |
| Disk integrity | All SQLite writes use explicit BEGIN / COMMIT / ROLLBACK — a crash mid-write leaves the previous valid state intact |
| Request flooding | Incoming HTTP request bodies are hard-capped at 10 MB |
| Address binding | During verification, the embedded public_key is hashed and compared against sender — a mismatched key is rejected |
14. Known Limitations
Kryptika is designed for learning, not production. Here's what's intentionally absent and why it matters:
| What's missing | What a real system would do |
|---|---|
| No wallet encryption | Private keys are stored as plain hex in wallets.json. A production wallet encrypts keys at rest using a password-derived key (BIP-38, AES-GCM, or similar). |
| No peer authentication | Any host that knows a node's IP can push a chain to /peers/receive. Real nodes authenticate peers and reject data from unknown sources. |
| No Merkle tree | Blocks store the full transaction list. Real blockchains use a Merkle tree so a single transaction's inclusion can be proved without downloading the whole block. |
| No UTXO set | Balance checks scan every block from genesis. Bitcoin maintains a set of unspent outputs so balance lookups take constant time regardless of chain length. |
| Fixed mining reward | The reward is always 10 KRY. Bitcoin halves it roughly every four years to cap total supply — Kryptika has no halving schedule. |
| No fee-priority ordering | The mempool includes transactions in arrival order. Real mempools rank by fee-per-byte and evict low-fee transactions under congestion. |
| Local-only peer discovery | The CLI scans localhost on ports 5000–5010 at startup. Remote nodes must be added manually via the CLI or dashboard. |
| Dashboard requires a running node | The Streamlit dashboard is a pure REST client with no blockchain logic of its own. At least one node must be running before the dashboard can do anything useful. |
15. License
Released under the MIT License — see the LICENSE file for the full text.
MIT © 2026 Kryptika Contributors
Built with pure Python · No blockchain frameworks · No shortcuts
Read the source. Break things. Learn how it works.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kryptika-1.2.0.tar.gz.
File metadata
- Download URL: kryptika-1.2.0.tar.gz
- Upload date:
- Size: 61.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73a6d0f783bd5792bf36397d7e414cebff8616538fcf5cc0fca7df3423a37352
|
|
| MD5 |
fa3aaf1e09e07419d4855343f0d237ff
|
|
| BLAKE2b-256 |
eb23a429790c9ebae5c79d3d8618d4322d9f2cb7493d4e0457c0d3ec890cc8af
|
File details
Details for the file kryptika-1.2.0-py3-none-any.whl.
File metadata
- Download URL: kryptika-1.2.0-py3-none-any.whl
- Upload date:
- Size: 34.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
715e5c0db45e6c5ee1e232ffad8c5139399abc128f217843f3d17410c83a2c7b
|
|
| MD5 |
fe563938dd981d577b36069aeaa30a69
|
|
| BLAKE2b-256 |
ef5d65a79ca4d8e0dfd983d29b05077e9427fe3d26dd40d939b3a4b9569fd6eb
|