From e366ceb336550a72c76efea4c98a2a08cca27bce Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 19 May 2026 14:25:18 +0530 Subject: 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) --- main/captive_portal.c | 133 +++++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 56 deletions(-) (limited to 'main/captive_portal.c') diff --git a/main/captive_portal.c b/main/captive_portal.c index c9bcf19..ea83906 100644 --- a/main/captive_portal.c +++ b/main/captive_portal.c @@ -2,7 +2,8 @@ #include "firewall.h" #include "session.h" #include "config.h" -#include "mint_health.h" +#include "mining_payment.h" +#include "stratum_proxy.h" #include "esp_log.h" #include "esp_wifi.h" #include "cJSON.h" @@ -32,6 +33,12 @@ static const char PORTAL_HTML_TEMPLATE[] = \ "max-width:400px;width:100%;text-align:center}" "h1{font-size:28px;margin-bottom:8px;color:#f7931a}" ".subtitle{color:#888;margin-bottom:24px;font-size:14px}" +".tabs{display:flex;gap:4px;margin-bottom:20px}" +".tab{flex:1;padding:10px;border:none;border-radius:8px;background:#252525;color:#888;" +"cursor:pointer;font-size:13px;font-weight:bold}" +".tab.active{background:#f7931a;color:#000}" +".tab-content{display:none}" +".tab-content.active{display:block}" ".price{background:#252525;border-radius:12px;padding:16px;margin-bottom:16px}" ".price-amount{font-size:36px;font-weight:bold;color:#f7931a}" ".price-unit{color:#888;font-size:14px}" @@ -43,24 +50,26 @@ static const char PORTAL_HTML_TEMPLATE[] = \ ".btn:disabled{background:#333;color:#666;cursor:not-allowed}" ".mints{background:#252525;border-radius:12px;padding:12px;margin-top:16px;text-align:left}" ".mints-title{color:#888;font-size:12px;margin-bottom:8px}" -".mint-item{display:flex;align-items:center;padding:6px 8px;margin-bottom:4px;" -"background:#1a1a1a;border-radius:6px;cursor:pointer}" -".mint-item:active{opacity:0.7}" -".mint-dot{width:8px;height:8px;border-radius:50%;margin-right:8px;flex-shrink:0}" -".mint-dot.green{background:#4caf50}" -".mint-dot.grey{background:#666}" -".mint-url{font-family:monospace;font-size:11px;color:#f7931a;word-break:break-all}" -".mint-url.dim{color:#666}" +".mint-url{font-family:monospace;font-size:11px;color:#f7931a;word-break:break-all;" +"background:#1a1a1a;padding:8px;border-radius:6px;cursor:pointer}" +".mint-url:active{opacity:0.7}" ".mint-hint{color:#666;font-size:10px;margin-top:4px}" +".mining-stats{background:#252525;border-radius:12px;padding:16px;margin-bottom:16px;text-align:left}" +".mining-stat{display:flex;justify-content:space-between;margin-bottom:8px;font-size:13px}" +".mining-stat .label{color:#888}" +".mining-stat .value{color:#f7931a;font-weight:bold}" "#status{margin-top:16px;padding:12px;border-radius:8px;display:none;font-size:14px}" "#status.success{display:block;background:#1a472a;color:#4caf50}" "#status.error{display:block;background:#471a1a;color:#f44336}" "#status.processing{display:block;background:#1a3a47;color:#2196f3}" +".mining-info{color:#666;font-size:11px;margin-top:12px;line-height:1.5}" "" "" "
" "

TollGate

" -"

Pay for internet access with ecash

" +"

Pay for internet access with ecash or mining

" +"__MINING_TABS__" +"
" "
" "
__PRICE__
" "
sats per minute
" @@ -69,21 +78,40 @@ static const char PORTAL_HTML_TEMPLATE[] = \ "" "
" "
SUPPORTED MINTS
" -"
__MINT_LIST__
" -"
Tap to copy • Green = reachable
" +"
__MINT_URL__
" +"
Tap to copy • Mint tokens at this URL before paying
" +"
" +"
" +"
" +"
" +"
Hashrate0.00 GH/s
" +"
Shares0
" +"
Hashprice0.00 sat/GH/s/day
" +"
Time earned0 min
" +"
" +"" +"
Mining earns internet time by contributing SHA256 hashpower. " +"Connect a Stratum miner to port __MINING_PORT__ or use the built-in web miner.
" "
" "
" "
" "" ""; @@ -143,36 +175,25 @@ static esp_err_t portal_handler(httpd_req_t *req) const char *tpl = PORTAL_HTML_TEMPLATE; size_t tpl_len = strlen(tpl); - char mint_list_html[4096]; - size_t mint_list_cap = sizeof(mint_list_html); - size_t mint_list_len = 0; - mint_list_html[0] = '\0'; - int mint_count = 0; - const mint_status_t *mints = mint_health_get_all(&mint_count); - for (int i = 0; i < mint_count; i++) { - const char *cls = mints[i].reachable ? "green" : "grey"; - const char *url_cls = mints[i].reachable ? "mint-url" : "mint-url dim"; - int written = snprintf(mint_list_html + mint_list_len, mint_list_cap - mint_list_len, - "
" - "" - "%s
", - mints[i].url, cls, url_cls, mints[i].url); - if (written > 0 && (size_t)written < mint_list_cap - mint_list_len) { - mint_list_len += (size_t)written; - } - } - if (mint_count == 0) { - const tollgate_config_t *cfg = tollgate_config_get(); - snprintf(mint_list_html, sizeof(mint_list_html), - "
" - "%s
", cfg->mint_url); - } - struct { const char *key; const char *val; } subs[] = { { "__AP_IP__", s_ap_ip_str }, { "__PRICE__", price_str }, - { "__MINT_LIST__", mint_list_html }, + { "__MINT_URL__", cfg->mint_url }, + { "__MINING_TABS__", cfg->mining_enabled ? + "
" + "" + "" + "
" : "" }, + { "__MINING_PORT__", cfg->mining_enabled ? + (char[]){ [0 ... 7] = 0 } : "3333" }, + { "__CASHU_ACTIVE__", "active" }, + { "__MINING_ACTIVE__", "" }, }; + char mining_port_buf[8] = "3333"; + if (cfg->mining_enabled) { + snprintf(mining_port_buf, sizeof(mining_port_buf), "%d", cfg->mining_port); + subs[4].val = mining_port_buf; + } int nsubs = sizeof(subs) / sizeof(subs[0]); size_t extra = 0; -- cgit v1.2.3