Files
aitbc/docs/reference/bootstrap/wallet_daemon.md
oib c8be9d7414 feat: add marketplace metrics, privacy features, and service registry endpoints
- Add Prometheus metrics for marketplace API throughput and error rates with new dashboard panels
- Implement confidential transaction models with encryption support and access control
- Add key management system with registration, rotation, and audit logging
- Create services and registry routers for service discovery and management
- Integrate ZK proof generation for privacy-preserving receipts
- Add metrics instru
2025-12-22 10:33:23 +01:00

336 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# wallet-daemon.md
> **Role:** Local wallet service (keys, signing, RPC) for the 🤖 AITBC 🤑 stack
> **Audience:** Windsurf (programming assistant) + developers
> **Stage:** Bootable without blockchain; later pluggable to chain node
---
## 1) What this daemon is (and isnt)
**Goals**
1. Generate/import encrypted wallets (seed or raw keys).
2. Derive accounts/addresses (HD, multiple curves).
3. Hold keys **locally** and sign messages/transactions/receipts.
4. Expose a minimal **RPC** for client/coordinator/miner.
5. Provide a mock “ledger view” (balance cache + test transfers) until the chain is ready.
**Non-Goals (for now)**
- No P2P networking.
- No full node / block validation.
- No remote key export (never leaves box unencrypted).
---
## 2) Architecture (minimal, extensible)
- **Process:** Python FastAPI app (`uvicorn`)
- **RPC:** HTTP+JSON (REST) and JSON-RPC (both; same server)
- **KeyStore:** on-disk, encrypted with **Argon2id + XChaCha20-Poly1305**
- **Curves:** `ed25519` (default), `secp256k1` (optional flag per-account)
- **HD Derivation:** BIP-39 seed → SLIP-10 (ed25519), BIP-32 (secp256k1)
- **Coin type (provisional):** `AITBC = 12345` (placeholder; replace once registered)
- **Auth:** Local-only by default (bind `127.0.0.1`), optional token header for remote.
- **Events:** Webhooks + local FIFO/Unix-socket stream for “signed” notifications.
- **Mock Ledger (stage-1):** sqlite table for balances & transfers; sync adapter later.
**Directory layout**
```
wallet-daemon/
├─ app/ # FastAPI service
│ ├─ main.py # entrypoint
│ ├─ api_rest.py # REST routes
│ ├─ api_jsonrpc.py # JSON-RPC methods
│ ├─ crypto/ # key, derivation, sign, addr
│ ├─ keystore/ # encrypted store backend
│ ├─ models/ # pydantic schemas
│ ├─ ledger_mock/ # sqlite-backed balances
│ └─ settings.py # config
├─ data/
│ ├─ keystore/ # *.kdb (per wallet)
│ └─ ledger.db
├─ tests/
└─ run.sh
```
---
## 3) Security model (Windsurf implementation notes)
- **Passwords:** Argon2id (tuned to machine; env overrides)
- `ARGON_TIME=4`, `ARGON_MEMORY=256MB`, `ARGON_PARALLELISM=2` (defaults)
- **Encryption:** libsodium `crypto_aead_xchacha20poly1305_ietf`
- **At-Rest Format (per wallet file)**
```
magic=v1-kdb
salt=32B
argon_params={t,m,p}
nonce=24B
ciphertext=… # includes seed or master private key; plus metadata JSON
```
- **In-memory:** zeroize sensitive bytes after use; use `memoryview`/`ctypes` scrubbing where possible.
- **API hardening:**
- Bind to `127.0.0.1` by default.
- Optional `X-Auth-Token: <TOKEN>` for REST/JSON-RPC.
- Rate limits on sign endpoints.
---
## 4) Key & address strategy
- **Wallet types**
1. **HD (preferred):** BIP-39 mnemonic (12/24 words) → master seed.
2. **Single-key:** import raw private key (ed25519/secp256k1).
- **Derivation paths**
- **ed25519 (SLIP-10):** `m / 44' / 12345' / account' / change / index`
- **secp256k1 (BIP-44):** `m / 44' / 12345' / account' / change / index`
- **Address format (temporary)**
- **ed25519:** `base32(bech32_hrp="ait")` of `blake2b-20(pubkey)`
- **secp256k1:** same hash → bech32; flag curve in metadata
> Replace HRP and hash rules if the canonical AITBC chain spec differs.
---
## 5) REST API (for Windsurf to scaffold)
**Headers**
- Optional: `X-Auth-Token: <token>`
- `Content-Type: application/json`
### 5.1 Wallet lifecycle
- `POST /v1/wallet/create`
- body: `{ "name": "main", "password": "…", "mnemonic_len": 24 }`
- returns: `{ "wallet_id": "…" }`
- `POST /v1/wallet/import-mnemonic`
- `{ "name":"…","password":"…","mnemonic":"…","passphrase":"" }`
- `POST /v1/wallet/import-key`
- `{ "name":"…","password":"…","curve":"ed25519|secp256k1","private_key_hex":"…" }`
- `POST /v1/wallet/unlock`
- `{ "wallet_id":"…","password":"…" }` → unlocks into memory for N seconds (config TTL)
- `POST /v1/wallet/lock` → no body
- `GET /v1/wallets` → list minimal metadata (never secrets)
### 5.2 Accounts & addresses
- `POST /v1/account/derive`
- `{ "wallet_id":"…","curve":"ed25519","path":"m/44'/12345'/0'/0/0" }`
- `GET /v1/accounts?wallet_id=…`
- `GET /v1/address/{account_id}` → `{ "address":"ait1…", "curve":"ed25519" }`
### 5.3 Signing
- `POST /v1/sign/message`
- `{ "account_id":"…","message_base64":"…" }` → `{ "signature_base64":"…" }`
- `POST /v1/sign/tx`
- `{ "account_id":"…","tx_bytes_base64":"…","type":"aitbc_v0" }` → signature + (optionally) signed blob
- `POST /v1/sign/receipt`
- `{ "account_id":"…","payload":"…"}`
- **Used by coordinator/miner** to sign job receipts & payouts.
### 5.4 Mock ledger (stage-1 only)
- `GET /v1/ledger/balance/{address}`
- `POST /v1/ledger/transfer`
- `{ "from":"…","to":"…","amount":"123.456","memo":"test" }`
- `GET /v1/ledger/tx/{txid}`
### 5.5 Webhooks
- `POST /v1/webhooks`
- `{ "url":"https://…/callback", "events":["signed","transfer"] }`
**Error model**
```json
{ "error": { "code": "WALLET_LOCKED|NOT_FOUND|BAD_PASSWORD|RATE_LIMIT", "detail": "…" } }
```
---
## 6) JSON-RPC mirror (method → params)
- `wallet_create(name, password, mnemonic_len)`
- `wallet_import_mnemonic(name, password, mnemonic, passphrase)`
- `wallet_import_key(name, password, curve, private_key_hex)`
- `wallet_unlock(wallet_id, password)` / `wallet_lock()`
- `account_derive(wallet_id, curve, path)`
- `sign_message(account_id, message_base64)`
- `sign_tx(account_id, tx_bytes_base64, type)`
- `ledger_getBalance(address)` / `ledger_transfer(from, to, amount, memo)`
Same auth header; endpoint `/rpc`.
---
## 7) Data schemas (Pydantic hints)
```py
class WalletMeta(BaseModel):
wallet_id: str
name: str
curves: list[str] # ["ed25519", "secp256k1"]
created_at: datetime
class AccountMeta(BaseModel):
account_id: str
wallet_id: str
curve: Literal["ed25519","secp256k1"]
path: str # HD path or "imported"
address: str # bech32 ait1...
class SignedResult(BaseModel):
signature_base64: str
public_key_hex: str
algo: str # e.g., ed25519
```
---
## 8) Configuration (ENV)
```
WALLET_BIND=127.0.0.1
WALLET_PORT=8555
WALLET_TOKEN= # optional
KEYSTORE_DIR=./data/keystore
LEDGER_DB=./data/ledger.db
UNLOCK_TTL_SEC=120
ARGON_TIME=4
ARGON_MEMORY_MB=256
ARGON_PARALLELISM=2
```
---
## 9) Minimal boot script (dev)
```bash
# run.sh
export WALLET_BIND=127.0.0.1
export WALLET_PORT=8555
export KEYSTORE_DIR=./data/keystore
mkdir -p "$KEYSTORE_DIR" data
exec uvicorn app.main:app --host ${WALLET_BIND} --port ${WALLET_PORT}
```
---
## 10) Systemd unit (prod, template)
```
[Unit]
Description=AITBC Wallet Daemon
After=network.target
[Service]
User=root
WorkingDirectory=/opt/aitbc/wallet-daemon
Environment=WALLET_BIND=127.0.0.1
Environment=WALLET_PORT=8555
Environment=KEYSTORE_DIR=/opt/aitbc/wallet-daemon/data/keystore
ExecStart=/usr/bin/uvicorn app.main:app --host 127.0.0.1 --port 8555
Restart=always
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
[Install]
WantedBy=multi-user.target
```
---
## 11) Curl smoke tests
```bash
# 1) Create + unlock
curl -s localhost:8555/v1/wallet/create -X POST \
-H 'Content-Type: application/json' \
-d '{"name":"main","password":"pw","mnemonic_len":24}'
curl -s localhost:8555/v1/wallets
# 2) Derive first account
curl -s localhost:8555/v1/account/derive -X POST \
-H 'Content-Type: application/json' \
-d '{"wallet_id":"W1","curve":"ed25519","path":"m/44'/12345'/0'/0/0"}'
# 3) Sign message
curl -s localhost:8555/v1/sign/message -X POST \
-H 'Content-Type: application/json' \
-d '{"account_id":"A1","message_base64":"aGVsbG8="}'
```
---
## 12) Coordinator/miner integration (stage-1)
**Coordinator needs:**
- `GET /v1/address/{account_id}` for payout address lookup.
- `POST /v1/sign/receipt` to sign `{job_id, miner_id, result_hash, ts}`.
- Optional webhook on `signed` to chain/queue the payout request.
**Miner needs:**
- Local message signing for **proof-of-work-done** receipts.
- Optional “ephemeral sub-accounts” derived at `change=1` for per-job audit.
---
## 13) Migration path to real chain
1. Introduce **ChainAdapter** interface:
- `get_balance(address)`, `broadcast_tx(signed_tx)`, `fetch_utxos|nonce`, `estimate_fee`.
2. Implement `MockAdapter` (current), then `AitbcNodeAdapter` (RPC to real node).
3. Swap via `WALLET_CHAIN=mock|aitbc`.
---
## 14) Windsurf tasks checklist
1. Create repo structure (see **Directory layout**).
2. Add dependencies: `fastapi`, `uvicorn`, `pydantic`, `argon2-cffi`, `pynacl` (or `libsodium` bindings), `bech32`, `sqlalchemy` (for mock ledger), `aiosqlite`.
3. Implement **keystore** (encrypt/decrypt, file IO, metadata).
4. Implement **HD derivation** (SLIP-10 for ed25519, BIP-32 for secp256k1).
5. Implement **address** helper (hash → bech32 with `ait`).
6. Implement **REST** routes, then JSON-RPC shim.
7. Implement **mock ledger** with sqlite + simple transfers.
8. Add **webhook** delivery (async task + retry).
9. Add **rate limits** on signing; add unlock TTL.
10. Write unit tests for keystore, derivation, signing.
11. Provide `run.sh` + systemd unit.
12. Add curl examples to `README`.
---
## 15) Open questions (defaults proposed)
1. Keep both curves or start **ed25519-only**? → **Start ed25519-only**, gate secp256k1 by flag.
2. HRP `ait` and hash `blake2b-20` acceptable as interim? → **Yes (interim)**.
3. Store **per-account tags** (e.g., “payout”, “ops”)? → **Yes**, simple string map.
---
## 16) Threat model notes (MVP)
- Local compromise = keys at risk ⇒ encourage **passphrase on mnemonic** + **short unlock TTL**.
- Add **IPC allowlist** if binding to non-localhost.
- Consider **YubiKey/PKCS#11** module later (signing via hardware).
---
## 17) Logging
- Default: INFO without sensitive fields.
- Redact: passwords, mnemonics, private keys, nonces.
- Correlate by `req_id` header (generate if missing).
---
## 18) License / Compliance
- Keep crypto libs permissive (MIT/ISC/BSD).
- Record algorithm choices & versions in `/about` endpoint for audits.
---
**Proceed to generate the scaffold (FastAPI app + keystore + ed25519 HD + REST) now?** `y` / `n`