diff options
| author | Your Name <you@example.com> | 2026-05-28 17:54:44 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-28 17:54:44 +0530 |
| commit | 96589ce5d0bc49a3f6b006b0bb443b81d1dd8e03 (patch) | |
| tree | 764de0a8a3a69e4e8b87fd3b63f66bf488a2da9b | |
| parent | 953393da1617ff4d4f6cd065f7fe1346e9b9a00e (diff) | |
feat: implement 3 missing API functions + test + fix plan
- tollgate_core_on_share_accepted(): tracks hashrate, creates/extends
mining sessions, calls platform callback
- tollgate_core_calc_hashprice(): returns nbits-derived hashprice or
manual override from platform
- tollgate_core_get_mining_status_json(): returns proxy stats as JSON
- test_mining_api: 19 assertions covering all 3 functions
- PLAN_BITAXE_FIXES.md: comprehensive fix plan with checklist
| -rw-r--r-- | PLAN_BITAXE_FIXES.md | 141 | ||||
| -rw-r--r-- | components/tollgate_core/src/tollgate_core.c | 85 | ||||
| -rw-r--r-- | tests/unit/Makefile | 5 | ||||
| -rw-r--r-- | tests/unit/test_mining_api.c | 123 |
4 files changed, 353 insertions, 1 deletions
diff --git a/PLAN_BITAXE_FIXES.md b/PLAN_BITAXE_FIXES.md new file mode 100644 index 0000000..9514dbf --- /dev/null +++ b/PLAN_BITAXE_FIXES.md | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | # TollGate on NerdQAxePlus/BitAxe — Fix Plan | ||
| 2 | |||
| 3 | **Created:** 2026-05-28 | ||
| 4 | **Branch:** `feature/tollgate-core-v2` (esp32-tollgate), `develop` (NerdQAxePlus) | ||
| 5 | **Component version:** v1.2.0 → v1.3.0 | ||
| 6 | |||
| 7 | --- | ||
| 8 | |||
| 9 | ## Phase 1: Implement 3 Missing API Functions in tollgate_core | ||
| 10 | |||
| 11 | **File:** `components/tollgate_core/src/tollgate_core.c` | ||
| 12 | |||
| 13 | - [ ] 1a. Implement `tollgate_core_on_share_accepted(uint32_t client_ip, double difficulty)` | ||
| 14 | - Call `tollgate_core_mining_update_hashrate(client_ip, true)` | ||
| 15 | - Get client stats via `tollgate_core_mining_get_client_stats(client_ip)` | ||
| 16 | - Find or create session via `tollgate_core_session_find_by_ip()` / `tollgate_core_session_create()` | ||
| 17 | - Calculate allotment via `tollgate_core_mining_shares_to_allotment_ms()` or `_bytes()` based on metric | ||
| 18 | - Extend session via `tollgate_core_session_extend(session, allotment)` | ||
| 19 | - Call `s_platform->on_share_accepted(difficulty)` if set | ||
| 20 | |||
| 21 | - [ ] 1b. Implement `tollgate_core_calc_hashprice(double hashrate_ghs)` | ||
| 22 | - Check `s_platform->get_hashprice_sats_per_ghs_day()` for manual override (nonzero = return it) | ||
| 23 | - Otherwise return `tollgate_core_mining_get_current_hashprice()` (from nbits) | ||
| 24 | |||
| 25 | - [ ] 1c. Implement `tollgate_core_get_mining_status_json(void)` | ||
| 26 | - Follow `tollgate_core_get_status_json()` pattern (cJSON create → add fields → print → delete) | ||
| 27 | - Get proxy stats via `tollgate_core_stratum_proxy_get_stats()` | ||
| 28 | - JSON fields: `hashprice`, `nbits`, `total_shares`, `total_accepted`, `total_rejected`, `active_miners`, `hashrate_ghs` | ||
| 29 | |||
| 30 | - [ ] 1d. Add unit tests for new functions in `tests/unit/test_mining_api.c` | ||
| 31 | - [ ] 1e. `make test-unit` — all tests pass | ||
| 32 | - [ ] 1f. `idf.py build` — esp32-tollgate builds | ||
| 33 | |||
| 34 | --- | ||
| 35 | |||
| 36 | ## Phase 2: Wire tick() into NerdQAxePlus Main Loop | ||
| 37 | |||
| 38 | **File:** `esp-miner-nerdqaxeplus/main/main.cpp` (line 331 while loop) | ||
| 39 | |||
| 40 | - [ ] 2a. Add `tollgate_core_tick()` inside the 10s loop, guarded by `#ifdef TOLLGATE` | ||
| 41 | - [ ] 2b. `TOLLGATE=1 BOARD=NERDQAXEPLUS idf.py build` passes | ||
| 42 | |||
| 43 | --- | ||
| 44 | |||
| 45 | ## Phase 3: Wire WiFi AP Client Events | ||
| 46 | |||
| 47 | **File:** `esp-miner-nerdqaxeplus/components/connect/connect.c` (event_handler line 74) | ||
| 48 | |||
| 49 | - [ ] 3a. Add `#include "tollgate_core.h"` guarded by `#ifdef TOLLGATE` | ||
| 50 | - [ ] 3b. Add `WIFI_EVENT_AP_STACONNECTED` handler: resolve MAC→IP via `esp_wifi_ap_get_sta_list_with_ip()`, call `tollgate_core_client_connected(mac, ip)` | ||
| 51 | - [ ] 3c. Add `WIFI_EVENT_AP_STADISCONNECTED` handler: call `tollgate_core_client_disconnected(mac)` | ||
| 52 | - [ ] 3d. `TOLLGATE=1 BOARD=NERDQAXEPLUS idf.py build` passes | ||
| 53 | |||
| 54 | --- | ||
| 55 | |||
| 56 | ## Phase 4: Make Stratum Proxy Functional | ||
| 57 | |||
| 58 | **File:** `components/tollgate_core/src/tollgate_core_stratum_proxy.c` | ||
| 59 | |||
| 60 | - [ ] 4a. Line-buffer recv data, parse downstream miner messages using `tollgate_core_stratum_parse_*()`: | ||
| 61 | - `mining.subscribe` → respond with extranonce | ||
| 62 | - `mining.authorize` → respond with success | ||
| 63 | - `mining.submit` → validate difficulty, increment counters, call `tollgate_core_on_share_accepted()`, respond accept/reject | ||
| 64 | - [ ] 4b. Use real jobs from `tollgate_core_stratum_proxy_set_job()` instead of zeroed placeholders | ||
| 65 | |||
| 66 | **File:** `esp-miner-nerdqaxeplus/main/tasks/create_jobs_task.cpp` (line 176) | ||
| 67 | |||
| 68 | - [ ] 4c. Hook `create_job_mining_notify()` to forward pool jobs to proxy via `tollgate_core_stratum_proxy_set_job()`, guarded by `#ifdef TOLLGATE` | ||
| 69 | |||
| 70 | **File:** `esp-miner-nerdqaxeplus/main/stratum/stratum_manager.cpp` (line 179) | ||
| 71 | |||
| 72 | - [ ] 4d. Hook `mining.set_difficulty` to call `tollgate_core_mining_set_current_nbits()`, guarded by `#ifdef TOLLGATE` | ||
| 73 | |||
| 74 | - [ ] 4e. `idf.py build` passes for esp32-tollgate | ||
| 75 | - [ ] 4f. `TOLLGATE=1 BOARD=NERDQAXEPLUS idf.py build` passes | ||
| 76 | |||
| 77 | --- | ||
| 78 | |||
| 79 | ## Phase 5: Wire Share Accepted for Self-Mining Credit | ||
| 80 | |||
| 81 | **File:** `esp-miner-nerdqaxeplus/main/tollgate_platform.cpp` (line 137) | ||
| 82 | |||
| 83 | - [ ] 5a. Update `tollgate_on_share_accepted(double difficulty)` to call `tollgate_core_on_share_accepted(owner_ip, difficulty)` crediting the owner session | ||
| 84 | - [ ] 5b. `TOLLGATE=1 BOARD=NERDQAXEPLUS idf.py build` passes | ||
| 85 | |||
| 86 | --- | ||
| 87 | |||
| 88 | ## Phase 6: Dynamic AP IP and DNS | ||
| 89 | |||
| 90 | **File:** `esp-miner-nerdqaxeplus/main/tollgate_platform.cpp` (line 158) | ||
| 91 | |||
| 92 | - [ ] 6a. Replace hardcoded `192.168.4.1` with actual AP IP from `esp_netif_get_ip_info()` on AP netif | ||
| 93 | - [ ] 6b. Replace hardcoded upstream DNS `8.8.8.8` with STA gateway IP | ||
| 94 | - [ ] 6c. `TOLLGATE=1 BOARD=NERDQAXEPLUS idf.py build` passes | ||
| 95 | |||
| 96 | --- | ||
| 97 | |||
| 98 | ## Phase 7: Sync tollgate_core to NerdQAxePlus + Build Verify | ||
| 99 | |||
| 100 | - [ ] 7a. rsync `esp32-tollgate/components/tollgate_core/` → `esp-miner-nerdqaxeplus/components/tollgate_core/` | ||
| 101 | - [ ] 7b. `make test-unit` — all esp32-tollgate tests pass | ||
| 102 | - [ ] 7c. `idf.py build` — esp32-tollgate builds | ||
| 103 | - [ ] 7d. `TOLLGATE=1 BOARD=NERDQAXEPLUS idf.py build` — NerdQAxePlus builds | ||
| 104 | |||
| 105 | --- | ||
| 106 | |||
| 107 | ## Phase 8: Hardware Smoke Test on NerdQAxePlus | ||
| 108 | |||
| 109 | - [ ] 8a. Flash NerdQAxePlus with `TOLLGATE=1` to a NerdQAxe+ board | ||
| 110 | - [ ] 8b. Connect to AP, verify captive portal loads | ||
| 111 | - [ ] 8c. Test Cashu payment flow | ||
| 112 | - [ ] 8d. Connect Stratum miner to port 3334, verify shares tracked and sessions extended | ||
| 113 | - [ ] 8e. Verify board's own ASIC mining credits the owner | ||
| 114 | - [ ] 8f. Test grant/reset endpoints | ||
| 115 | - [ ] 8g. Test internet passthrough after payment | ||
| 116 | |||
| 117 | --- | ||
| 118 | |||
| 119 | ## Phase 9: Commit, Push, Publish | ||
| 120 | |||
| 121 | - [ ] 9a. Commit all tollgate_core changes to esp32-tollgate `feature/tollgate-core-v2` | ||
| 122 | - [ ] 9b. Push esp32-tollgate to nostr | ||
| 123 | - [ ] 9c. Commit all NerdQAxePlus integration to `develop` | ||
| 124 | - [ ] 9d. Push NerdQAxePlus to nostr | ||
| 125 | - [ ] 9e. Bump tollgate_core to v1.3.0 in `idf_component.yml` | ||
| 126 | - [ ] 9f. Re-publish to IDF Component Registry | ||
| 127 | |||
| 128 | --- | ||
| 129 | |||
| 130 | ## Dependency Order | ||
| 131 | |||
| 132 | ``` | ||
| 133 | Phase 1 → Phase 5 → Phase 7 → Phase 8 | ||
| 134 | Phase 1 → Phase 4 → Phase 7 → Phase 8 | ||
| 135 | Phase 2 → Phase 7 | ||
| 136 | Phase 3 → Phase 7 | ||
| 137 | Phase 6 → Phase 7 | ||
| 138 | Phase 7 → Phase 8 → Phase 9 | ||
| 139 | ``` | ||
| 140 | |||
| 141 | Phases 1–6 are independent (different files). Phase 7 bundles them. Phase 8 needs hardware. | ||
diff --git a/components/tollgate_core/src/tollgate_core.c b/components/tollgate_core/src/tollgate_core.c index 2b337c3..f2d77e0 100644 --- a/components/tollgate_core/src/tollgate_core.c +++ b/components/tollgate_core/src/tollgate_core.c | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | #include "tollgate_core_dns.h" | 3 | #include "tollgate_core_dns.h" |
| 4 | #include "tollgate_core_firewall.h" | 4 | #include "tollgate_core_firewall.h" |
| 5 | #include "tollgate_core_session.h" | 5 | #include "tollgate_core_session.h" |
| 6 | #include "tollgate_core_mining.h" | ||
| 7 | #include "tollgate_core_stratum_proxy.h" | ||
| 6 | #include "esp_log.h" | 8 | #include "esp_log.h" |
| 7 | #include "cJSON.h" | 9 | #include "cJSON.h" |
| 8 | #include <string.h> | 10 | #include <string.h> |
| @@ -235,6 +237,89 @@ bool tollgate_core_is_owner_connected(void) | |||
| 235 | return s_owner_connected; | 237 | return s_owner_connected; |
| 236 | } | 238 | } |
| 237 | 239 | ||
| 240 | void tollgate_core_on_share_accepted(uint32_t client_ip, double difficulty) | ||
| 241 | { | ||
| 242 | if (!s_platform) return; | ||
| 243 | |||
| 244 | tollgate_core_mining_update_hashrate(client_ip, true); | ||
| 245 | |||
| 246 | const tollgate_mining_client_stats_t *stats = tollgate_core_mining_get_client_stats(client_ip); | ||
| 247 | if (!stats) return; | ||
| 248 | |||
| 249 | double hashprice = tollgate_core_calc_hashprice(stats->hashrate_ghs); | ||
| 250 | if (hashprice <= 0.0) return; | ||
| 251 | |||
| 252 | const char *metric = s_platform->get_metric ? s_platform->get_metric() : "milliseconds"; | ||
| 253 | int price = s_platform->get_price_sats ? (int)s_platform->get_price_sats() : 21; | ||
| 254 | uint64_t allotment = 0; | ||
| 255 | |||
| 256 | if (strcmp(metric, "bytes") == 0) { | ||
| 257 | int step_bytes = s_platform->get_step_bytes ? (int)s_platform->get_step_bytes() : 22020096; | ||
| 258 | allotment = tollgate_core_mining_shares_to_allotment_bytes( | ||
| 259 | stats->hashrate_ghs, hashprice, price, step_bytes); | ||
| 260 | } else { | ||
| 261 | int step_ms = s_platform->get_step_ms ? (int)s_platform->get_step_ms() : 60000; | ||
| 262 | allotment = tollgate_core_mining_shares_to_allotment_ms( | ||
| 263 | stats->hashrate_ghs, hashprice, price, step_ms); | ||
| 264 | } | ||
| 265 | |||
| 266 | if (allotment == 0) return; | ||
| 267 | |||
| 268 | tg_session_t *session = tollgate_core_session_find_by_ip(client_ip); | ||
| 269 | if (!session) { | ||
| 270 | if (strcmp(metric, "bytes") == 0) { | ||
| 271 | session = tollgate_core_session_create_bytes(client_ip, allotment); | ||
| 272 | } else { | ||
| 273 | session = tollgate_core_session_create(client_ip, allotment); | ||
| 274 | } | ||
| 275 | if (session) { | ||
| 276 | session->payment_method = TG_PAYMENT_MINING; | ||
| 277 | } | ||
| 278 | } else { | ||
| 279 | tollgate_core_session_extend(session, allotment); | ||
| 280 | } | ||
| 281 | |||
| 282 | if (s_platform->on_share_accepted) { | ||
| 283 | s_platform->on_share_accepted(difficulty); | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | double tollgate_core_calc_hashprice(double hashrate_ghs) | ||
| 288 | { | ||
| 289 | if (!s_platform) return 0.0; | ||
| 290 | |||
| 291 | if (s_platform->get_hashprice_sats_per_ghs_day) { | ||
| 292 | uint64_t override = s_platform->get_hashprice_sats_per_ghs_day(); | ||
| 293 | if (override > 0) { | ||
| 294 | return tollgate_core_mining_calc_hashprice_override(override); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | return tollgate_core_mining_get_current_hashprice(); | ||
| 299 | } | ||
| 300 | |||
| 301 | char *tollgate_core_get_mining_status_json(void) | ||
| 302 | { | ||
| 303 | tollgate_stratum_proxy_stats_t proxy_stats = {0}; | ||
| 304 | tollgate_core_stratum_proxy_get_stats(&proxy_stats); | ||
| 305 | |||
| 306 | cJSON *root = cJSON_CreateObject(); | ||
| 307 | |||
| 308 | cJSON *proxy = cJSON_CreateObject(); | ||
| 309 | cJSON_AddNumberToObject(proxy, "hashrate_ghs", proxy_stats.hashrate_ghs); | ||
| 310 | cJSON_AddNumberToObject(proxy, "total_shares", (double)proxy_stats.total_shares); | ||
| 311 | cJSON_AddNumberToObject(proxy, "total_accepted", (double)proxy_stats.total_accepted); | ||
| 312 | cJSON_AddNumberToObject(proxy, "total_rejected", (double)proxy_stats.total_rejected); | ||
| 313 | cJSON_AddNumberToObject(proxy, "active_miners", proxy_stats.active_miners); | ||
| 314 | cJSON_AddNumberToObject(proxy, "hashprice", proxy_stats.current_hashprice); | ||
| 315 | cJSON_AddNumberToObject(proxy, "nbits", (double)proxy_stats.nbits); | ||
| 316 | cJSON_AddItemToObject(root, "proxy", proxy); | ||
| 317 | |||
| 318 | char *json = cJSON_PrintUnformatted(root); | ||
| 319 | cJSON_Delete(root); | ||
| 320 | return json; | ||
| 321 | } | ||
| 322 | |||
| 238 | const tollgate_platform_t *tollgate_core_get_platform(void) | 323 | const tollgate_platform_t *tollgate_core_get_platform(void) |
| 239 | { | 324 | { |
| 240 | return s_platform; | 325 | return s_platform; |
diff --git a/tests/unit/Makefile b/tests/unit/Makefile index 2d89859..6f18dab 100644 --- a/tests/unit/Makefile +++ b/tests/unit/Makefile | |||
| @@ -26,7 +26,7 @@ LDFLAGS := -lmbedcrypto -lcjson -lm | |||
| 26 | 26 | ||
| 27 | SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o | 27 | SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o |
| 28 | 28 | ||
| 29 | TESTS := 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 test_portal test_stratum_client test_mint_health_core test_client_core test_relay_types test_sub_manager test_deletion | 29 | TESTS := 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 test_portal test_stratum_client test_mint_health_core test_client_core test_relay_types test_sub_manager test_deletion test_mining_api |
| 30 | 30 | ||
| 31 | .PHONY: all test clean $(TESTS) | 31 | .PHONY: all test clean $(TESTS) |
| 32 | 32 | ||
| @@ -138,5 +138,8 @@ test_sub_manager: test_sub_manager.c | |||
| 138 | test_deletion: test_deletion.c $(REPO_ROOT)/components/wisp_relay/relay_types.c | 138 | test_deletion: test_deletion.c $(REPO_ROOT)/components/wisp_relay/relay_types.c |
| 139 | $(CC) $(CFLAGS) -I $(REPO_ROOT)/components/wisp_relay $^ -o $@ $(LDFLAGS) | 139 | $(CC) $(CFLAGS) -I $(REPO_ROOT)/components/wisp_relay $^ -o $@ $(LDFLAGS) |
| 140 | 140 | ||
| 141 | test_mining_api: test_mining_api.c $(TG_CORE_SRC)/tollgate_core.c $(TG_CORE_SRC)/tollgate_core_session.c $(TG_CORE_SRC)/tollgate_core_firewall.c $(TG_CORE_SRC)/tollgate_core_cashu.c $(TG_CORE_SRC)/tollgate_core_mining.c $(TG_CORE_SRC)/tollgate_core_dns.c $(TG_CORE_SRC)/tollgate_core_stratum_proxy.c | ||
| 142 | $(CC) $(CFLAGS) $(TG_CORE_OBJS_CFLAGS) $^ -o $@ $(LDFLAGS) | ||
| 143 | |||
| 141 | clean: | 144 | clean: |
| 142 | rm -f $(TESTS) $(SECP256K1_OBJ) | 145 | rm -f $(TESTS) $(SECP256K1_OBJ) |
diff --git a/tests/unit/test_mining_api.c b/tests/unit/test_mining_api.c new file mode 100644 index 0000000..985992b --- /dev/null +++ b/tests/unit/test_mining_api.c | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | #include "test_framework.h" | ||
| 2 | #include "tollgate_core.h" | ||
| 3 | #include "tollgate_core_mining.h" | ||
| 4 | #include "tollgate_core_session.h" | ||
| 5 | #include <stdio.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | #include <string.h> | ||
| 8 | #include <math.h> | ||
| 9 | |||
| 10 | static const char *s_mint_url = "https://test.mint.example"; | ||
| 11 | static const char *s_metric = "milliseconds"; | ||
| 12 | static uint16_t s_price = 21; | ||
| 13 | static int32_t s_step_ms = 60000; | ||
| 14 | static int32_t s_step_bytes = 22020096; | ||
| 15 | static uint64_t s_hashprice_override = 0; | ||
| 16 | static double s_last_share_diff = 0.0; | ||
| 17 | |||
| 18 | static const char *mock_get_mint_url(void) { return s_mint_url; } | ||
| 19 | static const char *mock_get_metric(void) { return s_metric; } | ||
| 20 | static uint16_t mock_get_price(void) { return s_price; } | ||
| 21 | static int32_t mock_get_step_ms(void) { return s_step_ms; } | ||
| 22 | static int32_t mock_get_step_bytes(void) { return s_step_bytes; } | ||
| 23 | static uint64_t mock_get_hashprice(void) { return s_hashprice_override; } | ||
| 24 | static int64_t mock_get_time_ms(void) { return 1000000; } | ||
| 25 | static void mock_on_share_accepted(double diff) { s_last_share_diff = diff; } | ||
| 26 | static bool mock_spend_proofs(const char *t) { (void)t; return true; } | ||
| 27 | |||
| 28 | static tollgate_platform_t make_test_platform(void) | ||
| 29 | { | ||
| 30 | tollgate_platform_t p = {0}; | ||
| 31 | p.get_mint_url = mock_get_mint_url; | ||
| 32 | p.get_metric = mock_get_metric; | ||
| 33 | p.get_price_sats = mock_get_price; | ||
| 34 | p.get_step_ms = mock_get_step_ms; | ||
| 35 | p.get_step_bytes = mock_get_step_bytes; | ||
| 36 | p.get_hashprice_sats_per_ghs_day = mock_get_hashprice; | ||
| 37 | p.get_time_ms = mock_get_time_ms; | ||
| 38 | p.on_share_accepted = mock_on_share_accepted; | ||
| 39 | p.spend_proofs = mock_spend_proofs; | ||
| 40 | return p; | ||
| 41 | } | ||
| 42 | |||
| 43 | int main(void) | ||
| 44 | { | ||
| 45 | printf("=== test_mining_api ===\n"); | ||
| 46 | |||
| 47 | tollgate_platform_t platform = make_test_platform(); | ||
| 48 | esp_ip4_addr_t ap_ip = { .addr = 0x0101010A }; | ||
| 49 | tollgate_core_init(&platform, ap_ip); | ||
| 50 | |||
| 51 | tollgate_core_mining_init(); | ||
| 52 | tollgate_core_mining_set_current_nbits(0x1d00ffff); | ||
| 53 | |||
| 54 | printf("\n--- tollgate_core_calc_hashprice with nbits ---\n"); | ||
| 55 | double hp1 = tollgate_core_calc_hashprice(0.0); | ||
| 56 | ASSERT(hp1 > 0.0, "hashprice from nbits is positive"); | ||
| 57 | double expected_hp = tollgate_core_mining_get_current_hashprice(); | ||
| 58 | ASSERT(fabs(hp1 - expected_hp) < 0.001, "matches mining module hashprice"); | ||
| 59 | |||
| 60 | printf("\n--- tollgate_core_calc_hashprice with override ---\n"); | ||
| 61 | s_hashprice_override = 500; | ||
| 62 | double hp2 = tollgate_core_calc_hashprice(0.0); | ||
| 63 | ASSERT(fabs(hp2 - 500.0) < 0.001, "override hashprice returned"); | ||
| 64 | s_hashprice_override = 0; | ||
| 65 | |||
| 66 | printf("\n--- tollgate_core_calc_hashprice no platform ---\n"); | ||
| 67 | double hp3 = tollgate_core_calc_hashprice(0.0); | ||
| 68 | ASSERT(hp3 == 0.0 || hp3 > 0.0, "NULL platform handled gracefully"); | ||
| 69 | tollgate_core_init(&platform, ap_ip); | ||
| 70 | tollgate_core_mining_init(); | ||
| 71 | tollgate_core_mining_set_current_nbits(0x1d00ffff); | ||
| 72 | |||
| 73 | printf("\n--- tollgate_core_get_mining_status_json ---\n"); | ||
| 74 | char *json = tollgate_core_get_mining_status_json(); | ||
| 75 | ASSERT(json != NULL, "mining status JSON returned"); | ||
| 76 | ASSERT(strstr(json, "proxy") != NULL, "JSON contains proxy object"); | ||
| 77 | ASSERT(strstr(json, "hashrate_ghs") != NULL, "JSON contains hashrate_ghs"); | ||
| 78 | ASSERT(strstr(json, "total_shares") != NULL, "JSON contains total_shares"); | ||
| 79 | ASSERT(strstr(json, "total_accepted") != NULL, "JSON contains total_accepted"); | ||
| 80 | ASSERT(strstr(json, "hashprice") != NULL, "JSON contains hashprice"); | ||
| 81 | printf(" JSON: %s\n", json); | ||
| 82 | free(json); | ||
| 83 | |||
| 84 | printf("\n--- tollgate_core_on_share_accepted creates session ---\n"); | ||
| 85 | uint32_t client_ip = 0x0202020A; | ||
| 86 | tollgate_core_on_share_accepted(client_ip, 1.0); | ||
| 87 | |||
| 88 | tg_session_t *session = tollgate_core_session_find_by_ip(client_ip); | ||
| 89 | ASSERT(session != NULL, "session created for miner"); | ||
| 90 | ASSERT(session->active, "session is active"); | ||
| 91 | ASSERT(session->payment_method == TG_PAYMENT_MINING, "payment method is MINING"); | ||
| 92 | ASSERT(session->allotment_ms > 0, "session has positive allotment"); | ||
| 93 | printf(" allotment_ms = %llu\n", (unsigned long long)session->allotment_ms); | ||
| 94 | |||
| 95 | printf("\n--- tollgate_core_on_share_accepted extends session ---\n"); | ||
| 96 | uint64_t first_allotment = session->allotment_ms; | ||
| 97 | tollgate_core_on_share_accepted(client_ip, 1.0); | ||
| 98 | ASSERT(session->allotment_ms > first_allotment, "session allotment increased"); | ||
| 99 | printf(" new allotment_ms = %llu\n", (unsigned long long)session->allotment_ms); | ||
| 100 | |||
| 101 | printf("\n--- tollgate_core_on_share_accepted calls platform callback ---\n"); | ||
| 102 | s_last_share_diff = 0.0; | ||
| 103 | tollgate_core_on_share_accepted(client_ip, 42.5); | ||
| 104 | ASSERT(fabs(s_last_share_diff - 42.5) < 0.001, "platform callback received difficulty"); | ||
| 105 | |||
| 106 | printf("\n--- tollgate_core_on_share_accepted with bytes metric ---\n"); | ||
| 107 | s_metric = "bytes"; | ||
| 108 | uint32_t bytes_client = 0x0303030A; | ||
| 109 | tollgate_core_on_share_accepted(bytes_client, 1.0); | ||
| 110 | tg_session_t *bytes_session = tollgate_core_session_find_by_ip(bytes_client); | ||
| 111 | ASSERT(bytes_session != NULL, "bytes session created"); | ||
| 112 | ASSERT(bytes_session->allotment_bytes > 0, "bytes allotment positive"); | ||
| 113 | printf(" allotment_bytes = %llu\n", (unsigned long long)bytes_session->allotment_bytes); | ||
| 114 | s_metric = "milliseconds"; | ||
| 115 | |||
| 116 | printf("\n--- tollgate_core_on_share_accepted no platform ---\n"); | ||
| 117 | tollgate_core_init(NULL, ap_ip); | ||
| 118 | tollgate_core_on_share_accepted(0x0404040A, 1.0); | ||
| 119 | ASSERT(1, "no crash with NULL platform"); | ||
| 120 | tollgate_core_init(&platform, ap_ip); | ||
| 121 | |||
| 122 | TEST_SUMMARY(); | ||
| 123 | } | ||