upleb.uk

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

summaryrefslogtreecommitdiff
path: root/main/config.c
diff options
context:
space:
mode:
authorYour Name <you@example.com>2026-05-19 02:31:19 +0530
committerYour Name <you@example.com>2026-05-19 02:32:41 +0530
commit81f2dc52dc42d01c89dff45a5407ec40b8863052 (patch)
tree15018c2438639ca89dc6d33a5144c10d0b1c2af0 /main/config.c
parent75688d55b3c8d13c8c9a50da9668ec408f684cb3 (diff)
feat: local Nostr relay with relay selection, sync, and integration tests
Local Nostr relay (NIP-01) on port 4869 with LittleFS 4MB storage. All events published locally first, then synced to public relays via REQ-diff. Relay selection via NIP-11 HTTP probing with NIP-77 scoring and auto-failover. Components: - wisp_relay: 16-file local relay (ws_server, storage_engine, sub_manager, broadcaster, relay_validator, router, handlers, rate_limiter, nip11, deletion, flash_monitor, relay_types) - esp_littlefs: LittleFS VFS integration (git submodule) - negentropy: for future NIP-77 binary sync (git submodule) New source files: - local_relay.c/h: thin wrapper for relay init/start/publish - relay_selector.c/h: NIP-11 probe + scoring + auto-failover - sync_manager.c/h: REQ-diff sync (primary 30min, fallback 6h) Bug fixes: - config.c: use-after-free (cJSON_Delete before seed_relays/sync parsing) - local_relay: moved init to app_main for boot-time start (not gated on STA IP) Flash layout: 4MB LittleFS partition at 0x500000 for relay_store Test results (Board B, live hardware): - Smoke: ping + HTTP 4869 + NIP-11: PASS - NIP-11 info document: 10/11 PASS - WS pub/sub (connect, REQ/EOSE, EVENT/OK, CLOSE, concurrent): 6/6 PASS - Unit tests (relay_validator + relay_selector): 13/13 PASS Hardware test make targets in physical-router-test-automation/: - make relay-build, relay-flash-b, relay-test-smoke/nip11/pubsub/sync/full
Diffstat (limited to 'main/config.c')
-rw-r--r--main/config.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/main/config.c b/main/config.c
index 9dd2a1d..b991991 100644
--- a/main/config.c
+++ b/main/config.c
@@ -35,6 +35,8 @@ esp_err_t tollgate_config_init(void)
35 g_config.payout.mint_count = 0; 35 g_config.payout.mint_count = 0;
36 g_config.cvm_enabled = true; 36 g_config.cvm_enabled = true;
37 strncpy(g_config.cvm_relays, "wss://relay.primal.net", sizeof(g_config.cvm_relays) - 1); 37 strncpy(g_config.cvm_relays, "wss://relay.primal.net", sizeof(g_config.cvm_relays) - 1);
38 g_config.nostr_sync_interval_s = 1800;
39 g_config.nostr_fallback_sync_interval_s = 21600;
38 40
39 esp_vfs_spiffs_conf_t conf = { 41 esp_vfs_spiffs_conf_t conf = {
40 .base_path = "/spiffs", 42 .base_path = "/spiffs",
@@ -257,6 +259,28 @@ esp_err_t tollgate_config_init(void)
257 g_config.payout.mint_count = 1; 259 g_config.payout.mint_count = 1;
258 } 260 }
259 261
262 cJSON *seed_relays = cJSON_GetObjectItem(root, "nostr_seed_relays");
263 if (seed_relays && cJSON_IsArray(seed_relays)) {
264 int srcount = cJSON_GetArraySize(seed_relays);
265 if (srcount > TOLLGATE_MAX_SEED_RELAYS) srcount = TOLLGATE_MAX_SEED_RELAYS;
266 for (int i = 0; i < srcount; i++) {
267 cJSON *r = cJSON_GetArrayItem(seed_relays, i);
268 if (r && cJSON_IsString(r)) {
269 strncpy(g_config.nostr_seed_relays[i], r->valuestring,
270 sizeof(g_config.nostr_seed_relays[i]) - 1);
271 g_config.nostr_seed_relay_count++;
272 }
273 }
274 }
275
276 cJSON *sync_interval = cJSON_GetObjectItem(root, "nostr_sync_interval_s");
277 if (sync_interval) g_config.nostr_sync_interval_s = sync_interval->valueint;
278
279 cJSON *fallback_interval = cJSON_GetObjectItem(root, "nostr_fallback_sync_interval_s");
280 if (fallback_interval) g_config.nostr_fallback_sync_interval_s = fallback_interval->valueint;
281
282 cJSON_Delete(root);
283
260 if (g_config.payout.recipient_count == 0) { 284 if (g_config.payout.recipient_count == 0) {
261 strncpy(g_config.payout.recipients[0].lightning_address, "TollGate@coinos.io", 285 strncpy(g_config.payout.recipients[0].lightning_address, "TollGate@coinos.io",
262 sizeof(g_config.payout.recipients[0].lightning_address) - 1); 286 sizeof(g_config.payout.recipients[0].lightning_address) - 1);
@@ -264,14 +288,24 @@ esp_err_t tollgate_config_init(void)
264 g_config.payout.recipient_count = 1; 288 g_config.payout.recipient_count = 1;
265 } 289 }
266 290
267 cJSON_Delete(root);
268
269 if (g_config.nostr_relay_count == 0) { 291 if (g_config.nostr_relay_count == 0) {
270 strncpy(g_config.nostr_relays[0], "wss://relay.damus.io", sizeof(g_config.nostr_relays[0]) - 1); 292 strncpy(g_config.nostr_relays[0], "wss://relay.damus.io", sizeof(g_config.nostr_relays[0]) - 1);
271 strncpy(g_config.nostr_relays[1], "wss://nos.lol", sizeof(g_config.nostr_relays[1]) - 1); 293 strncpy(g_config.nostr_relays[1], "wss://nos.lol", sizeof(g_config.nostr_relays[1]) - 1);
272 g_config.nostr_relay_count = 2; 294 g_config.nostr_relay_count = 2;
273 } 295 }
274 296
297 if (g_config.nostr_seed_relay_count == 0) {
298 strncpy(g_config.nostr_seed_relays[0], "wss://relay.orangesync.tech",
299 sizeof(g_config.nostr_seed_relays[0]) - 1);
300 strncpy(g_config.nostr_seed_relays[1], "wss://relay.damus.io",
301 sizeof(g_config.nostr_seed_relays[1]) - 1);
302 strncpy(g_config.nostr_seed_relays[2], "wss://nos.lol",
303 sizeof(g_config.nostr_seed_relays[2]) - 1);
304 strncpy(g_config.nostr_seed_relays[3], "wss://relay.nostr.band",
305 sizeof(g_config.nostr_seed_relays[3]) - 1);
306 g_config.nostr_seed_relay_count = 4;
307 }
308
275 ESP_LOGI(TAG, "Config loaded: nsec=%s...%s, %d WiFi networks, price=%d sats/%dms", 309 ESP_LOGI(TAG, "Config loaded: nsec=%s...%s, %d WiFi networks, price=%d sats/%dms",
276 g_config.nsec, g_config.nsec + 60, g_config.network_count, 310 g_config.nsec, g_config.nsec + 60, g_config.network_count,
277 g_config.price_per_step, g_config.step_size_ms); 311 g_config.price_per_step, g_config.step_size_ms);