# blockchain-node/ — Minimal Chain (asset-backed by compute) ## 0) TL;DR boot path for Windsurf 1. Create the service: `apps/blockchain-node` (Python, FastAPI, asyncio, uvicorn). 2. Data layer: `sqlite` via `SQLModel` (later: PostgreSQL). 3. P2P: WebSocket gossip (lib: `websockets`) with a simple overlay (peer table + heartbeats). 4. Consensus (MVP): **PoA single-author** (devnet) → upgrade to **Compute-Backed Proof (CBP)** after coordinator & miner telemetry are wired. 5. Block content: **ComputeReceipts** = “proofs of delivered AI work” signed by miners, plus standard transfers. 6. Minting: AIToken minted per verified compute unit (e.g., `1 AIT = 1,000 token-ops` — calibrate later). 7. REST RPC: `/rpc/*` for clients & coordinator; `/p2p/*` for peers; `/admin/*` for node ops. 8. Ship a `devnet` script that starts: 1 bootstrap node, 1 coordinator-api mock, 1 miner mock, 1 client demo. --- ## 1) Goal & Scope - Provide a **minimal, testable blockchain node** that issues AITokens **only** when real compute was delivered (asset-backed). - Easy to run, easy to reset, deterministic devnet. - Strong boundaries so **coordinator-api** (job orchestration) and **miner-node** (workers) can integrate quickly. Out of scope (MVP): - Smart contracts VM. - Sharding/advanced networking. - Custodial wallets. (Use local keypairs for dev.) --- ## 2) Core Concepts ### 2.1 Actors - **Client**: pays AITokens to request compute jobs. - **Coordinator**: matches jobs ↔ miners; returns signed receipts. - **Miner**: executes jobs; produces **ComputeReceipt** signed with miner key. - **Blockchain Node**: validates receipts, mints AIT for miners, tracks balances, finalizes blocks. ### 2.2 Asset-Backed Minting - Unit of account: **AIToken (AIT)**. - A miner earns AIT when a **ComputeReceipt** is included in a block. - A receipt is valid iff: 1) Its `job_id` exists in coordinator logs, 2) `client_payment_tx` covers the quoted price, 3) `miner_sig` over `(job_id, hash(output_meta), compute_units, price, nonce)` is valid, 4) Not previously claimed (`receipt_id` unique). --- ## 3) Minimal Architecture ``` blockchain-node/ ├─ src/ │ ├─ main.py # FastAPI entry │ ├─ p2p.py # WS gossip, peer table, block relay │ ├─ consensus.py # PoA/CBP state machine │ ├─ types.py # dataclasses / pydantic models │ ├─ state.py # DB access (SQLModel), UTXO/Account │ ├─ mempool.py # tx pool (transfers + receipts) │ ├─ crypto.py # ed25519 keys, signatures, hashing │ ├─ receipts.py # receipt validation (with coordinator) │ ├─ blocks.py # block build/verify, difficulty stub │ ├─ rpc.py # REST/RPC routes for clients & ops │ └─ settings.py # env config ├─ tests/ │ └─ ... # unit & integration tests ├─ scripts/ │ ├─ devnet_up.sh # run bootstrap node + mocks │ └─ keygen.py # create node/miner/client keys ├─ README.md └─ requirements.txt ``` --- ## 4) Data Model (SQLModel) ### 4.1 Tables - `blocks(id, parent_id, height, timestamp, proposer, tx_count, hash, state_root, sig)` - `tx(id, block_id, type, payload_json, sender, nonce, fee, sig, hash, status)` - `accounts(address, balance, nonce, pubkey)` - `receipts(receipt_id, job_id, client_addr, miner_addr, compute_units, price, output_hash, miner_sig, status)` - `peers(node_id, addr, last_seen, score)` - `params(key, value)` — chain config (mint ratios, fee rate, etc.) ### 4.2 TX Types - `TRANSFER`: move AIT from A → B - `RECEIPT_CLAIM`: include a **ComputeReceipt**; mints to miner and settles client escrow - `STAKE/UNSTAKE` (later) - `PARAM_UPDATE` (PoA only, gated by admin key for devnet) --- ## 5) Block Format (JSON) ```json { "parent": "", "height": 123, "timestamp": 1699999999, "proposer": "", "txs": ["", "..."], "stateRoot": "", "sig": "" } ``` Header sign bytes = `hash(parent|height|timestamp|proposer|stateRoot)` --- ## 6) Consensus ### 6.1 MVP: PoA (Single Author) - One configured `PROPOSER_KEY` creates blocks at fixed interval (e.g., 2s). - Honest mode only for devnet; finality by canonical longest/height rule. ### 6.2 Upgrade: **Compute-Backed Proof (CBP)** - Each block’s **work score** = total `compute_units` in included receipts. - Proposer election = weighted round-robin by recent work score and stake (later). - Slashing: submitting invalid receipts reduces score; repeated offenses → temp ban. --- ## 7) Receipt Validation (Coordinator Check) `receipts.py` performs: 1) **Coordinator attestation** (HTTP call to coordinator-api): - `/attest/receipt` with `job_id`, `client`, `miner`, `price`, `compute_units`, `output_hash`. - Returns `{exists: bool, paid: bool, not_double_spent: bool, quote: {...}}`. 2) **Signature check**: verify `miner_sig` with miner’s `pubkey`. 3) **Economic checks**: ensure `client_payment_tx` exists & covers `price + fee`. > For devnet without live coordinator, ship a **mock** that returns deterministic attestation for known `job_id` ranges. --- ## 8) Fees & Minting - **Fee model (MVP)**: `fee = base_fee + k * payload_size`. - **Minting**: - Miner gets: `mint = compute_units * MINT_PER_UNIT`. - Coordinator gets: `coord_cut = mint * COORDINATOR_RATIO`. - Chain treasury (optional): small %, configurable in `params`. --- ## 9) RPC Surface (FastAPI) ### 9.1 Public - `POST /rpc/sendTx` → `{txHash}` - `GET /rpc/getTx/{txHash}` → `{status, receipt}` - `GET /rpc/getBlock/{heightOrHash}` - `GET /rpc/getHead` → `{height, hash}` - `GET /rpc/getBalance/{address}` → `{balance, nonce}` - `POST /rpc/estimateFee` → `{fee}` ### 9.2 Coordinator-facing - `POST /rpc/submitReceipt` (alias of `sendTx` with type `RECEIPT_CLAIM`) - `POST /rpc/attest` (devnet mock only) ### 9.3 Admin (devnet) - `POST /admin/paramSet` (PoA only) - `POST /admin/peers/add` `{addr}` - `POST /admin/mintFaucet` `{address, amount}` (devnet) ### 9.4 P2P (WS) - `GET /p2p/peers` → list - `WS /p2p/ws` → subscribe to gossip: `{"type":"block"|"tx"|"peer","data":...}` --- ## 10) Keys & Crypto - **ed25519** for account & node keys. - Address = `bech32(hrp="ait", sha256(pubkey)[0:20])`. - Sign bytes: - TX: `hash(type|sender|nonce|fee|payload_json_canonical)` - Block: header hash as above. Ship `scripts/keygen.py` for dev use. --- ## 11) Mempool Rules - Accept if: - `sig` valid, - `nonce == account.nonce + 1`, - `fee >= minFee`, - For `RECEIPT_CLAIM`: passes `receipts.validate()` *optimistically* (soft-accept), then **revalidate** at block time. Replacement: higher-fee replaces same `(sender, nonce)`. --- ## 12) Node Lifecycle **Start:** 1) Load config, open DB, ensure genesis. 2) Connect to bootstrap peers (if any). 3) Start RPC (FastAPI) + P2P WS server. 4) Start block proposer (if PoA key present). 5) Start peer heartbeats + gossip loops. **Shutdown:** - Graceful: flush mempool snapshot, close DB. --- ## 13) Genesis - `genesis.json`: - `chain_id`, `timestamp`, `accounts` (faucet), `params` (mint ratios, base fee), `authorities` (PoA keys). Provide `scripts/make_genesis.py`. --- ## 14) Devnet: End-to-End Demo ### 14.1 Components - **blockchain-node** (this repo) - **coordinator-api (mock)**: `/attest/receipt` returns valid for `job_id` in `[1..1_000_000]` - **miner-node (mock)**: posts `RECEIPT_CLAIM` for synthetic jobs - **client-web (demo)**: sends `TRANSFER` & displays balances ### 14.2 Flow 1) Client pays `price` to escrow address (coordinator). 2) Miner executes job; coordinator verifies output. 3) Miner submits **ComputeReceipt** → included in next block. 4) Mint AIT to miner; escrow settles; client charged. --- ## 15) Testing Strategy ### 15.1 Unit - `crypto`: keygen, sign/verify, address derivation - `state`: balances, nonce, persistence - `receipts`: signature + coordinator mock - `blocks`: header hash, stateRoot ### 15.2 Integration - Single node PoA: produce N blocks; submit transfers/receipts; assert balances. - Two nodes P2P: block/tx relay; head convergence. ### 15.3 Property tests - Nonce monotonicity; no double-spend; unique receipts. --- ## 16) Observability - Structured logs (JSON) with `component`, `event`, `height`, `latency_ms`. - `/rpc/metrics` (Prometheus format) — block time, mempool size, peers. --- ## 17) Configuration (ENV) - `CHAIN_ID=ait-devnet` - `DB_PATH=./data/chain.db` - `P2P_BIND=127.0.0.2:7070` - `RPC_BIND=127.0.0.2:8080` - `BOOTSTRAP_PEERS=ws://host:7070,...` - `PROPOSER_KEY=...` (optional for non-authors) - `MINT_PER_UNIT=1000` - `COORDINATOR_RATIO=0.05` Provide `.env.example`. --- ## 18) Minimal API Payloads ### 18.1 TRANSFER ```json { "type": "TRANSFER", "sender": "ait1...", "nonce": 1, "fee": 10, "payload": {"to":"ait1...","amount":12345}, "sig": "" } ``` ### 18.2 RECEIPT_CLAIM ```json { "type": "RECEIPT_CLAIM", "sender": "ait1miner...", "nonce": 7, "fee": 50, "payload": { "receipt_id": "rcpt_7f3a...", "job_id": "job_42", "client_addr": "ait1client...", "miner_addr": "ait1miner...", "compute_units": 2500, "price": 50000, "output_hash": "sha256:abcd...", "miner_sig": "" }, "sig": "" } ``` --- ## 19) Security Notes (MVP) - Devnet PoA means trust in proposer; do **not** expose to internet without firewall. - Enforce coordinator host allowlist for attest calls. - Rate-limit `/rpc/sendTx`. --- ## 20) Roadmap 1) ✅ PoA devnet with receipts. 2) 🔜 CBP proposer selection from rolling work score. 3) 🔜 Stake & slashing. 4) 🔜 Replace SQLite with PostgreSQL. 5) 🔜 Snapshots & fast-sync. 6) 🔜 Light client (SPV of receipts & balances). --- ## 21) Developer Tasks (Windsurf Order) 1) **Scaffold** project & `requirements.txt`: - `fastapi`, `uvicorn[standard]`, `sqlmodel`, `pydantic`, `websockets`, `pyyaml`, `python-dotenv`, `ed25519`, `orjson`. 2) **Implement**: - `crypto.py`, `types.py`, `state.py`. - `rpc.py` (public routes). - `mempool.py`. - `blocks.py` (build/validate). - `consensus.py` (PoA tick). - `p2p.py` (WS server + simple gossip). - `receipts.py` (mock coordinator). 3) **Wire** `main.py`: - Start RPC, P2P, PoA loops. 4) **Scripts**: - `scripts/keygen.py`, `scripts/make_genesis.py`, `scripts/devnet_up.sh`. 5) **Tests**: - Add unit + an integration test that mints on a receipt. 6) **Docs**: - Update `README.md` with curl examples. --- ## 22) Curl Snippets (Dev) - Faucet (dev only): ```bash curl -sX POST localhost:8080/admin/mintFaucet -H 'content-type: application/json' \ -d '{"address":"ait1client...","amount":1000000}' ``` - Transfer: ```bash curl -sX POST localhost:8080/rpc/sendTx -H 'content-type: application/json' \ -d @transfer.json ``` - Submit Receipt: ```bash curl -sX POST localhost:8080/rpc/submitReceipt -H 'content-type: application/json' \ -d @receipt_claim.json ``` --- ## 23) Definition of Done (MVP) - Node produces blocks on PoA. - Can transfer AIT between accounts. - Can submit a valid **ComputeReceipt** → miner balance increases; escrow decreases. - Two nodes converge on same head via P2P. - Basic metrics exposed. --- ## 24) Next Files to Create - `src/main.py` - `src/crypto.py` - `src/types.py` - `src/state.py` - `src/mempool.py` - `src/blocks.py` - `src/consensus.py` - `src/p2p.py` - `src/receipts.py` - `src/rpc.py` - `scripts/keygen.py`, `scripts/devnet_up.sh` - `.env.example`, `README.md`, `requirements.txt`