diff --git a/.gitignore b/.gitignore index 0b217ac8..e63f5ca6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ sdkconfig.old dependencies.lock # User specific VSCode -.vscode/* +**/.vscode/* # Production folder build/ diff --git a/components/bm1397/bm1397.c b/components/bm1397/bm1397.c index fbdc4508..2889493f 100644 --- a/components/bm1397/bm1397.c +++ b/components/bm1397/bm1397.c @@ -265,7 +265,7 @@ void BM1397_set_default_baud(void){ int BM1397_set_max_baud(void){ // divider of 0 for 3,125,000 - ESP_LOGI(TAG, "Setting max baud"); + ESP_LOGI(TAG, "Setting max baud of 3125000"); unsigned char baudrate[9] = { 0x00, MISC_CONTROL, 0x00, 0x00, 0b01100000, 0b00110001 };; //baudrate - misc_control _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, false); return 3125000; diff --git a/components/stratum/include/stratum_api.h b/components/stratum/include/stratum_api.h index cb24f091..841b24a1 100644 --- a/components/stratum/include/stratum_api.h +++ b/components/stratum/include/stratum_api.h @@ -20,6 +20,7 @@ typedef struct { uint32_t version; uint32_t target; uint32_t ntime; + uint32_t difficulty; } mining_notify; typedef enum { @@ -38,13 +39,13 @@ int subscribe_to_stratum(int socket, char ** extranonce, int * extranonce2_len); stratum_method parse_stratum_method(const char * stratum_json); -mining_notify parse_mining_notify_message(const char * stratum_json); +mining_notify * parse_mining_notify_message(const char * stratum_json, uint32_t difficulty); uint32_t parse_mining_set_difficulty_message(const char * stratum_json); uint32_t parse_mining_set_version_mask_message(const char * stratum_json); -void free_mining_notify(mining_notify params); +void free_mining_notify(mining_notify * params); int parse_stratum_subscribe_result_message(const char * result_json_str, char ** extranonce, diff --git a/components/stratum/mining.c b/components/stratum/mining.c index f43f99be..014085a5 100644 --- a/components/stratum/mining.c +++ b/components/stratum/mining.c @@ -60,6 +60,7 @@ bm_job construct_bm_job(mining_notify * params, const char * merkle_root) { new_job.starting_nonce = 0; new_job.target = params->target; new_job.ntime = params->ntime; + new_job.pool_diff = params->difficulty; hex2bin(merkle_root, new_job.merkle_root, 32); swap_endian_words(params->prev_block_hash, new_job.prev_block_hash); diff --git a/components/stratum/stratum_api.c b/components/stratum/stratum_api.c index 29bddef8..1e6a47bd 100644 --- a/components/stratum/stratum_api.c +++ b/components/stratum/stratum_api.c @@ -173,7 +173,7 @@ bool parse_stratum_result_message(const char * stratum_json, int16_t * parsed_id return result; } -mining_notify parse_mining_notify_message(const char * stratum_json) +mining_notify * parse_mining_notify_message(const char * stratum_json, uint32_t difficulty) { cJSON * json = cJSON_Parse(stratum_json); cJSON * method = cJSON_GetObjectItem(json, "method"); @@ -181,39 +181,41 @@ mining_notify parse_mining_notify_message(const char * stratum_json) assert(strcmp("mining.notify", method->valuestring) == 0); } - mining_notify new_work; + mining_notify * new_work = malloc(sizeof(mining_notify)); + new_work->difficulty = difficulty; cJSON * params = cJSON_GetObjectItem(json, "params"); - new_work.job_id = strdup(cJSON_GetArrayItem(params, 0)->valuestring); - new_work.prev_block_hash = strdup(cJSON_GetArrayItem(params, 1)->valuestring); - new_work.coinbase_1 = strdup(cJSON_GetArrayItem(params, 2)->valuestring); - new_work.coinbase_2 = strdup(cJSON_GetArrayItem(params, 3)->valuestring); + new_work->job_id = strdup(cJSON_GetArrayItem(params, 0)->valuestring); + new_work->prev_block_hash = strdup(cJSON_GetArrayItem(params, 1)->valuestring); + new_work->coinbase_1 = strdup(cJSON_GetArrayItem(params, 2)->valuestring); + new_work->coinbase_2 = strdup(cJSON_GetArrayItem(params, 3)->valuestring); cJSON * merkle_branch = cJSON_GetArrayItem(params, 4); - new_work.n_merkle_branches = cJSON_GetArraySize(merkle_branch); - if (new_work.n_merkle_branches > MAX_MERKLE_BRANCHES) { + new_work->n_merkle_branches = cJSON_GetArraySize(merkle_branch); + if (new_work->n_merkle_branches > MAX_MERKLE_BRANCHES) { printf("Too many Merkle branches.\n"); abort(); } - new_work.merkle_branches = malloc(HASH_SIZE * new_work.n_merkle_branches); - for (size_t i = 0; i < new_work.n_merkle_branches; i++) { - hex2bin(cJSON_GetArrayItem(merkle_branch, i)->valuestring, new_work.merkle_branches + HASH_SIZE * i, HASH_SIZE * 2); + new_work->merkle_branches = malloc(HASH_SIZE * new_work->n_merkle_branches); + for (size_t i = 0; i < new_work->n_merkle_branches; i++) { + hex2bin(cJSON_GetArrayItem(merkle_branch, i)->valuestring, new_work->merkle_branches + HASH_SIZE * i, HASH_SIZE * 2); } - new_work.version = strtoul(cJSON_GetArrayItem(params, 5)->valuestring, NULL, 16); - new_work.target = strtoul(cJSON_GetArrayItem(params, 6)->valuestring, NULL, 16); - new_work.ntime = strtoul(cJSON_GetArrayItem(params, 7)->valuestring, NULL, 16); + new_work->version = strtoul(cJSON_GetArrayItem(params, 5)->valuestring, NULL, 16); + new_work->target = strtoul(cJSON_GetArrayItem(params, 6)->valuestring, NULL, 16); + new_work->ntime = strtoul(cJSON_GetArrayItem(params, 7)->valuestring, NULL, 16); cJSON_Delete(json); return new_work; } -void free_mining_notify(mining_notify params) +void free_mining_notify(mining_notify * params) { - free(params.job_id); - free(params.prev_block_hash); - free(params.coinbase_1); - free(params.coinbase_2); - free(params.merkle_branches); + free(params->job_id); + free(params->prev_block_hash); + free(params->coinbase_1); + free(params->coinbase_2); + free(params->merkle_branches); + free(params); } int parse_stratum_subscribe_result_message(const char * result_json_str, diff --git a/components/stratum/test/test_mining.c b/components/stratum/test/test_mining.c index 8b431e44..087eb09f 100644 --- a/components/stratum/test/test_mining.c +++ b/components/stratum/test/test_mining.c @@ -82,10 +82,10 @@ TEST_CASE("Validate bm job construction 2", "[mining]") "\"params\":[\"21554471e8\",\"8bc8707eb169ad3bda101ae60c8d48bd00aff68a00006c8b0000000000000000\",\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03d8130cfabe6d6db0ba74b36edc62c9268c945b53ebf1a7865b88bcdd40235a7a63d0f5ed5b6c400100000000000000\",\"e8714455212f736c7573682f00000000033de04728000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae8c3686251b5ced65b6a65ea3e0491ac2975cd87c02b0640d3ec3c20005167770000000000000000266a24aa21a9eddffbecb5ef0a46324a3dd902fa84509a38d2c91548768845db5d6c2de0e33f6100000000\"," "[\"8ef6b79382a1fc5152c7e69b2dd4e3795ed758d6fe7748ef4d96e3ad8ac180b8\",\"5b6e1cfecd94050b763c2c6a08d4caabd54daee665aa8e41b53b39ec76b62707\",\"f85b768f83fffbb3927f7f440cb57a5ed386f368aae88ad9b9d92e7bc1cdce15\",\"e51b9391c39019d8a2a27becc048cc770f5d33b49a29779fdc7bed04767ca962\",\"9f5d08316ead260455ec532a58935411a3eecf3c9948a52325de495d7dd7b776\",\"57e10cad23a646ad3a87fcd34eae454567dbd44946e746ee6310a86b98afa4ac\",\"f3b65cc08b25901b657efb22f0a9a23e1a61ce1e268f801d8cfe782b4a0c5e5d\",\"648e00fe2a57dca155c7d4260bc52273b28adb42e1bceb45d5ee03f4a4c5d174\",\"43ad393f7efe4b7a29775dbbc10b3b2737e9457764a7b39bc8ac6b470b968ac8\",\"4964b9b2bf601dfb2bd62067acafe556650412b1e6fe32df48c39310f7dc255d\",\"44d354ac57fcb68b408df7f5396122195384914dd2db13d5766c334fc48c2069\",\"568514a2db82a055772218f52db2f5fa157c37a9ba16c1a239819e57f0d16218\"]," "\"20000004\",\"1705ae3a\",\"6470e2a1\",true]}"; - mining_notify params = parse_mining_notify_message(notify_json_str); - char * coinbase_tx = construct_coinbase_tx(params.coinbase_1, params.coinbase_2, "336508070fca95", "0000000000000000"); - char * merkle_root = calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])params.merkle_branches, params.n_merkle_branches); - bm_job job = construct_bm_job(¶ms, merkle_root); + mining_notify * params = parse_mining_notify_message(notify_json_str, 512); + char * coinbase_tx = construct_coinbase_tx(params->coinbase_1, params->coinbase_2, "336508070fca95", "0000000000000000"); + char * merkle_root = calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])params->merkle_branches, params->n_merkle_branches); + bm_job job = construct_bm_job(params, merkle_root); uint8_t expected_midstate_bin[32]; hex2bin("5FD281AF6A1750EAEE502C04067738BD46C82FC22112FFE797CE7F035D276126", expected_midstate_bin, 32); diff --git a/components/stratum/test/test_stratum_json.c b/components/stratum/test/test_stratum_json.c index 8bc3fa7c..11f6e25f 100644 --- a/components/stratum/test/test_stratum_json.c +++ b/components/stratum/test/test_stratum_json.c @@ -34,14 +34,14 @@ TEST_CASE("Parse stratum notify params", "[mining.notify]") "\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\"," "[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"]," "\"20000004\",\"1705c739\",\"64495522\",false]}"; - mining_notify params = parse_mining_notify_message(json_string); - TEST_ASSERT_EQUAL_STRING("1d2e0c4d3d", params.job_id); - TEST_ASSERT_EQUAL_STRING("ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000", params.prev_block_hash); - TEST_ASSERT_EQUAL_STRING("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000", params.coinbase_1); - TEST_ASSERT_EQUAL_STRING("41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000", params.coinbase_2); - TEST_ASSERT_EQUAL_UINT32(0x20000004, params.version); - TEST_ASSERT_EQUAL_UINT32(0x1705c739, params.target); - TEST_ASSERT_EQUAL_UINT32(0x64495522, params.ntime); + mining_notify * params = parse_mining_notify_message(json_string, 512); + TEST_ASSERT_EQUAL_STRING("1d2e0c4d3d", params->job_id); + TEST_ASSERT_EQUAL_STRING("ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000", params->prev_block_hash); + TEST_ASSERT_EQUAL_STRING("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000", params->coinbase_1); + TEST_ASSERT_EQUAL_STRING("41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000", params->coinbase_2); + TEST_ASSERT_EQUAL_UINT32(0x20000004, params->version); + TEST_ASSERT_EQUAL_UINT32(0x1705c739, params->target); + TEST_ASSERT_EQUAL_UINT32(0x64495522, params->ntime); } TEST_CASE("Test mining.subcribe result parsing", "[mining.subscribe]") diff --git a/main/tasks/asic_task.c b/main/tasks/asic_task.c index cc1db11a..1b7090b4 100644 --- a/main/tasks/asic_task.c +++ b/main/tasks/asic_task.c @@ -49,11 +49,11 @@ void ASIC_task(void * pvParameters) memcpy(&job.ntime, &next_bm_job->ntime, 4); memcpy(&job.merkle4, next_bm_job->merkle_root + 28, 4); memcpy(job.midstate, next_bm_job->midstate, 32); + if (active_jobs[job.job_id] != NULL) { - free(active_jobs[job.job_id]->jobid); - free(active_jobs[job.job_id]->extranonce2); - free(active_jobs[job.job_id]); + free_bm_job(active_jobs[job.job_id]); } + active_jobs[job.job_id] = next_bm_job; pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock); diff --git a/main/tasks/create_jobs_task.c b/main/tasks/create_jobs_task.c index d650b8ef..f8290c27 100644 --- a/main/tasks/create_jobs_task.c +++ b/main/tasks/create_jobs_task.c @@ -17,30 +17,24 @@ void create_jobs_task(void * pvParameters) while (1) { - char * next_notify_json_str = (char *) queue_dequeue(&GLOBAL_STATE->stratum_queue); - ESP_LOGI(TAG, "New Work Dequeued"); - - mining_notify params = parse_mining_notify_message(next_notify_json_str); + mining_notify * params = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue); + ESP_LOGI(TAG, "New Work Dequeued %s", params->job_id); uint32_t extranonce_2 = 0; while (extranonce_2 < UINT_MAX && GLOBAL_STATE->abandon_work == 0) { char * extranonce_2_str = extranonce_2_generate(extranonce_2, GLOBAL_STATE->extranonce_2_len); - char *coinbase_tx = construct_coinbase_tx(params.coinbase_1, params.coinbase_2, GLOBAL_STATE->extranonce_str, extranonce_2_str); - //ESP_LOGI(TAG, "Coinbase tx: %s", coinbase_tx); + + char *coinbase_tx = construct_coinbase_tx(params->coinbase_1, params->coinbase_2, GLOBAL_STATE->extranonce_str, extranonce_2_str); - char *merkle_root = calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])params.merkle_branches, params.n_merkle_branches); - //ESP_LOGI(TAG, "Merkle root: %s", merkle_root); - - bm_job next_job = construct_bm_job(¶ms, merkle_root); - - next_job.pool_diff = GLOBAL_STATE->stratum_difficulty; //each job is tied to the _current_ difficulty + char *merkle_root = calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])params->merkle_branches, params->n_merkle_branches); + bm_job next_job = construct_bm_job(params, merkle_root); bm_job * queued_next_job = malloc(sizeof(bm_job)); memcpy(queued_next_job, &next_job, sizeof(bm_job)); queued_next_job->extranonce2 = strdup(extranonce_2_str); - queued_next_job->jobid = strdup(params.job_id); + queued_next_job->jobid = strdup(params->job_id); queue_enqueue(&GLOBAL_STATE->ASIC_jobs_queue, queued_next_job); @@ -56,7 +50,6 @@ void create_jobs_task(void * pvParameters) } free_mining_notify(params); - free(next_notify_json_str); } } diff --git a/main/tasks/stratum_task.c b/main/tasks/stratum_task.c index 199186bf..0069b7ed 100644 --- a/main/tasks/stratum_task.c +++ b/main/tasks/stratum_task.c @@ -6,6 +6,7 @@ #include "bm1397.h" #include "global_state.h" + #define PORT CONFIG_STRATUM_PORT #define STRATUM_URL CONFIG_STRATUM_URL @@ -15,7 +16,6 @@ static const char *TAG = "stratum_task"; static ip_addr_t ip_Addr; static bool bDNSFound = false; -static bool difficulty_changed = false; void dns_found_cb(const char * name, const ip_addr_t * ipaddr, void * callback_arg) @@ -92,16 +92,12 @@ void stratum_task(void * pvParameters) stratum_method method = parse_stratum_method(line); - if (method == MINING_NOTIFY) { - if ((difficulty_changed || should_abandon_work(line)) && GLOBAL_STATE->stratum_queue.count > 0) { + + + if (method == MINING_NOTIFY) { + if (should_abandon_work(line) && GLOBAL_STATE->stratum_queue.count > 0) { + ESP_LOGI(TAG, "pool diff changed, clearing queues"); - if (difficulty_changed) { - ESP_LOGI(TAG, "pool diff changed, clearing queues"); - difficulty_changed = false; - } else { - ESP_LOGI(TAG, "clean_jobs is true, clearing queues"); - } - GLOBAL_STATE->abandon_work = 1; queue_clear(&GLOBAL_STATE->stratum_queue); @@ -113,26 +109,24 @@ void stratum_task(void * pvParameters) pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock); } if ( GLOBAL_STATE->stratum_queue.count == QUEUE_SIZE) { - char * next_notify_json_str = (char *) queue_dequeue(&GLOBAL_STATE->stratum_queue); - free(next_notify_json_str); + mining_notify * next_notify_json_str = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue); + free_mining_notify(next_notify_json_str); } - queue_enqueue(&GLOBAL_STATE->stratum_queue, line); + mining_notify * params = parse_mining_notify_message(line, GLOBAL_STATE->stratum_difficulty); + queue_enqueue(&GLOBAL_STATE->stratum_queue, params); } else if (method == MINING_SET_DIFFICULTY) { uint32_t new_difficulty = parse_mining_set_difficulty_message(line); if (new_difficulty != GLOBAL_STATE->stratum_difficulty) { GLOBAL_STATE->stratum_difficulty = new_difficulty; - difficulty_changed = true; ESP_LOGI(TAG, "Set stratum difficulty: %d", GLOBAL_STATE->stratum_difficulty); BM1397_set_job_difficulty_mask(GLOBAL_STATE->stratum_difficulty); } - free(line); } else if (method == MINING_SET_VERSION_MASK) { version_mask = parse_mining_set_version_mask_message(line); //1fffe000 ESP_LOGI(TAG, "Set version mask: %08x", version_mask); - free(line); } else if (method == STRATUM_RESULT) { int16_t parsed_id; @@ -143,12 +137,10 @@ void stratum_task(void * pvParameters) ESP_LOGI(TAG, "message id %d result rejected", parsed_id); SYSTEM_notify_rejected_share(&GLOBAL_STATE->SYSTEM_MODULE); } - free(line); - } else { - free(line); - } - - + } + + free(line); + } if (GLOBAL_STATE->sock != -1) diff --git a/main/work_queue.c b/main/work_queue.c index dbf04ce5..ed4d0e1f 100644 --- a/main/work_queue.c +++ b/main/work_queue.c @@ -1,4 +1,5 @@ #include "work_queue.h" +#include "esp_log.h" void queue_init(work_queue * queue) { queue->head = 0; @@ -47,8 +48,8 @@ void queue_clear(work_queue * queue) while (queue->count > 0) { - void * next_work = queue->buffer[queue->head]; - free(next_work); + mining_notify * next_work = queue->buffer[queue->head]; + free_mining_notify(next_work); queue->head = (queue->head + 1) % QUEUE_SIZE; queue->count--; }