From 11c1d087a87f08f71fae4a5c10e388ee2e15c93a Mon Sep 17 00:00:00 2001 From: Skot Date: Fri, 31 May 2024 17:43:10 -0400 Subject: [PATCH] Stratum message ordering fix (#192) * rough strategy for this fix. needs testing * seems to be working with OCEAN. need to make sure nothing else is broken * add version mask debug * removed stratum setup response results from A/R shares tally --- components/stratum/include/stratum_api.h | 11 ++- components/stratum/stratum_api.c | 115 +++++++++++++---------- main/global_state.h | 2 +- main/tasks/stratum_task.c | 31 +++--- 4 files changed, 92 insertions(+), 67 deletions(-) diff --git a/components/stratum/include/stratum_api.h b/components/stratum/include/stratum_api.h index b1b68d5d..5a7b8828 100644 --- a/components/stratum/include/stratum_api.h +++ b/components/stratum/include/stratum_api.h @@ -17,9 +17,14 @@ typedef enum MINING_SET_DIFFICULTY, MINING_SET_VERSION_MASK, STRATUM_RESULT, - STRATUM_RESULT_VERSION_MASK + STRATUM_RESULT_SETUP, + STRATUM_RESULT_VERSION_MASK, + STRATUM_RESULT_SUBSCRIBE } stratum_method; +static const int STRATUM_ID_SUBSCRIBE = 1; +static const int STRATUM_ID_CONFIGURE = 2; + typedef struct { char *job_id; @@ -37,6 +42,8 @@ typedef struct typedef struct { + char * extranonce_str; + int extranonce_2_len; int16_t message_id; // Indicates the type of request the message represents. @@ -57,7 +64,7 @@ void STRATUM_V1_initialize_buffer(); char *STRATUM_V1_receive_jsonrpc_line(int sockfd); -int STRATUM_V1_subscribe(int socket, char ** extranonce, int * extranonce2_len, char * model); +int STRATUM_V1_subscribe(int socket, char * model); void STRATUM_V1_parse(StratumApiV1Message *message, const char *stratum_json); diff --git a/components/stratum/stratum_api.c b/components/stratum/stratum_api.c index d00d78d3..d87f68cc 100644 --- a/components/stratum/stratum_api.c +++ b/components/stratum/stratum_api.c @@ -23,6 +23,7 @@ static size_t json_rpc_buffer_size = 0; static int send_uid = 1; static void debug_stratum_tx(const char *); +int _parse_stratum_subscribe_result_message(const char * result_json_str, char ** extranonce, int * extranonce2_len); void STRATUM_V1_initialize_buffer() { @@ -116,6 +117,8 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json) cJSON * method_json = cJSON_GetObjectItem(json, "method"); stratum_method result = STRATUM_UNKNOWN; + + //if there is a method, then use that to decide what to do if (method_json != NULL && cJSON_IsString(method_json)) { if (strcmp("mining.notify", method_json->valuestring) == 0) { result = MINING_NOTIFY; @@ -126,30 +129,78 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json) } else { ESP_LOGI(TAG, "unhandled method in stratum message: %s", stratum_json); } + + //if there is no method, then it is a result } else { // parse results cJSON * result_json = cJSON_GetObjectItem(json, "result"); cJSON * error_json = cJSON_GetObjectItem(json, "error"); + + //if the result is null, then it's a fail if (result_json == NULL) { message->response_success = false; - } else { + + //if it's an error, then it's a fail + } else if (!cJSON_IsNull(error_json)) { + if (parsed_id < 5) { + result = STRATUM_RESULT_SETUP; + } else { + result = STRATUM_RESULT; + } + message->response_success = false; + + //if the result is a boolean, then parse it + } else if (cJSON_IsBool(result_json)) { + if (parsed_id < 5) { + result = STRATUM_RESULT_SETUP; + } else { + result = STRATUM_RESULT; + } + if (cJSON_IsTrue(result_json)) { + message->response_success = true; + } else { + message->response_success = false; + } + + //if the id is STRATUM_ID_SUBSCRIBE parse it + } else if (parsed_id == STRATUM_ID_SUBSCRIBE) { + result = STRATUM_RESULT_SUBSCRIBE; + + cJSON * extranonce2_len_json = cJSON_GetArrayItem(result_json, 2); + if (extranonce2_len_json == NULL) { + ESP_LOGE(TAG, "Unable to parse extranonce2_len: %s", result_json->valuestring); + message->response_success = false; + goto done; + } + message->extranonce_2_len = extranonce2_len_json->valueint; + + cJSON * extranonce_json = cJSON_GetArrayItem(result_json, 1); + if (extranonce_json == NULL) { + ESP_LOGE(TAG, "Unable parse extranonce: %s", result_json->valuestring); + message->response_success = false; + goto done; + } + message->extranonce_str = malloc(strlen(extranonce_json->valuestring) + 1); + strcpy(message->extranonce_str, extranonce_json->valuestring); + message->response_success = true; + + //print the extranonce_str + ESP_LOGI(TAG, "extranonce_str: %s", message->extranonce_str); + ESP_LOGI(TAG, "extranonce_2_len: %d", message->extranonce_2_len); + + //if the id is STRATUM_ID_CONFIGURE parse it + } else if (parsed_id == STRATUM_ID_CONFIGURE) { cJSON * mask = cJSON_GetObjectItem(result_json, "version-rolling.mask"); if (mask != NULL) { result = STRATUM_RESULT_VERSION_MASK; message->version_mask = strtoul(mask->valuestring, NULL, 16); - } else if (cJSON_IsBool(result_json)) { - result = STRATUM_RESULT; - if (cJSON_IsTrue(result_json)) { - message->response_success = true; - } else { - message->response_success = false; - } - } else if (!cJSON_IsNull(error_json)) { - result = STRATUM_RESULT; - message->response_success = false; + ESP_LOGI(TAG, "Set version mask: %08lx", message->version_mask); } else { - ESP_LOGI(TAG, "unhandled result in stratum message: %s", stratum_json); + ESP_LOGI(TAG, "error setting version mask: %s", stratum_json); } + + } else { + ESP_LOGI(TAG, "unhandled result in stratum message: %s", stratum_json); } } @@ -197,7 +248,7 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json) uint32_t version_mask = strtoul(cJSON_GetArrayItem(params, 0)->valuestring, NULL, 16); message->version_mask = version_mask; } - + done: cJSON_Delete(json); } @@ -244,20 +295,13 @@ int _parse_stratum_subscribe_result_message(const char * result_json_str, char * return 0; } -int STRATUM_V1_subscribe(int socket, char ** extranonce, int * extranonce2_len, char * model) +int STRATUM_V1_subscribe(int socket, char * model) { // Subscribe char subscribe_msg[BUFFER_SIZE]; sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitaxe/%s\"]}\n", send_uid++, model); debug_stratum_tx(subscribe_msg); write(socket, subscribe_msg, strlen(subscribe_msg)); - char * line; - line = STRATUM_V1_receive_jsonrpc_line(socket); - ESP_LOGI(TAG, "Received result %s", line); - - _parse_stratum_subscribe_result_message(line, extranonce, extranonce2_len); - - free(line); return 1; } @@ -269,15 +313,6 @@ int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty) debug_stratum_tx(difficulty_msg); write(socket, difficulty_msg, strlen(difficulty_msg)); - /* TODO: fix race condition with first mining.notify message - char * line; - line = STRATUM_V1_receive_jsonrpc_line(socket); - - ESP_LOGI(TAG, "Received result %s", line); - - free(line); - */ - return 1; } @@ -320,26 +355,6 @@ void STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask) ESP_LOGI(TAG, "tx: %s", configure_msg); write(socket, configure_msg, strlen(configure_msg)); - char * line = STRATUM_V1_receive_jsonrpc_line(socket); - cJSON * json = cJSON_Parse(line); - - ESP_LOGI(TAG, "Received result %s", line); - - cJSON * result = cJSON_GetObjectItem(json, "result"); - if (result != NULL) { - cJSON * version_rolling_enabled = cJSON_GetObjectItem(result, "version-rolling"); - if (cJSON_IsBool(version_rolling_enabled) && cJSON_IsTrue(version_rolling_enabled)) { - cJSON * mask = cJSON_GetObjectItem(result, "version-rolling.mask"); - *version_mask = strtoul(mask->valuestring, NULL, 16); - ESP_LOGI(TAG, "Set version mask: %08lx", *version_mask); - } - }else{ - printf("configure_version result null\n"); - } - - cJSON_Delete(json); - free(line); - return; } diff --git a/main/global_state.h b/main/global_state.h index 5d3b195b..5d718e24 100644 --- a/main/global_state.h +++ b/main/global_state.h @@ -16,7 +16,7 @@ typedef struct { - uint8_t (*init_fn)(u_int64_t); + uint8_t (*init_fn)(uint64_t); task_result * (*receive_result_fn)(void * GLOBAL_STATE); int (*set_max_baud_fn)(void); void (*set_difficulty_mask_fn)(int); diff --git a/main/tasks/stratum_task.c b/main/tasks/stratum_task.c index b294934d..c36984e5 100644 --- a/main/tasks/stratum_task.c +++ b/main/tasks/stratum_task.c @@ -101,30 +101,24 @@ void stratum_task(void * pvParameters) continue; } - // mining.subscribe - STRATUM_V1_subscribe(GLOBAL_STATE->sock, &GLOBAL_STATE->extranonce_str, &GLOBAL_STATE->extranonce_2_len, - GLOBAL_STATE->asic_model); + ///// Start Stratum Action + // mining.subscribe - ID: 1 + STRATUM_V1_subscribe(GLOBAL_STATE->sock, GLOBAL_STATE->asic_model); - - // mining.configure + // mining.configure - ID: 2 STRATUM_V1_configure_version_rolling(GLOBAL_STATE->sock, &GLOBAL_STATE->version_mask); - - // This should come before the final step of authenticate so the first job is sent with the proper difficulty set - //mining.suggest_difficulty + //mining.suggest_difficulty - ID: 3 STRATUM_V1_suggest_difficulty(GLOBAL_STATE->sock, STRATUM_DIFFICULTY); char * username = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER); char * password = nvs_config_get_string(NVS_CONFIG_STRATUM_PASS, STRATUM_PW); + + //mining.authorize - ID: 4 STRATUM_V1_authenticate(GLOBAL_STATE->sock, username, password); free(password); free(username); - - - //ESP_LOGI(TAG, "Extranonce: %s", GLOBAL_STATE->extranonce_str); - //ESP_LOGI(TAG, "Extranonce 2 length: %d", GLOBAL_STATE->extranonce_2_len); - while (1) { char * line = STRATUM_V1_receive_jsonrpc_line(GLOBAL_STATE->sock); ESP_LOGI(TAG, "rx: %s", line); // debug incoming stratum messages @@ -160,10 +154,13 @@ void stratum_task(void * pvParameters) ESP_LOGI(TAG, "Set stratum difficulty: %ld", SYSTEM_TASK_MODULE.stratum_difficulty); } } else if (stratum_api_v1_message.method == MINING_SET_VERSION_MASK || - stratum_api_v1_message.method == STRATUM_RESULT_VERSION_MASK) { + stratum_api_v1_message.method == .0) { // 1fffe000 ESP_LOGI(TAG, "Set version mask: %08lx", stratum_api_v1_message.version_mask); GLOBAL_STATE->version_mask = stratum_api_v1_message.version_mask; + } else if (stratum_api_v1_message.method == STRATUM_RESULT_SUBSCRIBE) { + GLOBAL_STATE->extranonce_str = stratum_api_v1_message.extranonce_str; + GLOBAL_STATE->extranonce_2_len = stratum_api_v1_message.extranonce_2_len; } else if (stratum_api_v1_message.method == STRATUM_RESULT) { if (stratum_api_v1_message.response_success) { ESP_LOGI(TAG, "message result accepted"); @@ -172,6 +169,12 @@ void stratum_task(void * pvParameters) ESP_LOGE(TAG, "message result rejected"); SYSTEM_notify_rejected_share(&GLOBAL_STATE->SYSTEM_MODULE); } + } else if (stratum_api_v1_message.method == STRATUM_RESULT_SETUP) { + if (stratum_api_v1_message.response_success) { + ESP_LOGI(TAG, "setup message accepted"); + } else { + ESP_LOGE(TAG, "setup message rejected"); + } } }