diff options
| author | Your Name <you@example.com> | 2026-05-22 03:48:46 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-22 03:48:46 +0530 |
| commit | ed06f7eeab28c1fa6242c4ea6c3b9c933661fc06 (patch) | |
| tree | 96230dd069102688318f73b60b8322255ea30cad /main | |
| parent | 7009d2e0ac346376733863966374eac296e0471e (diff) | |
feat(cvm): fix CVM MCP roundtrip - task creation, subscription, relay selection
- Move CVM server start before mint_health_start (avoids RAM fragmentation)
- Fix NIP-01 subscription: #p tag must be array not string
- Fix read loop: tolerate TLS timeouts, don't disconnect
- Reduce TLS timeout from 15s to 5s for faster event delivery
- Add WS frame logging for debugging
- Sign test events with board's nsec (--sec flag) for owner auth
- Change default CVM relay to nos.lol (forwards ephemeral kind 25910)
- MCP get_config and get_balance roundtrips confirmed working
- Unit tests pass (16/16)
Diffstat (limited to 'main')
| -rw-r--r-- | main/config.c | 2 | ||||
| -rw-r--r-- | main/cvm_server.c | 64 | ||||
| -rw-r--r-- | main/tollgate_main.c | 18 |
3 files changed, 49 insertions, 35 deletions
diff --git a/main/config.c b/main/config.c index e3cbf46..2edb6da 100644 --- a/main/config.c +++ b/main/config.c | |||
| @@ -36,7 +36,7 @@ esp_err_t tollgate_config_init(void) | |||
| 36 | g_config.payout.recipient_count = 0; | 36 | g_config.payout.recipient_count = 0; |
| 37 | g_config.payout.mint_count = 0; | 37 | g_config.payout.mint_count = 0; |
| 38 | g_config.cvm_enabled = true; | 38 | g_config.cvm_enabled = true; |
| 39 | strncpy(g_config.cvm_relays, "wss://relay.primal.net", sizeof(g_config.cvm_relays) - 1); | 39 | strncpy(g_config.cvm_relays, "wss://nos.lol", 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; | 42 | g_config.nostr_sync_interval_s = 1800; |
diff --git a/main/cvm_server.c b/main/cvm_server.c index f3a5ab8..1ac5cb6 100644 --- a/main/cvm_server.c +++ b/main/cvm_server.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "esp_tls.h" | 12 | #include "esp_tls.h" |
| 13 | #include "esp_crt_bundle.h" | 13 | #include "esp_crt_bundle.h" |
| 14 | #include "esp_random.h" | 14 | #include "esp_random.h" |
| 15 | #include "esp_heap_caps.h" | ||
| 15 | #include "freertos/FreeRTOS.h" | 16 | #include "freertos/FreeRTOS.h" |
| 16 | #include "freertos/task.h" | 17 | #include "freertos/task.h" |
| 17 | #include <string.h> | 18 | #include <string.h> |
| @@ -150,7 +151,7 @@ static esp_err_t ws_connect(const char *relay_url, esp_tls_t **tls_out) | |||
| 150 | 151 | ||
| 151 | esp_tls_cfg_t tls_cfg = { | 152 | esp_tls_cfg_t tls_cfg = { |
| 152 | .crt_bundle_attach = esp_crt_bundle_attach, | 153 | .crt_bundle_attach = esp_crt_bundle_attach, |
| 153 | .timeout_ms = 15000, | 154 | .timeout_ms = 5000, |
| 154 | }; | 155 | }; |
| 155 | esp_tls_t *tls = esp_tls_init(); | 156 | esp_tls_t *tls = esp_tls_init(); |
| 156 | if (!tls) return ESP_ERR_NO_MEM; | 157 | if (!tls) return ESP_ERR_NO_MEM; |
| @@ -507,7 +508,9 @@ static esp_err_t subscribe_to_relay(esp_tls_t *tls, const char *npub) | |||
| 507 | cJSON *kinds = cJSON_CreateArray(); | 508 | cJSON *kinds = cJSON_CreateArray(); |
| 508 | cJSON_AddItemToArray(kinds, cJSON_CreateNumber(25910)); | 509 | cJSON_AddItemToArray(kinds, cJSON_CreateNumber(25910)); |
| 509 | cJSON_AddItemToObject(filter, "kinds", kinds); | 510 | cJSON_AddItemToObject(filter, "kinds", kinds); |
| 510 | cJSON_AddStringToObject(filter, "#p", npub); | 511 | cJSON *p_tag = cJSON_CreateArray(); |
| 512 | cJSON_AddItemToArray(p_tag, cJSON_CreateString(npub)); | ||
| 513 | cJSON_AddItemToObject(filter, "#p", p_tag); | ||
| 511 | cJSON_AddNumberToObject(filter, "limit", 100); | 514 | cJSON_AddNumberToObject(filter, "limit", 100); |
| 512 | cJSON_AddItemToArray(sub, filter); | 515 | cJSON_AddItemToArray(sub, filter); |
| 513 | 516 | ||
| @@ -556,33 +559,33 @@ static void cvm_relay_task(void *arg) | |||
| 556 | } | 559 | } |
| 557 | 560 | ||
| 558 | int64_t last_ping_time = (int64_t)(xTaskGetTickCount() * portTICK_PERIOD_MS) / 1000; | 561 | int64_t last_ping_time = (int64_t)(xTaskGetTickCount() * portTICK_PERIOD_MS) / 1000; |
| 559 | int consecutive_timeouts = 0; | ||
| 560 | while (g_running) { | 562 | while (g_running) { |
| 561 | int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1); | 563 | int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1); |
| 562 | if (rlen < 0) { | ||
| 563 | ESP_LOGW(TAG, "Read error on %s (rlen=%d)", relay_url, rlen); | ||
| 564 | break; | ||
| 565 | } | ||
| 566 | if (rlen == 0) { | 564 | if (rlen == 0) { |
| 565 | ESP_LOGW(TAG, "Connection closed by relay"); | ||
| 567 | break; | 566 | break; |
| 568 | } else { | 567 | } |
| 569 | consecutive_timeouts = 0; | 568 | if (rlen < 0) { |
| 570 | if ((buf[0] & 0x0F) == 0x01) { | 569 | vTaskDelay(pdMS_TO_TICKS(100)); |
| 571 | char *text = parse_ws_text_frame(buf, rlen); | 570 | continue; |
| 572 | if (text) { | 571 | } |
| 573 | if (strlen(text) > 0) { | 572 | |
| 574 | process_relay_message(relay_url, text); | 573 | ESP_LOGI(TAG, "WS frame received: %d bytes, opcode=0x%02x", rlen, buf[0] & 0x0F); |
| 575 | } | 574 | |
| 576 | free(text); | 575 | if ((buf[0] & 0x0F) == 0x01) { |
| 576 | char *text = parse_ws_text_frame(buf, rlen); | ||
| 577 | if (text) { | ||
| 578 | if (strlen(text) > 0) { | ||
| 579 | process_relay_message(relay_url, text); | ||
| 577 | } | 580 | } |
| 578 | } else if ((buf[0] & 0x0F) == 0x09) { | 581 | free(text); |
| 579 | ESP_LOGD(TAG, "Relay ping received, sending pong"); | ||
| 580 | uint8_t pong[2] = {0x8A, 0x00}; | ||
| 581 | esp_tls_conn_write(tls, pong, 2); | ||
| 582 | } else if ((buf[0] & 0x0F) == 0x08) { | ||
| 583 | ESP_LOGW(TAG, "Relay sent close frame"); | ||
| 584 | break; | ||
| 585 | } | 582 | } |
| 583 | } else if ((buf[0] & 0x0F) == 0x09) { | ||
| 584 | uint8_t pong[2] = {0x8A, 0x00}; | ||
| 585 | esp_tls_conn_write(tls, pong, 2); | ||
| 586 | } else if ((buf[0] & 0x0F) == 0x08) { | ||
| 587 | ESP_LOGW(TAG, "Relay sent close frame"); | ||
| 588 | break; | ||
| 586 | } | 589 | } |
| 587 | 590 | ||
| 588 | int64_t now = (int64_t)(xTaskGetTickCount() * portTICK_PERIOD_MS) / 1000; | 591 | int64_t now = (int64_t)(xTaskGetTickCount() * portTICK_PERIOD_MS) / 1000; |
| @@ -590,7 +593,6 @@ static void cvm_relay_task(void *arg) | |||
| 590 | uint8_t ping[2] = {0x89, 0x00}; | 593 | uint8_t ping[2] = {0x89, 0x00}; |
| 591 | esp_tls_conn_write(tls, ping, 2); | 594 | esp_tls_conn_write(tls, ping, 2); |
| 592 | last_ping_time = now; | 595 | last_ping_time = now; |
| 593 | ESP_LOGD(TAG, "Sent WS keepalive ping"); | ||
| 594 | } | 596 | } |
| 595 | } | 597 | } |
| 596 | 598 | ||
| @@ -726,8 +728,20 @@ void cvm_server_start(void) | |||
| 726 | const tollgate_config_t *cfg = tollgate_config_get(); | 728 | const tollgate_config_t *cfg = tollgate_config_get(); |
| 727 | const char *relay = (cfg->cvm_relays[0]) ? cfg->cvm_relays : "wss://relay.primal.net"; | 729 | const char *relay = (cfg->cvm_relays[0]) ? cfg->cvm_relays : "wss://relay.primal.net"; |
| 728 | 730 | ||
| 731 | ESP_LOGI(TAG, "Starting CVM relay task (free internal: %u, largest: %u)", | ||
| 732 | heap_caps_get_free_size(MALLOC_CAP_INTERNAL), | ||
| 733 | heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL)); | ||
| 734 | |||
| 729 | char *relay_copy = strdup(relay); | 735 | char *relay_copy = strdup(relay); |
| 730 | xTaskCreate(cvm_relay_task, "cvm_relay", 16384, relay_copy, 5, &g_task); | 736 | BaseType_t ret = xTaskCreatePinnedToCore(cvm_relay_task, "cvm_relay", 16384, relay_copy, 5, &g_task, 1); |
| 737 | if (ret != pdPASS) { | ||
| 738 | ESP_LOGE(TAG, "Failed to create cvm_relay task (ret=%d, free internal: %u)", | ||
| 739 | ret, heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); | ||
| 740 | g_running = false; | ||
| 741 | free(relay_copy); | ||
| 742 | return; | ||
| 743 | } | ||
| 744 | ESP_LOGI(TAG, "CVM relay task created on core %d", xPortGetCoreID()); | ||
| 731 | } | 745 | } |
| 732 | 746 | ||
| 733 | void cvm_server_stop(void) | 747 | void cvm_server_stop(void) |
diff --git a/main/tollgate_main.c b/main/tollgate_main.c index 60503eb..2d4fa22 100644 --- a/main/tollgate_main.c +++ b/main/tollgate_main.c | |||
| @@ -237,6 +237,12 @@ static void start_services(void) | |||
| 237 | session_manager_init(); | 237 | session_manager_init(); |
| 238 | 238 | ||
| 239 | const tollgate_config_t *cfg = tollgate_config_get(); | 239 | const tollgate_config_t *cfg = tollgate_config_get(); |
| 240 | |||
| 241 | if (cfg->cvm_enabled) { | ||
| 242 | cvm_server_init(); | ||
| 243 | cvm_server_start(); | ||
| 244 | } | ||
| 245 | |||
| 240 | mint_health_init(cfg->accepted_mints, cfg->accepted_mint_count); | 246 | mint_health_init(cfg->accepted_mints, cfg->accepted_mint_count); |
| 241 | mint_health_start(); | 247 | mint_health_start(); |
| 242 | 248 | ||
| @@ -268,19 +274,13 @@ static void start_services(void) | |||
| 268 | 274 | ||
| 269 | xTaskCreate(publish_wifistr_task, "wifistr_init", 16384, NULL, 3, NULL); | 275 | xTaskCreate(publish_wifistr_task, "wifistr_init", 16384, NULL, 3, NULL); |
| 270 | 276 | ||
| 271 | const tollgate_config_t *cfg2 = tollgate_config_get(); | 277 | if (cfg->mining_enabled) { |
| 272 | if (cfg2->cvm_enabled) { | ||
| 273 | cvm_server_init(); | ||
| 274 | cvm_server_start(); | ||
| 275 | } | ||
| 276 | |||
| 277 | if (cfg2->mining_enabled) { | ||
| 278 | ESP_LOGI(TAG, "Mining subsystem enabled, initializing..."); | 278 | ESP_LOGI(TAG, "Mining subsystem enabled, initializing..."); |
| 279 | mining_payment_init(); | 279 | mining_payment_init(); |
| 280 | stratum_client_init(); | 280 | stratum_client_init(); |
| 281 | stratum_proxy_init(cfg2->mining_port); | 281 | stratum_proxy_init(cfg->mining_port); |
| 282 | 282 | ||
| 283 | if (cfg2->mining_payout_mode != MINING_PAYOUT_UPSTREAM) { | 283 | if (cfg->mining_payout_mode != MINING_PAYOUT_UPSTREAM) { |
| 284 | stratum_client_start(); | 284 | stratum_client_start(); |
| 285 | } | 285 | } |
| 286 | 286 | ||