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 14:25:18 +0530
committerYour Name <you@example.com>2026-05-19 14:25:18 +0530
commite366ceb336550a72c76efea4c98a2a08cca27bce (patch)
tree4b45ac6f6e97b6763f81aa6d4a9b968d23e41235 /main/config.c
parent163b8badec9359373a8fc016c2b1fe9ee38e6406 (diff)
feat(mining): Bitcoin mining-for-bandwidth payment system
New modules: - mining_payment.c/h: hashprice calc (nbits->difficulty->sat/GH/s/day), share validation, client stats, allotment conversion (ms + bytes) - stratum_client.c/h: SV1 upstream pool connection (subscribe/authorize/submit) - stratum_proxy.c/h: Local SV1 TCP server for downstream miners, job broadcast - sw_miner.c/h: Software SHA256d miner (ESP32 CPU fallback) - asic_miner.c/h: ASIC detection stub (BM1366/BM1368 SPI) Config: - config.h/c: mining_payout_mode_t enum (auto/pool/upstream/proxy_only), stratum pool settings, mining port, hashprice override, sandbox mint access - Defaults fill nostr_seed_relays (8/8) and nostr_relays (4/4) with fast relays Integration into existing modules: - session.h/c: payment_method_t enum (CASHU/MINING/BYTES) - firewall.h/c: firewall_set_mining_port(), firewall_set_sandbox_mint_access() - tollgate_api.c: GET /mining/job, POST /mining/share, GET /mining/stats - tollgate_client.h/c: TG_CLIENT_MINING state, mining discovery tag parsing - tollgate_main.c: mining init in start_services(), stratum_client_tick() in loop - captive_portal.c: tabbed Cashu/Mine UI with live hashrate polling Unit tests (69 new assertions across 4 suites): - test_mining_payment (23 tests): nbits->difficulty, hashprice, client stats, allotment - test_stratum_proxy (21 tests): job set/get, stats, type validation - test_session_payment_method (12 tests): PAYMENT_METHOD enum, bytes/cashu methods - test_tollgate_client_mining (20 tests): mining tag parsing, discovery struct - test_firewall_sandbox (16 tests): client grant/revoke, max clients, setters Enhanced test stubs: - BaseType_t/pdPASS in freertos/task.h - lwip: sockets.h, etharp.h, prot/ip.h, prot/ip4.h, prot/tcp.h, netif.h - dns_server.h, esp_wifi_ap_get_sta_list.h Build fixes: - cvm_server.c: replace esp_timer_get_time() with xTaskGetTickCount(), fix process_relay_message() 3-arg call to 2-arg, add WS keepalive ping - stratum_proxy.c: widen task_name buffer 16->20 - sw_miner.c: add missing #include esp_random.h - nucula_src: save_proofs() moved to public in wallet.hpp Nostr relay updates: - nostr_seed_relays: +relay.anzenkodo.workers.dev, +nostr.koning-degraaf.nl, +knostr.neutrine.com, +nostr.einundzwanzig.space (8/8 slots) - nostr_relays: +relay.anzenkodo.workers.dev, +nostr.koning-degraaf.nl (4/4 slots) Squash-merge of feature/mining-payment (5 commits: c75230e..9d98ba1)
Diffstat (limited to 'main/config.c')
-rw-r--r--main/config.c87
1 files changed, 83 insertions, 4 deletions
diff --git a/main/config.c b/main/config.c
index 5e3b247..6644b3a 100644
--- a/main/config.c
+++ b/main/config.c
@@ -39,6 +39,13 @@ esp_err_t tollgate_config_init(void)
39 strncpy(g_config.cvm_relays, "wss://relay.primal.net", sizeof(g_config.cvm_relays) - 1); 39 strncpy(g_config.cvm_relays, "wss://relay.primal.net", sizeof(g_config.cvm_relays) - 1);
40 strncpy(g_config.wifi_auth_mode, "WPA2", sizeof(g_config.wifi_auth_mode) - 1); 40 strncpy(g_config.wifi_auth_mode, "WPA2", sizeof(g_config.wifi_auth_mode) - 1);
41 g_config.display_enabled = true; 41 g_config.display_enabled = true;
42 g_config.nostr_sync_interval_s = 1800;
43 g_config.nostr_fallback_sync_interval_s = 21600;
44 g_config.mining_enabled = false;
45 g_config.mining_payout_mode = MINING_PAYOUT_AUTO;
46 g_config.stratum_port = 3333;
47 g_config.mining_port = 3334;
48 g_config.mining_sandbox_mint_access = true;
42 49
43 esp_vfs_spiffs_conf_t conf = { 50 esp_vfs_spiffs_conf_t conf = {
44 .base_path = "/spiffs", 51 .base_path = "/spiffs",
@@ -314,6 +321,68 @@ esp_err_t tollgate_config_init(void)
314 g_config.payout.mint_count = 1; 321 g_config.payout.mint_count = 1;
315 } 322 }
316 323
324 cJSON *seed_relays = cJSON_GetObjectItem(root, "nostr_seed_relays");
325 if (seed_relays && cJSON_IsArray(seed_relays)) {
326 int srcount = cJSON_GetArraySize(seed_relays);
327 if (srcount > TOLLGATE_MAX_SEED_RELAYS) srcount = TOLLGATE_MAX_SEED_RELAYS;
328 for (int i = 0; i < srcount; i++) {
329 cJSON *r = cJSON_GetArrayItem(seed_relays, i);
330 if (r && cJSON_IsString(r)) {
331 strncpy(g_config.nostr_seed_relays[i], r->valuestring,
332 sizeof(g_config.nostr_seed_relays[i]) - 1);
333 g_config.nostr_seed_relay_count++;
334 }
335 }
336 }
337
338 cJSON *sync_interval = cJSON_GetObjectItem(root, "nostr_sync_interval_s");
339 if (sync_interval) g_config.nostr_sync_interval_s = sync_interval->valueint;
340
341 cJSON *fallback_interval = cJSON_GetObjectItem(root, "nostr_fallback_sync_interval_s");
342 if (fallback_interval) g_config.nostr_fallback_sync_interval_s = fallback_interval->valueint;
343
344 cJSON *mining = cJSON_GetObjectItem(root, "mining");
345 if (mining && cJSON_IsObject(mining)) {
346 cJSON *m_en = cJSON_GetObjectItem(mining, "enabled");
347 if (m_en && cJSON_IsBool(m_en)) g_config.mining_enabled = cJSON_IsTrue(m_en);
348
349 cJSON *m_mode = cJSON_GetObjectItem(mining, "payout_mode");
350 if (m_mode && cJSON_IsString(m_mode)) {
351 if (strcmp(m_mode->valuestring, "pool") == 0) g_config.mining_payout_mode = MINING_PAYOUT_POOL;
352 else if (strcmp(m_mode->valuestring, "upstream") == 0) g_config.mining_payout_mode = MINING_PAYOUT_UPSTREAM;
353 else if (strcmp(m_mode->valuestring, "proxy_only") == 0) g_config.mining_payout_mode = MINING_PAYOUT_PROXY_ONLY;
354 }
355
356 cJSON *m_host = cJSON_GetObjectItem(mining, "stratum_host");
357 if (m_host && cJSON_IsString(m_host)) strncpy(g_config.stratum_host, m_host->valuestring, sizeof(g_config.stratum_host) - 1);
358
359 cJSON *m_port = cJSON_GetObjectItem(mining, "stratum_port");
360 if (m_port) g_config.stratum_port = (uint16_t)m_port->valueint;
361
362 cJSON *m_user = cJSON_GetObjectItem(mining, "stratum_user");
363 if (m_user && cJSON_IsString(m_user)) strncpy(g_config.stratum_user, m_user->valuestring, sizeof(g_config.stratum_user) - 1);
364
365 cJSON *m_pass = cJSON_GetObjectItem(mining, "stratum_pass");
366 if (m_pass && cJSON_IsString(m_pass)) strncpy(g_config.stratum_pass, m_pass->valuestring, sizeof(g_config.stratum_pass) - 1);
367
368 cJSON *m_fb_host = cJSON_GetObjectItem(mining, "stratum_fallback_host");
369 if (m_fb_host && cJSON_IsString(m_fb_host)) strncpy(g_config.stratum_fallback_host, m_fb_host->valuestring, sizeof(g_config.stratum_fallback_host) - 1);
370
371 cJSON *m_fb_port = cJSON_GetObjectItem(mining, "stratum_fallback_port");
372 if (m_fb_port) g_config.stratum_fallback_port = (uint16_t)m_fb_port->valueint;
373
374 cJSON *m_mport = cJSON_GetObjectItem(mining, "mining_port");
375 if (m_mport) g_config.mining_port = (uint16_t)m_mport->valueint;
376
377 cJSON *m_hp = cJSON_GetObjectItem(mining, "hashprice_sats_per_ghs_day");
378 if (m_hp) g_config.hashprice_sats_per_ghs_day = (uint64_t)m_hp->valuedouble;
379
380 cJSON *m_sandbox = cJSON_GetObjectItem(mining, "sandbox_mint_access");
381 if (m_sandbox && cJSON_IsBool(m_sandbox)) g_config.mining_sandbox_mint_access = cJSON_IsTrue(m_sandbox);
382 }
383
384 cJSON_Delete(root);
385
317 if (g_config.payout.recipient_count == 0) { 386 if (g_config.payout.recipient_count == 0) {
318 strncpy(g_config.payout.recipients[0].lightning_address, "TollGate@coinos.io", 387 strncpy(g_config.payout.recipients[0].lightning_address, "TollGate@coinos.io",
319 sizeof(g_config.payout.recipients[0].lightning_address) - 1); 388 sizeof(g_config.payout.recipients[0].lightning_address) - 1);
@@ -321,8 +390,6 @@ esp_err_t tollgate_config_init(void)
321 g_config.payout.recipient_count = 1; 390 g_config.payout.recipient_count = 1;
322 } 391 }
323 392
324 cJSON_Delete(root);
325
326 if (g_config.accepted_mint_count == 0 && g_config.mint_url[0] != '\0') { 393 if (g_config.accepted_mint_count == 0 && g_config.mint_url[0] != '\0') {
327 strncpy(g_config.accepted_mints[0], g_config.mint_url, 394 strncpy(g_config.accepted_mints[0], g_config.mint_url,
328 sizeof(g_config.accepted_mints[0]) - 1); 395 sizeof(g_config.accepted_mints[0]) - 1);
@@ -332,7 +399,11 @@ esp_err_t tollgate_config_init(void)
332 if (g_config.nostr_relay_count == 0) { 399 if (g_config.nostr_relay_count == 0) {
333 strncpy(g_config.nostr_relays[0], "wss://relay.damus.io", sizeof(g_config.nostr_relays[0]) - 1); 400 strncpy(g_config.nostr_relays[0], "wss://relay.damus.io", sizeof(g_config.nostr_relays[0]) - 1);
334 strncpy(g_config.nostr_relays[1], "wss://nos.lol", sizeof(g_config.nostr_relays[1]) - 1); 401 strncpy(g_config.nostr_relays[1], "wss://nos.lol", sizeof(g_config.nostr_relays[1]) - 1);
335 g_config.nostr_relay_count = 2; 402 strncpy(g_config.nostr_relays[2], "wss://relay.anzenkodo.workers.dev",
403 sizeof(g_config.nostr_relays[2]) - 1);
404 strncpy(g_config.nostr_relays[3], "wss://nostr.koning-degraaf.nl",
405 sizeof(g_config.nostr_relays[3]) - 1);
406 g_config.nostr_relay_count = 4;
336 } 407 }
337 408
338 if (g_config.nostr_seed_relay_count == 0) { 409 if (g_config.nostr_seed_relay_count == 0) {
@@ -344,7 +415,15 @@ esp_err_t tollgate_config_init(void)
344 sizeof(g_config.nostr_seed_relays[2]) - 1); 415 sizeof(g_config.nostr_seed_relays[2]) - 1);
345 strncpy(g_config.nostr_seed_relays[3], "wss://relay.nostr.band", 416 strncpy(g_config.nostr_seed_relays[3], "wss://relay.nostr.band",
346 sizeof(g_config.nostr_seed_relays[3]) - 1); 417 sizeof(g_config.nostr_seed_relays[3]) - 1);
347 g_config.nostr_seed_relay_count = 4; 418 strncpy(g_config.nostr_seed_relays[4], "wss://relay.anzenkodo.workers.dev",
419 sizeof(g_config.nostr_seed_relays[4]) - 1);
420 strncpy(g_config.nostr_seed_relays[5], "wss://nostr.koning-degraaf.nl",
421 sizeof(g_config.nostr_seed_relays[5]) - 1);
422 strncpy(g_config.nostr_seed_relays[6], "wss://knostr.neutrine.com",
423 sizeof(g_config.nostr_seed_relays[6]) - 1);
424 strncpy(g_config.nostr_seed_relays[7], "wss://nostr.einundzwanzig.space",
425 sizeof(g_config.nostr_seed_relays[7]) - 1);
426 g_config.nostr_seed_relay_count = 8;
348 } 427 }
349 428
350 ESP_LOGI(TAG, "Config loaded: nsec=%s...%s, %d WiFi networks, %d accepted mints, price=%d sats/%dms", 429 ESP_LOGI(TAG, "Config loaded: nsec=%s...%s, %d WiFi networks, %d accepted mints, price=%d sats/%dms",