From 4b7a6d8146098e18e3396bf64ed4adb22338d735 Mon Sep 17 00:00:00 2001 From: shufps Date: Mon, 9 Sep 2024 15:10:08 +0200 Subject: [PATCH] seems to be working --- src/NerdMinerV2.ino.cpp | 3 + src/drivers/nerd-nos/bm1397.cpp | 65 +++------ src/drivers/nerd-nos/bm1397.h | 40 +----- src/drivers/nerd-nos/common.h | 39 +----- src/drivers/nerd-nos/crc.h | 12 +- src/drivers/nerd-nos/mining.cpp | 44 ++---- src/drivers/nerd-nos/mining.h | 42 +++--- src/drivers/nerd-nos/nerdnos.h | 66 +++++++++ src/drivers/nerd-nos/serial.cpp | 12 ++ src/drivers/nerd-nos/serial.h | 4 +- src/drivers/nerd-nos/utils.cpp | 48 +++++++ src/drivers/nerd-nos/utils.h | 7 +- src/mining.cpp | 126 +---------------- src/mining.h | 2 +- src/mining_nerdnos.cpp | 232 ++++++++++++++++++++++++++++++++ src/mining_nerdnos.h | 6 + src/monitor.cpp | 79 ++++++----- src/stratum.cpp | 6 + src/stratum.h | 4 +- 19 files changed, 487 insertions(+), 350 deletions(-) create mode 100644 src/drivers/nerd-nos/nerdnos.h create mode 100644 src/mining_nerdnos.cpp create mode 100644 src/mining_nerdnos.h diff --git a/src/NerdMinerV2.ino.cpp b/src/NerdMinerV2.ino.cpp index 3b24b7a..4165105 100644 --- a/src/NerdMinerV2.ino.cpp +++ b/src/NerdMinerV2.ino.cpp @@ -17,6 +17,9 @@ #include "drivers/nerd-nos/bm1397.h" #include "drivers/nerd-nos/serial.h" +#ifdef NERD_NOS +#include "mining_nerdnos.h" +#endif #ifdef TOUCH_ENABLE #include "TouchHandler.h" diff --git a/src/drivers/nerd-nos/bm1397.cpp b/src/drivers/nerd-nos/bm1397.cpp index fe1dc87..1588cf0 100644 --- a/src/drivers/nerd-nos/bm1397.cpp +++ b/src/drivers/nerd-nos/bm1397.cpp @@ -7,6 +7,7 @@ #include "freertos/task.h" #include "../devices/device.h" #include "crc.h" +#include "utils.h" #define TYPE_JOB 0x20 #define TYPE_CMD 0x40 @@ -48,7 +49,6 @@ typedef struct __attribute__((__packed__)) static const char *TAG = "bm1397Module"; static uint8_t asic_response_buffer[CHUNK_SIZE]; -static uint32_t prev_nonce = 0; static task_result result; uint32_t increment_bitmask(const uint32_t value, const uint32_t mask); @@ -101,7 +101,7 @@ static void _send_read_address(void) { unsigned char read_address[2] = {0x00, 0x00}; // send serial data - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1397_SERIALTX_DEBUG); } static void _send_chain_inactive(void) @@ -109,7 +109,7 @@ static void _send_chain_inactive(void) unsigned char read_address[2] = {0x00, 0x00}; // send serial data - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_INACTIVE), read_address, 2, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_INACTIVE), read_address, 2, BM1397_SERIALTX_DEBUG); } static void _set_chip_address(uint8_t chipAddr) @@ -117,7 +117,7 @@ static void _set_chip_address(uint8_t chipAddr) unsigned char read_address[2] = {chipAddr, 0x00}; // send serial data - _send_BM1397((TYPE_CMD | GROUP_SINGLE | CMD_SETADDRESS), read_address, 2, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_SINGLE | CMD_SETADDRESS), read_address, 2, BM1397_SERIALTX_DEBUG); } void BM1397_send_hash_frequency(float frequency) @@ -187,12 +187,12 @@ void BM1397_send_hash_frequency(float frequency) for (i = 0; i < 2; i++) { vTaskDelay(10 / portTICK_PERIOD_MS); - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), prefreqall, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), prefreqall, 6, BM1397_SERIALTX_DEBUG); } for (i = 0; i < 2; i++) { vTaskDelay(10 / portTICK_PERIOD_MS); - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), freqbufall, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), freqbufall, 6, BM1397_SERIALTX_DEBUG); } vTaskDelay(10 / portTICK_PERIOD_MS); @@ -228,24 +228,24 @@ static uint8_t _send_init(uint64_t frequency, uint16_t asic_count) } unsigned char init[6] = {0x00, CLOCK_ORDER_CONTROL_0, 0x00, 0x00, 0x00, 0x00}; // init1 - clock_order_control0 - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init, 6, BM1397_SERIALTX_DEBUG); unsigned char init2[6] = {0x00, CLOCK_ORDER_CONTROL_1, 0x00, 0x00, 0x00, 0x00}; // init2 - clock_order_control1 - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init2, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init2, 6, BM1397_SERIALTX_DEBUG); unsigned char init3[9] = {0x00, ORDERED_CLOCK_ENABLE, 0x00, 0x00, 0x00, 0x01}; // init3 - ordered_clock_enable - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init3, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init3, 6, BM1397_SERIALTX_DEBUG); unsigned char init4[9] = {0x00, CORE_REGISTER_CONTROL, 0x80, 0x00, 0x80, 0x74}; // init4 - init_4_? - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init4, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init4, 6, BM1397_SERIALTX_DEBUG); BM1397_set_job_difficulty_mask(BM1397_INITIAL_DIFFICULTY); unsigned char init5[9] = {0x00, PLL3_PARAMETER, 0xC0, 0x70, 0x01, 0x11}; // init5 - pll3_parameter - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init5, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init5, 6, BM1397_SERIALTX_DEBUG); unsigned char init6[9] = {0x00, FAST_UART_CONFIGURATION, 0x06, 0x00, 0x00, 0x0F}; // init6 - fast_uart_configuration - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init6, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init6, 6, BM1397_SERIALTX_DEBUG); BM1397_set_default_baud(); @@ -294,7 +294,7 @@ int BM1397_set_default_baud(void) { // default divider of 26 (11010) for 115,749 unsigned char baudrate[9] = {0x00, MISC_CONTROL, 0x00, 0x00, 0b01111010, 0b00110001}; // baudrate - misc_control - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, BM1397_SERIALTX_DEBUG); return 115749; } @@ -304,7 +304,7 @@ int BM1397_set_max_baud(void) 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, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, BM1397_SERIALTX_DEBUG); return 3125000; } @@ -317,7 +317,7 @@ void BM1397_set_job_difficulty_mask(int difficulty) // The mask must be a power of 2 so there are no holes // Correct: {0b00000000, 0b00000000, 0b11111111, 0b11111111} // Incorrect: {0b00000000, 0b00000000, 0b11100111, 0b11111111} - difficulty = _largest_power_of_two(difficulty) - 1; // (difficulty - 1) if it is a pow 2 then step down to second largest for more hashrate sampling + difficulty = largest_power_of_two(difficulty) - 1; // (difficulty - 1) if it is a pow 2 then step down to second largest for more hashrate sampling // convert difficulty into char array // Ex: 256 = {0b00000000, 0b00000000, 0b00000000, 0b11111111}, {0x00, 0x00, 0x00, 0xff} @@ -329,18 +329,18 @@ void BM1397_set_job_difficulty_mask(int difficulty) // So a mask of 512 looks like 0b00000000 00000000 00000001 1111111 // and not 0b00000000 00000000 10000000 1111111 - job_difficulty_mask[5 - i] = _reverse_bits(value); + job_difficulty_mask[5 - i] = reverse_bits(value); } ESP_LOGI(TAG, "Setting job ASIC mask to %d", difficulty); - _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), job_difficulty_mask, 6, BM1937_SERIALTX_DEBUG); + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), job_difficulty_mask, 6, BM1397_SERIALTX_DEBUG); } void BM1397_send_work(bm_job_t *next_bm_job, uint8_t job_id) { - job_packet job; + job_packet_t job; // max job number is 128 // there is still some really weird logic with the job id bits for the asic to sort out // so we have it limited to 128 and it has to increment by 4 @@ -360,7 +360,7 @@ void BM1397_send_work(bm_job_t *next_bm_job, uint8_t job_id) memcpy(job.midstate3, next_bm_job->midstate3, 32); } - _send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t*) &job, sizeof(job_packet), BM1397_DEBUG_WORK); + _send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t*) &job, sizeof(job_packet_t), BM1397_DEBUG_WORK); } asic_result *BM1397_receive_work(uint16_t timeout) @@ -392,7 +392,6 @@ asic_result *BM1397_receive_work(uint16_t timeout) task_result *BM1397_proccess_work(uint32_t version, uint16_t timeout) { - asic_result *asic_result = BM1397_receive_work(timeout); if (asic_result == NULL) @@ -401,9 +400,6 @@ task_result *BM1397_proccess_work(uint32_t version, uint16_t timeout) return NULL; } - uint8_t nonce_found = 0; - uint32_t first_nonce = 0; - uint8_t rx_job_id = (asic_result->job_id & 0xfc) >> 2; uint8_t rx_midstate_index = asic_result->job_id & 0x03; @@ -413,29 +409,6 @@ task_result *BM1397_proccess_work(uint32_t version, uint16_t timeout) rolled_version = increment_bitmask(rolled_version, 0x1fffe000); } - // ASIC may return the same nonce multiple times - // or one that was already found - // most of the time it behavies however - if (nonce_found == 0) - { - first_nonce = asic_result->nonce; - nonce_found = 1; - } - else if (asic_result->nonce == first_nonce) - { - // stop if we've already seen this nonce - return NULL; - } - - if (asic_result->nonce == prev_nonce) - { - return NULL; - } - else - { - prev_nonce = asic_result->nonce; - } - result.job_id = rx_job_id; result.nonce = asic_result->nonce; result.rolled_version = rolled_version; diff --git a/src/drivers/nerd-nos/bm1397.h b/src/drivers/nerd-nos/bm1397.h index 5304723..743d140 100644 --- a/src/drivers/nerd-nos/bm1397.h +++ b/src/drivers/nerd-nos/bm1397.h @@ -1,49 +1,15 @@ #pragma once #include -#include "common.h" -#include "mining.h" +#include "nerdnos.h" #include "crc.h" #define CRC5_MASK 0x1F -#define BM1397_INITIAL_DIFFICULTY 64 -#define BM1937_SERIALTX_DEBUG false -#define BM1937_SERIALRX_DEBUG true //false +#define BM1397_SERIALTX_DEBUG false +#define BM1397_SERIALRX_DEBUG true //false #define BM1397_DEBUG_WORK false //causes insane amount of debug output - -typedef struct -{ - float frequency; -} bm1397Module; - -typedef enum -{ - JOB_PACKET = 0, - CMD_PACKET = 1, -} packet_type_t; - -typedef enum -{ - JOB_RESP = 0, - CMD_RESP = 1, -} response_type_t; - -typedef struct __attribute__((__packed__)) -{ - uint8_t job_id; - uint8_t num_midstates; - uint8_t starting_nonce[4]; - uint8_t nbits[4]; - uint8_t ntime[4]; - uint8_t merkle4[4]; - uint8_t midstate[32]; - uint8_t midstate1[32]; - uint8_t midstate2[32]; - uint8_t midstate3[32]; -} job_packet; - uint8_t BM1397_init(uint64_t frequency, uint16_t asic_count); void BM1397_send_work(bm_job_t * next_bm_job, uint8_t job_id); diff --git a/src/drivers/nerd-nos/common.h b/src/drivers/nerd-nos/common.h index 6b98342..b8488ae 100644 --- a/src/drivers/nerd-nos/common.h +++ b/src/drivers/nerd-nos/common.h @@ -1,41 +1,6 @@ -#ifndef COMMON_H_ -#define COMMON_H_ +#pragma once #include - -typedef struct __attribute__((__packed__)) -{ - uint8_t job_id; - uint32_t nonce; - uint32_t rolled_version; -} task_result; - -static unsigned char _reverse_bits(unsigned char num) -{ - unsigned char reversed = 0; - int i; - - for (i = 0; i < 8; i++) { - reversed <<= 1; // Left shift the reversed variable by 1 - reversed |= num & 1; // Use bitwise OR to set the rightmost bit of reversed to the current bit of num - num >>= 1; // Right shift num by 1 to get the next bit - } - - return reversed; -} - -static int _largest_power_of_two(int num) -{ - int power = 0; - - while (num > 1) { - num = num >> 1; - power++; - } - - return 1 << power; -} +#include void printBufferHex(const char *prefix, const uint8_t* buf, size_t len); - -#endif \ No newline at end of file diff --git a/src/drivers/nerd-nos/crc.h b/src/drivers/nerd-nos/crc.h index 1f4b1df..d9f4194 100644 --- a/src/drivers/nerd-nos/crc.h +++ b/src/drivers/nerd-nos/crc.h @@ -1,18 +1,8 @@ -#ifndef CRC_H_ -#define CRC_H_ +#pragma once #include -#ifdef __cplusplus -extern "C" { -#endif - uint8_t crc5(uint8_t *buffer, uint16_t len); uint16_t crc16(uint8_t *buffer, uint16_t len); uint16_t crc16_false(uint8_t *buffer, uint16_t len); -#ifdef __cplusplus -} -#endif - -#endif // CRC_H_ \ No newline at end of file diff --git a/src/drivers/nerd-nos/mining.cpp b/src/drivers/nerd-nos/mining.cpp index b742f8d..6f2ed8e 100644 --- a/src/drivers/nerd-nos/mining.cpp +++ b/src/drivers/nerd-nos/mining.cpp @@ -11,6 +11,7 @@ #include "utils.h" #include "stratum.h" #include "mbedtls/sha256.h" +#include "../../mining.h" ///////cgminer nonce testing /* truediffone == 0x00000000FFFF0000000000000000000000000000000000000000000000000000 @@ -18,7 +19,7 @@ static const double truediffone = 26959535291011309493156476344723991336010898738574164086137773096960.0; /* testing a nonce and return the diff - 0 means invalid */ -double asic_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const uint32_t rolled_version) +double nerdnos_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const uint32_t rolled_version, uint8_t hash_result[32]) { double d64, s64, ds; unsigned char header[80]; @@ -38,7 +39,6 @@ double asic_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const ui memcpy(header + 76, &nonce, 4); unsigned char hash_buffer[32]; - unsigned char hash_result[32]; // double hash the header mbedtls_sha256(header, 80, hash_buffer, 0); @@ -51,29 +51,7 @@ double asic_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const ui return ds; } - -uint32_t increment_bitmask(const uint32_t value, const uint32_t mask) -{ - // if mask is zero, just return the original value - if (mask == 0) - return value; - - uint32_t carry = (value & mask) + (mask & -mask); // increment the least significant bit of the mask - uint32_t overflow = carry & ~mask; // find overflowed bits that are not in the mask - uint32_t new_value = (value & ~mask) | (carry & mask); // set bits according to the mask - - // Handle carry propagation - if (overflow > 0) - { - uint32_t carry_mask = (overflow << 1); // shift left to get the mask where carry should be propagated - new_value = increment_bitmask(new_value, carry_mask); // recursively handle carry propagation - } - - return new_value; -} - - -void calculate_merkle_root_hash(const char *coinbase_tx, mining_job* job, char merkle_root_hash[65]) +static void calculate_merkle_root_hash(const char *coinbase_tx, mining_job* job, char merkle_root_hash[65]) { size_t coinbase_tx_bin_len = strlen(coinbase_tx) / 2; uint8_t coinbase_tx_bin[coinbase_tx_bin_len]; @@ -93,7 +71,7 @@ void calculate_merkle_root_hash(const char *coinbase_tx, mining_job* job, char m } // take a mining_notify struct with ascii hex strings and convert it to a bm_job struct -void construct_bm_job(mining_job *job, const char *merkle_root, uint32_t version_mask, bm_job_t *new_job) +static void construct_bm_job(mining_job *job, const char *merkle_root, uint32_t version_mask, bm_job_t *new_job) { new_job->version = strtoul(job->version.c_str(), NULL, 16); new_job->target = strtoul(job->nbits.c_str(), NULL, 16); @@ -139,7 +117,7 @@ void construct_bm_job(mining_job *job, const char *merkle_root, uint32_t version new_job->num_midstates = 4; } -void asic_create_job(mining_subscribe *mWorker, mining_job *job, bm_job_t *next_job, uint32_t extranonce_2) { +void nerdnos_create_job(mining_subscribe *mWorker, mining_job *job, bm_job_t *next_job, uint32_t extranonce_2, uint32_t stratum_difficulty) { char extranonce_2_str[mWorker->extranonce2_size * 2 + 1]; // +1 zero termination snprintf(extranonce_2_str, sizeof(extranonce_2_str), "%0*lx", (int) mWorker->extranonce2_size * 2, extranonce_2); @@ -156,20 +134,24 @@ void asic_create_job(mining_subscribe *mWorker, mining_job *job, bm_job_t *next_ next_job->jobid = strdup(job->job_id.c_str()); next_job->extranonce2 = strdup(extranonce_2_str); - //next_job->pool_diff = stratum_difficulty; + next_job->pool_diff = stratum_difficulty; } -void asic_send_work(bm_job_t *next_bm_job, uint8_t job_id) { +void nerdnos_send_work(bm_job_t *next_bm_job, uint8_t job_id) { BM1397_send_work(next_bm_job, job_id); } -task_result *asic_proccess_work(uint32_t version, uint16_t timeout) { +task_result *nerdnos_proccess_work(uint32_t version, uint16_t timeout) { return BM1397_proccess_work(version, timeout); } -void asic_free_bm_job(bm_job_t *job) { +void nerdnos_free_bm_job(bm_job_t *job) { free(job->jobid); free(job->extranonce2); // mark as free job->ntime = 0; +} + +void nerdnos_set_asic_difficulty(uint32_t difficulty) { + BM1397_set_job_difficulty_mask(difficulty); } \ No newline at end of file diff --git a/src/drivers/nerd-nos/mining.h b/src/drivers/nerd-nos/mining.h index 4c1e666..63098c9 100644 --- a/src/drivers/nerd-nos/mining.h +++ b/src/drivers/nerd-nos/mining.h @@ -1,33 +1,25 @@ #pragma once #include -#include "common.h" -//#include "stratum.h" +#include "nerdnos.h" +// forward declaration to resolve circular inclusions +typedef struct mining_subscribe mining_subscribe; +typedef struct mining_job mining_job; -typedef struct -{ - uint32_t version; - uint32_t version_mask; - uint8_t prev_block_hash[32]; - uint8_t prev_block_hash_be[32]; - uint8_t merkle_root[32]; - uint8_t merkle_root_be[32]; - uint32_t ntime; - uint32_t target; // aka difficulty, aka nbits - uint32_t starting_nonce; +// set the asic hardware difficulty +void nerdnos_set_asic_difficulty(uint32_t current_difficulty); - uint8_t num_midstates; - uint8_t midstate[32]; - uint8_t midstate1[32]; - uint8_t midstate2[32]; - uint8_t midstate3[32]; - char *jobid; - char *extranonce2; -} bm_job_t; +// create asic job +void nerdnos_create_job(mining_subscribe *mWorker, mining_job *job, bm_job_t *next_job, uint32_t extranonce_2, uint32_t stratum_difficulty); +// send new work to the asic +void nerdnos_send_work(bm_job_t *next_bm_job, uint8_t job_id); -void asic_send_work(bm_job_t *next_bm_job, uint8_t job_id); -task_result *asic_proccess_work(uint32_t version, uint16_t timeout); +// receive and process responses +task_result *nerdnos_proccess_work(uint32_t version, uint16_t timeout); -double asic_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const uint32_t rolled_version); -void asic_free_bm_job(bm_job_t *job); \ No newline at end of file +// test difficulty +double nerdnos_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const uint32_t rolled_version, uint8_t hash_result[32]); + +// free allocated RAM for strings on bm_job_t +void nerdnos_free_bm_job(bm_job_t *job); diff --git a/src/drivers/nerd-nos/nerdnos.h b/src/drivers/nerd-nos/nerdnos.h new file mode 100644 index 0000000..f5c4972 --- /dev/null +++ b/src/drivers/nerd-nos/nerdnos.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +#define BM1397_INITIAL_DIFFICULTY 128 + +typedef struct __attribute__((__packed__)) +{ + uint8_t job_id; + uint32_t nonce; + uint32_t rolled_version; +} task_result; + +typedef struct +{ + uint32_t version; + uint32_t version_mask; + uint8_t prev_block_hash[32]; + uint8_t prev_block_hash_be[32]; + uint8_t merkle_root[32]; + uint8_t merkle_root_be[32]; + uint32_t ntime; + uint32_t target; // aka difficulty, aka nbits + uint32_t starting_nonce; + + uint8_t num_midstates; + uint8_t midstate[32]; + uint8_t midstate1[32]; + uint8_t midstate2[32]; + uint8_t midstate3[32]; + char *jobid; + char *extranonce2; + uint32_t pool_diff; +} bm_job_t; + +/* +typedef struct +{ + float frequency; +} bm1397Module; +*/ +typedef enum +{ + JOB_PACKET = 0, + CMD_PACKET = 1, +} packet_type_t; + +typedef enum +{ + JOB_RESP = 0, + CMD_RESP = 1, +} response_type_t; + +typedef struct __attribute__((__packed__)) +{ + uint8_t job_id; + uint8_t num_midstates; + uint8_t starting_nonce[4]; + uint8_t nbits[4]; + uint8_t ntime[4]; + uint8_t merkle4[4]; + uint8_t midstate[32]; + uint8_t midstate1[32]; + uint8_t midstate2[32]; + uint8_t midstate3[32]; +} job_packet_t; diff --git a/src/drivers/nerd-nos/serial.cpp b/src/drivers/nerd-nos/serial.cpp index 70f48b9..7a88b2c 100644 --- a/src/drivers/nerd-nos/serial.cpp +++ b/src/drivers/nerd-nos/serial.cpp @@ -51,12 +51,24 @@ int SERIAL_send(uint8_t *data, int len, bool debug) return uart_write_bytes(UART_NUM_1, (const char *)data, len); } +int SERIAL_check_for_data() { + int length; + uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length); + return length; +} + + /// @brief waits for a serial response from the device /// @param buf buffer to read data into /// @param buf number of ms to wait before timing out /// @return number of bytes read, or -1 on error int16_t SERIAL_rx(uint8_t *buf, uint16_t size, uint16_t timeout_ms) { + // don't return incomplete data + if (SERIAL_check_for_data() < size) { + return 0; + } + int16_t bytes_read = uart_read_bytes(UART_NUM_1, buf, size, timeout_ms / portTICK_PERIOD_MS); // if (bytes_read > 0) { // printf("rx: "); diff --git a/src/drivers/nerd-nos/serial.h b/src/drivers/nerd-nos/serial.h index ae165c1..b4850c8 100644 --- a/src/drivers/nerd-nos/serial.h +++ b/src/drivers/nerd-nos/serial.h @@ -1,5 +1,4 @@ -#ifndef SERIAL_H_ -#define SERIAL_H_ +#pragma once #define CHUNK_SIZE 1024 @@ -10,4 +9,3 @@ int16_t SERIAL_rx(uint8_t *, uint16_t, uint16_t); void SERIAL_clear_buffer(void); void SERIAL_set_baud(int baud); -#endif /* SERIAL_H_ */ \ No newline at end of file diff --git a/src/drivers/nerd-nos/utils.cpp b/src/drivers/nerd-nos/utils.cpp index 3cf2fbf..01a47e1 100644 --- a/src/drivers/nerd-nos/utils.cpp +++ b/src/drivers/nerd-nos/utils.cpp @@ -306,4 +306,52 @@ uint32_t flip32(uint32_t val) ret |= (val & 0xFF0000) >> 8; ret |= (val & 0xFF000000) >> 24; return ret; +} + + +unsigned char reverse_bits(unsigned char num) +{ + unsigned char reversed = 0; + int i; + + for (i = 0; i < 8; i++) { + reversed <<= 1; // Left shift the reversed variable by 1 + reversed |= num & 1; // Use bitwise OR to set the rightmost bit of reversed to the current bit of num + num >>= 1; // Right shift num by 1 to get the next bit + } + + return reversed; +} + +int largest_power_of_two(int num) +{ + int power = 0; + + while (num > 1) { + num = num >> 1; + power++; + } + + return 1 << power; +} + + +uint32_t increment_bitmask(const uint32_t value, const uint32_t mask) +{ + // if mask is zero, just return the original value + if (mask == 0) + return value; + + uint32_t carry = (value & mask) + (mask & -mask); // increment the least significant bit of the mask + uint32_t overflow = carry & ~mask; // find overflowed bits that are not in the mask + uint32_t new_value = (value & ~mask) | (carry & mask); // set bits according to the mask + + // Handle carry propagation + if (overflow > 0) + { + uint32_t carry_mask = (overflow << 1); // shift left to get the mask where carry should be propagated + new_value = increment_bitmask(new_value, carry_mask); // recursively handle carry propagation + } + + return new_value; } \ No newline at end of file diff --git a/src/drivers/nerd-nos/utils.h b/src/drivers/nerd-nos/utils.h index a1e6a20..78b6852 100644 --- a/src/drivers/nerd-nos/utils.h +++ b/src/drivers/nerd-nos/utils.h @@ -1,4 +1,4 @@ -#pragma one +#pragma once #include #include @@ -33,3 +33,8 @@ void prettyHex(unsigned char *buf, int len); uint32_t flip32(uint32_t val); +unsigned char reverse_bits(unsigned char num); + +int largest_power_of_two(int num); + +uint32_t increment_bitmask(const uint32_t value, const uint32_t mask); diff --git a/src/mining.cpp b/src/mining.cpp index 76c31dd..95a6c90 100644 --- a/src/mining.cpp +++ b/src/mining.cpp @@ -14,11 +14,6 @@ #include "drivers/displays/display.h" #include "drivers/storage/storage.h" -#ifdef NERD_NOS -#include "drivers/nerd-nos/mining.h" -#endif - - nvs_handle_t stat_handle; uint32_t templates = 0; @@ -41,8 +36,8 @@ extern TSettings Settings; IPAddress serverIP(1, 1, 1, 1); //Temporally save poolIPaddres //Global work data -static WiFiClient client; -static miner_data mMiner; //Global miner data (Create a miner class TODO) +WiFiClient client; +miner_data mMiner; //Global miner data (Create a miner class TODO) mining_subscribe mWorker; mining_job mJob; monitor_data mMonitor; @@ -103,12 +98,14 @@ bool checkPoolInactivity(unsigned int keepAliveTime, unsigned long inactivityTim }*/ } +#ifndef NERD_NOS if(elapsedKHs == 0){ //Check if hashrate is 0 during inactivityTIme if(mStart0Hashrate == 0) mStart0Hashrate = millis(); if((millis()-mStart0Hashrate) > inactivityTime) { mStart0Hashrate=0; return true;} return false; } +#endif mStart0Hashrate = 0; return false; @@ -372,121 +369,6 @@ void runMiner(void * task_id) { } } -void asic_create_job(mining_subscribe *mWorker, mining_job *job, bm_job_t *next_job, uint32_t extranonce_2); - -// we can have 32 different job ids -bm_job_t asic_jobs[32]; - -void runASIC(void * task_id) { - Serial.printf("[MINER] Started runASIC Task!\n"); - - uint32_t extranonce_2 = 0; - while(1) { - // wait for new job - while(1) { - if (mMiner.newJob == true) { - break; - } - vTaskDelay(100 / portTICK_PERIOD_MS); //Small delay - } - - if(mMiner.newJob) { - mMiner.newJob = false; //Clear newJob flag - } - mMiner.inRun = true; //Set inRun flag - - Serial.println(">>> STARTING TO HASH NONCES"); - uint32_t startT = micros(); - - memset(asic_jobs, 0, sizeof(asic_jobs)); - - // we are assuming the version doesn't change from job to job - uint32_t version = strtoul(mJob.version.c_str(), NULL, 16); - - mMonitor.NerdStatus = NM_hashing; - - while (mMiner.inRun) { - extranonce_2++; - - // use extranonce2 as job id - uint8_t asic_job_id = (uint8_t) (extranonce_2 % 32); - - // if it was used before, we have to free the pointers - if (asic_jobs[asic_job_id].ntime) { - asic_free_bm_job(&asic_jobs[asic_job_id]); - } - - // create the next asic job - asic_create_job(&mWorker, &mJob, &asic_jobs[asic_job_id], extranonce_2); - - // send the job and - asic_send_work(&asic_jobs[asic_job_id], asic_job_id); - - // wait 30ms for the response - // the pointer returned is the RS232 receive buffer :shushing-face: - // but we only have a single thread so it should be okay - task_result *result = asic_proccess_work(version, 30); - - // if we haven't received anything in time, so send a new job - if (!result) { - continue; - } - - // if we have received a job we don't know - if (!asic_jobs[result->job_id].ntime) { - Serial.printf("No Job found for received ID %02x\n", result->job_id); - continue; - } - - // check the nonce difficulty - double diff_hash = asic_test_nonce_value( - &asic_jobs[result->job_id], - result->nonce, - result->rolled_version); - - Serial.print(" - Current diff share: "); Serial.println(diff_hash, 12); - Serial.print(" - Current pool diff : "); Serial.println(mMiner.poolDifficulty, 12); - - // update best diff - if (diff_hash > best_diff) - best_diff = diff_hash; - - if(diff_hash > mMiner.poolDifficulty) - { - tx_mining_submit_asic(client, mWorker, &asic_jobs[result->job_id], result); - Serial.println("valid share!"); -/* - Serial.print(" - Current diff share: "); Serial.println(diff_hash,12); - Serial.print(" - Current pool diff : "); Serial.println(mMiner.poolDifficulty,12); -*/ -/* - Serial.print(" - TX SHARE: "); - for (size_t i = 0; i < 32; i++) - Serial.printf("%02x", hash[i]); -*/ - #ifdef DEBUG_MINING - Serial.println(""); - Serial.print(" - Current nonce: "); Serial.println(nonce); - Serial.print(" - Current block header: "); - for (size_t i = 0; i < 80; i++) { - Serial.printf("%02x", mMiner.bytearray_blockheader[i]); - } - #endif - Serial.println(""); - mLastTXtoPool = millis(); - } - } - Serial.println ("MINER WORK ABORTED >> waiting new job"); - mMiner.inRun = false; - uint32_t duration = micros() - startT; -/* - if (esp_task_wdt_reset() == ESP_OK) - Serial.print(">>> Resetting watchdog timer"); -*/ - } - -} - #define DELAY 100 #define REDRAW_EVERY 10 diff --git a/src/mining.h b/src/mining.h index c010572..930e780 100644 --- a/src/mining.h +++ b/src/mining.h @@ -20,7 +20,7 @@ String printLocalTime(void); void resetStat(); -typedef struct{ +typedef struct { uint8_t bytearray_target[32]; uint8_t bytearray_pooltarget[32]; uint8_t merkle_result[32]; diff --git a/src/mining_nerdnos.cpp b/src/mining_nerdnos.cpp new file mode 100644 index 0000000..d96fc11 --- /dev/null +++ b/src/mining_nerdnos.cpp @@ -0,0 +1,232 @@ +#include +#include +#include +#include +#include +#include +//#include "ShaTests/nerdSHA256.h" +#include "ShaTests/nerdSHA256plus.h" +#include "stratum.h" +#include "mining.h" +#include "utils.h" +#include "monitor.h" +#include "timeconst.h" +#include "drivers/displays/display.h" +#include "drivers/storage/storage.h" + +#include "drivers/nerd-nos/nerdnos.h" +#include "mining_nerdnos.h" + +extern WiFiClient client; +extern mining_subscribe mWorker; +extern mining_job mJob; +extern miner_data mMiner; +extern monitor_data mMonitor; + +extern pthread_mutex_t job_mutex; +extern double best_diff; +extern unsigned long mLastTXtoPool; + +// to track the jobs +// we can have 32 different job ids +static bm_job_t asic_jobs[32] = {0}; + +// to track hashrate +#define ASIC_HISTORY_SIZE 128 + +typedef struct { + uint32_t diffs[ASIC_HISTORY_SIZE]; + uint32_t timestamps[ASIC_HISTORY_SIZE]; + uint32_t newest; + uint32_t oldest; + uint64_t sum; + double avg_gh; + double duration; + int shares; +} history_t; + +static pthread_mutex_t job_interval_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t job_interval_cond = PTHREAD_COND_INITIALIZER; + +history_t history = {0}; + +double nerdnos_get_avg_hashrate() { + return history.avg_gh; +} + +// incremental ringbuffer based hashrate calculation +static void calculate_hashrate(history_t *history, uint32_t diff) { + // if we have wrapped around at least once our ringbuffer is full + // and we have to remove the oldest element + if (history->newest + 1 >= ASIC_HISTORY_SIZE) { + history->sum -= history->diffs[history->oldest % ASIC_HISTORY_SIZE]; + history->oldest++; + } + // add and store the newest sample + history->sum += diff; + history->diffs[history->newest % ASIC_HISTORY_SIZE] = diff; + history->timestamps[history->newest % ASIC_HISTORY_SIZE] = micros(); + + uint64_t oldest_timestamp = history->timestamps[history->oldest % ASIC_HISTORY_SIZE]; + uint64_t newest_timestamp = history->timestamps[history->newest % ASIC_HISTORY_SIZE]; + + history->duration = (double) (newest_timestamp - oldest_timestamp) / 1.0e6; + history->shares = (int) history->newest - (int) history->oldest + 1; + + if (history->duration) { + double avg = (double) (history->sum << 32llu) / history->duration; + history->avg_gh = avg / 1.0e9; + } + + history->newest++; +} + +// triggers the job creation +static void create_job_timer(TimerHandle_t xTimer) +{ + pthread_mutex_lock(&job_interval_mutex); + pthread_cond_signal(&job_interval_cond); + pthread_mutex_unlock(&job_interval_mutex); +} + +void runASIC(void * task_id) { + Serial.printf("[MINER] Started runASIC Task!\n"); + + // Create the timer + TimerHandle_t job_timer = xTimerCreate("NERDNOS_Job_Timer", NERDNOS_JOB_INTERVAL_MS / portTICK_PERIOD_MS, pdTRUE, NULL, create_job_timer); + + if (job_timer == NULL) { + Serial.println("Failed to create NERNOS timer"); + return; + } + + // Start the timer + if (xTimerStart(job_timer, 0) != pdPASS) { + Serial.println("Failed to start NERDNOS timer"); + return; + } + + uint32_t extranonce_2 = 0; + while(1) { + // wait for new job + while(1) { + if (mMiner.newJob == true) { + break; + } + vTaskDelay(100 / portTICK_PERIOD_MS); //Small delay + } + + if(mMiner.newJob) { + mMiner.newJob = false; //Clear newJob flag + } + mMiner.inRun = true; //Set inRun flag + + Serial.println(">>> STARTING TO HASH NONCES"); + uint32_t startT = micros(); + + memset(asic_jobs, 0, sizeof(asic_jobs)); + + // we are assuming the version doesn't change from job to job + uint32_t version = strtoul(mJob.version.c_str(), NULL, 16); + + mMonitor.NerdStatus = NM_hashing; + + uint32_t current_difficulty = 0; + + while (mMiner.inRun) { + // wait for the timer to start a new job + // also yields the CPU + pthread_mutex_lock(&job_interval_mutex); + pthread_cond_wait(&job_interval_cond, &job_interval_mutex); + pthread_mutex_unlock(&job_interval_mutex); + + // increment extranonce2 + extranonce_2++; + + // use extranonce2 as job id + uint8_t asic_job_id = (uint8_t) (extranonce_2 % 32); + + // if it was used before, we have to free the pointers + if (asic_jobs[asic_job_id].ntime) { + nerdnos_free_bm_job(&asic_jobs[asic_job_id]); + } + + // create the next asic job + // make sure that another task doesn't mess with the data while + // we are using it + pthread_mutex_lock(&job_mutex); + if (current_difficulty != mMiner.poolDifficulty) { + current_difficulty = mMiner.poolDifficulty; + nerdnos_set_asic_difficulty(current_difficulty); + Serial.printf("Set difficulty to %llu\n", current_difficulty); + } + nerdnos_create_job(&mWorker, &mJob, &asic_jobs[asic_job_id], extranonce_2, current_difficulty); + pthread_mutex_unlock(&job_mutex); + + // send the job and + nerdnos_send_work(&asic_jobs[asic_job_id], asic_job_id); + + // the pointer returned is the RS232 receive buffer :shushing-face: + // but we only have a single thread so it should be okay + // process all results if we have more than one + // this is okay because serial uses a buffer and (most likely^^) DMA + task_result *result = 0; + while (result = nerdnos_proccess_work(version, 1), result != NULL) { + // if we have received a job we don't know + if (!asic_jobs[result->job_id].ntime) { + Serial.printf("No Job found for received ID %02x\n", result->job_id); + continue; + } + + uint8_t hash[32]; + + // check the nonce difficulty + double diff_hash = nerdnos_test_nonce_value( + &asic_jobs[result->job_id], + result->nonce, + result->rolled_version, + hash); + + // update best diff + if (diff_hash > best_diff) + best_diff = diff_hash; + + // calculate the hashrate + if (diff_hash >= asic_jobs[result->job_id].pool_diff) { + calculate_hashrate(&history, asic_jobs[result->job_id].pool_diff); + Serial.printf("avg hashrate: %.2fGH/s (history spans %2.fs, %d shares)\n", history.avg_gh, history.duration, history.shares); + } + + if(diff_hash > mMiner.poolDifficulty) + { + tx_mining_submit_asic(client, mWorker, &asic_jobs[result->job_id], result); + Serial.println("valid share!"); + Serial.print(" - Current diff share: "); Serial.println(diff_hash,12); + Serial.print(" - Current pool diff : "); Serial.println(mMiner.poolDifficulty,12); + Serial.print(" - TX SHARE: "); + for (size_t i = 0; i < 32; i++) + Serial.printf("%02x", hash[i]); + + #ifdef DEBUG_MINING + Serial.println(""); + Serial.print(" - Current nonce: "); Serial.println(nonce); + Serial.print(" - Current block header: "); + for (size_t i = 0; i < 80; i++) { + Serial.printf("%02x", mMiner.bytearray_blockheader[i]); + } + #endif + Serial.println(""); + mLastTXtoPool = millis(); + } + } + } + Serial.println ("MINER WORK ABORTED >> waiting new job"); + mMiner.inRun = false; + uint32_t duration = micros() - startT; +/* + if (esp_task_wdt_reset() == ESP_OK) + Serial.print(">>> Resetting watchdog timer"); +*/ + } + +} diff --git a/src/mining_nerdnos.h b/src/mining_nerdnos.h new file mode 100644 index 0000000..f58f852 --- /dev/null +++ b/src/mining_nerdnos.h @@ -0,0 +1,6 @@ +#pragma once + +#define NERDNOS_JOB_INTERVAL_MS 30 + +void runASIC(void * task_id); +double nerdnos_get_avg_hashrate(); \ No newline at end of file diff --git a/src/monitor.cpp b/src/monitor.cpp index f7dc057..02b4640 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -9,6 +9,10 @@ #include "monitor.h" #include "drivers/storage/storage.h" +#ifdef NERD_NOS +#include "mining_nerdnos.h" +#endif + extern uint32_t templates; extern uint32_t hashes; extern uint32_t Mhashes; @@ -24,7 +28,7 @@ extern double best_diff; // track best diff extern monitor_data mMonitor; //from saved config -extern TSettings Settings; +extern TSettings Settings; bool invertColors = false; WiFiUDP ntpUDP; @@ -40,7 +44,7 @@ void setup_monitor(void){ /******** TIME ZONE SETTING *****/ timeClient.begin(); - + // Adjust offset depending on your zone // GMT +2 in seconds (zona horaria de Europa Central) timeClient.setTimeOffset(3600 * Settings.Timezone); @@ -55,11 +59,11 @@ void setup_monitor(void){ unsigned long mGlobalUpdate =0; void updateGlobalData(void){ - + if((mGlobalUpdate == 0) || (millis() - mGlobalUpdate > UPDATE_Global_min * 60 * 1000)){ - + if (WiFi.status() != WL_CONNECTED) return; - + //Make first API call to get global hash and current difficulty HTTPClient http; try { @@ -68,7 +72,7 @@ void updateGlobalData(void){ if (httpCode == HTTP_CODE_OK) { String payload = http.getString(); - + DynamicJsonDocument doc(1024); deserializeJson(doc, payload); String temp = ""; @@ -86,14 +90,14 @@ void updateGlobalData(void){ } http.end(); - + //Make third API call to get fees http.begin(getFees); httpCode = http.GET(); if (httpCode == HTTP_CODE_OK) { String payload = http.getString(); - + DynamicJsonDocument doc(1024); deserializeJson(doc, payload); String temp = ""; @@ -108,7 +112,7 @@ void updateGlobalData(void){ mGlobalUpdate = millis(); } - + http.end(); } catch(...) { http.end(); @@ -119,11 +123,11 @@ void updateGlobalData(void){ unsigned long mHeightUpdate = 0; String getBlockHeight(void){ - + if((mHeightUpdate == 0) || (millis() - mHeightUpdate > UPDATE_Height_min * 60 * 1000)){ - + if (WiFi.status() != WL_CONNECTED) return current_block; - + HTTPClient http; try { http.begin(getHeightAPI); @@ -136,24 +140,24 @@ String getBlockHeight(void){ current_block = payload; mHeightUpdate = millis(); - } + } http.end(); } catch(...) { http.end(); } } - + return current_block; } unsigned long mBTCUpdate = 0; String getBTCprice(void){ - + if((mBTCUpdate == 0) || (millis() - mBTCUpdate > UPDATE_BTC_min * 60 * 1000)){ - + if (WiFi.status() != WL_CONNECTED) return (String(bitcoin_price) + "$"); - + HTTPClient http; try { http.begin(getBTCAPI); @@ -170,13 +174,13 @@ String getBTCprice(void){ mBTCUpdate = millis(); } - + http.end(); } catch(...) { http.end(); } } - + return (String(bitcoin_price) + "$"); } @@ -186,7 +190,7 @@ unsigned long initialTime = 0; unsigned long mPoolUpdate = 0; void getTime(unsigned long* currentHours, unsigned long* currentMinutes, unsigned long* currentSeconds){ - + //Check if need an NTP call to check current time if((mTriggerUpdate == 0) || (millis() - mTriggerUpdate > UPDATE_PERIOD_h * 60 * 60 * 1000)){ //60 sec. * 60 min * 1000ms if(WiFi.status() == WL_CONNECTED) { @@ -206,7 +210,7 @@ void getTime(unsigned long* currentHours, unsigned long* currentMinutes, unsigne } String getDate(){ - + unsigned long elapsedTime = (millis() - mTriggerUpdate) / 1000; // Tiempo transcurrido en segundos unsigned long currentTime = initialTime + elapsedTime; // La hora actual @@ -229,15 +233,22 @@ String getTime(void){ char LocalHour[10]; sprintf(LocalHour, "%02d:%02d", currentHours, currentMinutes); - + String mystring(LocalHour); return LocalHour; } +#ifdef NERD_NOS +String getCurrentHashRate(unsigned long mElapsed) { + // we have too little space for 2 digits after the decimal point + return String(nerdnos_get_avg_hashrate(), 1); +} +#else String getCurrentHashRate(unsigned long mElapsed) { return String((1.0 * (elapsedKHs * 1000)) / mElapsed, 2); } +#endif mining_data getMiningData(unsigned long mElapsed) { @@ -328,7 +339,7 @@ String getPoolAPIUrl(void) { poolAPIUrl = String(getPublicPool); if (Settings.PoolAddress == "public-pool.io") { poolAPIUrl = "https://public-pool.io:40557/api/client/"; - } + } else { if (Settings.PoolAddress == "nerdminers.org") { poolAPIUrl = "https://pool.nerdminers.org/users/"; @@ -354,13 +365,13 @@ String getPoolAPIUrl(void) { } pool_data getPoolData(void){ - //pool_data pData; - if((mPoolUpdate == 0) || (millis() - mPoolUpdate > UPDATE_POOL_min * 60 * 1000)){ - if (WiFi.status() != WL_CONNECTED) return pData; + //pool_data pData; + if((mPoolUpdate == 0) || (millis() - mPoolUpdate > UPDATE_POOL_min * 60 * 1000)){ + if (WiFi.status() != WL_CONNECTED) return pData; //Make first API call to get global hash and current difficulty HTTPClient http; - http.setReuse(true); - try { + http.setReuse(true); + try { String btcWallet = Settings.BtcWallet; // Serial.println(btcWallet); if (btcWallet.indexOf(".")>0) btcWallet = btcWallet.substring(0,btcWallet.indexOf(".")); @@ -397,16 +408,16 @@ pool_data getPoolData(void){ double temp; if (doc.containsKey("bestDifficulty")) { - temp = doc["bestDifficulty"].as(); + temp = doc["bestDifficulty"].as(); char best_diff_string[16] = {0}; suffix_string(temp, best_diff_string, 16, 0); pData.bestDifficulty = String(best_diff_string); } doc.clear(); mPoolUpdate = millis(); - Serial.println("\n####### Pool Data OK!"); + Serial.println("\n####### Pool Data OK!"); } else { - Serial.println("\n####### Pool Data HTTP Error!"); + Serial.println("\n####### Pool Data HTTP Error!"); /* Serial.println(httpCode); String payload = http.getString(); Serial.println(payload); */ @@ -415,18 +426,18 @@ pool_data getPoolData(void){ pData.workersHash = "E"; pData.workersCount = 0; http.end(); - return pData; + return pData; } http.end(); } catch(...) { - Serial.println("####### Pool Error!"); + Serial.println("####### Pool Error!"); // mPoolUpdate = millis(); pData.bestDifficulty = "P"; pData.workersHash = "Error"; pData.workersCount = 0; http.end(); return pData; - } + } } return pData; } diff --git a/src/stratum.cpp b/src/stratum.cpp index d63619f..a5ec3ac 100644 --- a/src/stratum.cpp +++ b/src/stratum.cpp @@ -10,7 +10,9 @@ #include "utils.h" #include "version.h" +#include +pthread_mutex_t job_mutex = PTHREAD_MUTEX_INITIALIZER; StaticJsonDocument doc; unsigned long id = 1; @@ -99,9 +101,11 @@ bool parse_mining_subscribe(String line, mining_subscribe& mSubscribe) if (error || checkError(doc)) return false; if (!doc.containsKey("result")) return false; + pthread_mutex_lock(&job_mutex); mSubscribe.sub_details = String((const char*) doc["result"][0][0][1]); mSubscribe.extranonce1 = String((const char*) doc["result"][1]); mSubscribe.extranonce2_size = doc["result"][2]; + pthread_mutex_unlock(&job_mutex); return true; } @@ -179,6 +183,7 @@ bool parse_mining_notify(String line, mining_job& mJob) if (error) return false; if (!doc.containsKey("params")) return false; + pthread_mutex_lock(&job_mutex); mJob.job_id = String((const char*) doc["params"][0]); mJob.prev_block_hash = String((const char*) doc["params"][1]); mJob.coinb1 = String((const char*) doc["params"][2]); @@ -188,6 +193,7 @@ bool parse_mining_notify(String line, mining_job& mJob) mJob.nbits = String((const char*) doc["params"][6]); mJob.ntime = String((const char*) doc["params"][7]); mJob.clean_jobs = doc["params"][8]; //bool + pthread_mutex_unlock(&job_mutex); #ifdef DEBUG_MINING Serial.print(" job_id: "); Serial.println(mJob.job_id); diff --git a/src/stratum.h b/src/stratum.h index b6951e3..c0c2ff9 100644 --- a/src/stratum.h +++ b/src/stratum.h @@ -16,7 +16,7 @@ #define BUFFER_JSON_DOC 4096 #define BUFFER 1024 -typedef struct { +typedef struct mining_subscribe { String sub_details; String extranonce1; String extranonce2; @@ -25,7 +25,7 @@ typedef struct { char wPass[20]; } mining_subscribe; -typedef struct { +typedef struct mining_job { String job_id; String prev_block_hash; String coinb1;