kryptika 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kryptika-1.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kryptika Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,643 @@
1
+ Metadata-Version: 2.4
2
+ Name: kryptika
3
+ Version: 1.1.0
4
+ Summary: A complete blockchain implementation in pure Python — SHA-256 block hashing, Proof of Work consensus, ECDSA P-256 signed transactions, live P2P networking, SQLite persistence, and a thread-safe REST node. One dependency. No frameworks.
5
+ Author: Kryptika Contributors
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Kryptika Contributors
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Keywords: blockchain,cryptocurrency,proof-of-work,ecdsa,p2p,bitcoin,educational
29
+ Classifier: Development Status :: 4 - Beta
30
+ Classifier: Intended Audience :: Education
31
+ Classifier: Intended Audience :: Developers
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Programming Language :: Python :: 3
34
+ Classifier: Programming Language :: Python :: 3.10
35
+ Classifier: Programming Language :: Python :: 3.11
36
+ Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
38
+ Classifier: Topic :: Software Development :: Libraries
39
+ Classifier: Topic :: Security :: Cryptography
40
+ Classifier: Topic :: Education
41
+ Classifier: Operating System :: OS Independent
42
+ Requires-Python: >=3.10
43
+ Description-Content-Type: text/markdown
44
+ License-File: LICENSE
45
+ Requires-Dist: cryptography>=41.0
46
+ Dynamic: license-file
47
+
48
+ <div align="center">
49
+
50
+ <br/>
51
+
52
+ <pre>
53
+ ██╗ ██╗██████╗ ██╗ ██╗██████╗ ████████╗██╗██╗ ██╗ █████╗
54
+ ██║ ██╔╝██╔══██╗╚██╗ ██╔╝██╔══██╗╚══██╔══╝██║██║ ██╔╝██╔══██╗
55
+ █████╔╝ ██████╔╝ ╚████╔╝ ██████╔╝ ██║ ██║█████╔╝ ███████║
56
+ ██╔═██╗ ██╔══██╗ ╚██╔╝ ██╔═══╝ ██║ ██║██╔═██╗ ██╔══██║
57
+ ██║ ██╗██║ ██║ ██║ ██║ ██║ ██║██║ ██╗██║ ██║
58
+ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
59
+ </pre>
60
+
61
+ **A blockchain built from scratch in pure Python.**
62
+ *No frameworks. No shortcuts. Every line written to be read, not just run.*
63
+
64
+ [![Python](https://img.shields.io/badge/Python-3.10%2B-3776AB?style=for-the-badge&logo=python&logoColor=white)](https://python.org)
65
+ [![Version](https://img.shields.io/badge/Version-1.1.0-6C63FF?style=for-the-badge)](https://github.com/aryanap07/Kryptika)
66
+ [![License: MIT](https://img.shields.io/badge/License-MIT-22C55E?style=for-the-badge)](LICENSE)
67
+ <br/>
68
+
69
+ </div>
70
+
71
+ ---
72
+
73
+ ## What is Kryptika?
74
+
75
+ Kryptika is a complete blockchain built from the ground up in pure Python — SHA-256 hashing, Proof of Work mining, ECDSA-signed transactions, live peer-to-peer networking, SQLite persistence, and a fully thread-safe node. Every primitive is hand-written and readable.
76
+
77
+ It's for developers who want to stop wondering how blockchains work and just see it happen. Clone it, run it, break it, read it.
78
+
79
+ ---
80
+
81
+ ## Table of Contents
82
+
83
+ 1. [Features](#1-features)
84
+ 2. [How It Works](#2-how-it-works)
85
+ 3. [Project Structure](#3-project-structure)
86
+ 4. [Requirements & Installation](#4-requirements--installation)
87
+ 5. [Quick Start](#5-quick-start)
88
+ 6. [Running a Node](#6-running-a-node)
89
+ 7. [Wallet CLI](#7-wallet-cli)
90
+ 8. [Multi-Node Network](#8-multi-node-network)
91
+ 9. [REST API Reference](#9-rest-api-reference)
92
+ 10. [Running the Tests](#10-running-the-tests)
93
+ 11. [Architecture Notes](#11-architecture-notes)
94
+ 12. [Security Model](#12-security-model)
95
+ 13. [Known Limitations](#13-known-limitations)
96
+ 14. [License](#14-license)
97
+
98
+ ---
99
+
100
+ ## 1. Features
101
+
102
+ ### Chain
103
+
104
+ | Feature | Detail |
105
+ |---|---|
106
+ | SHA-256 Hashing | Tamper-evident block linking |
107
+ | Genesis Block | Deterministic chain bootstrap |
108
+
109
+ ### Mining
110
+
111
+ | Feature | Detail |
112
+ |---|---|
113
+ | Proof of Work | Configurable leading-zero difficulty |
114
+ | Mining Reward | Fixed 10-coin base reward + fees |
115
+
116
+ ### Wallets
117
+
118
+ | Feature | Detail |
119
+ |---|---|
120
+ | ECDSA P-256 Key Pairs | Cryptographically secure key generation |
121
+ | Address Derivation | Address = SHA-256 of public key |
122
+
123
+ ### Transactions
124
+
125
+ | Feature | Detail |
126
+ |---|---|
127
+ | Cryptographic Signatures | ECDSA-signed; verified by all nodes |
128
+ | Gas Fees | Per-transaction fee that rewards the miner; defaults to 0.5 coins |
129
+ | Replay Protection | `tx_id` checked against chain + mempool |
130
+ | Decimal Precision | 8 decimal places — no floating-point drift |
131
+
132
+ ### Network
133
+
134
+ | Feature | Detail |
135
+ |---|---|
136
+ | P2P Broadcast | New blocks propagate to all peers instantly |
137
+ | Longest-Chain Consensus | Forks resolve automatically |
138
+ | REST API | Full HTTP interface with CORS support |
139
+
140
+ ### Safety
141
+
142
+ | Feature | Detail |
143
+ |---|---|
144
+ | Mempool Guard | Effective-balance checked before queuing |
145
+ | Double-Spend Guard | Per-sender spend tracked across each block |
146
+ | Thread Safety | PoW runs outside the node lock; reads always non-blocking |
147
+
148
+ ### Storage
149
+
150
+ | Feature | Detail |
151
+ |---|---|
152
+ | Atomic Persistence | SQLite with explicit `BEGIN / COMMIT / ROLLBACK` |
153
+ | Per-Node Databases | Each node keeps its own `chain_<port>.db` |
154
+
155
+ ---
156
+
157
+ ## 2. How It Works
158
+
159
+ ### Blocks and the Chain
160
+
161
+ Every block holds a list of transactions, a timestamp, a nonce, and a hash of the block before it. Change even a single byte anywhere and the hash changes — snapping every link that follows. Tampering is caught immediately.
162
+
163
+ Block `0` is the **genesis block** — always empty, always identical. Every block after it locks onto the previous block's hash, forming a chain that can't be quietly rewritten.
164
+
165
+ ```
166
+ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
167
+ │ Block 0 │ │ Block 1 │ │ Block 2 │
168
+ │ (Genesis) │────→│ │────→│ │
169
+ │ prev: 000000 │ │ prev: 000a1b2c │ │ prev: 000f3d9a │
170
+ │ hash: 000a1b2c │ │ hash: 000f3d9a │ │ hash: 000c77e1 │
171
+ └──────────────────┘ └──────────────────┘ └──────────────────┘
172
+ ```
173
+
174
+ ### Proof of Work
175
+
176
+ To add a block, a miner must find a `nonce` that makes the block's SHA-256 hash start with a specific number of zeros. There's no shortcut — it takes thousands of attempts. That's the point. Rewriting history would mean redoing all that work, which is what makes the chain trustworthy.
177
+
178
+ ```python
179
+ # Conceptual example — difficulty 3
180
+ while not block_hash.startswith("000"):
181
+ block.nonce += 1
182
+ block_hash = sha256(block)
183
+ ```
184
+
185
+ > Each extra leading zero requires roughly 16× more hashes — the difficulty scales exponentially.
186
+
187
+ ### Wallets and Addresses
188
+
189
+ A wallet is an ECDSA P-256 key pair. Your address is just a SHA-256 hash of your public key — safe to share with anyone. Your private key never leaves your machine; it's what you use to prove you authorised a transaction.
190
+
191
+ ```
192
+ Private key ──(ECDSA P-256)──→ Public key ──(SHA-256)──→ Address
193
+ SECRET — never share shareable shareable
194
+ ```
195
+
196
+ ### Transactions
197
+
198
+ When you send coins, you sign a small payload with your private key. That signature gets attached to the transaction and broadcast to the network. Every node can verify it's genuinely from you using your public key — without ever needing to see the private key itself.
199
+
200
+ ```
201
+ { sender, recipient, amount, fee } + private key
202
+
203
+ ECDSA P-256
204
+
205
+ signature ──→ broadcast to all nodes
206
+
207
+ node verifies with public key ✓
208
+ ```
209
+
210
+ ### The Mempool
211
+
212
+ Before a transaction lands on the chain, it sits in the **mempool** — a waiting room for unconfirmed transactions. Miners pick them up and bundle them into the next block. The miner earns the base reward plus every fee in that block, so if you want faster confirmation, offer a higher fee.
213
+
214
+ ```
215
+ Mempool: [alice→bob 5.0 | fee: 0.5] [bob→carol 2.0 | fee: 0.5] [carol→dave 1.0 | fee: 0.5]
216
+ ↓ miner picks up & mines
217
+ Block mined → miner earns base reward + all fees
218
+ ```
219
+
220
+ ### Consensus — Longest Chain Wins
221
+
222
+ Sometimes two nodes mine a block at exactly the same moment. That's 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 and broadcasts it, every other node sees the longer chain and switches over. No votes, no coordination, no manual intervention.
223
+
224
+ ```
225
+ Fork:
226
+ Node A: [0]──[1]──[2]──[3a] ← tied
227
+ Node B: [0]──[1]──[2]──[3b] ← tied
228
+
229
+ Node A mines next:
230
+ Node A: [0]──[1]──[2]──[3a]──[4] ← broadcasts, wins (longer)
231
+ Node B: [0]──[1]──[2]──[3a]──[4] ← drops [3b], adopts A's chain
232
+ ```
233
+
234
+ ---
235
+
236
+ ## 3. Project Structure
237
+
238
+ ```
239
+ kryptika/ ← project root — run all commands here
240
+
241
+ ├── run_node.py ← start a blockchain node
242
+ ├── wallet_cli.py ← interactive wallet & transaction manager
243
+ ├── pyproject.toml ← package metadata and entry points
244
+ ├── LICENSE
245
+
246
+ ├── kryptika/ ← main Python package
247
+ │ │
248
+ │ ├── core/ ← blockchain primitives
249
+ │ │ ├── transaction.py ← Wallet (keygen, sign) + Transaction (create, verify)
250
+ │ │ ├── block.py ← Block (hash, nonce, serialisation)
251
+ │ │ └── blockchain.py ← Blockchain (mine, validate, balance, history)
252
+ │ │
253
+ │ ├── network/ ← P2P layer
254
+ │ │ ├── node.py ← Node (mempool, broadcast, sync — thread-safe)
255
+ │ │ └── server.py ← HTTP REST server (all endpoints)
256
+ │ │
257
+ │ ├── storage/ ← persistence layer
258
+ │ │ └── storage.py ← SQLiteStorage (atomic save + load + migration)
259
+ │ │
260
+ │ └── main.py ← standalone demo script
261
+
262
+ └── tests/
263
+ ├── test_core.py ← 34 unit tests (core primitives)
264
+ ├── test_storage.py ← 5 unit tests (persistence)
265
+ └── test_network.py ← 13 integration tests (live HTTP servers)
266
+ ```
267
+
268
+ ---
269
+
270
+ ## 4. Requirements & Installation
271
+
272
+ You'll need **Python 3.10 or newer**. Kryptika has exactly one external dependency — the `cryptography` library for ECDSA. Everything else is the Python standard library.
273
+
274
+ ### Option A — Quick install
275
+
276
+ ```bash
277
+ pip install cryptography>=41.0
278
+ ```
279
+
280
+ That's all you need to run every script.
281
+
282
+ ### Option B — Install as a package
283
+
284
+ ```bash
285
+ pip install -e .
286
+ ```
287
+
288
+ This gives you the `kryptika-node` command globally inside your environment — handy if you're running multiple nodes and don't want to `cd` each time.
289
+
290
+ **Activate a virtual environment first (recommended):**
291
+
292
+ ```bash
293
+ # Create
294
+ python -m venv .venv
295
+
296
+ # macOS / Linux
297
+ source .venv/bin/activate
298
+
299
+ # Windows — Command Prompt
300
+ .venv\Scripts\activate.bat
301
+
302
+ # Windows — PowerShell
303
+ .venv\Scripts\Activate.ps1
304
+ ```
305
+
306
+ ---
307
+
308
+ ## 5. Quick Start
309
+
310
+ Don't want to spin up a server yet? Run the full blockchain lifecycle — wallets, mining, transactions, tamper detection — in a single script:
311
+
312
+ ```bash
313
+ python -m kryptika.main
314
+ ```
315
+
316
+ Here's what it does:
317
+ - Creates wallets for Alice, Bob, and Carol
318
+ - Mines a few blocks
319
+ - Sends signed transactions between wallets
320
+ - Checks balances
321
+ - Deliberately corrupts a block and shows the chain catching it
322
+
323
+ Expected output:
324
+
325
+ ```
326
+ [Blockchain] Genesis block mined.
327
+ [Wallet] Alice: 3f9a2b1c...
328
+ [Wallet] Bob: 7d4e8f0a...
329
+ [Mine] Block #1 mined — reward → Alice
330
+ [Send] Alice → Bob: 5.0 coins (fee: 0.1)
331
+ [Mine] Block #2 mined — reward → Alice
332
+ [Balance] Alice: 14.9 Bob: 5.0
333
+ [Tamper] Modified block detected — chain is INVALID ✓
334
+ ```
335
+
336
+ ---
337
+
338
+ ## 6. Running a Node
339
+
340
+ ```bash
341
+ python run_node.py # port 5000, difficulty 3
342
+ python run_node.py 5001 # port 5001, difficulty 3
343
+ python run_node.py 5001 4 # port 5001, difficulty 4
344
+ ```
345
+
346
+ Each node writes its chain to its own `chain_<port>.db` file, so you can run multiple nodes on the same machine without them stepping on each other.
347
+
348
+ When a node starts, you'll see this:
349
+
350
+ ```
351
+ ╔═══════════════════════════════════════════════╗
352
+ ║ Kryptika Node ║
353
+ ╠═══════════════════════════════════════════════╣
354
+ ║ Port : 5000 ║
355
+ ║ Difficulty : 3 ║
356
+ ║ Database : chain_5000.db ║
357
+ ╠═══════════════════════════════════════════════╣
358
+ ║ GET /chain /status /peers /peers/sync ║
359
+ ║ GET /mine?address=<addr> ║
360
+ ║ GET /balance/<addr> /history/<addr> ║
361
+ ║ GET /transactions/pending /wallet/new ║
362
+ ║ POST /peers/add /peers/receive ║
363
+ ║ POST /transactions/new /transactions/receive ║
364
+ ╚═══════════════════════════════════════════════╝
365
+ ```
366
+
367
+ > **Tip:** If you installed via `pip install -e .`, you can also use `kryptika-node` instead of `python run_node.py`.
368
+
369
+ ---
370
+
371
+ ## 7. Wallet CLI
372
+
373
+ The wallet CLI is your terminal interface for everything wallet-related — creating wallets, checking balances, sending coins, mining, and managing peers.
374
+
375
+ ### Launching
376
+
377
+ ```bash
378
+ python wallet_cli.py # scans ports 5000–5010 and lets you pick
379
+ python wallet_cli.py 5001 # connect directly to port 5001
380
+ python wallet_cli.py 192.168.1.5:5000 # connect to a node on another machine
381
+ ```
382
+
383
+ ### Picking a node
384
+
385
+ If you don't specify a port, the CLI scans for whatever nodes are already running and shows you a list:
386
+
387
+ ```
388
+ ╔════════════════════════════════════════════════════════╗
389
+ ║ Kryptika Wallet CLI - Node Selection ║
390
+ ╠════════════════════════════════════════════════════════╣
391
+ ║ Scanning for running nodes... ║
392
+ ║ ║
393
+ ║ [1] localhost:5000 height=4 peers=1 mempool=0 ║
394
+ ║ [2] localhost:5001 height=4 peers=1 mempool=2 ║
395
+ ║ ║
396
+ ║ [c] Enter a custom address ║
397
+ ║ ║
398
+ ║ Select node (Enter for [1]): ║
399
+ ╚════════════════════════════════════════════════════════╝
400
+ ```
401
+
402
+ ### Menu
403
+
404
+ ```
405
+ ╔════════════════════════════════════════╗
406
+ ║ Kryptika Wallet ║
407
+ ╠════════════════════════════════════════╣
408
+ ║ 1. Create / load wallet ║
409
+ ║ 2. Show balance ║
410
+ ║ 3. Send coins ║
411
+ ║ 4. Transaction history ║
412
+ ║ 5. Mine a block ║
413
+ ║ 6. View pending transactions ║
414
+ ║ 7. View the full chain ║
415
+ ║ 8. Node status ║
416
+ ║ 9. Manage peers / multi-node ║
417
+ ║ 0. Exit ║
418
+ ╚════════════════════════════════════════╝
419
+ ```
420
+
421
+ > ⚠️ **Heads up:** `wallets.json` stores your private keys in plain hex. Don't share this file and don't commit it to version control.
422
+
423
+ ---
424
+
425
+ ## 8. Multi-Node Network
426
+
427
+ ### Setting up a 3-node network
428
+
429
+ Open three terminals from the project root and start a node in each:
430
+
431
+ ```bash
432
+ # Terminal 1
433
+ python run_node.py 5000
434
+
435
+ # Terminal 2
436
+ python run_node.py 5001
437
+
438
+ # Terminal 3
439
+ python run_node.py 5002
440
+ ```
441
+
442
+ ### Connecting the nodes
443
+
444
+ ```bash
445
+ python wallet_cli.py 5000
446
+ ```
447
+
448
+ Go to **option 9 → Add a peer** and add the other two:
449
+
450
+ ```
451
+ Add peer: localhost:5001 ← syncs and registers both ways
452
+ Add peer: localhost:5002 ← syncs and registers both ways
453
+ ```
454
+
455
+ Then open the CLI on port 5001 and do the last connection:
456
+
457
+ ```
458
+ Add peer: localhost:5002 ← all three nodes now know each other
459
+ ```
460
+
461
+ Your network is now **fully meshed** — mine on any node and every other node sees the new block instantly.
462
+
463
+ ### Recommended workflow
464
+
465
+ 1. Mine a few blocks on port 5000 to get some coins in circulation.
466
+ 2. Connect all three peers together.
467
+ 3. Submit transactions from any node — they'll propagate automatically.
468
+ 4. Mine from any node — the new block broadcasts to everyone.
469
+ 5. All nodes settle on the same chain.
470
+
471
+ ### How forks resolve
472
+
473
+ If two nodes happen to mine at the same height at the same time, a temporary fork forms. This is normal. As soon as any node mines the next block, it broadcasts a chain that's one block longer. Every other node sees it, validates it, and switches over. Forks self-heal in seconds.
474
+
475
+ > Transactions broadcast to one node's mempool immediately reach all peers. If a peer misses the initial broadcast, it picks up the transaction when the block syncs anyway.
476
+
477
+ ---
478
+
479
+ ## 9. REST API Reference
480
+
481
+ Every response is JSON. If something goes wrong, the response will have an `"error"` key explaining what happened.
482
+
483
+ ### GET Endpoints
484
+
485
+ | Endpoint | Description | Response |
486
+ |---|---|---|
487
+ | `GET /chain` | Full chain as a JSON array | `[{"index": 0, ...}, ...]` |
488
+ | `GET /status` | Node health summary | `{"height": 4, "mempool": 1, ...}` |
489
+ | `GET /peers` | List of connected peers | `{"peers": ["localhost:5001"]}` |
490
+ | `GET /peers/sync` | Pull chains from all peers; adopt the longest | `{"replaced": true, "height": 5}` |
491
+ | `GET /mine?address=<addr>` | Mine pending transactions; send reward to `<addr>` | `{"index": 4, "miner_reward": 10.5}` |
492
+ | `GET /balance/<address>` | Confirmed coin balance for an address | `{"balance": 9.5}` |
493
+ | `GET /history/<address>` | All confirmed transactions for an address | `{"count": 3, "history": [...]}` |
494
+ | `GET /transactions/pending` | Transactions sitting in the mempool | `{"count": 1, "transactions": [...]}` |
495
+ | `GET /wallet/new` | Generate a fresh address (private key is not saved) | `{"address": "abc123..."}` |
496
+
497
+ ### POST Endpoints
498
+
499
+ | Endpoint | Body | Description |
500
+ |---|---|---|
501
+ | `POST /peers/add` | `{"address": "localhost:5001"}` | Connect to another node |
502
+ | `POST /peers/receive` | `[{block}, ...]` | Accept a chain broadcast from a peer |
503
+ | `POST /transactions/new` | `{transaction dict}` | Submit a signed transaction |
504
+ | `POST /transactions/receive` | `{transaction dict}` | Accept a peer-broadcast transaction |
505
+
506
+ ### curl Examples
507
+
508
+ ```bash
509
+ # Check node status
510
+ curl http://localhost:5000/status
511
+
512
+ # Check a balance
513
+ curl http://localhost:5000/balance/<address>
514
+
515
+ # Mine a block (reward goes to your address)
516
+ curl "http://localhost:5000/mine?address=<your_address>"
517
+
518
+ # Submit a signed transaction
519
+ curl -X POST http://localhost:5000/transactions/new \
520
+ -H "Content-Type: application/json" \
521
+ -d '{"sender": "...", "recipient": "...", "amount": 5.0, "fee": 0.5, "signature": "...", "public_key": "..."}'
522
+
523
+ # Connect to another node
524
+ curl -X POST http://localhost:5000/peers/add \
525
+ -H "Content-Type: application/json" \
526
+ -d '{"address": "localhost:5001"}'
527
+
528
+ # Sync with all peers
529
+ curl http://localhost:5000/peers/sync
530
+ ```
531
+
532
+ ---
533
+
534
+ ## 10. Running the Tests
535
+
536
+ Make sure your virtual environment is active, then run from the project root:
537
+
538
+ ```bash
539
+ python tests/test_core.py # 34 unit tests
540
+ python tests/test_storage.py # 5 storage tests
541
+ python tests/test_network.py # 13 integration tests
542
+ ```
543
+
544
+ Or run everything at once with pytest:
545
+
546
+ ```bash
547
+ pytest
548
+ ```
549
+
550
+ All 52 tests should go green. The network tests spin up real HTTP servers on ports 5100–5114 and clean up after themselves, so they won't interfere with any nodes you have running.
551
+
552
+ ### What's covered
553
+
554
+ **Core — 34 tests**
555
+ - Transaction creation, signing, and signature verification
556
+ - Tamper detection on signed transactions
557
+ - Coinbase transactions and mining rewards
558
+ - Block hashing and determinism
559
+ - Proof of Work enforcement and difficulty compliance
560
+ - Chain validation — tampered data, broken links, invalid signatures
561
+ - Balance calculation and fee accounting
562
+ - Replay attack prevention via `tx_id`
563
+ - Batch double-spend rejection inside `mine_block()`
564
+
565
+ **Storage — 5 tests**
566
+ - Full save/load round-trip with chain integrity verified
567
+ - Hash preservation across serialise / deserialise cycle
568
+ - Atomic overwrite — a new save fully replaces old data without corruption
569
+
570
+ **Network — 13 tests**
571
+ - All HTTP endpoints: chain, mine, balance, peers, transactions
572
+ - P2P broadcast — mine on one node, watch it show up on a connected peer
573
+ - Sync — a shorter chain adopts the longer one from a peer
574
+ - Threading — `/status` stays responsive while `/mine` is grinding through PoW
575
+
576
+ ---
577
+
578
+ ## 11. Architecture Notes
579
+
580
+ ### Why PoW runs outside the node lock
581
+
582
+ When you call `/mine`, the Proof of Work computation happens before the lock is acquired. Only the final step — appending the block and saving to disk — is protected. This means `/status`, `/balance`, `/history`, and all read endpoints stay fast and responsive even when mining is in progress. If a peer pushes a longer chain while you're mid-mine, the block you were building gets quietly discarded instead of creating a conflict.
583
+
584
+ ### Why amounts use Decimal arithmetic
585
+
586
+ Python's `float` type drifts. After enough transactions, `balance == expected_value` can 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 with satoshis.
587
+
588
+ ### Why `wallets.json` is written atomically
589
+
590
+ When saving wallets, the code writes to a temporary `.tmp` file first, then calls `os.replace()`. On every platform, `os.replace()` is atomic — either the full file lands or nothing changes. A crash in the middle of writing can't leave you with a half-written, unreadable wallet file.
591
+
592
+ ### Why the confirmed `tx_id` cache is incremental
593
+
594
+ `Node._confirmed_ids` is a set that grows with the chain rather than being rebuilt from scratch on every transaction check. When a block is mined, only its `tx_id`s get added. When a longer chain is adopted via sync, the set rebuilds once. This avoids an O(N×M) scan on every incoming transaction while keeping replay protection intact.
595
+
596
+ ---
597
+
598
+ ## 12. Security Model
599
+
600
+ Here's what Kryptika does and doesn't protect against:
601
+
602
+ | Property | How it's enforced |
603
+ |---|---|
604
+ | **Signature forgery** | ECDSA P-256 — you can't sign a transaction without the private key |
605
+ | **Tamper detection** | SHA-256 chain hashing — one changed byte breaks all downstream links |
606
+ | **Replay attacks** | `tx_id` is checked against both the confirmed chain and the mempool on every submission |
607
+ | **Mempool double-spend** | Effective balance = confirmed minus pending; checked before any transaction is queued |
608
+ | **Block double-spend** | `batch_spend` tracks cumulative spend per sender within each call to `mine_block()` |
609
+ | **Thread safety** | `RLock` protects all state mutations; PoW runs outside the lock so reads never block |
610
+ | **Disk integrity** | SQLite writes use explicit `BEGIN / COMMIT / ROLLBACK` — no partial saves |
611
+ | **Request flooding** | Incoming HTTP request bodies are hard-capped at 10 MB |
612
+
613
+ ---
614
+
615
+ ## 13. Known Limitations
616
+
617
+ Kryptika is built for learning, not production. Here's what it deliberately leaves out — and what a real system would do instead:
618
+
619
+ | What's missing | Why it matters |
620
+ |---|---|
621
+ | **No wallet encryption** | Private keys sit in `wallets.json` as plain hex. Real wallets encrypt keys at rest (BIP-38, AES with a password, etc.). |
622
+ | **No peer authentication** | Anyone who knows your IP can push a chain to `/peers/receive`. Production nodes verify and whitelist peers before accepting data. |
623
+ | **No Merkle tree** | Blocks store the full transaction list. Real blockchains use Merkle trees so you can prove a transaction is in a block without downloading the whole thing. |
624
+ | **No UTXO set** | Checking your balance means scanning every block from genesis. Bitcoin keeps a set of unspent outputs so lookups are constant-time instead. |
625
+ | **Fixed mining reward** | The reward is always 10 coins. Bitcoin halves it roughly every four years to limit total supply — Kryptika doesn't. |
626
+ | **No fee-priority queue** | Every pending transaction gets included in the next block regardless of fee size. Real mempools sort by fee and drop low-priority transactions when congested. |
627
+ | **localhost-only peer discovery** | The node listens on all interfaces, but the CLI only scans `localhost` ports automatically. To connect a remote node, you have to add it manually. |
628
+
629
+ ---
630
+
631
+ ## 14. License
632
+
633
+ Released under the **MIT License** — see the [`LICENSE`](LICENSE) file for details.
634
+
635
+ ---
636
+
637
+ <div align="center">
638
+
639
+ Built with pure Python · No blockchain frameworks · No shortcuts
640
+
641
+ *Read the source. Break things. Learn how it works.*
642
+
643
+ </div>