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
This commit is contained in:
oib
2025-12-22 10:33:23 +01:00
parent d98b2c7772
commit c8be9d7414
260 changed files with 59033 additions and 351 deletions

View File

@ -0,0 +1,335 @@
# 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`