upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/CHECKLIST.md
diff options
context:
space:
mode:
Diffstat (limited to 'CHECKLIST.md')
-rw-r--r--CHECKLIST.md98
1 files changed, 64 insertions, 34 deletions
diff --git a/CHECKLIST.md b/CHECKLIST.md
index 3b50c2a..02c8a4c 100644
--- a/CHECKLIST.md
+++ b/CHECKLIST.md
@@ -70,40 +70,69 @@
70- [x] DNS query logging for unauthenticated clients 70- [x] DNS query logging for unauthenticated clients
71- [x] Verified working with GrapheneOS phone (commit `236b61d`) 71- [x] Verified working with GrapheneOS phone (commit `236b61d`)
72 72
73## Phase 3: On-Device Wallet + ESP32-to-ESP32 Payments — IN PROGRESS 73## Phase 3: On-Device Wallet + Nostr Identity + Wifistr — IN PROGRESS
74### Wallet Module (wallet.c/h) 74### nucula Wallet Integration
75- [x] `hash_to_curve()` — SHA256 try-and-increment with Cashu domain separator 75- [x] Add nucula as git submodule (`nucula_src/`)
76- [x] `point_add()`, `scalar_mul()` — mbedTLS secp256k1 primitives 76- [x] Create `components/secp256k1/` (symlink to nucula's libsecp256k1)
77- [x] `random_scalar()` — ESP32 hardware RNG mod curve order 77- [x] Create `components/nucula_lib/` (C++ bridge + C API)
78- [x] Proof storage: `wallet_add_proofs()`, `wallet_remove_proof()`, `wallet_clear()` 78- [x] C bridge: `nucula_wallet.h` (init, receive, send, swap_all, balance, proofs_json)
79- [x] Keyset fetching: `wallet_fetch_keysets()` — GET /v1/keys from mint 79- [x] All wallet operations tested on Board A: pay, swap, send, persistence
80- [x] Full swap: `wallet_swap_proofs()` — generates blinded messages, POST /v1/swap, unblinds signatures 80
81- [x] Token creation: `wallet_create_token()` — encode proofs as `cashuA` token 81### Nostr Identity Derivation (identity.c/h)
82- [x] Wallet API endpoints: `GET /wallet`, `POST /wallet/swap`, `POST /wallet/send` 82- [x] Create `identity.h` — API: `identity_init(nsec_hex)`, derived value accessors
83- [x] Payment flow integration: received proofs added to wallet after session creation 83- [x] Create `identity.c` — HMAC-SHA512 derivation via mbedtls, npub via secp256k1
84- [x] mbedTLS 3.x compatibility (no direct point field access, no point_negate) 84- [x] Derive STA MAC: `tollgate_derive(nsec, "sta-mac", 0)` → 6 bytes, locally administered
85- [x] Unblinding: `C = C_ + (order - r) * G` approach 85- [x] Derive AP MAC: `tollgate_derive(nsec, "ap-mac", 0)` → 6 bytes, locally administered
86- [x] Clean build (0 warnings, 0 errors) 86- [x] Derive SSID: `"TollGate-" + hex(AP_MAC[3:6])`
87 87- [x] Derive AP IP: hash-based from AP MAC bytes
88### Wallet Persistence (wallet_persist.c/h) 88- [x] Compute npub: secp256k1 x-only pubkey from nsec
89- [ ] Implement `wallet_persist_save()` — serialize wallet to `/spiffs/wallet.json` 89- [x] Set MACs via `esp_wifi_set_mac()` in boot sequence
90- [ ] Implement `wallet_persist_load()` — deserialize wallet from `/spiffs/wallet.json` on boot 90
91- [ ] Add `persist_threshold_sats` to config.json and config struct 91### Nostr Event Signing (nostr_event.c/h)
92- [ ] Threshold logic: only persist when `balance >= persist_threshold_sats` 92- [x] Create `nostr_event.h` — NIP-01 event struct + sign/serialize API
93- [ ] Wire `wallet_persist_save()` into wallet mutations (add_proofs, swap, create_token) 93- [x] Create `nostr_event.c` — canonical JSON, SHA-256 ID, Schnorr signature
94- [ ] Wire `wallet_persist_load()` into `wallet_init()` 94- [x] Uses `secp256k1_schnorrsig_sign32()` for BIP-340 signatures
95- [ ] Build and verify clean compile 95
96### Geohash Encoding (geohash.c/h)
97- [x] Create `geohash.h` — `geohash_encode(lat, lon, precision, out)`
98- [x] Create `geohash.c` — standard base-32 geohash encoding
99
100### Wifistr Service Discovery (wifistr.c/h)
101- [x] Create `wifistr.h` — `wifistr_publish()` API
102- [x] Create `wifistr.c` — kind 38787 event builder + WebSocket relay publish
103- [x] Build event with tags: d, ssid, h, security, g, c
104- [x] WebSocket client: raw TCP + TLS (esp_tls.h) + HTTP Upgrade
105- [x] Publish on boot + periodic timer (6h default)
106
107### Config Changes (config.c/h)
108- [x] Add to struct: nsec, npub, nostr_geohash, nostr_relays, nostr_publish_interval_s, sta_mac, ap_mac
109- [x] Remove from JSON parsing: ap_ssid, ap_ip (now derived from nsec)
110- [x] Keep: ap_password, ap_channel, ap_max_conn (hardcoded defaults)
111- [x] Update default config.json template with nsec and Nostr fields
112
113### Boot Sequence Changes (tollgate_main.c)
114- [x] Call `identity_init(nsec)` after config load, before WiFi init
115- [x] Set STA/AP MAC via `esp_wifi_set_mac()` after `esp_wifi_init()`, before `esp_wifi_start()`
116- [x] Remove old `tollgate_config_derive_unique()` call
117- [x] Use derived SSID/IP in AP configuration
118- [x] Start wifistr publish task after services start
119
120### Build System
121- [x] Add identity.c, nostr_event.c, geohash.c, wifistr.c to CMakeLists.txt SRCS
122- [x] Add `secp256k1` to REQUIRES (for identity.c and nostr_event.c)
123- [x] Clean build (0 errors, 0 warnings)
96 124
97### Hardware Testing 125### Hardware Testing
98- [ ] Flash Board A, verify wallet boot (keyset fetch succeeds) 126- [x] Flash Board A, verify wallet boot (keyset fetch succeeds)
99- [ ] Pay Board A with Cashu token, verify proofs stored (GET /wallet) 127- [x] Pay Board A with Cashu token, verify proofs stored (GET /wallet)
100- [ ] Test POST /wallet/swap on Board A 128- [x] Test POST /wallet/swap on Board A
101- [ ] Test POST /wallet/send on Board A, verify token is valid 129- [x] Test POST /wallet/send on Board A, verify token is valid
102- [ ] Verify persistence survives reboot on Board A 130- [x] Flash Board A with new identity derivation, verify derived SSID/MAC/IP
103- [ ] Flash Board B with TollGate firmware 131- [x] Verify captive portal works with new SSID/IP
104- [ ] Load Board B with balance (pay it a token) 132- [x] Verify payment flow still works with identity-derived config
105- [ ] Board B creates send token via POST /wallet/send 133- [x] Verify wifistr event published to relay (damus + nos.lol)
106- [ ] Cross-board payment: Board B token → Board A (laptop relay) 134- [ ] Flash Board B with new firmware (different nsec)
135- [ ] Cross-board payment: Board B token → Board A
107- [ ] Verify both boards show correct balances after cross-board payment 136- [ ] Verify both boards show correct balances after cross-board payment
108 137
109### Tests 25-27 (deferred from Phase 2, need Board B) 138### Tests 25-27 (deferred from Phase 2, need Board B)
@@ -131,8 +160,9 @@
131 160
132## Reminders 161## Reminders
133- Do NOT ask for instructions — proceed independently, skip blocked items, work on unblocked ones 162- Do NOT ask for instructions — proceed independently, skip blocked items, work on unblocked ones
134- Board A: `/dev/ttyACM0`, MAC `94:a9:90:2e:37:7c`, SSID `TollGate-377C`, AP IP `10.55.85.1` 163- Board A: `/dev/ttyACM0`, factory MAC `94:a9:90:2e:37:7c`
135- Board B: `/dev/ttyACM1`, MAC `fc:01:2c:c5:50:50` 164- Board B: `/dev/ttyACM1`, factory MAC `fc:01:2c:c5:50:50`
165- Identity is now derived from nsec in config.json (SSID, IP, MAC all deterministic)
136- testnut.cashu.space auto-pays invoices: `cashu -h https://testnut.cashu.space invoice <amount>` 166- testnut.cashu.space auto-pays invoices: `cashu -h https://testnut.cashu.space invoice <amount>`
137- Token generation: `cashu -h https://testnut.cashu.space send --legacy <amount> 2>&1 | grep '^cashuA' | head -1` 167- Token generation: `cashu -h https://testnut.cashu.space send --legacy <amount> 2>&1 | grep '^cashuA' | head -1`
138- sudo password: `c03rad0r123` 168- sudo password: `c03rad0r123`