upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYour Name <you@example.com>2026-05-23 02:18:41 +0530
committerYour Name <you@example.com>2026-05-23 02:18:41 +0530
commit10c69b0ddc34a1fafada3f8b68a622b4aa2bea77 (patch)
treeee85d02a1569adc70364b6acaea0beb0b4038526
parent969dfe9ea52ed304ae44d7f7adbc5219f90497dd (diff)
chore: fix unit test build rules, add relay_selector+relay_validator tests, persist core extraction planHEADmaster
-rw-r--r--PLAN_TOLLGATE_CORE_EXTRACTION.md281
-rw-r--r--tests/unit/Makefile8
-rw-r--r--tests/unit/stubs/freertos/FreeRTOS.h1
-rwxr-xr-xtests/unit/test_beacon_pricebin35744 -> 0 bytes
-rwxr-xr-xtests/unit/test_displaybin24816 -> 0 bytes
-rwxr-xr-xtests/unit/test_firewall_sandboxbin30568 -> 0 bytes
-rwxr-xr-xtests/unit/test_marketbin49456 -> 0 bytes
-rwxr-xr-xtests/unit/test_mining_paymentbin28664 -> 0 bytes
-rwxr-xr-xtests/unit/test_negentropy_adapterbin21216 -> 0 bytes
-rwxr-xr-xtests/unit/test_session_payment_methodbin54680 -> 0 bytes
-rwxr-xr-xtests/unit/test_stratum_proxybin40784 -> 0 bytes
-rwxr-xr-xtests/unit/test_tollgate_client_miningbin48448 -> 0 bytes
12 files changed, 289 insertions, 1 deletions
diff --git a/PLAN_TOLLGATE_CORE_EXTRACTION.md b/PLAN_TOLLGATE_CORE_EXTRACTION.md
new file mode 100644
index 0000000..28b9ac3
--- /dev/null
+++ b/PLAN_TOLLGATE_CORE_EXTRACTION.md
@@ -0,0 +1,281 @@
1# TollGate Core Extraction Plan
2
3## Goal
4
5Extract TollGate business logic into a **reusable standalone C library** (`tollgate_core/`) wrapped by a **thin ESP-IDF component** (`components/tollgate_esp/`), so that:
6
7- **BitAxe/NerdQAxePlus** gets: full captive portal + Stratum V1 mining + eCash payment + session management
8- **ESP32-TollGate** gets: all of the above + Nostr identity + relay + CVM + display
9- **Desktop/CI** gets: pure logic tests with no ESP-IDF stubs needed
10
11---
12
13## Architecture Overview
14
15```
16┌─────────────────────────────────────────────────────────┐
17│ Consumer Application (main/) │
18│ esp32-tollgate: tollgate_main.c, tollgate_api.c, etc. │
19│ esp-miner: main.cpp, asic_result_task.cpp │
20└────────────────────┬────────────────────────────────────┘
21
22 ┌────────────┴─────────────┐
23 │ components/tollgate_esp │ ← ESP-IDF component wrapper
24 │ (implements platform_t │ via idf_component.yml
25 │ using ESP-IDF APIs) │
26 └────────────┬────────────┘
27
28 ┌────────────────┴────────────────┐
29 │ tollgate_core/ │ ← Standalone C library
30 │ (zero ESP-IDF deps) │
31 │ │
32 │ Layer 0: Pure Logic │
33 │ cashu_decode, allotment, │
34 │ session state machine, │
35 │ mining_payment economics │
36 │ │
37 │ Layer 1: Protocol Logic │
38 │ DNS parser + server logic, │
39 │ Stratum V1 protocol, │
40 │ beacon IE builder/parser │
41 │ │
42 │ Layer 2: Platform-dependent │
43 │ (via tollgate_platform.h) │
44 │ HTTP client, task creation, │
45 │ socket I/O, time source, │
46 │ logging, wallet operations │
47 └─────────────────────────────────┘
48```
49
50## Module Classification
51
52| Module | Layer | Goes into tollgate_core? | Notes |
53|--------|-------|--------------------------|-------|
54| `cashu.c` — token decode, allotment math | 0 | **Yes** | Pure C + cJSON + mbedtls base64/sha256 |
55| `session.c` — lifecycle, expiry, extend | 0 | **Yes** | Pure state machine, time via callback |
56| `mining_payment.c` — hashprice, allotment | 0 | **Yes** | Pure math (nbits→difficulty→hashprice→allotment) |
57| `dns_server.c` — DNS protocol, per-client auth | 1 | **Yes** | Protocol parser pure; socket IO via platform |
58| `stratum_proxy.c` — SV1 TCP server | 1 | **Yes** | JSON protocol pure; TCP via platform |
59| `stratum_client.c` — SV1 pool client | 1 | **Yes** | JSON protocol pure; TCP via platform |
60| `beacon_price.c` — WiFi IE builder/parser | 1 | **Yes** | IE struct packing pure; esp_wifi_set_vendor_ie via platform |
61| `market.c` — IE scanner, cheapest finder | 1 | **Yes** | IE parser + price comparison pure; scan results via platform |
62| `firewall.c` — client allowlist, NAT filter | 2 | **Yes** | Allowlist logic pure; lwIP hook + MAC resolve via platform |
63| `config.c` — JSON config parsing | — | **No** | Stays in consumer. Core takes config via `platform_t` |
64| `identity.c` — HMAC derivation from nsec | — | **No** | Nostr-specific, stays in esp32-tollgate |
65| `nostr_event.c` — Schnorr signing | — | **No** | Nostr-specific |
66| `wifistr.c` — kind 38787 events | — | **No** | Nostr-specific |
67| `cvm_server.c` — MCP over Nostr | — | **No** | Nostr-specific |
68| `relay_selector.c` — NIP-11 probing | — | **No** | Nostr-specific |
69| `sync_manager.c` — REQ-diff sync | — | **No** | Nostr-specific |
70| `local_relay.c` — NIP-01 server | — | **No** | Nostr-specific |
71| `display.c` — TFT rendering | — | **No** | Hardware-specific |
72| `tollgate_client.c` — downstream auto-pay | — | **No** | Consumes core API, but isn't core itself |
73| `nucula_lib` — wallet C++ impl | — | **No** | External dep; core uses wallet via platform callback |
74| `mint_health.c` — health probe + wallet queue | — | **Partial** | Health state machine extractable; wallet queue stays in consumer |
75
76## Platform Interface (`tollgate_platform.h`)
77
78```c
79typedef struct {
80 // --- Config access ---
81 uint16_t (*get_price_sats)(void);
82 int32_t (*get_step_ms)(void);
83 int64_t (*get_step_bytes)(void);
84 const char* (*get_mint_url)(void);
85 const char* (*get_metric)(void);
86
87 // --- Time ---
88 int64_t (*get_time_ms)(void);
89
90 // --- Logging ---
91 void (*log_info)(const char *tag, const char *fmt, ...);
92 void (*log_warn)(const char *tag, const char *fmt, ...);
93 void (*log_error)(const char *tag, const char *fmt, ...);
94
95 // --- Wallet (can be NULL — accepts payment without spending) ---
96 bool (*wallet_receive)(const char *token);
97 bool (*wallet_send)(uint64_t amount, char *buf, size_t buf_len);
98 uint64_t (*wallet_balance)(void);
99
100 // --- HTTP client (for checkstate) ---
101 int (*http_post)(const char *url, const char *headers,
102 const char *body, int body_len,
103 char *resp, int resp_len);
104
105 // --- Task/thread creation ---
106 bool (*create_task)(void (*fn)(void*), void *arg,
107 const char *name, int stack_bytes, int priority);
108
109 // --- Socket I/O (for DNS + Stratum) ---
110 int (*socket_udp)(void);
111 int (*socket_tcp)(void);
112 int (*socket_bind)(int fd, uint32_t ip, uint16_t port);
113 int (*socket_listen)(int fd, int backlog);
114 int (*socket_accept)(int fd, uint32_t *client_ip, uint16_t *client_port);
115 int (*socket_recvfrom)(int fd, void *buf, int len,
116 uint32_t *src_ip, uint16_t *src_port);
117 int (*socket_sendto)(int fd, const void *buf, int len,
118 uint32_t dest_ip, uint16_t dest_port);
119 int (*socket_read)(int fd, void *buf, int len);
120 int (*socket_write)(int fd, const void *buf, int len);
121 void (*socket_close)(int fd);
122 void (*socket_set_recv_timeout)(int fd, int ms);
123
124 // --- WiFi/MAC (for firewall + beacon + market) ---
125 bool (*get_sta_mac_ip_list)(void *list_out, int max, int *count_out);
126 bool (*set_vendor_ie)(bool enable, const void *ie_data, int ie_len);
127 int (*arp_get_mac)(uint32_t ip, uint8_t *mac_out);
128 void (*napt_enable)(uint32_t ip, bool enable);
129
130 // --- Mining config ---
131 bool (*mining_enabled)(void);
132 const char* (*get_stratum_host)(void);
133 uint16_t (*get_stratum_port)(void);
134 const char* (*get_stratum_user)(void);
135 const char* (*get_stratum_pass)(void);
136 uint16_t (*get_mining_port)(void);
137 uint64_t (*get_hashprice_override)(void);
138
139 // --- Random ---
140 void (*fill_random)(void *buf, int len);
141
142} tollgate_platform_t;
143```
144
145## Directory Structure
146
147```
148tollgate_core/ ← standalone C library (CMakeLists.txt, no ESP-IDF)
149 CMakeLists.txt
150 include/
151 tollgate_core.h
152 tollgate_platform.h
153 src/
154 tollgate_core.c
155 tollgate_cashu.c/h
156 tollgate_session.c/h
157 tollgate_dns.c/h
158 tollgate_firewall.c/h
159 tollgate_mining.c/h
160 tollgate_stratum_client.c/h
161 tollgate_stratum_proxy.c/h
162 tollgate_beacon.c/h
163 tollgate_market.c/h
164
165components/tollgate_esp/ ← ESP-IDF component wrapper
166 CMakeLists.txt
167 idf_component.yml
168 src/
169 tollgate_esp_platform.c
170 tollgate_esp_http.c
171 tollgate_esp_sockets.c
172 tollgate_esp_wifi.c
173 tollgate_esp_wallet.c
174 tollgate_esp_tasks.c
175
176main/ ← esp32-tollgate specific (shrinks)
177 tollgate_main.c, tollgate_api.c, captive_portal.c
178 config.c, identity.c, nostr_event.c, wifistr.c
179 cvm_server.c, mcp_handler.c, local_relay.c
180 relay_selector.c, sync_manager.c
181 display.c, font.c
182 mint_health.c, tollgate_client.c
183```
184
185---
186
187## Implementation Phases
188
189### Phase 0: Housekeeping
190
191- [x] Archive stale branches to `/home/c03rad0r/mining-work-backup/` as git bundles
192- [x] Commit `PLAN_pytest_migration.md`
193- [x] Fix `nucula_src` submodule drift
194- [ ] Fix missing unit test build rules (`test_relay_selector.c`, `test_relay_validator.c`)
195- [ ] Remove broken test binaries from TESTS list (`test_display`, `test_negentropy_adapter`)
196- [ ] Run `make test-unit` — confirm green baseline
197- [ ] Create branch `feature/tollgate-core-v2` from master
198
199### Phase 1: Create Skeleton
200
201- [ ] Create `tollgate_core/` directory with `CMakeLists.txt`, `include/`, `src/`
202- [ ] Define `tollgate_platform.h` interface (all callbacks)
203- [ ] Define `tollgate_core.h` public API
204- [ ] Create empty `tollgate_core.c` with `tollgate_core_init()`, `tollgate_core_tick()`
205- [ ] Create `components/tollgate_esp/` skeleton with empty `tollgate_esp_platform.c`
206- [ ] Wire into `main/CMakeLists.txt` as dependency
207- [ ] Verify: project builds, runs on hardware, no behavioral change
208
209### Phase 2: Extract Layer 0 — Pure Logic
210
211- [ ] `tollgate_cashu.c` — token decode, allotment math, checkstate (via platform HTTP)
212- [ ] `tollgate_session.c` — lifecycle, expiry, extend, bytes/time support
213- [ ] `tollgate_mining.c` — hashprice, nbits→difficulty, shares-to-allotment, client stats
214- [ ] Port unit tests to test `tollgate_core/` directly (no ESP-IDF stubs)
215- [ ] Verify: `make test-unit` passes with new tests
216
217### Phase 3: Extract Layer 1 — Protocol Logic
218
219- [ ] `tollgate_dns.c` — DNS protocol parser, hijack, forward, per-client auth
220- [ ] `tollgate_firewall.c` — client allowlist, NAT filter, lwIP hook
221- [ ] `tollgate_stratum_client.c` — SV1 pool client (subscribe, authorize, submit)
222- [ ] `tollgate_stratum_proxy.c` — SV1 local proxy (TCP server, job broadcast)
223- [ ] `tollgate_beacon.c` — Vendor IE builder/parser
224- [ ] `tollgate_market.c` — price scanner, LRU entries, cheapest finder
225- [ ] Wire `tollgate_core.c` orchestrator to all subsystems
226- [ ] Verify: Build on hardware, run all integration tests
227
228### Phase 4: ESP-IDF Wrapper
229
230- [ ] `tollgate_esp_platform.c` — implement all `tollgate_platform_t` callbacks
231- [ ] `components/tollgate_esp/CMakeLists.txt` — REQUIRES tollgate_core + ESP-IDF
232- [ ] `components/tollgate_esp/idf_component.yml` — IDF Component Registry
233- [ ] Verify: Full build + flash + all tests pass on Board A
234
235### Phase 5: Wire main/ to Use tollgate_core
236
237- [ ] Update `main/tollgate_main.c` — replace direct calls with tollgate_core API
238- [ ] Update `main/tollgate_api.c` — payment → `tollgate_core_process_payment()`
239- [ ] Update `main/captive_portal.c` — grant/reset → tollgate_core calls
240- [ ] Remove old `main/session.c`, `main/firewall.c`, `main/dns_server.c`, `main/cashu.c`, etc.
241- [ ] Verify: `make test-unit` passes, flash to board, run `make pytest-all-a`
242
243### Phase 6: NerdQAxePlus Integration
244
245- [ ] Update `main/tollgate_platform.cpp` to implement new `tollgate_platform_t`
246- [ ] Wire `asic_result_task.cpp` → `tollgate_core_process_share()`
247- [ ] Wire `main.cpp` → `tollgate_core_init()` + `tollgate_core_dns_start()` + `tollgate_core_tick()`
248- [ ] Verify: `BOARD=NERDAXE TOLLGATE=1 idf.py build` passes
249
250### Phase 7: Publishing + CI
251
252- [ ] Publish `tollgate_esp` component to IDF Component Registry
253- [ ] Add CI pipeline: build tollgate_core with host gcc + run pure-logic tests
254- [ ] Add CI pipeline: build tollgate_esp for ESP32-S3 target
255- [ ] Update documentation
256
257---
258
259## Risks and Mitigations
260
261| Risk | Impact | Mitigation |
262|------|--------|------------|
263| RAM budget — tollgate_core statics consume more memory | Board crashes | Profile before/after with `heap_caps_get_free_size`. Keep static arrays same size. |
264| Platform callback overhead on hot path (firewall) | Performance | Firewall filter already a function pointer. No extra overhead. |
265| nucula_lib coupling — C++ but core is C | Build complexity | Wallet stays behind platform callback. Core never includes nucula headers. |
266| Existing branches have useful work | Lost effort | Archived to `/home/c03rad0r/mining-work-backup/` as git bundles. |
267| Test breakage during extraction | Regression | Run full test suite after each phase. Commit after each green phase. |
268
269## Estimated Time
270
271| Phase | Description | Time |
272|-------|-------------|------|
273| 0 | Housekeeping | 30 min |
274| 1 | Skeleton | 2 hours |
275| 2 | Layer 0: Pure logic | 4 hours |
276| 3 | Layer 1: Protocol logic | 6 hours |
277| 4 | ESP-IDF wrapper | 4 hours |
278| 5 | Wire main/ | 6 hours |
279| 6 | NerdQAxePlus integration | 4 hours |
280| 7 | Publishing + CI | 2 hours |
281| **Total** | | **~29 hours** |
diff --git a/tests/unit/Makefile b/tests/unit/Makefile
index b0b6922..cb06472 100644
--- a/tests/unit/Makefile
+++ b/tests/unit/Makefile
@@ -22,7 +22,7 @@ LDFLAGS := -lmbedcrypto -lcjson -lm
22 22
23SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o 23SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o
24 24
25TESTS := test_geohash test_identity test_nostr_event test_cashu test_session test_tollgate_client test_lnurl_pay test_lightning_payout test_mcp_handler test_nip04 test_cvm_server test_display test_negentropy_adapter test_beacon_price test_market test_mint_health test_mining_payment test_stratum_proxy test_session_payment_method test_tollgate_client_mining test_firewall_sandbox 25TESTS := test_geohash test_identity test_nostr_event test_cashu test_session test_tollgate_client test_lnurl_pay test_lightning_payout test_mcp_handler test_nip04 test_cvm_server test_beacon_price test_market test_mint_health test_mining_payment test_stratum_proxy test_session_payment_method test_tollgate_client_mining test_firewall_sandbox test_relay_selector test_relay_validator
26 26
27.PHONY: all test clean $(TESTS) 27.PHONY: all test clean $(TESTS)
28 28
@@ -105,5 +105,11 @@ test_tollgate_client_mining: test_tollgate_client_mining.c
105test_firewall_sandbox: test_firewall_sandbox.c $(REPO_ROOT)/main/firewall.c 105test_firewall_sandbox: test_firewall_sandbox.c $(REPO_ROOT)/main/firewall.c
106 $(CC) $(CFLAGS) -include stubs/dns_server.h $< $(REPO_ROOT)/main/firewall.c -o $@ $(LDFLAGS) 106 $(CC) $(CFLAGS) -include stubs/dns_server.h $< $(REPO_ROOT)/main/firewall.c -o $@ $(LDFLAGS)
107 107
108test_relay_selector: test_relay_selector.c
109 $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
110
111test_relay_validator: test_relay_validator.c $(REPO_ROOT)/main/nostr_event.c $(REPO_ROOT)/main/identity.c $(REPO_ROOT)/components/wisp_relay/relay_validator.c $(SECP256K1_OBJ)
112 $(CC) $(CFLAGS) -I $(SECP256K1_PRIV_INC) -I $(REPO_ROOT)/main -I $(REPO_ROOT)/components/wisp_relay $< $(REPO_ROOT)/main/nostr_event.c $(REPO_ROOT)/main/identity.c $(REPO_ROOT)/components/wisp_relay/relay_validator.c $(SECP256K1_OBJ) -o $@ $(LDFLAGS)
113
108clean: 114clean:
109 rm -f $(TESTS) $(SECP256K1_OBJ) 115 rm -f $(TESTS) $(SECP256K1_OBJ)
diff --git a/tests/unit/stubs/freertos/FreeRTOS.h b/tests/unit/stubs/freertos/FreeRTOS.h
index 543d4e4..fc38846 100644
--- a/tests/unit/stubs/freertos/FreeRTOS.h
+++ b/tests/unit/stubs/freertos/FreeRTOS.h
@@ -11,6 +11,7 @@ static inline uint32_t xTaskGetTickCount(void) { return 0; }
11static inline void vTaskDelay(uint32_t ticks) { (void)ticks; } 11static inline void vTaskDelay(uint32_t ticks) { (void)ticks; }
12#define pdMS_TO_TICKS(ms) ((ms) / 10) 12#define pdMS_TO_TICKS(ms) ((ms) / 10)
13#define portTICK_PERIOD_MS 10 13#define portTICK_PERIOD_MS 10
14#define configTICK_RATE_HZ 100
14#define portMAX_DELAY 0xFFFFFFFF 15#define portMAX_DELAY 0xFFFFFFFF
15#define pdTRUE 1 16#define pdTRUE 1
16#define pdFALSE 0 17#define pdFALSE 0
diff --git a/tests/unit/test_beacon_price b/tests/unit/test_beacon_price
deleted file mode 100755
index a9f6357..0000000
--- a/tests/unit/test_beacon_price
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_display b/tests/unit/test_display
deleted file mode 100755
index 9b8364e..0000000
--- a/tests/unit/test_display
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_firewall_sandbox b/tests/unit/test_firewall_sandbox
deleted file mode 100755
index 3e2895b..0000000
--- a/tests/unit/test_firewall_sandbox
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_market b/tests/unit/test_market
deleted file mode 100755
index 8efac8e..0000000
--- a/tests/unit/test_market
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_mining_payment b/tests/unit/test_mining_payment
deleted file mode 100755
index d38bf9d..0000000
--- a/tests/unit/test_mining_payment
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_negentropy_adapter b/tests/unit/test_negentropy_adapter
deleted file mode 100755
index 64b6053..0000000
--- a/tests/unit/test_negentropy_adapter
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_session_payment_method b/tests/unit/test_session_payment_method
deleted file mode 100755
index 950a72f..0000000
--- a/tests/unit/test_session_payment_method
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_stratum_proxy b/tests/unit/test_stratum_proxy
deleted file mode 100755
index 963df67..0000000
--- a/tests/unit/test_stratum_proxy
+++ /dev/null
Binary files differ
diff --git a/tests/unit/test_tollgate_client_mining b/tests/unit/test_tollgate_client_mining
deleted file mode 100755
index d331bd1..0000000
--- a/tests/unit/test_tollgate_client_mining
+++ /dev/null
Binary files differ