cleaning and optimizing stratum_task/stratum_api

This commit is contained in:
Ben 2023-06-08 09:50:05 -04:00 committed by johnny9
parent c3301aab30
commit 35358e0e44
9 changed files with 231 additions and 244 deletions

View File

@ -10,6 +10,15 @@
#define COINBASE_SIZE 100
#define COINBASE2_SIZE 128
typedef enum {
STRATUM_UNKNOWN,
MINING_NOTIFY,
MINING_SET_DIFFICULTY,
MINING_SET_VERSION_MASK,
STRATUM_RESULT
} stratum_method;
typedef struct {
char * job_id;
char * prev_block_hash;
@ -23,45 +32,43 @@ typedef struct {
uint32_t difficulty;
} mining_notify;
typedef enum {
STRATUM_UNKNOWN,
MINING_NOTIFY,
MINING_SET_DIFFICULTY,
MINING_SET_VERSION_MASK,
STRATUM_RESULT
} stratum_method;
typedef struct {
void initialize_stratum_buffer();
int16_t message_id;
stratum_method method;
char * receive_jsonrpc_line(int sockfd);
//mining.notify
int should_abandon_work;
mining_notify * mining_notification;
//mining.set_difficulty
uint32_t new_difficulty;
//mining.set_version_mask
uint32_t version_mask;
//result
bool response_success;
} StratumApiV1Message;
int subscribe_to_stratum(int socket, char ** extranonce, int * extranonce2_len);
stratum_method parse_stratum_method(const char * stratum_json);
void STRATUM_V1_initialize_buffer();
mining_notify * parse_mining_notify_message(const char * stratum_json, uint32_t difficulty);
char * STRATUM_V1_receive_jsonrpc_line(int sockfd);
uint32_t parse_mining_set_difficulty_message(const char * stratum_json);
int STRATUM_V1_subscribe(int socket, char ** extranonce, int * extranonce2_len);
uint32_t parse_mining_set_version_mask_message(const char * stratum_json);
void STRATUM_V1_parse(StratumApiV1Message* message, const char * stratum_json);
void free_mining_notify(mining_notify * params);
int parse_stratum_subscribe_result_message(const char * result_json_str,
char ** extranonce,
int * extranonce2_len);
void STRATUM_V1_free_mining_notify(mining_notify * params);
bool parse_stratum_result_message(const char * stratum_json, int16_t *);
int auth_to_stratum(int socket, const char * username);
int STRATUM_V1_authenticate(int socket, const char * username);
void configure_version_rolling(int socket);
void STRATUM_V1_configure_version_rolling(int socket);
int suggest_difficulty(int socket, uint32_t difficulty);
int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty);
void submit_share(int socket, const char * username, const char * jobid,
void STRATUM_V1_submit_share(int socket, const char * username, const char * jobid,
const uint32_t ntime, const char * extranonce_2, const uint32_t nonce);
int should_abandon_work(const char * mining_notify_json_str);
#endif // STRATUM_API_H

View File

@ -17,7 +17,7 @@ static int send_uid = 1;
static void debug_stratum_tx(const char *);
void initialize_stratum_buffer()
void STRATUM_V1_initialize_buffer()
{
json_rpc_buffer = malloc(BUFFER_SIZE);
json_rpc_buffer_size = BUFFER_SIZE;
@ -60,10 +60,10 @@ static void realloc_json_buffer(size_t len)
json_rpc_buffer_size = new;
}
char * receive_jsonrpc_line(int sockfd)
char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
{
if (json_rpc_buffer == NULL) {
initialize_stratum_buffer();
STRATUM_V1_initialize_buffer();
}
char *line, *tok = NULL;
char recv_buffer[BUFFER_SIZE];
@ -97,9 +97,19 @@ char * receive_jsonrpc_line(int sockfd)
return line;
}
stratum_method parse_stratum_method(const char * stratum_json)
void STRATUM_V1_parse(StratumApiV1Message* message, const char * stratum_json)
{
cJSON * json = cJSON_Parse(stratum_json);
cJSON * id_json = cJSON_GetObjectItem(json, "id");
int16_t parsed_id = -1;
if (id_json != NULL && cJSON_IsNumber(id_json)) {
parsed_id = id_json->valueint;
}
message->message_id = parsed_id;
cJSON * method_json = cJSON_GetObjectItem(json, "method");
stratum_method result = STRATUM_UNKNOWN;
if (method_json != NULL && cJSON_IsString(method_json)) {
@ -114,101 +124,75 @@ stratum_method parse_stratum_method(const char * stratum_json)
//parse results
cJSON * result_json = cJSON_GetObjectItem(json, "result");
if (result_json != NULL && cJSON_IsBool(result_json)) {
result = STRATUM_RESULT;
bool response_success = false;
if (result_json != NULL && cJSON_IsTrue(result_json)) {
response_success = true;
}
message->response_success = response_success;
}
}
cJSON_Delete(json);
return result;
}
message->method = result;
uint32_t parse_mining_set_difficulty_message(const char * stratum_json)
{
cJSON * json = cJSON_Parse(stratum_json);
cJSON * method = cJSON_GetObjectItem(json, "method");
if (method != NULL && cJSON_IsString(method)) {
assert(strcmp("mining.set_difficulty", method->valuestring) == 0);
}
if (message->method == MINING_NOTIFY) {
cJSON * params = cJSON_GetObjectItem(json, "params");
uint32_t difficulty = cJSON_GetArrayItem(params, 0)->valueint;
mining_notify * new_work = malloc(sizeof(mining_notify));
//new_work->difficulty = difficulty;
cJSON * params = cJSON_GetObjectItem(json, "params");
new_work->job_id = strdup(cJSON_GetArrayItem(params, 0)->valuestring);
new_work->prev_block_hash = strdup(cJSON_GetArrayItem(params, 1)->valuestring);
new_work->coinbase_1 = strdup(cJSON_GetArrayItem(params, 2)->valuestring);
new_work->coinbase_2 = strdup(cJSON_GetArrayItem(params, 3)->valuestring);
cJSON_Delete(json);
return difficulty;
}
cJSON * merkle_branch = cJSON_GetArrayItem(params, 4);
new_work->n_merkle_branches = cJSON_GetArraySize(merkle_branch);
if (new_work->n_merkle_branches > MAX_MERKLE_BRANCHES) {
printf("Too many Merkle branches.\n");
abort();
}
new_work->merkle_branches = malloc(HASH_SIZE * new_work->n_merkle_branches);
for (size_t i = 0; i < new_work->n_merkle_branches; i++) {
hex2bin(cJSON_GetArrayItem(merkle_branch, i)->valuestring, new_work->merkle_branches + HASH_SIZE * i, HASH_SIZE * 2);
}
uint32_t parse_mining_set_version_mask_message(const char * stratum_json)
{
cJSON * json = cJSON_Parse(stratum_json);
cJSON * method = cJSON_GetObjectItem(json, "method");
if (method != NULL && cJSON_IsString(method)) {
assert(strcmp("mining.set_version_mask", method->valuestring) == 0);
}
new_work->version = strtoul(cJSON_GetArrayItem(params, 5)->valuestring, NULL, 16);
new_work->target = strtoul(cJSON_GetArrayItem(params, 6)->valuestring, NULL, 16);
new_work->ntime = strtoul(cJSON_GetArrayItem(params, 7)->valuestring, NULL, 16);
cJSON * params = cJSON_GetObjectItem(json, "params");
uint32_t version_mask = strtoul(cJSON_GetArrayItem(params, 0)->valuestring, NULL, 16);
message->mining_notification = new_work;
cJSON_Delete(json);
return version_mask;
}
bool parse_stratum_result_message(const char * stratum_json, int16_t * parsed_id)
{
cJSON * json = cJSON_Parse(stratum_json);
cJSON * result_json = cJSON_GetObjectItem(json, "result");
cJSON * id_json = cJSON_GetObjectItem(json, "id");
int value = cJSON_IsTrue(cJSON_GetArrayItem(params, 8));
message->should_abandon_work = value;
if (id_json != NULL && cJSON_IsNumber(id_json)) {
*parsed_id = id_json->valueint;
} else {
*parsed_id = -1;
}
}else if (message->method == MINING_SET_DIFFICULTY) {
cJSON * params = cJSON_GetObjectItem(json, "params");
uint32_t difficulty = cJSON_GetArrayItem(params, 0)->valueint;
message->new_difficulty = difficulty;
} else if (message->method == MINING_SET_VERSION_MASK) {
cJSON * params = cJSON_GetObjectItem(json, "params");
uint32_t version_mask = strtoul(cJSON_GetArrayItem(params, 0)->valuestring, NULL, 16);
message->version_mask = version_mask;
bool result = false;
if (result_json != NULL && cJSON_IsTrue(result_json)) {
result = true;
}
cJSON_Delete(json);
return result;
}
mining_notify * parse_mining_notify_message(const char * stratum_json, uint32_t difficulty)
{
cJSON * json = cJSON_Parse(stratum_json);
cJSON * method = cJSON_GetObjectItem(json, "method");
if (method != NULL && cJSON_IsString(method)) {
assert(strcmp("mining.notify", method->valuestring) == 0);
}
mining_notify * new_work = malloc(sizeof(mining_notify));
new_work->difficulty = difficulty;
cJSON * params = cJSON_GetObjectItem(json, "params");
new_work->job_id = strdup(cJSON_GetArrayItem(params, 0)->valuestring);
new_work->prev_block_hash = strdup(cJSON_GetArrayItem(params, 1)->valuestring);
new_work->coinbase_1 = strdup(cJSON_GetArrayItem(params, 2)->valuestring);
new_work->coinbase_2 = strdup(cJSON_GetArrayItem(params, 3)->valuestring);
cJSON * merkle_branch = cJSON_GetArrayItem(params, 4);
new_work->n_merkle_branches = cJSON_GetArraySize(merkle_branch);
if (new_work->n_merkle_branches > MAX_MERKLE_BRANCHES) {
printf("Too many Merkle branches.\n");
abort();
}
new_work->merkle_branches = malloc(HASH_SIZE * new_work->n_merkle_branches);
for (size_t i = 0; i < new_work->n_merkle_branches; i++) {
hex2bin(cJSON_GetArrayItem(merkle_branch, i)->valuestring, new_work->merkle_branches + HASH_SIZE * i, HASH_SIZE * 2);
}
new_work->version = strtoul(cJSON_GetArrayItem(params, 5)->valuestring, NULL, 16);
new_work->target = strtoul(cJSON_GetArrayItem(params, 6)->valuestring, NULL, 16);
new_work->ntime = strtoul(cJSON_GetArrayItem(params, 7)->valuestring, NULL, 16);
cJSON_Delete(json);
return new_work;
}
void free_mining_notify(mining_notify * params)
void STRATUM_V1_free_mining_notify(mining_notify * params)
{
free(params->job_id);
free(params->prev_block_hash);
@ -218,7 +202,7 @@ void free_mining_notify(mining_notify * params)
free(params);
}
int parse_stratum_subscribe_result_message(const char * result_json_str,
int _parse_stratum_subscribe_result_message(const char * result_json_str,
char ** extranonce,
int * extranonce2_len)
{
@ -253,7 +237,7 @@ int parse_stratum_subscribe_result_message(const char * result_json_str,
return 0;
}
int subscribe_to_stratum(int socket, char ** extranonce, int * extranonce2_len)
int STRATUM_V1_subscribe(int socket, char ** extranonce, int * extranonce2_len)
{
// Subscribe
char subscribe_msg[BUFFER_SIZE];
@ -261,27 +245,27 @@ int subscribe_to_stratum(int socket, char ** extranonce, int * extranonce2_len)
debug_stratum_tx(subscribe_msg);
write(socket, subscribe_msg, strlen(subscribe_msg));
char * line;
line = receive_jsonrpc_line(socket);
line = STRATUM_V1_receive_jsonrpc_line(socket);
ESP_LOGI(TAG, "Received result %s", line);
parse_stratum_subscribe_result_message(line, extranonce, extranonce2_len);
_parse_stratum_subscribe_result_message(line, extranonce, extranonce2_len);
free(line);
return 1;
}
int suggest_difficulty(int socket, uint32_t difficulty)
int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty)
{
char difficulty_msg[BUFFER_SIZE];
sprintf(difficulty_msg, "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%d]}\n", send_uid++, difficulty);
sprintf(difficulty_msg, "{\"id\": %d, \"method\": \"mining.STRATUM_V1_suggest_difficulty\", \"params\": [%d]}\n", send_uid++, difficulty);
debug_stratum_tx(difficulty_msg);
write(socket, difficulty_msg, strlen(difficulty_msg));
/* TODO: fix race condition with first mining.notify message
char * line;
line = receive_jsonrpc_line(socket);
line = STRATUM_V1_receive_jsonrpc_line(socket);
ESP_LOGI(TAG, "Received result %s", line);
@ -291,7 +275,7 @@ int suggest_difficulty(int socket, uint32_t difficulty)
return 1;
}
int auth_to_stratum(int socket, const char * username)
int STRATUM_V1_authenticate(int socket, const char * username)
{
char authorize_msg[BUFFER_SIZE];
sprintf(authorize_msg, "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"x\"]}\n",
@ -303,7 +287,7 @@ int auth_to_stratum(int socket, const char * username)
return 1;
}
void submit_share(int socket, const char * username, const char * jobid,
void STRATUM_V1_submit_share(int socket, const char * username, const char * jobid,
const uint32_t ntime, const char * extranonce_2, const uint32_t nonce)
{
char submit_msg[BUFFER_SIZE];
@ -314,16 +298,8 @@ void submit_share(int socket, const char * username, const char * jobid,
}
int should_abandon_work(const char * mining_notify_json_str)
{
cJSON * root = cJSON_Parse(mining_notify_json_str);
cJSON * params = cJSON_GetObjectItem(root, "params");
int value = cJSON_IsTrue(cJSON_GetArrayItem(params, 8));
cJSON_Delete(root);
return value;
}
void configure_version_rolling(int socket)
void STRATUM_V1_configure_version_rolling(int socket)
{
// Configure
char configure_msg[BUFFER_SIZE * 2];

View File

@ -76,29 +76,29 @@ TEST_CASE("Validate bm job construction", "[mining]")
}
// Values calculated from esp-miner/components/stratum/test/verifiers/bm1397.py
TEST_CASE("Validate bm job construction 2", "[mining]")
{
const char * notify_json_str = "{\"id\":null,\"method\":\"mining.notify\","
"\"params\":[\"21554471e8\",\"8bc8707eb169ad3bda101ae60c8d48bd00aff68a00006c8b0000000000000000\",\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03d8130cfabe6d6db0ba74b36edc62c9268c945b53ebf1a7865b88bcdd40235a7a63d0f5ed5b6c400100000000000000\",\"e8714455212f736c7573682f00000000033de04728000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae8c3686251b5ced65b6a65ea3e0491ac2975cd87c02b0640d3ec3c20005167770000000000000000266a24aa21a9eddffbecb5ef0a46324a3dd902fa84509a38d2c91548768845db5d6c2de0e33f6100000000\","
"[\"8ef6b79382a1fc5152c7e69b2dd4e3795ed758d6fe7748ef4d96e3ad8ac180b8\",\"5b6e1cfecd94050b763c2c6a08d4caabd54daee665aa8e41b53b39ec76b62707\",\"f85b768f83fffbb3927f7f440cb57a5ed386f368aae88ad9b9d92e7bc1cdce15\",\"e51b9391c39019d8a2a27becc048cc770f5d33b49a29779fdc7bed04767ca962\",\"9f5d08316ead260455ec532a58935411a3eecf3c9948a52325de495d7dd7b776\",\"57e10cad23a646ad3a87fcd34eae454567dbd44946e746ee6310a86b98afa4ac\",\"f3b65cc08b25901b657efb22f0a9a23e1a61ce1e268f801d8cfe782b4a0c5e5d\",\"648e00fe2a57dca155c7d4260bc52273b28adb42e1bceb45d5ee03f4a4c5d174\",\"43ad393f7efe4b7a29775dbbc10b3b2737e9457764a7b39bc8ac6b470b968ac8\",\"4964b9b2bf601dfb2bd62067acafe556650412b1e6fe32df48c39310f7dc255d\",\"44d354ac57fcb68b408df7f5396122195384914dd2db13d5766c334fc48c2069\",\"568514a2db82a055772218f52db2f5fa157c37a9ba16c1a239819e57f0d16218\"],"
"\"20000004\",\"1705ae3a\",\"6470e2a1\",true]}";
mining_notify * params = parse_mining_notify_message(notify_json_str, 512);
char * coinbase_tx = construct_coinbase_tx(params->coinbase_1, params->coinbase_2, "336508070fca95", "0000000000000000");
char * merkle_root = calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])params->merkle_branches, params->n_merkle_branches);
bm_job job = construct_bm_job(params, merkle_root);
// TEST_CASE("Validate bm job construction 2", "[mining]")
// {
// const char * notify_json_str = "{\"id\":null,\"method\":\"mining.notify\","
// "\"params\":[\"21554471e8\",\"8bc8707eb169ad3bda101ae60c8d48bd00aff68a00006c8b0000000000000000\",\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03d8130cfabe6d6db0ba74b36edc62c9268c945b53ebf1a7865b88bcdd40235a7a63d0f5ed5b6c400100000000000000\",\"e8714455212f736c7573682f00000000033de04728000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae8c3686251b5ced65b6a65ea3e0491ac2975cd87c02b0640d3ec3c20005167770000000000000000266a24aa21a9eddffbecb5ef0a46324a3dd902fa84509a38d2c91548768845db5d6c2de0e33f6100000000\","
// "[\"8ef6b79382a1fc5152c7e69b2dd4e3795ed758d6fe7748ef4d96e3ad8ac180b8\",\"5b6e1cfecd94050b763c2c6a08d4caabd54daee665aa8e41b53b39ec76b62707\",\"f85b768f83fffbb3927f7f440cb57a5ed386f368aae88ad9b9d92e7bc1cdce15\",\"e51b9391c39019d8a2a27becc048cc770f5d33b49a29779fdc7bed04767ca962\",\"9f5d08316ead260455ec532a58935411a3eecf3c9948a52325de495d7dd7b776\",\"57e10cad23a646ad3a87fcd34eae454567dbd44946e746ee6310a86b98afa4ac\",\"f3b65cc08b25901b657efb22f0a9a23e1a61ce1e268f801d8cfe782b4a0c5e5d\",\"648e00fe2a57dca155c7d4260bc52273b28adb42e1bceb45d5ee03f4a4c5d174\",\"43ad393f7efe4b7a29775dbbc10b3b2737e9457764a7b39bc8ac6b470b968ac8\",\"4964b9b2bf601dfb2bd62067acafe556650412b1e6fe32df48c39310f7dc255d\",\"44d354ac57fcb68b408df7f5396122195384914dd2db13d5766c334fc48c2069\",\"568514a2db82a055772218f52db2f5fa157c37a9ba16c1a239819e57f0d16218\"],"
// "\"20000004\",\"1705ae3a\",\"6470e2a1\",true]}";
// mining_notify * params = parse_mining_notify_message(notify_json_str, 512);
// char * coinbase_tx = construct_coinbase_tx(params->coinbase_1, params->coinbase_2, "336508070fca95", "0000000000000000");
// char * merkle_root = calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])params->merkle_branches, params->n_merkle_branches);
// bm_job job = construct_bm_job(params, merkle_root);
uint8_t expected_midstate_bin[32];
hex2bin("5FD281AF6A1750EAEE502C04067738BD46C82FC22112FFE797CE7F035D276126", expected_midstate_bin, 32);
// bytes are reversed for the midstate on the bm job command packet
reverse_bytes(expected_midstate_bin, 32);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_midstate_bin, job.midstate, 32);
TEST_ASSERT_EQUAL_UINT32(0x1705ae3a, job.target);
TEST_ASSERT_EQUAL_UINT32(0x6470e2a1, job.ntime);
TEST_ASSERT_EQUAL_UINT8(0x8a, job.merkle_root[28]);
TEST_ASSERT_EQUAL_UINT8(0xdd, job.merkle_root[29]);
TEST_ASSERT_EQUAL_UINT8(0xa8, job.merkle_root[30]);
TEST_ASSERT_EQUAL_UINT8(0x6a, job.merkle_root[31]);
}
// uint8_t expected_midstate_bin[32];
// hex2bin("5FD281AF6A1750EAEE502C04067738BD46C82FC22112FFE797CE7F035D276126", expected_midstate_bin, 32);
// // bytes are reversed for the midstate on the bm job command packet
// reverse_bytes(expected_midstate_bin, 32);
// TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_midstate_bin, job.midstate, 32);
// TEST_ASSERT_EQUAL_UINT32(0x1705ae3a, job.target);
// TEST_ASSERT_EQUAL_UINT32(0x6470e2a1, job.ntime);
// TEST_ASSERT_EQUAL_UINT8(0x8a, job.merkle_root[28]);
// TEST_ASSERT_EQUAL_UINT8(0xdd, job.merkle_root[29]);
// TEST_ASSERT_EQUAL_UINT8(0xa8, job.merkle_root[30]);
// TEST_ASSERT_EQUAL_UINT8(0x6a, job.merkle_root[31]);
// }
TEST_CASE("Test extranonce 2 generation", "[mining extranonce2]")
{

View File

@ -1,77 +1,79 @@
#include "unity.h"
#include "stratum_api.h"
TEST_CASE("Parse stratum method", "[stratum]")
{
const char * json_string = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
"[\"1b4c3d9041\","
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
"\"20000004\",\"1705c739\",\"64495522\",false]}";
stratum_method method = parse_stratum_method(json_string);
TEST_ASSERT_EQUAL(MINING_NOTIFY, method);
// TEST_CASE("Parse stratum method", "[stratum]")
// {
// const char * json_string = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
// "[\"1b4c3d9041\","
// "\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
// "\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
// "\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
// "[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
// "\"20000004\",\"1705c739\",\"64495522\",false]}";
// stratum_method method = parse_stratum_method(json_string);
// TEST_ASSERT_EQUAL(MINING_NOTIFY, method);
const char * json_string_2 = "{\"id\":null,\"method\":\"mining.set_difficulty\",\"params\":[1638]}";
stratum_method method_2 = parse_stratum_method(json_string_2);
TEST_ASSERT_EQUAL(MINING_SET_DIFFICULTY, method_2);
}
// const char * json_string_2 = "{\"id\":null,\"method\":\"mining.set_difficulty\",\"params\":[1638]}";
// stratum_method method_2 = parse_stratum_method(json_string_2);
// TEST_ASSERT_EQUAL(MINING_SET_DIFFICULTY, method_2);
// }
TEST_CASE("Parse stratum set_difficulty params", "[mining.set_difficulty]")
{
const char * json_string = "{\"id\":null,\"method\":\"mining.set_difficulty\",\"params\":[1638]}";
uint32_t difficulty = parse_mining_set_difficulty_message(json_string);
TEST_ASSERT_EQUAL(1638, difficulty);
}
TEST_CASE("Parse stratum notify params", "[mining.notify]")
{
const char * json_string = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
"[\"1d2e0c4d3d\","
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
"\"20000004\",\"1705c739\",\"64495522\",false]}";
mining_notify * params = parse_mining_notify_message(json_string, 512);
TEST_ASSERT_EQUAL_STRING("1d2e0c4d3d", params->job_id);
TEST_ASSERT_EQUAL_STRING("ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000", params->prev_block_hash);
TEST_ASSERT_EQUAL_STRING("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000", params->coinbase_1);
TEST_ASSERT_EQUAL_STRING("41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000", params->coinbase_2);
TEST_ASSERT_EQUAL_UINT32(0x20000004, params->version);
TEST_ASSERT_EQUAL_UINT32(0x1705c739, params->target);
TEST_ASSERT_EQUAL_UINT32(0x64495522, params->ntime);
}
// TEST_CASE("Parse stratum set_difficulty params", "[mining.set_difficulty]")
// {
// const char * json_string = "{\"id\":null,\"method\":\"mining.set_difficulty\",\"params\":[1638]}";
// uint32_t difficulty = parse_mining_set_difficulty_message(json_string);
// TEST_ASSERT_EQUAL(1638, difficulty);
// }
TEST_CASE("Test mining.subcribe result parsing", "[mining.subscribe]")
{
const char * json_string = "{\"result\":["
"[[\"mining.set_difficulty\",\"731ec5e0649606ff\"],"
"[\"mining.notify\",\"731ec5e0649606ff\"]],"
"\"e9695791\",4],"
"\"id\":1,\"error\":null}";
// TEST_CASE("Parse stratum notify params", "[mining.notify]")
// {
// const char * json_string = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
// "[\"1d2e0c4d3d\","
// "\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
// "\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
// "\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
// "[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
// "\"20000004\",\"1705c739\",\"64495522\",false]}";
// mining_notify * params = parse_mining_notify_message(json_string, 512);
// TEST_ASSERT_EQUAL_STRING("1d2e0c4d3d", params->job_id);
// TEST_ASSERT_EQUAL_STRING("ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000", params->prev_block_hash);
// TEST_ASSERT_EQUAL_STRING("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000", params->coinbase_1);
// TEST_ASSERT_EQUAL_STRING("41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000", params->coinbase_2);
// TEST_ASSERT_EQUAL_UINT32(0x20000004, params->version);
// TEST_ASSERT_EQUAL_UINT32(0x1705c739, params->target);
// TEST_ASSERT_EQUAL_UINT32(0x64495522, params->ntime);
// }
char * extranonce = NULL;
int extranonce2_len = 0;
int result = parse_stratum_subscribe_result_message(json_string, &extranonce, &extranonce2_len);
TEST_ASSERT_EQUAL(result, 0);
TEST_ASSERT_EQUAL_STRING(extranonce, "e9695791");
TEST_ASSERT_EQUAL_INT(extranonce2_len, 4);
}
// 'private' function
// TEST_CASE("Test mining.subcribe result parsing", "[mining.subscribe]")
// {
// const char * json_string = "{\"result\":["
// "[[\"mining.set_difficulty\",\"731ec5e0649606ff\"],"
// "[\"mining.notify\",\"731ec5e0649606ff\"]],"
// "\"e9695791\",4],"
// "\"id\":1,\"error\":null}";
TEST_CASE("Test mining.notify abandon old work", "[mining.notify]")
{
const char * mining_notify_false = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
"[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\",false]}";
const char * mining_notify_true = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
"[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\",true]}";
const char * mining_notify_invalid = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
"[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\",3]}";
const char * mining_notify_invalid_2 = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
"[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\"]}";
TEST_ASSERT_EQUAL_INT(0, should_abandon_work(mining_notify_false));
TEST_ASSERT_EQUAL_INT(1, should_abandon_work(mining_notify_true));
TEST_ASSERT_EQUAL_INT(0, should_abandon_work(mining_notify_invalid));
TEST_ASSERT_EQUAL_INT(0, should_abandon_work(mining_notify_invalid_2));
}
// char * extranonce = NULL;
// int extranonce2_len = 0;
// int result = _parse_stratum_subscribe_result_message(json_string, &extranonce, &extranonce2_len);
// TEST_ASSERT_EQUAL(result, 0);
// TEST_ASSERT_EQUAL_STRING(extranonce, "e9695791");
// TEST_ASSERT_EQUAL_INT(extranonce2_len, 4);
// }
// TEST_CASE("Test mining.notify abandon old work", "[mining.notify]")
// {
// const char * mining_notify_false = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
// "[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\",false]}";
// const char * mining_notify_true = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
// "[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\",true]}";
// const char * mining_notify_invalid = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
// "[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\",3]}";
// const char * mining_notify_invalid_2 = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
// "[\"\",\"\",\"\",\"\",[\"\"],\"\",\"\",\"\"]}";
// TEST_ASSERT_EQUAL_INT(0, should_abandon_work(mining_notify_false));
// TEST_ASSERT_EQUAL_INT(1, should_abandon_work(mining_notify_true));
// TEST_ASSERT_EQUAL_INT(0, should_abandon_work(mining_notify_invalid));
// TEST_ASSERT_EQUAL_INT(0, should_abandon_work(mining_notify_invalid_2));
// }

View File

@ -4,6 +4,7 @@
#include "work_queue.h"
#include "bm1397.h"
#include "system.h"
#include "stratum_api.h"
@ -17,6 +18,7 @@ typedef struct {
bm1397Module BM1397_MODULE;
SystemModule SYSTEM_MODULE;
char * extranonce_str;
int extranonce_2_len;
int abandon_work;

View File

@ -114,7 +114,7 @@ void ASIC_task(void * pvParameters)
{
SYSTEM_notify_found_nonce(&GLOBAL_STATE->SYSTEM_MODULE, active_jobs[nonce.job_id]->pool_diff);
submit_share(GLOBAL_STATE->sock, STRATUM_USER, active_jobs[nonce.job_id]->jobid, active_jobs[nonce.job_id]->ntime,
STRATUM_V1_submit_share(GLOBAL_STATE->sock, STRATUM_USER, active_jobs[nonce.job_id]->jobid, active_jobs[nonce.job_id]->ntime,
active_jobs[nonce.job_id]->extranonce2, nonce.nonce);
}

View File

@ -49,7 +49,7 @@ void create_jobs_task(void * pvParameters)
ASIC_jobs_queue_clear(&GLOBAL_STATE->ASIC_jobs_queue);
}
free_mining_notify(params);
STRATUM_V1_free_mining_notify(params);
}
}

View File

@ -17,6 +17,8 @@ static const char *TAG = "stratum_task";
static ip_addr_t ip_Addr;
static bool bDNSFound = false;
static StratumApiV1Message stratum_api_v1_message = {};
void dns_found_cb(const char * name, const ip_addr_t * ipaddr, void * callback_arg)
{
@ -30,7 +32,7 @@ void stratum_task(void * pvParameters)
GlobalState *GLOBAL_STATE = (GlobalState*)pvParameters;
initialize_stratum_buffer();
STRATUM_V1_initialize_buffer();
char host_ip[20];
int addr_family = 0;
int ip_protocol = 0;
@ -72,31 +74,30 @@ void stratum_task(void * pvParameters)
break;
}
uint32_t version_mask = 0;
subscribe_to_stratum(GLOBAL_STATE->sock, &GLOBAL_STATE->extranonce_str, &GLOBAL_STATE->extranonce_2_len);
STRATUM_V1_subscribe(GLOBAL_STATE->sock, &GLOBAL_STATE->extranonce_str, &GLOBAL_STATE->extranonce_2_len);
configure_version_rolling(GLOBAL_STATE->sock);
STRATUM_V1_configure_version_rolling(GLOBAL_STATE->sock);
auth_to_stratum(GLOBAL_STATE->sock, STRATUM_USER);
STRATUM_V1_authenticate(GLOBAL_STATE->sock, STRATUM_USER);
ESP_LOGI(TAG, "Extranonce: %s", GLOBAL_STATE->extranonce_str);
ESP_LOGI(TAG, "Extranonce 2 length: %d", GLOBAL_STATE->extranonce_2_len);
suggest_difficulty(GLOBAL_STATE->sock, STRATUM_DIFFICULTY);
STRATUM_V1_suggest_difficulty(GLOBAL_STATE->sock, STRATUM_DIFFICULTY);
while (1)
{
char * line = receive_jsonrpc_line( GLOBAL_STATE->sock);
char * line = STRATUM_V1_receive_jsonrpc_line( GLOBAL_STATE->sock);
ESP_LOGI(TAG, "rx: %s", line); //debug incoming stratum messages
STRATUM_V1_parse(&stratum_api_v1_message, line);
free(line);
stratum_method method = parse_stratum_method(line);
if (method == MINING_NOTIFY) {
if (should_abandon_work(line) && GLOBAL_STATE->stratum_queue.count > 0) {
ESP_LOGI(TAG, "pool diff changed, clearing queues");
if (stratum_api_v1_message.method == MINING_NOTIFY) {
//ESP_LOGI(TAG, "Mining Notify");
if (stratum_api_v1_message.should_abandon_work) { // I think this has concurrency issues? // && GLOBAL_STATE->stratum_queue.count > 0) {
ESP_LOGI(TAG, "abandoning work");
GLOBAL_STATE->abandon_work = 1;
queue_clear(&GLOBAL_STATE->stratum_queue);
@ -110,36 +111,35 @@ void stratum_task(void * pvParameters)
}
if ( GLOBAL_STATE->stratum_queue.count == QUEUE_SIZE) {
mining_notify * next_notify_json_str = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue);
free_mining_notify(next_notify_json_str);
STRATUM_V1_free_mining_notify(next_notify_json_str);
}
mining_notify * params = parse_mining_notify_message(line, GLOBAL_STATE->stratum_difficulty);
queue_enqueue(&GLOBAL_STATE->stratum_queue, params);
} else if (method == MINING_SET_DIFFICULTY) {
uint32_t new_difficulty = parse_mining_set_difficulty_message(line);
if (new_difficulty != GLOBAL_STATE->stratum_difficulty) {
GLOBAL_STATE->stratum_difficulty = new_difficulty;
stratum_api_v1_message.mining_notification->difficulty = GLOBAL_STATE->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 != GLOBAL_STATE->stratum_difficulty) {
GLOBAL_STATE->stratum_difficulty = stratum_api_v1_message.new_difficulty;
ESP_LOGI(TAG, "Set stratum difficulty: %d", GLOBAL_STATE->stratum_difficulty);
BM1397_set_job_difficulty_mask(GLOBAL_STATE->stratum_difficulty);
}
} else if (method == MINING_SET_VERSION_MASK) {
version_mask = parse_mining_set_version_mask_message(line);
} else if (stratum_api_v1_message.method == MINING_SET_VERSION_MASK) {
//1fffe000
ESP_LOGI(TAG, "Set version mask: %08x", version_mask);
ESP_LOGI(TAG, "Set version mask: %08x", stratum_api_v1_message.version_mask);
} else if (method == STRATUM_RESULT) {
int16_t parsed_id;
if (parse_stratum_result_message(line, &parsed_id)) {
ESP_LOGI(TAG, "message id %d result accepted", parsed_id);
} 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->SYSTEM_MODULE);
} else {
ESP_LOGI(TAG, "message id %d result rejected", parsed_id);
ESP_LOGI(TAG, "message result rejected");
SYSTEM_notify_rejected_share(&GLOBAL_STATE->SYSTEM_MODULE);
}
}
free(line);
}

View File

@ -49,7 +49,7 @@ void queue_clear(work_queue * queue)
while (queue->count > 0)
{
mining_notify * next_work = queue->buffer[queue->head];
free_mining_notify(next_work);
STRATUM_V1_free_mining_notify(next_work);
queue->head = (queue->head + 1) % QUEUE_SIZE;
queue->count--;
}