mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-03-17 21:32:52 +01:00
Refactor stratum code
This commit is contained in:
parent
deaa291675
commit
b843bcbbb1
@ -120,23 +120,19 @@ void ASIC_set_job_difficulty_mask(GlobalState * GLOBAL_STATE, uint8_t mask) {
|
||||
}
|
||||
|
||||
// .send_work_fn = BM1366_send_work,
|
||||
void ASIC_send_work(GlobalState * GLOBAL_STATE, void * next_job) {
|
||||
int ASIC_send_work(GlobalState * GLOBAL_STATE, void * next_job) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
BM1397_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
return BM1397_send_work(GLOBAL_STATE, next_job);
|
||||
case DEVICE_ULTRA:
|
||||
BM1366_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
return BM1366_send_work(GLOBAL_STATE, next_job);
|
||||
case DEVICE_SUPRA:
|
||||
BM1368_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
return BM1368_send_work(GLOBAL_STATE, next_job);
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
BM1370_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
return BM1370_send_work(GLOBAL_STATE, next_job);
|
||||
default:
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,9 +389,8 @@ void BM1366_set_job_difficulty_mask(int difficulty)
|
||||
|
||||
static uint8_t id = 0;
|
||||
|
||||
void BM1366_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
int BM1366_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
{
|
||||
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
|
||||
BM1366_job job;
|
||||
@ -405,22 +404,20 @@ void BM1366_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32);
|
||||
memcpy(&job.version, &next_bm_job->version, 4);
|
||||
|
||||
//debug sent jobs - this can get crazy if the interval is short
|
||||
#if BM1366_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X (%d)", job.job_id, next_bm_job->connection_id);
|
||||
#endif
|
||||
|
||||
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) {
|
||||
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
|
||||
}
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] = next_bm_job;
|
||||
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
GLOBAL_STATE->valid_jobs[job.job_id] = 1;
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
|
||||
//debug sent jobs - this can get crazy if the interval is short
|
||||
#if BM1366_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
|
||||
#endif
|
||||
|
||||
_send_BM1366((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1366_job), BM1366_DEBUG_WORK);
|
||||
|
||||
return job.job_id;
|
||||
}
|
||||
|
||||
asic_result * BM1366_receive_work(void)
|
||||
@ -470,7 +467,6 @@ static uint32_t reverse_uint32(uint32_t val)
|
||||
|
||||
task_result * BM1366_proccess_work(void * pvParameters)
|
||||
{
|
||||
|
||||
asic_result * asic_result = BM1366_receive_work();
|
||||
|
||||
if (asic_result == NULL) {
|
||||
@ -485,11 +481,6 @@ task_result * BM1366_proccess_work(void * pvParameters)
|
||||
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
|
||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
||||
ESP_LOGW(TAG, "Invalid job found, 0x%02X", job_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
||||
|
||||
result.job_id = job_id;
|
||||
|
@ -314,7 +314,7 @@ void BM1368_set_job_difficulty_mask(int difficulty)
|
||||
|
||||
static uint8_t id = 0;
|
||||
|
||||
void BM1368_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
int BM1368_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
{
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
|
||||
@ -329,21 +329,19 @@ void BM1368_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32);
|
||||
memcpy(&job.version, &next_bm_job->version, 4);
|
||||
|
||||
#if BM1368_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X (%d)", job.job_id, next_bm_job->connection_id);
|
||||
#endif
|
||||
|
||||
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) {
|
||||
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
|
||||
}
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] = next_bm_job;
|
||||
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
GLOBAL_STATE->valid_jobs[job.job_id] = 1;
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
|
||||
#if BM1368_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
|
||||
#endif
|
||||
|
||||
_send_BM1368((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1368_job), BM1368_DEBUG_WORK);
|
||||
|
||||
return job.job_id;
|
||||
}
|
||||
|
||||
asic_result * BM1368_receive_work(void)
|
||||
@ -407,11 +405,6 @@ task_result * BM1368_proccess_work(void * pvParameters)
|
||||
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
|
||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
||||
ESP_LOGW(TAG, "Invalid job found, 0x%02X", job_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
||||
|
||||
result.job_id = job_id;
|
||||
|
@ -420,7 +420,7 @@ void BM1370_set_job_difficulty_mask(int difficulty)
|
||||
|
||||
static uint8_t id = 0;
|
||||
|
||||
void BM1370_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
int BM1370_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
{
|
||||
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
@ -436,22 +436,20 @@ void BM1370_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32);
|
||||
memcpy(&job.version, &next_bm_job->version, 4);
|
||||
|
||||
//debug sent jobs - this can get crazy if the interval is short
|
||||
#if BM1370_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X (%d)", job.job_id, next_bm_job->connection_id);
|
||||
#endif
|
||||
|
||||
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) {
|
||||
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
|
||||
}
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] = next_bm_job;
|
||||
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
GLOBAL_STATE->valid_jobs[job.job_id] = 1;
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
|
||||
//debug sent jobs - this can get crazy if the interval is short
|
||||
#if BM1370_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
|
||||
#endif
|
||||
|
||||
_send_BM1370((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1370_job), BM1370_DEBUG_WORK);
|
||||
|
||||
return job.job_id;
|
||||
}
|
||||
|
||||
asic_result * BM1370_receive_work(void)
|
||||
@ -523,11 +521,6 @@ task_result * BM1370_proccess_work(void * pvParameters)
|
||||
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
|
||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
||||
ESP_LOGW(TAG, "Invalid job nonce found, 0x%02X", job_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
||||
|
||||
result.job_id = job_id;
|
||||
|
@ -360,7 +360,7 @@ void BM1397_set_job_difficulty_mask(int difficulty)
|
||||
|
||||
static uint8_t id = 0;
|
||||
|
||||
void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||
int BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||
{
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
@ -386,6 +386,10 @@ void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||
memcpy(job.midstate3, next_bm_job->midstate3, 32);
|
||||
}
|
||||
|
||||
#if BM1397_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X (%d)", job.job_id, next_bm_job->connection_id);
|
||||
#endif
|
||||
|
||||
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL)
|
||||
{
|
||||
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
|
||||
@ -393,15 +397,9 @@ void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] = next_bm_job;
|
||||
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
GLOBAL_STATE->valid_jobs[job.job_id] = 1;
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
|
||||
#if BM1397_DEBUG_JOBS
|
||||
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
|
||||
#endif
|
||||
|
||||
_send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(job_packet), BM1397_DEBUG_WORK);
|
||||
|
||||
return job.job_id;
|
||||
}
|
||||
|
||||
asic_result *BM1397_receive_work(void)
|
||||
@ -456,11 +454,6 @@ task_result *BM1397_proccess_work(void *pvParameters)
|
||||
uint8_t rx_midstate_index = asic_result->job_id & 0x03;
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
if (GLOBAL_STATE->valid_jobs[rx_job_id] == 0)
|
||||
{
|
||||
ESP_LOGW(TAG, "Invalid job nonce found, id=%d", rx_job_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->version;
|
||||
for (int i = 0; i < rx_midstate_index; i++)
|
||||
|
@ -17,7 +17,7 @@ uint16_t ASIC_get_small_core_count(GlobalState * GLOBAL_STATE);
|
||||
task_result * ASIC_proccess_work(GlobalState * GLOBAL_STATE);
|
||||
int ASIC_set_max_baud(GlobalState * GLOBAL_STATE);
|
||||
void ASIC_set_job_difficulty_mask(GlobalState * GLOBAL_STATE, uint8_t mask);
|
||||
void ASIC_send_work(GlobalState * GLOBAL_STATE, void * next_job);
|
||||
int ASIC_send_work(GlobalState * GLOBAL_STATE, void * next_job);
|
||||
void ASIC_set_version_mask(GlobalState * GLOBAL_STATE, uint32_t mask);
|
||||
bool ASIC_set_frequency(GlobalState * GLOBAL_STATE, float target_frequency);
|
||||
esp_err_t ASIC_set_device_model(GlobalState * GLOBAL_STATE);
|
||||
|
@ -10,10 +10,10 @@
|
||||
#define CRC5_MASK 0x1F
|
||||
#define BM1366_ASIC_DIFFICULTY 256
|
||||
|
||||
#define BM1366_SERIALTX_DEBUG false
|
||||
#define BM1366_SERIALRX_DEBUG false
|
||||
#define BM1366_SERIALTX_DEBUG true
|
||||
#define BM1366_SERIALRX_DEBUG true
|
||||
#define BM1366_DEBUG_WORK false //causes insane amount of debug output
|
||||
#define BM1366_DEBUG_JOBS false //causes insane amount of debug output
|
||||
#define BM1366_DEBUG_JOBS true //causes insane amount of debug output
|
||||
|
||||
static const uint64_t BM1366_CORE_COUNT = 112;
|
||||
static const uint64_t BM1366_SMALL_CORE_COUNT = 894;
|
||||
@ -36,7 +36,7 @@ typedef struct __attribute__((__packed__))
|
||||
} BM1366_job;
|
||||
|
||||
uint8_t BM1366_init(uint64_t frequency, uint16_t asic_count);
|
||||
void BM1366_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
int BM1366_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1366_set_job_difficulty_mask(int);
|
||||
void BM1366_set_version_mask(uint32_t version_mask);
|
||||
int BM1366_set_max_baud(void);
|
||||
|
@ -36,7 +36,7 @@ typedef struct __attribute__((__packed__))
|
||||
} BM1368_job;
|
||||
|
||||
uint8_t BM1368_init(uint64_t frequency, uint16_t asic_count);
|
||||
void BM1368_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
int BM1368_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1368_set_job_difficulty_mask(int);
|
||||
void BM1368_set_version_mask(uint32_t version_mask);
|
||||
int BM1368_set_max_baud(void);
|
||||
|
@ -36,7 +36,7 @@ typedef struct __attribute__((__packed__))
|
||||
} BM1370_job;
|
||||
|
||||
uint8_t BM1370_init(uint64_t frequency, uint16_t asic_count);
|
||||
void BM1370_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
int BM1370_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1370_set_job_difficulty_mask(int);
|
||||
void BM1370_set_version_mask(uint32_t version_mask);
|
||||
int BM1370_set_max_baud(void);
|
||||
|
@ -50,7 +50,7 @@ typedef struct __attribute__((__packed__))
|
||||
} job_packet;
|
||||
|
||||
uint8_t BM1397_init(uint64_t frequency, uint16_t asic_count);
|
||||
void BM1397_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
int BM1397_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1397_set_job_difficulty_mask(int);
|
||||
void BM1397_set_version_mask(uint32_t version_mask);
|
||||
int BM1397_set_max_baud(void);
|
||||
|
@ -15,6 +15,8 @@ typedef struct
|
||||
uint32_t target; // aka difficulty, aka nbits
|
||||
uint32_t starting_nonce;
|
||||
|
||||
uint8_t connection_id;
|
||||
|
||||
uint8_t num_midstates;
|
||||
uint8_t midstate[32];
|
||||
uint8_t midstate1[32];
|
||||
|
@ -28,6 +28,7 @@ static const int STRATUM_ID_SUBSCRIBE = 2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t connection_id;
|
||||
char *job_id;
|
||||
char *prev_block_hash;
|
||||
char *coinbase_1;
|
||||
@ -62,21 +63,28 @@ typedef struct
|
||||
char * error_str;
|
||||
} StratumApiV1Message;
|
||||
|
||||
void STRATUM_V1_initialize_buffer();
|
||||
|
||||
char *STRATUM_V1_receive_jsonrpc_line(int sockfd);
|
||||
typedef struct {
|
||||
char *data;
|
||||
size_t size;
|
||||
} StratumApiV1Buffer;
|
||||
|
||||
int STRATUM_V1_subscribe(int socket, int send_uid, char * model);
|
||||
StratumApiV1Buffer *STRATUM_V1_buffer_create();
|
||||
void STRATUM_V1_buffer_init(StratumApiV1Buffer *buf);
|
||||
|
||||
void STRATUM_V1_parse(StratumApiV1Message *message, const char *stratum_json);
|
||||
char *STRATUM_V1_receive_jsonrpc_line(const char * POOL_TAG, int sockfd, StratumApiV1Buffer *json_buf);
|
||||
|
||||
int STRATUM_V1_subscribe(const char * POOL_TAG,int socket, int send_uid, char * model);
|
||||
|
||||
void STRATUM_V1_parse(const char * POOL_TAG, StratumApiV1Message *message, const char *stratum_json);
|
||||
|
||||
void STRATUM_V1_free_mining_notify(mining_notify *params);
|
||||
|
||||
int STRATUM_V1_authenticate(int socket, int send_uid, const char *username, const char *pass);
|
||||
int STRATUM_V1_authenticate(const char * POOL_TAG, int socket, int send_uid, const char *username, const char *pass);
|
||||
|
||||
int STRATUM_V1_configure_version_rolling(int socket, int send_uid, uint32_t * version_mask);
|
||||
int STRATUM_V1_configure_version_rolling(const char * POOL_TAG,int socket, int send_uid);
|
||||
|
||||
int STRATUM_V1_suggest_difficulty(int socket, int send_uid, uint32_t difficulty);
|
||||
int STRATUM_V1_suggest_difficulty(const char * POOL_TAG, int socket, int send_uid, uint32_t difficulty);
|
||||
|
||||
int STRATUM_V1_submit_share(int socket, int send_uid, const char *username, const char *jobid,
|
||||
const char *extranonce_2, const uint32_t ntime, const uint32_t nonce,
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "mining.h"
|
||||
#include "utils.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
void free_bm_job(bm_job *job)
|
||||
{
|
||||
@ -61,6 +62,7 @@ bm_job construct_bm_job(mining_notify *params, const char *merkle_root, const ui
|
||||
new_job.target = params->target;
|
||||
new_job.ntime = params->ntime;
|
||||
new_job.pool_diff = params->difficulty;
|
||||
new_job.connection_id = params->connection_id;
|
||||
|
||||
hex2bin(merkle_root, new_job.merkle_root, 32);
|
||||
|
||||
|
@ -16,93 +16,95 @@
|
||||
#define BUFFER_SIZE 1024
|
||||
static const char * TAG = "stratum_api";
|
||||
|
||||
static char * json_rpc_buffer = NULL;
|
||||
static size_t json_rpc_buffer_size = 0;
|
||||
static void debug_stratum_tx(const char * POOL_TAG, const char *);
|
||||
int _parse_stratum_subscribe_result_message(const char * POOL_TAG, const char * result_json_str, char ** extranonce, int * extranonce2_len);
|
||||
|
||||
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()
|
||||
{
|
||||
json_rpc_buffer = malloc(BUFFER_SIZE);
|
||||
json_rpc_buffer_size = BUFFER_SIZE;
|
||||
if (json_rpc_buffer == NULL) {
|
||||
printf("Error: Failed to allocate memory for buffer\n");
|
||||
StratumApiV1Buffer *STRATUM_V1_buffer_create() {
|
||||
StratumApiV1Buffer *buf = malloc(sizeof(StratumApiV1Buffer));
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Error: Failed to allocate memory for StratumApiV1Buffer\n");
|
||||
exit(1);
|
||||
}
|
||||
memset(json_rpc_buffer, 0, BUFFER_SIZE);
|
||||
|
||||
STRATUM_V1_buffer_init(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void cleanup_stratum_buffer()
|
||||
{
|
||||
free(json_rpc_buffer);
|
||||
void STRATUM_V1_buffer_init(StratumApiV1Buffer *buf) {
|
||||
buf->data = malloc(BUFFER_SIZE);
|
||||
buf->size = BUFFER_SIZE;
|
||||
|
||||
if (!buf->data) {
|
||||
fprintf(stderr, "Error: Failed to allocate memory for buffer\n");
|
||||
exit(1);
|
||||
}
|
||||
memset(buf->data, 0, buf->size);
|
||||
}
|
||||
|
||||
static void realloc_json_buffer(size_t len)
|
||||
{
|
||||
size_t old, new;
|
||||
void STRATUM_V1_buffer_clear(StratumApiV1Buffer *buf) {
|
||||
memset(buf->data, 0, BUFFER_SIZE);
|
||||
buf->size = 0;
|
||||
}
|
||||
|
||||
old = strlen(json_rpc_buffer);
|
||||
new = old + len + 1;
|
||||
void STRATUM_V1_buffer_realloc(StratumApiV1Buffer *buf, size_t additional_len) {
|
||||
size_t old_size = strlen(buf->data);
|
||||
size_t new_size = old_size + additional_len + 1;
|
||||
|
||||
if (new < json_rpc_buffer_size) {
|
||||
if (new_size <= buf->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
new = new + (BUFFER_SIZE - (new % BUFFER_SIZE));
|
||||
void * new_sockbuf = realloc(json_rpc_buffer, new);
|
||||
new_size += BUFFER_SIZE - (new_size % BUFFER_SIZE);
|
||||
char *new_data = realloc(buf->data, new_size);
|
||||
|
||||
if (new_sockbuf == NULL) {
|
||||
if (!new_data) {
|
||||
fprintf(stderr, "Error: realloc failed in recalloc_sock()\n");
|
||||
ESP_LOGI(TAG, "Restarting System because of ERROR: realloc failed in recalloc_sock");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
json_rpc_buffer = new_sockbuf;
|
||||
memset(json_rpc_buffer + old, 0, new - old);
|
||||
json_rpc_buffer_size = new;
|
||||
buf->data = new_data;
|
||||
memset(buf->data + old_size, 0, new_size - old_size);
|
||||
buf->size = new_size;
|
||||
}
|
||||
|
||||
char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
|
||||
char *STRATUM_V1_receive_jsonrpc_line(const char * POOL_TAG, int sockfd, StratumApiV1Buffer *json_buf)
|
||||
{
|
||||
if (json_rpc_buffer == NULL) {
|
||||
STRATUM_V1_initialize_buffer();
|
||||
}
|
||||
char *line, *tok = NULL;
|
||||
char recv_buffer[BUFFER_SIZE];
|
||||
int nbytes;
|
||||
size_t buflen = 0;
|
||||
|
||||
if (!strstr(json_rpc_buffer, "\n")) {
|
||||
if (!strstr(json_buf->data, "\n")) {
|
||||
do {
|
||||
memset(recv_buffer, 0, BUFFER_SIZE);
|
||||
nbytes = recv(sockfd, recv_buffer, BUFFER_SIZE - 1, 0);
|
||||
if (nbytes == -1) {
|
||||
ESP_LOGI(TAG, "Error: recv (errno %d: %s)", errno, strerror(errno));
|
||||
if (json_rpc_buffer) {
|
||||
free(json_rpc_buffer);
|
||||
json_rpc_buffer=0;
|
||||
}
|
||||
return 0;
|
||||
if (nbytes <= 0)
|
||||
{
|
||||
ESP_LOGI(POOL_TAG, "Error: recv (errno %d: %s)", errno, strerror(errno));
|
||||
STRATUM_V1_buffer_clear(json_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
realloc_json_buffer(nbytes);
|
||||
strncat(json_rpc_buffer, recv_buffer, nbytes);
|
||||
} while (!strstr(json_rpc_buffer, "\n"));
|
||||
STRATUM_V1_buffer_realloc(json_buf, nbytes);
|
||||
strncat(json_buf->data, recv_buffer, nbytes);
|
||||
} while (!strstr(json_buf->data, "\n"));
|
||||
}
|
||||
buflen = strlen(json_rpc_buffer);
|
||||
tok = strtok(json_rpc_buffer, "\n");
|
||||
buflen = strlen(json_buf->data);
|
||||
tok = strtok(json_buf->data, "\n");
|
||||
line = strdup(tok);
|
||||
int len = strlen(line);
|
||||
if (buflen > len + 1)
|
||||
memmove(json_rpc_buffer, json_rpc_buffer + len + 1, buflen - len + 1);
|
||||
memmove(json_buf->data, json_buf->data + len + 1, buflen - len + 1);
|
||||
else
|
||||
strcpy(json_rpc_buffer, "");
|
||||
strcpy(json_buf->data, "");
|
||||
return line;
|
||||
}
|
||||
|
||||
void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
void STRATUM_V1_parse(const char * POOL_TAG, StratumApiV1Message * message, const char * stratum_json)
|
||||
{
|
||||
cJSON * json = cJSON_Parse(stratum_json);
|
||||
|
||||
@ -127,7 +129,7 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
} else if (strcmp("client.reconnect", method_json->valuestring) == 0) {
|
||||
result = CLIENT_RECONNECT;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "unhandled method in stratum message: %s", stratum_json);
|
||||
ESP_LOGI(POOL_TAG, "unhandled method in stratum message: %s", stratum_json);
|
||||
}
|
||||
|
||||
//if there is no method, then it is a result
|
||||
@ -184,7 +186,7 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
|
||||
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);
|
||||
ESP_LOGE(POOL_TAG, "Unable to parse extranonce2_len: %s", result_json->valuestring);
|
||||
message->response_success = false;
|
||||
goto done;
|
||||
}
|
||||
@ -192,7 +194,7 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
|
||||
cJSON * extranonce_json = cJSON_GetArrayItem(result_json, 1);
|
||||
if (extranonce_json == NULL) {
|
||||
ESP_LOGE(TAG, "Unable parse extranonce: %s", result_json->valuestring);
|
||||
ESP_LOGE(POOL_TAG, "Unable parse extranonce: %s", result_json->valuestring);
|
||||
message->response_success = false;
|
||||
goto done;
|
||||
}
|
||||
@ -201,8 +203,8 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
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);
|
||||
ESP_LOGI(POOL_TAG, "extranonce_str: %s", message->extranonce_str);
|
||||
ESP_LOGI(POOL_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) {
|
||||
@ -210,13 +212,13 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
if (mask != NULL) {
|
||||
result = STRATUM_RESULT_VERSION_MASK;
|
||||
message->version_mask = strtoul(mask->valuestring, NULL, 16);
|
||||
ESP_LOGI(TAG, "Set version mask: %08lx", message->version_mask);
|
||||
ESP_LOGI(POOL_TAG, "Set version mask: %08lx", message->version_mask);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "error setting version mask: %s", stratum_json);
|
||||
ESP_LOGI(POOL_TAG, "error setting version mask: %s", stratum_json);
|
||||
}
|
||||
|
||||
} else {
|
||||
ESP_LOGI(TAG, "unhandled result in stratum message: %s", stratum_json);
|
||||
ESP_LOGI(POOL_TAG, "unhandled result in stratum message: %s", stratum_json);
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,29 +280,29 @@ void STRATUM_V1_free_mining_notify(mining_notify * params)
|
||||
free(params);
|
||||
}
|
||||
|
||||
int _parse_stratum_subscribe_result_message(const char * result_json_str, char ** extranonce, int * extranonce2_len)
|
||||
int _parse_stratum_subscribe_result_message(const char * POOL_TAG, const char * result_json_str, char ** extranonce, int * extranonce2_len)
|
||||
{
|
||||
cJSON * root = cJSON_Parse(result_json_str);
|
||||
if (root == NULL) {
|
||||
ESP_LOGE(TAG, "Unable to parse %s", result_json_str);
|
||||
ESP_LOGE(POOL_TAG, "Unable to parse %s", result_json_str);
|
||||
return -1;
|
||||
}
|
||||
cJSON * result = cJSON_GetObjectItem(root, "result");
|
||||
if (result == NULL) {
|
||||
ESP_LOGE(TAG, "Unable to parse subscribe result %s", result_json_str);
|
||||
ESP_LOGE(POOL_TAG, "Unable to parse subscribe result %s", result_json_str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON * extranonce2_len_json = cJSON_GetArrayItem(result, 2);
|
||||
if (extranonce2_len_json == NULL) {
|
||||
ESP_LOGE(TAG, "Unable to parse extranonce2_len: %s", result->valuestring);
|
||||
ESP_LOGE(POOL_TAG, "Unable to parse extranonce2_len: %s", result->valuestring);
|
||||
return -1;
|
||||
}
|
||||
*extranonce2_len = extranonce2_len_json->valueint;
|
||||
|
||||
cJSON * extranonce_json = cJSON_GetArrayItem(result, 1);
|
||||
if (extranonce_json == NULL) {
|
||||
ESP_LOGE(TAG, "Unable parse extranonce: %s", result->valuestring);
|
||||
ESP_LOGE(POOL_TAG, "Unable parse extranonce: %s", result->valuestring);
|
||||
return -1;
|
||||
}
|
||||
*extranonce = malloc(strlen(extranonce_json->valuestring) + 1);
|
||||
@ -311,33 +313,33 @@ int _parse_stratum_subscribe_result_message(const char * result_json_str, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int STRATUM_V1_subscribe(int socket, int send_uid, char * model)
|
||||
int STRATUM_V1_subscribe(const char * POOL_TAG, int socket, int send_uid, char * model)
|
||||
{
|
||||
// Subscribe
|
||||
char subscribe_msg[BUFFER_SIZE];
|
||||
const esp_app_desc_t *app_desc = esp_app_get_description();
|
||||
const char *version = app_desc->version;
|
||||
sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitaxe/%s/%s\"]}\n", send_uid, model, version);
|
||||
debug_stratum_tx(subscribe_msg);
|
||||
debug_stratum_tx(POOL_TAG, subscribe_msg);
|
||||
|
||||
return write(socket, subscribe_msg, strlen(subscribe_msg));
|
||||
}
|
||||
|
||||
int STRATUM_V1_suggest_difficulty(int socket, int send_uid, uint32_t difficulty)
|
||||
int STRATUM_V1_suggest_difficulty(const char * POOL_TAG, int socket, int send_uid, uint32_t difficulty)
|
||||
{
|
||||
char difficulty_msg[BUFFER_SIZE];
|
||||
sprintf(difficulty_msg, "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n", send_uid, difficulty);
|
||||
debug_stratum_tx(difficulty_msg);
|
||||
debug_stratum_tx(POOL_TAG, difficulty_msg);
|
||||
|
||||
return write(socket, difficulty_msg, strlen(difficulty_msg));
|
||||
}
|
||||
|
||||
int STRATUM_V1_authenticate(int socket, int send_uid, const char * username, const char * pass)
|
||||
int STRATUM_V1_authenticate(const char * POOL_TAG, int socket, int send_uid, const char * username, const char * pass)
|
||||
{
|
||||
char authorize_msg[BUFFER_SIZE];
|
||||
sprintf(authorize_msg, "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n", send_uid, username,
|
||||
pass);
|
||||
debug_stratum_tx(authorize_msg);
|
||||
debug_stratum_tx(POOL_TAG, authorize_msg);
|
||||
|
||||
return write(socket, authorize_msg, strlen(authorize_msg));
|
||||
}
|
||||
@ -356,31 +358,31 @@ int STRATUM_V1_submit_share(int socket, int send_uid, const char * username, con
|
||||
sprintf(submit_msg,
|
||||
"{\"id\": %d, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%08lx\", \"%08lx\", \"%08lx\"]}\n",
|
||||
send_uid, username, jobid, extranonce_2, ntime, nonce, version);
|
||||
debug_stratum_tx(submit_msg);
|
||||
debug_stratum_tx(TAG, submit_msg);
|
||||
|
||||
return write(socket, submit_msg, strlen(submit_msg));
|
||||
}
|
||||
|
||||
int STRATUM_V1_configure_version_rolling(int socket, int send_uid, uint32_t * version_mask)
|
||||
int STRATUM_V1_configure_version_rolling(const char * POOL_TAG, int socket, int send_uid)
|
||||
{
|
||||
char configure_msg[BUFFER_SIZE * 2];
|
||||
sprintf(configure_msg,
|
||||
"{\"id\": %d, \"method\": \"mining.configure\", \"params\": [[\"version-rolling\"], {\"version-rolling.mask\": "
|
||||
"\"ffffffff\"}]}\n",
|
||||
send_uid);
|
||||
debug_stratum_tx(configure_msg);
|
||||
debug_stratum_tx(POOL_TAG, configure_msg);
|
||||
|
||||
return write(socket, configure_msg, strlen(configure_msg));
|
||||
}
|
||||
|
||||
static void debug_stratum_tx(const char * msg)
|
||||
static void debug_stratum_tx(const char * POOL_TAG, const char * msg)
|
||||
{
|
||||
//remove the trailing newline
|
||||
char * newline = strchr(msg, '\n');
|
||||
if (newline != NULL) {
|
||||
*newline = '\0';
|
||||
}
|
||||
ESP_LOGI(TAG, "tx: %s", msg);
|
||||
ESP_LOGI(POOL_TAG, "tx: %s", msg);
|
||||
|
||||
//put it back!
|
||||
if (newline != NULL) {
|
||||
|
@ -13,7 +13,7 @@ TEST_CASE("Parse stratum method", "[stratum]")
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_standard);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string_standard);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_INT(0, stratum_api_v1_message.should_abandon_work);
|
||||
}
|
||||
@ -30,7 +30,7 @@ TEST_CASE("Parse stratum mining.notify abandon work", "[stratum]")
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_abandon_work_false);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string_abandon_work_false);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_INT(0, stratum_api_v1_message.should_abandon_work);
|
||||
|
||||
@ -42,7 +42,7 @@ TEST_CASE("Parse stratum mining.notify abandon work", "[stratum]")
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",true]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_abandon_work);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string_abandon_work);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_INT(1, stratum_api_v1_message.should_abandon_work);
|
||||
|
||||
@ -54,7 +54,7 @@ TEST_CASE("Parse stratum mining.notify abandon work", "[stratum]")
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",\"64495522\",true]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_abandon_work_length_9);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string_abandon_work_length_9);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_INT(1, stratum_api_v1_message.should_abandon_work);
|
||||
}
|
||||
@ -63,7 +63,7 @@ TEST_CASE("Parse stratum set_difficulty params", "[mining.set_difficulty]")
|
||||
{
|
||||
const char *json_string = "{\"id\":null,\"method\":\"mining.set_difficulty\",\"params\":[1638]}";
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(MINING_SET_DIFFICULTY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL(1638, stratum_api_v1_message.new_difficulty);
|
||||
}
|
||||
@ -78,7 +78,7 @@ 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]}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL_STRING("1d2e0c4d3d", stratum_api_v1_message.mining_notification->job_id);
|
||||
TEST_ASSERT_EQUAL_STRING("ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000", stratum_api_v1_message.mining_notification->prev_block_hash);
|
||||
TEST_ASSERT_EQUAL_STRING("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000", stratum_api_v1_message.mining_notification->coinbase_1);
|
||||
@ -109,7 +109,7 @@ TEST_CASE("Parse stratum mining.set_version_mask params", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char *json_string = "{\"id\":1,\"method\":\"mining.set_version_mask\",\"params\":[\"1fffe000\"]}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(1, stratum_api_v1_message.message_id);
|
||||
TEST_ASSERT_EQUAL(MINING_SET_VERSION_MASK, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_HEX32(0x1fffe000, stratum_api_v1_message.version_mask);
|
||||
@ -119,14 +119,14 @@ TEST_CASE("Parse stratum result success", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_setup_message = {};
|
||||
const char* resp1 = "{\"id\":4,\"error\":null,\"result\":true}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_setup_message, resp1);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_setup_message, resp1);
|
||||
TEST_ASSERT_EQUAL(4, stratum_api_v1_setup_message.message_id);
|
||||
TEST_ASSERT_EQUAL(STRATUM_RESULT_SETUP, stratum_api_v1_setup_message.method);
|
||||
TEST_ASSERT_TRUE(stratum_api_v1_setup_message.response_success);
|
||||
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char* json_string = "{\"id\":5,\"error\":null,\"result\":true}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(5, stratum_api_v1_message.message_id);
|
||||
TEST_ASSERT_EQUAL(STRATUM_RESULT, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_TRUE(stratum_api_v1_message.response_success);
|
||||
@ -136,7 +136,7 @@ TEST_CASE("Parse stratum result success with large id", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char *json_string = "{\"id\":32769,\"error\":null,\"result\":true}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(32769, stratum_api_v1_message.message_id);
|
||||
TEST_ASSERT_EQUAL(STRATUM_RESULT, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_TRUE(stratum_api_v1_message.response_success);
|
||||
@ -146,7 +146,7 @@ TEST_CASE("Parse stratum result success with larger id", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char *json_string = "{\"id\":65536,\"error\":null,\"result\":true}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(65536, stratum_api_v1_message.message_id);
|
||||
TEST_ASSERT_EQUAL(STRATUM_RESULT, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_TRUE(stratum_api_v1_message.response_success);
|
||||
@ -156,7 +156,7 @@ TEST_CASE("Parse stratum result error", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_setup_message = {};
|
||||
const char* resp1 = "{\"id\":4,\"result\":null,\"error\":[21,\"Job not found\",\"\"]}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_setup_message, resp1);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_setup_message, resp1);
|
||||
TEST_ASSERT_EQUAL(4, stratum_api_v1_setup_message.message_id);
|
||||
TEST_ASSERT_EQUAL(STRATUM_RESULT_SETUP, stratum_api_v1_setup_message.method);
|
||||
TEST_ASSERT_FALSE(stratum_api_v1_setup_message.response_success);
|
||||
@ -164,7 +164,7 @@ TEST_CASE("Parse stratum result error", "[stratum]")
|
||||
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char* json_string = "{\"id\":5,\"result\":null,\"error\":[21,\"Job not found\",\"\"]}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(5, stratum_api_v1_message.message_id);
|
||||
TEST_ASSERT_EQUAL(STRATUM_RESULT, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_FALSE(stratum_api_v1_message.response_success);
|
||||
@ -175,7 +175,7 @@ TEST_CASE("Parse stratum result alternative error", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char *json_string = "{\"reject-reason\":\"Above target 2\",\"result\":false,\"error\":null,\"id\":8}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
STRATUM_V1_parse("STRATUM_TEST", &stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(8, stratum_api_v1_message.message_id);
|
||||
TEST_ASSERT_EQUAL(STRATUM_RESULT, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_FALSE(stratum_api_v1_message.response_success);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "power_management_task.h"
|
||||
#include "serial.h"
|
||||
#include "stratum_api.h"
|
||||
#include "stratum_task.h"
|
||||
#include "work_queue.h"
|
||||
|
||||
#define STRATUM_USER CONFIG_STRATUM_USER
|
||||
@ -45,7 +46,7 @@ typedef enum
|
||||
// task_result * (*receive_result_fn)(void * GLOBAL_STATE);
|
||||
// int (*set_max_baud_fn)(void);
|
||||
// void (*set_difficulty_mask_fn)(int);
|
||||
// void (*send_work_fn)(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
// int (*send_work_fn)(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
// void (*set_version_mask)(uint32_t);
|
||||
// } AsicFunctions;
|
||||
|
||||
@ -114,31 +115,15 @@ typedef struct
|
||||
double asic_job_frequency_ms;
|
||||
uint32_t ASIC_difficulty;
|
||||
|
||||
work_queue stratum_queue;
|
||||
work_queue ASIC_jobs_queue;
|
||||
|
||||
bm1397Module BM1397_MODULE;
|
||||
SystemModule SYSTEM_MODULE;
|
||||
AsicTaskModule ASIC_TASK_MODULE;
|
||||
PowerManagementModule POWER_MANAGEMENT_MODULE;
|
||||
SelfTestModule SELF_TEST_MODULE;
|
||||
|
||||
char * extranonce_str;
|
||||
int extranonce_2_len;
|
||||
int abandon_work;
|
||||
|
||||
uint8_t * valid_jobs;
|
||||
pthread_mutex_t valid_jobs_lock;
|
||||
|
||||
uint32_t stratum_difficulty;
|
||||
uint32_t version_mask;
|
||||
bool new_stratum_version_rolling_msg;
|
||||
|
||||
int sock;
|
||||
|
||||
// A message ID that must be unique per request that expects a response.
|
||||
// For requests not expecting a response (called notifications), this is null.
|
||||
int send_uid;
|
||||
work_queue ASIC_jobs_queue;
|
||||
StratumConnection connections[MAX_STRATUM_POOLS];
|
||||
uint8_t current_connection_id;
|
||||
|
||||
bool ASIC_initalized;
|
||||
bool psram_is_available;
|
||||
|
@ -544,7 +544,7 @@ static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
cJSON_AddNumberToObject(root, "hashRate", GLOBAL_STATE->SYSTEM_MODULE.current_hashrate);
|
||||
cJSON_AddStringToObject(root, "bestDiff", GLOBAL_STATE->SYSTEM_MODULE.best_diff_string);
|
||||
cJSON_AddStringToObject(root, "bestSessionDiff", GLOBAL_STATE->SYSTEM_MODULE.best_session_diff_string);
|
||||
cJSON_AddNumberToObject(root, "stratumDiff", GLOBAL_STATE->stratum_difficulty);
|
||||
cJSON_AddNumberToObject(root, "stratumDiff", GLOBAL_STATE->connections[GLOBAL_STATE->current_connection_id].stratum_difficulty);
|
||||
|
||||
cJSON_AddNumberToObject(root, "isUsingFallbackStratum", GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback);
|
||||
|
||||
|
14
main/main.c
14
main/main.c
@ -1,3 +1,4 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
@ -23,10 +24,6 @@
|
||||
#include "asic.h"
|
||||
|
||||
static GlobalState GLOBAL_STATE = {
|
||||
.extranonce_str = NULL,
|
||||
.extranonce_2_len = 0,
|
||||
.abandon_work = 0,
|
||||
.version_mask = 0,
|
||||
.ASIC_initalized = false
|
||||
};
|
||||
|
||||
@ -123,12 +120,9 @@ void app_main(void)
|
||||
free(wifi_pass);
|
||||
free(hostname);
|
||||
|
||||
GLOBAL_STATE.new_stratum_version_rolling_msg = false;
|
||||
|
||||
wifi_softap_off();
|
||||
|
||||
if (GLOBAL_STATE.valid_model) {
|
||||
queue_init(&GLOBAL_STATE.stratum_queue);
|
||||
queue_init(&GLOBAL_STATE.ASIC_jobs_queue);
|
||||
|
||||
SERIAL_init();
|
||||
@ -137,8 +131,12 @@ void app_main(void)
|
||||
SERIAL_clear_buffer();
|
||||
|
||||
GLOBAL_STATE.ASIC_initalized = true;
|
||||
GLOBAL_STATE.current_connection_id = 0;
|
||||
|
||||
xTaskCreate(stratum_task, "stratum admin", 8192, (void *) &GLOBAL_STATE, 5, NULL);
|
||||
xTaskCreate(stratum_task_primary, "stratum primary task", 8192, (void *) &GLOBAL_STATE, 5, NULL);
|
||||
xTaskCreate(stratum_task_secondary, "stratum secondary task", 8192, (void *) &GLOBAL_STATE, 5, NULL);
|
||||
xTaskCreate(stratum_task_watchdog, "stratum watchdog", 8192, (void *) &GLOBAL_STATE, 5, NULL);
|
||||
// xTaskCreate(stratum_task, "stratum admin", 8192, (void *) &GLOBAL_STATE, 5, NULL);
|
||||
xTaskCreate(create_jobs_task, "stratum miner", 8192, (void *) &GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(ASIC_task, "asic", 8192, (void *) &GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(ASIC_result_task, "asic result", 8192, (void *) &GLOBAL_STATE, 15, NULL);
|
||||
|
@ -390,11 +390,9 @@ void self_test(void * pvParameters)
|
||||
}
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs = malloc(sizeof(bm_job *) * 128);
|
||||
GLOBAL_STATE->valid_jobs = malloc(sizeof(uint8_t) * 128);
|
||||
|
||||
for (int i = 0; i < 128; i++) {
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[i] = NULL;
|
||||
GLOBAL_STATE->valid_jobs[i] = 0;
|
||||
}
|
||||
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
@ -488,7 +486,6 @@ void self_test(void * pvParameters)
|
||||
}
|
||||
|
||||
free(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs);
|
||||
free(GLOBAL_STATE->valid_jobs);
|
||||
|
||||
if (test_core_voltage(GLOBAL_STATE) != ESP_OK) {
|
||||
tests_done(GLOBAL_STATE, TESTS_FAILED);
|
||||
|
@ -28,8 +28,14 @@ void ASIC_result_task(void *pvParameters)
|
||||
}
|
||||
|
||||
uint8_t job_id = asic_result->job_id;
|
||||
StratumConnection *current_connection = &GLOBAL_STATE->connections[GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->connection_id];
|
||||
if (current_connection->state != STRATUM_CONNECTED)
|
||||
{
|
||||
ESP_LOGW(TAG, "Connection for job 0x%02X no longer open", job_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0)
|
||||
if (current_connection->jobs[job_id] == 0)
|
||||
{
|
||||
ESP_LOGW(TAG, "Invalid job nonce found, 0x%02X", job_id);
|
||||
continue;
|
||||
@ -46,11 +52,10 @@ void ASIC_result_task(void *pvParameters)
|
||||
|
||||
if (nonce_diff >= GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->pool_diff)
|
||||
{
|
||||
char * user = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_user : GLOBAL_STATE->SYSTEM_MODULE.pool_user;
|
||||
int ret = STRATUM_V1_submit_share(
|
||||
GLOBAL_STATE->sock,
|
||||
GLOBAL_STATE->send_uid++,
|
||||
user,
|
||||
current_connection->sock,
|
||||
current_connection->send_uid++,
|
||||
current_connection->username,
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->jobid,
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->extranonce2,
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->ntime,
|
||||
@ -59,7 +64,7 @@ void ASIC_result_task(void *pvParameters)
|
||||
|
||||
if (ret < 0) {
|
||||
ESP_LOGI(TAG, "Unable to write share to socket. Closing connection. Ret: %d (errno %d: %s)", ret, errno, strerror(errno));
|
||||
stratum_close_connection(GLOBAL_STATE);
|
||||
stratum_close_connection(current_connection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,11 @@ void ASIC_task(void *pvParameters)
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.semaphore = xSemaphoreCreateBinary();
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs = malloc(sizeof(bm_job *) * 128);
|
||||
GLOBAL_STATE->valid_jobs = malloc(sizeof(uint8_t) * 128);
|
||||
// GLOBAL_STATE->stratum_context.jobs = malloc(sizeof(uint8_t) * 128);
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[i] = NULL;
|
||||
GLOBAL_STATE->valid_jobs[i] = 0;
|
||||
// GLOBAL_STATE->stratum_context.jobs[i] = 0;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "ASIC Job Interval: %.2f ms", GLOBAL_STATE->asic_job_frequency_ms);
|
||||
@ -35,17 +35,30 @@ void ASIC_task(void *pvParameters)
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
bm_job *next_bm_job = (bm_job *)queue_dequeue(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
StratumConnection *current_connection = &GLOBAL_STATE->connections[next_bm_job->connection_id];
|
||||
|
||||
if (next_bm_job->pool_diff != GLOBAL_STATE->stratum_difficulty)
|
||||
if (next_bm_job->connection_id != GLOBAL_STATE->current_connection_id)
|
||||
{
|
||||
ESP_LOGI(TAG, "New pool difficulty %lu", next_bm_job->pool_diff);
|
||||
GLOBAL_STATE->stratum_difficulty = next_bm_job->pool_diff;
|
||||
continue;
|
||||
}
|
||||
|
||||
//(*GLOBAL_STATE->ASIC_functions.send_work_fn)(GLOBAL_STATE, next_bm_job); // send the job to the ASIC
|
||||
ASIC_send_work(GLOBAL_STATE, next_bm_job);
|
||||
if (current_connection->state != STRATUM_CONNECTED)
|
||||
{
|
||||
ESP_LOGW(TAG, "Connection for job no longer open. Skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_connection->stratum_difficulty != next_bm_job->pool_diff)
|
||||
{
|
||||
ESP_LOGI(TAG, "New pool difficulty %lu", next_bm_job->pool_diff);
|
||||
current_connection->stratum_difficulty = next_bm_job->pool_diff;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(¤t_connection->jobs_lock);
|
||||
int job_id = ASIC_send_work(GLOBAL_STATE, next_bm_job);
|
||||
current_connection->jobs[job_id] = 1;
|
||||
pthread_mutex_unlock(¤t_connection->jobs_lock);
|
||||
|
||||
// Time to execute the above code is ~0.3ms
|
||||
// Delay for ASIC(s) to finish the job
|
||||
|
@ -15,7 +15,7 @@ static const char *TAG = "create_jobs_task";
|
||||
#define QUEUE_LOW_WATER_MARK 10 // Adjust based on your requirements
|
||||
|
||||
static bool should_generate_more_work(GlobalState *GLOBAL_STATE);
|
||||
static void generate_work(GlobalState *GLOBAL_STATE, mining_notify *notification, uint32_t extranonce_2);
|
||||
static void generate_work(GlobalState *GLOBAL_STATE, StratumConnection *active_connection, mining_notify *notification, uint32_t extranonce_2);
|
||||
|
||||
void create_jobs_task(void *pvParameters)
|
||||
{
|
||||
@ -23,42 +23,56 @@ void create_jobs_task(void *pvParameters)
|
||||
|
||||
while (1)
|
||||
{
|
||||
mining_notify *mining_notification = (mining_notify *)queue_dequeue(&GLOBAL_STATE->stratum_queue);
|
||||
if (mining_notification == NULL) {
|
||||
uint16_t current_connection_id = GLOBAL_STATE->current_connection_id;
|
||||
StratumConnection *active_connection = &GLOBAL_STATE->connections[current_connection_id];
|
||||
|
||||
if (active_connection->state != STRATUM_CONNECTED)
|
||||
{
|
||||
ESP_LOGD(TAG, "Connection ID %d not ready.", current_connection_id);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
mining_notify *mining_notification = (mining_notify *)queue_dequeue(&active_connection->stratum_queue);
|
||||
if (mining_notification == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to dequeue mining notification");
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS); // Wait a bit before trying again
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "New Work Dequeued %s", mining_notification->job_id);
|
||||
|
||||
if (GLOBAL_STATE->new_stratum_version_rolling_msg) {
|
||||
ESP_LOGI(TAG, "Set chip version rolls %i", (int)(GLOBAL_STATE->version_mask >> 13));
|
||||
//(GLOBAL_STATE->ASIC_functions.set_version_mask)(GLOBAL_STATE->version_mask);
|
||||
ASIC_set_version_mask(GLOBAL_STATE, GLOBAL_STATE->version_mask);
|
||||
GLOBAL_STATE->new_stratum_version_rolling_msg = false;
|
||||
if (active_connection->new_stratum_version_rolling_msg) {
|
||||
ESP_LOGI(TAG, "Set chip version rolls %i", (int)(active_connection->version_mask >> 13));
|
||||
ASIC_set_version_mask(GLOBAL_STATE, active_connection->version_mask);
|
||||
active_connection->new_stratum_version_rolling_msg = false;
|
||||
}
|
||||
|
||||
uint32_t extranonce_2 = 0;
|
||||
while (GLOBAL_STATE->stratum_queue.count < 1 && GLOBAL_STATE->abandon_work == 0)
|
||||
while (active_connection->stratum_queue.count < 1 && active_connection->abandon_work == 0)
|
||||
{
|
||||
if (active_connection->state != STRATUM_CONNECTED)
|
||||
break;
|
||||
else if (current_connection_id != GLOBAL_STATE->current_connection_id)
|
||||
break;
|
||||
|
||||
if (should_generate_more_work(GLOBAL_STATE))
|
||||
{
|
||||
generate_work(GLOBAL_STATE, mining_notification, extranonce_2);
|
||||
generate_work(GLOBAL_STATE, active_connection, mining_notification, extranonce_2);
|
||||
|
||||
// Increase extranonce_2 for the next job.
|
||||
extranonce_2++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no more work needed, wait a bit before checking again.
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (GLOBAL_STATE->abandon_work == 1)
|
||||
if (active_connection->abandon_work == 1)
|
||||
{
|
||||
GLOBAL_STATE->abandon_work = 0;
|
||||
active_connection->abandon_work = 0;
|
||||
ASIC_jobs_queue_clear(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
xSemaphoreGive(GLOBAL_STATE->ASIC_TASK_MODULE.semaphore);
|
||||
}
|
||||
@ -72,15 +86,21 @@ static bool should_generate_more_work(GlobalState *GLOBAL_STATE)
|
||||
return GLOBAL_STATE->ASIC_jobs_queue.count < QUEUE_LOW_WATER_MARK;
|
||||
}
|
||||
|
||||
static void generate_work(GlobalState *GLOBAL_STATE, mining_notify *notification, uint32_t extranonce_2)
|
||||
static void generate_work(GlobalState *GLOBAL_STATE, StratumConnection *active_connection, mining_notify *notification, uint32_t extranonce_2)
|
||||
{
|
||||
char *extranonce_2_str = extranonce_2_generate(extranonce_2, GLOBAL_STATE->extranonce_2_len);
|
||||
char *extranonce_2_str = extranonce_2_generate(extranonce_2, active_connection->extranonce_2_len);
|
||||
if (extranonce_2_str == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to generate extranonce_2");
|
||||
return;
|
||||
}
|
||||
|
||||
char *coinbase_tx = construct_coinbase_tx(notification->coinbase_1, notification->coinbase_2, GLOBAL_STATE->extranonce_str, extranonce_2_str);
|
||||
if (active_connection->extranonce_str == NULL)
|
||||
{
|
||||
ESP_LOGW(TAG, "active_connection->extranonce_str == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
char *coinbase_tx = construct_coinbase_tx(notification->coinbase_1, notification->coinbase_2, active_connection->extranonce_str, extranonce_2_str);
|
||||
if (coinbase_tx == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to construct coinbase_tx");
|
||||
free(extranonce_2_str);
|
||||
@ -95,7 +115,7 @@ static void generate_work(GlobalState *GLOBAL_STATE, mining_notify *notification
|
||||
return;
|
||||
}
|
||||
|
||||
bm_job next_job = construct_bm_job(notification, merkle_root, GLOBAL_STATE->version_mask);
|
||||
bm_job next_job = construct_bm_job(notification, merkle_root, active_connection->version_mask);
|
||||
|
||||
bm_job *queued_next_job = malloc(sizeof(bm_job));
|
||||
if (queued_next_job == NULL) {
|
||||
@ -109,7 +129,7 @@ static void generate_work(GlobalState *GLOBAL_STATE, mining_notify *notification
|
||||
memcpy(queued_next_job, &next_job, sizeof(bm_job));
|
||||
queued_next_job->extranonce2 = extranonce_2_str; // Transfer ownership
|
||||
queued_next_job->jobid = strdup(notification->job_id);
|
||||
queued_next_job->version_mask = GLOBAL_STATE->version_mask;
|
||||
queued_next_job->version_mask = active_connection->version_mask;
|
||||
|
||||
queue_enqueue(&GLOBAL_STATE->ASIC_jobs_queue, queued_next_job);
|
||||
|
||||
|
@ -23,18 +23,14 @@
|
||||
#define FALLBACK_STRATUM_PW CONFIG_FALLBACK_STRATUM_PW
|
||||
#define STRATUM_DIFFICULTY CONFIG_STRATUM_DIFFICULTY
|
||||
|
||||
#define MAX_RETRY_ATTEMPTS 3
|
||||
#define MAX_CRITICAL_RETRY_ATTEMPTS 5
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
static const char * TAG = "stratum_task";
|
||||
|
||||
static StratumApiV1Message stratum_api_v1_message = {};
|
||||
static SystemTaskModule SYSTEM_TASK_MODULE = {.stratum_difficulty = 8192};
|
||||
static int addr_family = AF_INET;
|
||||
static int ip_protocol = IPPROTO_IP;
|
||||
|
||||
static const char * primary_stratum_url;
|
||||
static uint16_t primary_stratum_port;
|
||||
void stratum_process(const char * POOL_TAG, GlobalState * GLOBAL_STATE, StratumConnection * connection);
|
||||
void stratum_task(const char * POOL_TAG, GlobalState * GLOBAL_STATE, StratumConnection * connection);
|
||||
void stratum_task_init_connection(StratumConnection * connection);
|
||||
|
||||
struct timeval tcp_snd_timeout = {
|
||||
.tv_sec = 5,
|
||||
@ -48,313 +44,334 @@ struct timeval tcp_rcv_timeout = {
|
||||
|
||||
bool is_wifi_connected() {
|
||||
wifi_ap_record_t ap_info;
|
||||
if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
return esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK;
|
||||
}
|
||||
|
||||
void stratum_task_primary(void * pvParameters)
|
||||
{
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
|
||||
StratumConnection * connection = &GLOBAL_STATE->connections[0];
|
||||
|
||||
stratum_task_init_connection(connection);
|
||||
connection->id = 0;
|
||||
connection->host = GLOBAL_STATE->SYSTEM_MODULE.pool_url;
|
||||
connection->port = GLOBAL_STATE->SYSTEM_MODULE.pool_port;
|
||||
connection->username = GLOBAL_STATE->SYSTEM_MODULE.pool_user;
|
||||
connection->password = GLOBAL_STATE->SYSTEM_MODULE.pool_pass;
|
||||
|
||||
ESP_LOGI(TAG, "Opening connection to primary pool: %s:%d", connection->host, connection->port);
|
||||
|
||||
stratum_task("primary_pool", GLOBAL_STATE, connection);
|
||||
}
|
||||
|
||||
void stratum_task_secondary(void * pvParameters)
|
||||
{
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
|
||||
StratumConnection * connection = &GLOBAL_STATE->connections[1];
|
||||
|
||||
stratum_task_init_connection(connection);
|
||||
connection->id = 1;
|
||||
connection->host = GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_url;
|
||||
connection->port = GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_port;
|
||||
connection->username = GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_user;
|
||||
connection->password = GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_pass;
|
||||
|
||||
ESP_LOGI(TAG, "Opening connection to secondary pool: %s:%d", connection->host, connection->port);
|
||||
|
||||
stratum_task("secondary_pool", GLOBAL_STATE, connection);
|
||||
}
|
||||
|
||||
void stratum_task_watchdog(void *pvParameters)
|
||||
{
|
||||
ESP_LOGI(TAG, "Starting Stratum Watchdog.");
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
// Always fail back over to the Primary when it is back up.
|
||||
if (GLOBAL_STATE->current_connection_id != 0 &&
|
||||
GLOBAL_STATE->connections[0].state == STRATUM_CONNECTED)
|
||||
{
|
||||
GLOBAL_STATE->current_connection_id = 0;
|
||||
GLOBAL_STATE->connections[0].new_stratum_version_rolling_msg = true;
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback = false;
|
||||
ESP_LOGI(TAG, "Switching back to primary pool.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// No need to do anything if the current connection is stable.
|
||||
if (GLOBAL_STATE->connections[GLOBAL_STATE->current_connection_id].state == STRATUM_CONNECTED)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Loop through all connections to try to find a healthy one.
|
||||
for (int i = 1; i < MAX_STRATUM_POOLS; i++)
|
||||
{
|
||||
if (GLOBAL_STATE->current_connection_id == i)
|
||||
continue;
|
||||
|
||||
// Lets wait until this pool is done retrying before moving forward.
|
||||
if (GLOBAL_STATE->connections[i].state == STRATUM_CONNECTING)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (GLOBAL_STATE->connections[i].state == STRATUM_CONNECTED)
|
||||
{
|
||||
GLOBAL_STATE->current_connection_id = i;
|
||||
GLOBAL_STATE->connections[i].new_stratum_version_rolling_msg = true;
|
||||
ESP_LOGI(TAG, "Switching to pool: %s", GLOBAL_STATE->connections[i].host);
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cleanQueue(GlobalState * GLOBAL_STATE) {
|
||||
ESP_LOGI(TAG, "Clean Jobs: clearing queue");
|
||||
GLOBAL_STATE->abandon_work = 1;
|
||||
queue_clear(&GLOBAL_STATE->stratum_queue);
|
||||
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
ASIC_jobs_queue_clear(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
for (int i = 0; i < 128; i = i + 4) {
|
||||
GLOBAL_STATE->valid_jobs[i] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
void stratum_reset_uid(StratumConnection * connection)
|
||||
{
|
||||
connection->send_uid = 1;
|
||||
}
|
||||
|
||||
void stratum_reset_uid(GlobalState * GLOBAL_STATE)
|
||||
void stratum_close_connection(StratumConnection * connection)
|
||||
{
|
||||
ESP_LOGI(TAG, "Resetting stratum uid");
|
||||
GLOBAL_STATE->send_uid = 1;
|
||||
}
|
||||
|
||||
|
||||
void stratum_close_connection(GlobalState * GLOBAL_STATE)
|
||||
{
|
||||
if (GLOBAL_STATE->sock < 0) {
|
||||
if (connection->sock < 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "Socket already shutdown, not shutting down again..");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "Shutting down socket and restarting...");
|
||||
shutdown(GLOBAL_STATE->sock, SHUT_RDWR);
|
||||
close(GLOBAL_STATE->sock);
|
||||
cleanQueue(GLOBAL_STATE);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
close(connection->sock);
|
||||
}
|
||||
|
||||
void stratum_primary_heartbeat(void * pvParameters)
|
||||
void stratum_clear_queue(const char * POOL_TAG, StratumConnection * connection)
|
||||
{
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
ESP_LOGD(POOL_TAG, "Clearing queues for connection.");
|
||||
|
||||
ESP_LOGI(TAG, "Starting heartbeat thread for primary pool: %s:%d", primary_stratum_url, primary_stratum_port);
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
connection->abandon_work = 1;
|
||||
queue_clear(&connection->stratum_queue);
|
||||
|
||||
int addr_family = AF_INET;
|
||||
int ip_protocol = IPPROTO_IP;
|
||||
pthread_mutex_lock(&connection->jobs_lock);
|
||||
for (int i = 0; i < 128; i++) {
|
||||
connection->jobs[i] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&connection->jobs_lock);
|
||||
}
|
||||
|
||||
struct timeval tcp_timeout = {
|
||||
.tv_sec = 5,
|
||||
.tv_usec = 0
|
||||
};
|
||||
|
||||
while (1)
|
||||
void stratum_task_init_connection(StratumConnection * connection)
|
||||
{
|
||||
queue_init(&connection->stratum_queue);
|
||||
connection->extranonce_str = NULL,
|
||||
connection->extranonce_2_len = 0,
|
||||
connection->version_mask = 0,
|
||||
connection->abandon_work = 0;
|
||||
connection->buf = STRATUM_V1_buffer_create();
|
||||
connection->stratum_difficulty = 1024;
|
||||
connection->send_uid = 1;
|
||||
connection->sock = -1;
|
||||
connection->retry_attempts = 0;
|
||||
connection->state = STRATUM_CONNECTING;
|
||||
connection->message = malloc(sizeof(StratumApiV1Message));
|
||||
connection->jobs = malloc(sizeof(uint8_t) * 128);
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
if (GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback == false) {
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
char host_ip[INET_ADDRSTRLEN];
|
||||
ESP_LOGD(TAG, "Running Heartbeat on: %s!", primary_stratum_url);
|
||||
|
||||
if (!is_wifi_connected()) {
|
||||
ESP_LOGD(TAG, "Heartbeat. Failed WiFi check!");
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct hostent *primary_dns_addr = gethostbyname(primary_stratum_url);
|
||||
if (primary_dns_addr == NULL) {
|
||||
ESP_LOGD(TAG, "Heartbeat. Failed DNS check for: %s!", primary_stratum_url);
|
||||
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
inet_ntop(AF_INET, (void *)primary_dns_addr->h_addr_list[0], host_ip, sizeof(host_ip));
|
||||
|
||||
struct sockaddr_in dest_addr;
|
||||
dest_addr.sin_addr.s_addr = inet_addr(host_ip);
|
||||
dest_addr.sin_family = AF_INET;
|
||||
dest_addr.sin_port = htons(primary_stratum_port);
|
||||
|
||||
int sock = socket(addr_family, SOCK_STREAM, ip_protocol);
|
||||
if (sock < 0) {
|
||||
ESP_LOGD(TAG, "Heartbeat. Failed socket create check!");
|
||||
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
|
||||
if (err != 0)
|
||||
{
|
||||
ESP_LOGD(TAG, "Heartbeat. Failed connect check: %s:%d (errno %d: %s)", host_ip, primary_stratum_port, errno, strerror(errno));
|
||||
close(sock);
|
||||
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO , &tcp_timeout, sizeof(tcp_timeout)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt SO_RCVTIMEO ");
|
||||
}
|
||||
|
||||
int send_uid = 1;
|
||||
STRATUM_V1_subscribe(sock, send_uid++, GLOBAL_STATE->asic_model_str);
|
||||
STRATUM_V1_authenticate(sock, send_uid++, GLOBAL_STATE->SYSTEM_MODULE.pool_user, GLOBAL_STATE->SYSTEM_MODULE.pool_pass);
|
||||
|
||||
char recv_buffer[BUFFER_SIZE];
|
||||
memset(recv_buffer, 0, BUFFER_SIZE);
|
||||
int bytes_received = recv(sock, recv_buffer, BUFFER_SIZE - 1, 0);
|
||||
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
|
||||
if (bytes_received == -1) {
|
||||
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strstr(recv_buffer, "mining.notify") != NULL) {
|
||||
ESP_LOGI(TAG, "Heartbeat successful and in fallback mode. Switching back to primary.");
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback = false;
|
||||
stratum_close_connection(GLOBAL_STATE);
|
||||
continue;
|
||||
}
|
||||
|
||||
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
||||
connection->jobs[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void stratum_task(void * pvParameters)
|
||||
void stratum_handle_disconnect(const char * POOL_TAG, StratumConnection * connection)
|
||||
{
|
||||
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||
stratum_close_connection(connection);
|
||||
|
||||
primary_stratum_url = GLOBAL_STATE->SYSTEM_MODULE.pool_url;
|
||||
primary_stratum_port = GLOBAL_STATE->SYSTEM_MODULE.pool_port;
|
||||
char * stratum_url = GLOBAL_STATE->SYSTEM_MODULE.pool_url;
|
||||
uint16_t port = GLOBAL_STATE->SYSTEM_MODULE.pool_port;
|
||||
if (connection->state == STRATUM_CONNECTED)
|
||||
{
|
||||
ESP_LOGE(POOL_TAG, "Pool disconnected.");
|
||||
}
|
||||
|
||||
STRATUM_V1_initialize_buffer();
|
||||
char host_ip[20];
|
||||
int addr_family = AF_INET;
|
||||
int ip_protocol = IPPROTO_IP;
|
||||
int retry_attempts = 0;
|
||||
int retry_critical_attempts = 0;
|
||||
stratum_clear_queue(POOL_TAG, connection);
|
||||
|
||||
xTaskCreate(stratum_primary_heartbeat, "stratum primary heartbeat", 8192, pvParameters, 1, NULL);
|
||||
connection->retry_attempts++;
|
||||
|
||||
ESP_LOGI(TAG, "Opening connection to pool: %s:%d", stratum_url, port);
|
||||
if (connection->retry_attempts <= 3)
|
||||
{
|
||||
connection->state = STRATUM_CONNECTING;
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
else
|
||||
{
|
||||
int delay_ms = 1000 + (connection->retry_attempts * 1000);
|
||||
if (delay_ms > 30 * 1000) delay_ms = 30000;
|
||||
|
||||
connection->state = STRATUM_DISCONNECTED;
|
||||
vTaskDelay(delay_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void stratum_task(const char * POOL_TAG, GlobalState * GLOBAL_STATE, StratumConnection * connection)
|
||||
{
|
||||
while (1) {
|
||||
connection->state = STRATUM_CONNECTING;
|
||||
connection->send_uid = 1;
|
||||
|
||||
if (!is_wifi_connected()) {
|
||||
ESP_LOGI(TAG, "WiFi disconnected, attempting to reconnect...");
|
||||
ESP_LOGI(POOL_TAG, "WiFi disconnected, attempting to reconnect...");
|
||||
connection->state = STRATUM_CONNECTING;
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (retry_attempts >= MAX_RETRY_ATTEMPTS)
|
||||
{
|
||||
if (GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_url == NULL || GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_url[0] == '\0') {
|
||||
ESP_LOGI(TAG, "Unable to switch to fallback. No url configured. (retries: %d)...", retry_attempts);
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback = false;
|
||||
retry_attempts = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback = !GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback;
|
||||
ESP_LOGI(TAG, "Switching target due to too many failures (retries: %d)...", retry_attempts);
|
||||
retry_attempts = 0;
|
||||
}
|
||||
|
||||
stratum_url = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_url : GLOBAL_STATE->SYSTEM_MODULE.pool_url;
|
||||
port = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_port : GLOBAL_STATE->SYSTEM_MODULE.pool_port;
|
||||
|
||||
struct hostent *dns_addr = gethostbyname(stratum_url);
|
||||
struct hostent *dns_addr = gethostbyname(connection->host);
|
||||
if (dns_addr == NULL) {
|
||||
retry_attempts++;
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGE(POOL_TAG, "Unable to resolve DNS.");
|
||||
stratum_handle_disconnect(POOL_TAG, connection);
|
||||
continue;
|
||||
}
|
||||
inet_ntop(AF_INET, (void *)dns_addr->h_addr_list[0], host_ip, sizeof(host_ip));
|
||||
|
||||
ESP_LOGI(TAG, "Connecting to: stratum+tcp://%s:%d (%s)", stratum_url, port, host_ip);
|
||||
inet_ntop(AF_INET, (void *)dns_addr->h_addr_list[0], connection->ip_address, sizeof(connection->ip_address));
|
||||
|
||||
struct sockaddr_in dest_addr;
|
||||
dest_addr.sin_addr.s_addr = inet_addr(host_ip);
|
||||
dest_addr.sin_addr.s_addr = inet_addr(connection->ip_address);
|
||||
dest_addr.sin_family = AF_INET;
|
||||
dest_addr.sin_port = htons(port);
|
||||
dest_addr.sin_port = htons(connection->port);
|
||||
|
||||
GLOBAL_STATE->sock = socket(addr_family, SOCK_STREAM, ip_protocol);
|
||||
if (GLOBAL_STATE->sock < 0) {
|
||||
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
|
||||
if (++retry_critical_attempts > MAX_CRITICAL_RETRY_ATTEMPTS) {
|
||||
ESP_LOGE(TAG, "Max retry attempts reached, restarting...");
|
||||
esp_restart();
|
||||
}
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
connection->sock = socket(addr_family, SOCK_STREAM, ip_protocol);
|
||||
if (connection->sock < 0) {
|
||||
ESP_LOGE(POOL_TAG, "Unable to create the socket.");
|
||||
close(connection->sock);
|
||||
stratum_handle_disconnect(POOL_TAG, connection);
|
||||
continue;
|
||||
}
|
||||
retry_critical_attempts = 0;
|
||||
|
||||
ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, port);
|
||||
int err = connect(GLOBAL_STATE->sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
|
||||
int err = connect(connection->sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
|
||||
if (err != 0)
|
||||
{
|
||||
retry_attempts++;
|
||||
ESP_LOGE(TAG, "Socket unable to connect to %s:%d (errno %d: %s)", stratum_url, port, errno, strerror(errno));
|
||||
// close the socket
|
||||
shutdown(GLOBAL_STATE->sock, SHUT_RDWR);
|
||||
close(GLOBAL_STATE->sock);
|
||||
// instead of restarting, retry this every 5 seconds
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGE(POOL_TAG, "Unable to connect to socket.");
|
||||
close(connection->sock);
|
||||
stratum_handle_disconnect(POOL_TAG, connection);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setsockopt(GLOBAL_STATE->sock, SOL_SOCKET, SO_SNDTIMEO, &tcp_snd_timeout, sizeof(tcp_snd_timeout)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt SO_SNDTIMEO");
|
||||
if (setsockopt(connection->sock, SOL_SOCKET, SO_SNDTIMEO, &tcp_snd_timeout, sizeof(tcp_snd_timeout)) != 0) {
|
||||
ESP_LOGE(POOL_TAG, "Fail to setsockopt SO_SNDTIMEO");
|
||||
}
|
||||
|
||||
if (setsockopt(GLOBAL_STATE->sock, SOL_SOCKET, SO_RCVTIMEO , &tcp_rcv_timeout, sizeof(tcp_rcv_timeout)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt SO_RCVTIMEO ");
|
||||
if (setsockopt(connection->sock, SOL_SOCKET, SO_RCVTIMEO , &tcp_rcv_timeout, sizeof(tcp_rcv_timeout)) != 0) {
|
||||
ESP_LOGE(POOL_TAG, "Fail to setsockopt SO_RCVTIMEO ");
|
||||
}
|
||||
|
||||
stratum_reset_uid(GLOBAL_STATE);
|
||||
cleanQueue(GLOBAL_STATE);
|
||||
stratum_reset_uid(connection);
|
||||
|
||||
///// Start Stratum Action
|
||||
// mining.configure - ID: 1
|
||||
STRATUM_V1_configure_version_rolling(GLOBAL_STATE->sock, GLOBAL_STATE->send_uid++, &GLOBAL_STATE->version_mask);
|
||||
STRATUM_V1_configure_version_rolling(POOL_TAG, connection->sock, connection->send_uid++);
|
||||
STRATUM_V1_subscribe(POOL_TAG, connection->sock, connection->send_uid++, GLOBAL_STATE->asic_model_str);
|
||||
STRATUM_V1_authenticate(POOL_TAG, connection->sock, connection->send_uid++, connection->username, connection->password);
|
||||
STRATUM_V1_suggest_difficulty(POOL_TAG, connection->sock, connection->send_uid++, STRATUM_DIFFICULTY);
|
||||
|
||||
// mining.subscribe - ID: 2
|
||||
STRATUM_V1_subscribe(GLOBAL_STATE->sock, GLOBAL_STATE->send_uid++, GLOBAL_STATE->asic_model_str);
|
||||
connection->abandon_work = 0;
|
||||
|
||||
char * username = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_user : GLOBAL_STATE->SYSTEM_MODULE.pool_user;
|
||||
char * password = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_pass : GLOBAL_STATE->SYSTEM_MODULE.pool_pass;
|
||||
stratum_process(POOL_TAG, GLOBAL_STATE, connection);
|
||||
|
||||
//mining.authorize - ID: 3
|
||||
STRATUM_V1_authenticate(GLOBAL_STATE->sock, GLOBAL_STATE->send_uid++, username, password);
|
||||
if (GLOBAL_STATE->current_connection_id == connection->id)
|
||||
ASIC_jobs_queue_clear(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
}
|
||||
}
|
||||
|
||||
//mining.suggest_difficulty - ID: 4
|
||||
STRATUM_V1_suggest_difficulty(GLOBAL_STATE->sock, GLOBAL_STATE->send_uid++, STRATUM_DIFFICULTY);
|
||||
void stratum_process(const char * POOL_TAG, GlobalState * GLOBAL_STATE, StratumConnection * connection)
|
||||
{
|
||||
while (1) {
|
||||
char * line = STRATUM_V1_receive_jsonrpc_line(POOL_TAG, connection->sock, connection->buf);
|
||||
if (!line) {
|
||||
ESP_LOGE(POOL_TAG, "Failed to receive JSON-RPC line, reconnecting...");
|
||||
stratum_handle_disconnect(POOL_TAG, connection);
|
||||
break;
|
||||
}
|
||||
|
||||
// Everything is set up, lets make sure we don't abandon work unnecessarily.
|
||||
GLOBAL_STATE->abandon_work = 0;
|
||||
ESP_LOGI(POOL_TAG, "rx: %s", line);
|
||||
STRATUM_V1_parse(POOL_TAG, connection->message, line);
|
||||
free(line);
|
||||
|
||||
while (1) {
|
||||
char * line = STRATUM_V1_receive_jsonrpc_line(GLOBAL_STATE->sock);
|
||||
if (!line) {
|
||||
ESP_LOGE(TAG, "Failed to receive JSON-RPC line, reconnecting...");
|
||||
retry_attempts++;
|
||||
stratum_close_connection(GLOBAL_STATE);
|
||||
break;
|
||||
if (connection->message->method == MINING_NOTIFY)
|
||||
{
|
||||
if (GLOBAL_STATE->current_connection_id == connection->id)
|
||||
SYSTEM_notify_new_ntime(GLOBAL_STATE, connection->message->mining_notification->ntime);
|
||||
|
||||
if (connection->message->should_abandon_work && connection->stratum_queue.count > 0)
|
||||
{
|
||||
ESP_LOGI(POOL_TAG, "Abandoning the Stratum queues.");
|
||||
stratum_clear_queue(POOL_TAG, connection);
|
||||
if (GLOBAL_STATE->current_connection_id == connection->id)
|
||||
ASIC_jobs_queue_clear(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
}
|
||||
if (connection->stratum_queue.count >= QUEUE_SIZE)
|
||||
{
|
||||
mining_notify * next_notify_json_str = (mining_notify *) queue_dequeue(&connection->stratum_queue);
|
||||
STRATUM_V1_free_mining_notify(next_notify_json_str);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "rx: %s", line); // debug incoming stratum messages
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, line);
|
||||
free(line);
|
||||
connection->message->mining_notification->difficulty = connection->stratum_difficulty;
|
||||
connection->message->mining_notification->connection_id = connection->id;
|
||||
queue_enqueue(&connection->stratum_queue, connection->message->mining_notification);
|
||||
}
|
||||
else if (connection->message->method == MINING_SET_DIFFICULTY)
|
||||
{
|
||||
if (connection->stratum_difficulty != connection->message->new_difficulty)
|
||||
{
|
||||
connection->stratum_difficulty = connection->message->new_difficulty;
|
||||
ESP_LOGI(POOL_TAG, "Set stratum difficulty: %ld", connection->stratum_difficulty);
|
||||
}
|
||||
}
|
||||
else if (connection->message->method == MINING_SET_VERSION_MASK ||
|
||||
connection->message->method == STRATUM_RESULT_VERSION_MASK)
|
||||
{
|
||||
ESP_LOGI(POOL_TAG, "Set version mask: %08lx", connection->message->version_mask);
|
||||
connection->version_mask = connection->message->version_mask;
|
||||
connection->new_stratum_version_rolling_msg = true;
|
||||
}
|
||||
else if (connection->message->method == STRATUM_RESULT_SUBSCRIBE)
|
||||
{
|
||||
connection->extranonce_str = connection->message->extranonce_str;
|
||||
connection->extranonce_2_len = connection->message->extranonce_2_len;
|
||||
}
|
||||
else if (connection->message->method == CLIENT_RECONNECT)
|
||||
{
|
||||
ESP_LOGE(POOL_TAG, "Pool requested client reconnect...");
|
||||
stratum_clear_queue(POOL_TAG, connection);
|
||||
stratum_close_connection(connection);
|
||||
break;
|
||||
}
|
||||
else if (connection->message->method == STRATUM_RESULT)
|
||||
{
|
||||
if (connection->message->response_success)
|
||||
{
|
||||
ESP_LOGI(POOL_TAG, "message result accepted");
|
||||
SYSTEM_notify_accepted_share(GLOBAL_STATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGW(POOL_TAG, "message result rejected: %s", connection->message->error_str ? connection->message->error_str : "unknown");
|
||||
SYSTEM_notify_rejected_share(GLOBAL_STATE);
|
||||
}
|
||||
}
|
||||
else if (connection->message->method == STRATUM_RESULT_SETUP)
|
||||
{
|
||||
if (connection->message->response_success)
|
||||
{
|
||||
connection->retry_attempts = 0;
|
||||
connection->state = STRATUM_CONNECTED;
|
||||
|
||||
if (stratum_api_v1_message.method == MINING_NOTIFY) {
|
||||
SYSTEM_notify_new_ntime(GLOBAL_STATE, stratum_api_v1_message.mining_notification->ntime);
|
||||
if (stratum_api_v1_message.should_abandon_work &&
|
||||
(GLOBAL_STATE->stratum_queue.count > 0 || GLOBAL_STATE->ASIC_jobs_queue.count > 0)) {
|
||||
cleanQueue(GLOBAL_STATE);
|
||||
}
|
||||
if (GLOBAL_STATE->stratum_queue.count == QUEUE_SIZE) {
|
||||
mining_notify * next_notify_json_str = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue);
|
||||
STRATUM_V1_free_mining_notify(next_notify_json_str);
|
||||
}
|
||||
stratum_api_v1_message.mining_notification->difficulty = SYSTEM_TASK_MODULE.stratum_difficulty;
|
||||
queue_enqueue(&GLOBAL_STATE->stratum_queue, stratum_api_v1_message.mining_notification);
|
||||
} else if (stratum_api_v1_message.method == MINING_SET_DIFFICULTY) {
|
||||
if (stratum_api_v1_message.new_difficulty != SYSTEM_TASK_MODULE.stratum_difficulty) {
|
||||
SYSTEM_TASK_MODULE.stratum_difficulty = stratum_api_v1_message.new_difficulty;
|
||||
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) {
|
||||
// 1fffe000
|
||||
ESP_LOGI(TAG, "Set version mask: %08lx", stratum_api_v1_message.version_mask);
|
||||
GLOBAL_STATE->version_mask = stratum_api_v1_message.version_mask;
|
||||
GLOBAL_STATE->new_stratum_version_rolling_msg = true;
|
||||
} 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 == CLIENT_RECONNECT) {
|
||||
ESP_LOGE(TAG, "Pool requested client reconnect...");
|
||||
stratum_close_connection(GLOBAL_STATE);
|
||||
break;
|
||||
} else if (stratum_api_v1_message.method == STRATUM_RESULT) {
|
||||
if (stratum_api_v1_message.response_success) {
|
||||
ESP_LOGI(TAG, "message result accepted");
|
||||
SYSTEM_notify_accepted_share(GLOBAL_STATE);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "message result rejected: %s", stratum_api_v1_message.error_str);
|
||||
SYSTEM_notify_rejected_share(GLOBAL_STATE, stratum_api_v1_message.error_str);
|
||||
}
|
||||
} else if (stratum_api_v1_message.method == STRATUM_RESULT_SETUP) {
|
||||
// Reset retry attempts after successfully receiving data.
|
||||
retry_attempts = 0;
|
||||
if (stratum_api_v1_message.response_success) {
|
||||
ESP_LOGI(TAG, "setup message accepted");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "setup message rejected: %s", stratum_api_v1_message.error_str);
|
||||
}
|
||||
ESP_LOGI(POOL_TAG, "setup message accepted");
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(POOL_TAG, "setup message rejected: %s", connection->message->error_str ? connection->message->error_str : "unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
@ -1,12 +1,53 @@
|
||||
#ifndef STRATUM_TASK_H_
|
||||
#define STRATUM_TASK_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include "work_queue.h"
|
||||
|
||||
#define MAX_STRATUM_POOLS 2
|
||||
|
||||
typedef enum {
|
||||
STRATUM_CONNECTING,
|
||||
STRATUM_CONNECTED,
|
||||
STRATUM_DISCONNECTED,
|
||||
} connection_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t stratum_difficulty;
|
||||
} SystemTaskModule;
|
||||
uint8_t id;
|
||||
|
||||
void stratum_task(void *pvParameters);
|
||||
void stratum_close_connection(GlobalState * GLOBAL_STATE);
|
||||
connection_state_t state;
|
||||
|
||||
uint32_t stratum_difficulty;
|
||||
uint32_t version_mask;
|
||||
|
||||
bool new_stratum_version_rolling_msg;
|
||||
|
||||
char * extranonce_str;
|
||||
int extranonce_2_len;
|
||||
|
||||
int send_uid;
|
||||
int sock;
|
||||
char * username;
|
||||
char * password;
|
||||
char * host;
|
||||
char ip_address[20];
|
||||
uint16_t port;
|
||||
uint32_t retry_attempts;
|
||||
|
||||
work_queue stratum_queue;
|
||||
|
||||
uint8_t * jobs;
|
||||
pthread_mutex_t jobs_lock;
|
||||
bool abandon_work;
|
||||
|
||||
StratumApiV1Message *message;
|
||||
StratumApiV1Buffer *buf;
|
||||
} StratumConnection;
|
||||
|
||||
void stratum_task_watchdog(void * pvParameters);
|
||||
void stratum_task_primary(void * pvParameters);
|
||||
void stratum_task_secondary(void * pvParameters);
|
||||
void stratum_close_connection(StratumConnection * connection);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user