From 27b24d3c3ef3e672eb83643a049ab0f6a86cfcc1 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Tue, 16 May 2023 18:42:47 -0400 Subject: [PATCH] bm1397: integrate with stratum WIP --- components/stratum/include/mining.h | 4 +- components/stratum/include/stratum_api.h | 3 + components/stratum/include/utils.h | 2 + components/stratum/mining.c | 12 ++-- components/stratum/stratum_api.c | 10 +++ components/stratum/utils.c | 8 +++ main/bm1397.c | 2 +- main/bm1397.h | 2 +- main/miner.c | 88 +++++++++++++++++++----- main/serial.c | 17 +++-- main/serial.h | 3 + main/work_queue.c | 8 +-- main/work_queue.h | 11 ++- 13 files changed, 127 insertions(+), 43 deletions(-) diff --git a/components/stratum/include/mining.h b/components/stratum/include/mining.h index cb4b10b8..c2425692 100644 --- a/components/stratum/include/mining.h +++ b/components/stratum/include/mining.h @@ -9,10 +9,12 @@ typedef struct { uint32_t ntime; uint32_t merkle_root_end; uint8_t midstate[32]; + char * jobid; + char * extranonce2; } bm_job; char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2, - const char * extranonce, int extranonce_2_len); + const char * extranonce, const char * extranonce_2); char * calculate_merkle_root_hash(const char * coinbase_tx, const uint8_t merkle_branches[][32], const int num_merkle_branches); diff --git a/components/stratum/include/stratum_api.h b/components/stratum/include/stratum_api.h index 60a02ef6..0e0ea72a 100644 --- a/components/stratum/include/stratum_api.h +++ b/components/stratum/include/stratum_api.h @@ -45,6 +45,9 @@ int parse_stratum_subscribe_result_message(const char * result_json_str, int auth_to_stratum(int socket, const char * username); +void 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 \ No newline at end of file diff --git a/components/stratum/include/utils.h b/components/stratum/include/utils.h index fd547da8..31a76580 100644 --- a/components/stratum/include/utils.h +++ b/components/stratum/include/utils.h @@ -23,4 +23,6 @@ void single_sha256_bin(const uint8_t * data, const size_t data_len, uint8_t * de void swap_endian_words(const char * hex, uint8_t * output); +void reverse_bytes(uint8_t * data, size_t len); + #endif // STRATUM_UTILS_H \ No newline at end of file diff --git a/components/stratum/mining.c b/components/stratum/mining.c index 7e8dedc5..38025441 100644 --- a/components/stratum/mining.c +++ b/components/stratum/mining.c @@ -3,14 +3,10 @@ #include "utils.h" char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2, - const char * extranonce, int extranonce_2_len) + const char * extranonce, const char * extranonce_2) { int coinbase_tx_len = strlen(coinbase_1) + strlen(coinbase_2) - + strlen(extranonce) + extranonce_2_len * 2 + 1; - - char extranonce_2[extranonce_2_len * 2 + 1]; - memset(extranonce_2, '9', extranonce_2_len * 2); - extranonce_2[extranonce_2_len * 2] = '\0'; + + strlen(extranonce) + strlen(extranonce_2) + 1; char * coinbase_tx = malloc(coinbase_tx_len); strcpy(coinbase_tx, coinbase_1); @@ -59,10 +55,10 @@ bm_job construct_bm_job(uint32_t version, const char * prev_block_hash, const ch uint8_t midstate_data[64]; memcpy(midstate_data, &version, 4); - swap_endian_words(prev_block_hash, midstate_data + 4); + //swap_endian_words(prev_block_hash, midstate_data + 4); memcpy(midstate_data + 36, merkle_root_bin, 28); single_sha256_bin(midstate_data, 64, new_job.midstate); - + //reverse_bytes(new_job.midstate, 32); memcpy(&new_job.merkle_root_end, merkle_root_bin + 28, 4); return new_job; diff --git a/components/stratum/stratum_api.c b/components/stratum/stratum_api.c index 34239f95..456a8fc7 100644 --- a/components/stratum/stratum_api.c +++ b/components/stratum/stratum_api.c @@ -231,6 +231,16 @@ int auth_to_stratum(int socket, const char * username) return 1; } +void 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]; + sprintf(submit_msg, "{\"id\": %d, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%08x\", \"%08x\"]}\n", + send_uid++, username, jobid, extranonce_2, ntime, nonce); + ESP_LOGI(TAG, "Submit: %s", submit_msg); + write(socket, submit_msg, strlen(submit_msg)); +} + int should_abandon_work(const char * mining_notify_json_str) { cJSON * root = cJSON_Parse(mining_notify_json_str); diff --git a/components/stratum/utils.c b/components/stratum/utils.c index 52926ca4..107ccb00 100644 --- a/components/stratum/utils.c +++ b/components/stratum/utils.c @@ -145,3 +145,11 @@ void swap_endian_words(const char * hex_words, uint8_t * output) { } } } + +void reverse_bytes(uint8_t * data, size_t len) { + for (int i = 0; i < len / 2; ++i) { + uint8_t temp = data[i]; + data[i] = data[len - 1 - i]; + data[len - 1 - i] = temp; + } +} diff --git a/main/bm1397.c b/main/bm1397.c index 482c1973..35581882 100644 --- a/main/bm1397.c +++ b/main/bm1397.c @@ -48,7 +48,7 @@ void parse_job_response(unsigned char *buf, int len) { nonce = (struct nonce_response *)buf; printf("nonce: %08X @ %02X\n", flip32(nonce->nonce), nonce->job_id); - + return; } void parse_cmd_packet(unsigned char *buf, int len) { diff --git a/main/bm1397.h b/main/bm1397.h index e9271c96..a5a68180 100644 --- a/main/bm1397.h +++ b/main/bm1397.h @@ -40,7 +40,7 @@ struct __attribute__((__packed__)) job_packet { uint8_t nbits[4]; uint8_t ntime[4]; uint8_t merkle4[4]; - uint8_t midstates[4][32]; + uint8_t midstate[32]; }; struct __attribute__((__packed__)) nonce_response { diff --git a/main/miner.c b/main/miner.c index f226b8e8..5d47c282 100755 --- a/main/miner.c +++ b/main/miner.c @@ -20,6 +20,7 @@ #include "system.h" #include "serial.h" +#include "bm1397.h" #if defined(CONFIG_EXAMPLE_IPV4) #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR @@ -40,24 +41,80 @@ TaskHandle_t sysTaskHandle = NULL; TaskHandle_t serialTaskHandle = NULL; static work_queue g_queue; +static work_queue g_bm_queue; static char * extranonce_str = NULL; static int extranonce_2_len = 0; -static void mining_task(void *pvParameters) +static int sock; + +static void AsicTask(void * pvParameters) +{ + init_serial(); + + init_BM1397(); + + //reset the bm1397 + reset_BM1397(); + + //send the init command + send_read_address(); + + //read back response + debug_serial_rx(); + + //send the init commands + send_init(); + + int termination_flag = 0; + uint8_t buf[CHUNK_SIZE]; + memset(buf, 0, 1024); + + while (1) { + int id = 1; + bm_job * next_bm_job = (bm_job *) queue_dequeue(&g_bm_queue, &termination_flag); + struct job_packet job; + job.job_id = id++; + job.num_midstates = 1; + memcpy(&job.starting_nonce, &next_bm_job->starting_nonce, 4); + memcpy(&job.nbits, &next_bm_job->target, 4); + memcpy(&job.ntime, &next_bm_job->ntime, 4); + memcpy(&job.merkle4, &next_bm_job->merkle_root_end, 4); + memcpy(&job.midstate, &next_bm_job->midstate, 32); + + send_work(&job); + uint16_t received = serial_rx(buf); + if (received > 0) { + ESP_LOGI(TAG, "Received %d bytes from bm1397", received); + struct nonce_response nonce; + memcpy((void *) &nonce, buf, sizeof(struct nonce_response)); + //reverse_bytes((uint8_t *) &nonce.nonce, 4); + print_hex((uint8_t *) &nonce.nonce, 4, 4, "nonce: "); + memset(buf, 0, 1024); + submit_share(sock, STRATUM_USERNAME, next_bm_job->jobid, + next_bm_job->ntime, next_bm_job->extranonce2, nonce.nonce); + } + } +} + +static void mining_task(void * pvParameters) { int termination_flag = 0; - while(true) { - char * next_notify_json_str = queue_dequeue(&g_queue, &termination_flag); + while (1) { + char * next_notify_json_str = (char *) queue_dequeue(&g_queue, &termination_flag); ESP_LOGI(TAG, "New Work Dequeued"); ESP_LOGI(TAG, "Notify json: %s", next_notify_json_str); uint32_t free_heap_size = esp_get_free_heap_size(); - ESP_LOGI(TAG, "miner heap free size: %lu bytes", free_heap_size); + ESP_LOGI(TAG, "miner heap free size: %u bytes", free_heap_size); mining_notify params = parse_mining_notify_message(next_notify_json_str); + char extranonce_2[extranonce_2_len * 2 + 1]; + memset(extranonce_2, '9', extranonce_2_len * 2); + extranonce_2[extranonce_2_len * 2] = '\0'; + char * coinbase_tx = construct_coinbase_tx(params.coinbase_1, params.coinbase_2, - extranonce_str, extranonce_2_len); + extranonce_str, extranonce_2); ESP_LOGI(TAG, "Coinbase tx: %s", coinbase_tx); char * merkle_root = calculate_merkle_root_hash(coinbase_tx, @@ -67,25 +124,23 @@ static void mining_task(void *pvParameters) bm_job next_job = construct_bm_job(params.version, params.prev_block_hash, merkle_root, params.ntime, params.target); - + ESP_LOGI(TAG, "bm_job: "); print_hex((uint8_t *) &next_job.target, 4, 4, "target: "); print_hex((uint8_t *) &next_job.ntime, 4, 4, "ntime: "); print_hex((uint8_t *) &next_job.merkle_root_end, 4, 4, "merkle root end: "); print_hex(next_job.midstate, 32, 32, "midstate: "); + bm_job * queued_next_job = malloc(sizeof(bm_job)); + memcpy(queued_next_job, &next_job, sizeof(bm_job)); + queued_next_job->extranonce2 = strdup(extranonce_2); + queued_next_job->jobid = strdup(params.job_id); + queue_enqueue(&g_bm_queue, queued_next_job); + free_mining_notify(params); free(coinbase_tx); free(merkle_root); free(next_notify_json_str); - - // TODO: Process BM Job / Loop until nonce range consumed or we need - // to grab the latest notify - - // TODO: When nonce found, submit shares - // snprintf(submit_msg, BUFFER_SIZE, - // "{\"id\": 4, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%08x\"]}\n", - // user, job_id, ntime, extranonce2, nonce); } } @@ -117,7 +172,7 @@ static void admin_task(void *pvParameters) struct sockaddr_storage dest_addr = {0}; ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, &ip_protocol, &addr_family, &dest_addr)); #endif - int sock = socket(addr_family, SOCK_STREAM, ip_protocol); + sock = socket(addr_family, SOCK_STREAM, ip_protocol); if (sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); @@ -179,10 +234,11 @@ void app_main(void) ESP_ERROR_CHECK(example_connect()); xTaskCreate(SysTask, "System_Task", 4096, NULL, 10, &sysTaskHandle); - xTaskCreate(SerialTask, "serial_test", 4096, NULL, 10, &serialTaskHandle); queue_init(&g_queue); + queue_init(&g_bm_queue); xTaskCreate(admin_task, "stratum admin", 8192, NULL, 5, NULL); xTaskCreate(mining_task, "stratum miner", 8192, NULL, 5, NULL); + xTaskCreate(AsicTask, "asic", 4096, NULL, 10, &serialTaskHandle); } diff --git a/main/serial.c b/main/serial.c index 645ccb91..615141ac 100644 --- a/main/serial.c +++ b/main/serial.c @@ -49,10 +49,16 @@ int send_serial(uint8_t *data, int len) { } /// @brief waits for a serial response from the device -/// @param buf bufffer to read data into +/// @param buf buffer to read data into /// @return number of bytes read, or -1 on error int16_t serial_rx(uint8_t * buf) { - return uart_read_bytes(UART_NUM_1, buf, BUF_SIZE, 20 / portTICK_RATE_MS); + int16_t bytes_read = uart_read_bytes(UART_NUM_1, buf, BUF_SIZE, 20 / portTICK_RATE_MS); + if (bytes_read > 0) { + printf("bm rx\n"); + prettyHex((unsigned char*) buf, bytes_read); + printf("\n"); + } + return bytes_read; } void debug_serial_rx(void) { @@ -72,7 +78,6 @@ void debug_serial_rx(void) { memset(buf, 0, 1024); } - void SerialTask(void *arg) { @@ -94,9 +99,9 @@ void SerialTask(void *arg) { //setup a nice test job //this should find nonce 258a8b34 @ 50 - uint8_t work1[146] = {0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xE0, 0x05, 0x17, 0x24, 0x27, 0x36, 0x64, 0xF5, 0x63, 0x54, 0xDA, 0x33, 0xE2, 0xDE, 0x8F, 0xFC, 0xDD, 0x48, 0x96, 0xE1, 0x36, 0xD7, 0x03, 0x5C, 0xBB, 0x5F, 0xA3, 0xFD, 0x5F, 0x68, 0x39, 0xAA, 0xA4, 0xBE, 0x10, 0x9C, 0x7E, 0x00, 0x78, 0x4E, 0x69, 0x34, 0xAC, 0x84, 0x05, 0x65, 0xAE, 0x32, 0x58, 0x09, 0xBB, 0xEA, 0x44, 0x6D, 0x61, 0x57, 0xF2, 0x61, 0xBE, 0x58, 0x33, 0xFA, 0xA8, 0x1D, 0x9A, 0x16, 0xBF, 0xE0, 0x82, 0x64, 0x37, 0x91, 0x15, 0xB6, 0x32, 0x93, 0xC4, 0x83, 0x42, 0xB2, 0xE6, 0x63, 0x96, 0xE0, 0x25, 0x02, 0x9E, 0x01, 0x76, 0xD9, 0x24, 0x0F, 0xD3, 0x57, 0x27, 0x38, 0xE2, 0x65, 0xDD, 0xCD, 0xBD, 0x01, 0xE0, 0x61, 0xFB, 0x57, 0x5D, 0xD6, 0xAB, 0xAE, 0xFD, 0x6B, 0x5F, 0x77, 0x74, 0x5C, 0x64, 0x2C, 0xF3, 0x34, 0x2F, 0x82, 0xB3, 0xCC, 0xC1, 0x2D, 0x84, 0xDD, 0xCB, 0x10, 0xDE, 0x5E, 0xE0, 0xCD, 0x9C, 0x5B, 0x65, 0x92, 0xBB}; - struct job_packet test_job; - memcpy((uint8_t *)&test_job, work1, 146); + //uint8_t work1[146] = {0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xE0, 0x05, 0x17, 0x24, 0x27, 0x36, 0x64, 0xF5, 0x63, 0x54, 0xDA, 0x33, 0xE2, 0xDE, 0x8F, 0xFC, 0xDD, 0x48, 0x96, 0xE1, 0x36, 0xD7, 0x03, 0x5C, 0xBB, 0x5F, 0xA3, 0xFD, 0x5F, 0x68, 0x39, 0xAA, 0xA4, 0xBE, 0x10, 0x9C, 0x7E, 0x00, 0x78, 0x4E, 0x69, 0x34, 0xAC, 0x84, 0x05, 0x65, 0xAE, 0x32, 0x58, 0x09, 0xBB, 0xEA, 0x44, 0x6D, 0x61, 0x57, 0xF2, 0x61, 0xBE, 0x58, 0x33, 0xFA, 0xA8, 0x1D, 0x9A, 0x16, 0xBF, 0xE0, 0x82, 0x64, 0x37, 0x91, 0x15, 0xB6, 0x32, 0x93, 0xC4, 0x83, 0x42, 0xB2, 0xE6, 0x63, 0x96, 0xE0, 0x25, 0x02, 0x9E, 0x01, 0x76, 0xD9, 0x24, 0x0F, 0xD3, 0x57, 0x27, 0x38, 0xE2, 0x65, 0xDD, 0xCD, 0xBD, 0x01, 0xE0, 0x61, 0xFB, 0x57, 0x5D, 0xD6, 0xAB, 0xAE, 0xFD, 0x6B, 0x5F, 0x77, 0x74, 0x5C, 0x64, 0x2C, 0xF3, 0x34, 0x2F, 0x82, 0xB3, 0xCC, 0xC1, 0x2D, 0x84, 0xDD, 0xCB, 0x10, 0xDE, 0x5E, 0xE0, 0xCD, 0x9C, 0x5B, 0x65, 0x92, 0xBB}; + //struct job_packet test_job; + //memcpy((uint8_t *)&test_job, work1, 146); send_work(&test_job); diff --git a/main/serial.h b/main/serial.h index 234144e5..fbf5eaea 100644 --- a/main/serial.h +++ b/main/serial.h @@ -5,5 +5,8 @@ void SerialTask(void *arg); int send_serial(uint8_t *, int); +void init_serial(void); +void debug_serial_rx(void); +int16_t serial_rx(uint8_t * buf); #endif /* SERIAL_H_ */ \ No newline at end of file diff --git a/main/work_queue.c b/main/work_queue.c index dd28b764..25017f4f 100644 --- a/main/work_queue.c +++ b/main/work_queue.c @@ -9,7 +9,7 @@ void queue_init(work_queue * queue) { pthread_cond_init(&queue->not_full, NULL); } -void queue_enqueue(work_queue * queue, char * new_work) { +void queue_enqueue(work_queue * queue, void * new_work) { pthread_mutex_lock(&queue->lock); while (queue->count == QUEUE_SIZE) { @@ -24,7 +24,7 @@ void queue_enqueue(work_queue * queue, char * new_work) { pthread_mutex_unlock(&queue->lock); } -char * queue_dequeue(work_queue * queue, int *termination_flag) { +void * queue_dequeue(work_queue * queue, int *termination_flag) { pthread_mutex_lock(&queue->lock); while (queue->count == 0) { @@ -35,7 +35,7 @@ char * queue_dequeue(work_queue * queue, int *termination_flag) { pthread_cond_wait(&queue->not_empty, &queue->lock); } - char * next_work = queue->buffer[queue->head]; + void * next_work = queue->buffer[queue->head]; queue->head = (queue->head + 1) % QUEUE_SIZE; queue->count--; @@ -51,7 +51,7 @@ void queue_clear(work_queue * queue) while (queue->count > 0) { - char * next_work = queue->buffer[queue->head]; + void * next_work = queue->buffer[queue->head]; free(next_work); queue->head = (queue->head + 1) % QUEUE_SIZE; queue->count--; diff --git a/main/work_queue.h b/main/work_queue.h index a9f8b873..3afcef93 100644 --- a/main/work_queue.h +++ b/main/work_queue.h @@ -2,12 +2,11 @@ #define WORK_QUEUE_H #include -#include "stratum_api.h" #define QUEUE_SIZE 3 typedef struct { - char * buffer[QUEUE_SIZE]; + void * buffer[QUEUE_SIZE]; int head; int tail; int count; @@ -16,9 +15,9 @@ typedef struct { pthread_cond_t not_full; } work_queue; -void queue_init(work_queue *queue); -void queue_enqueue(work_queue *queue, char * new_work); -char * queue_dequeue(work_queue *queue, int *termination_flag); -void queue_clear(work_queue *queue); +void queue_init(work_queue * queue); +void queue_enqueue(work_queue * queue, void * new_work); +void * queue_dequeue(work_queue * queue, int * termination_flag); +void queue_clear(work_queue * queue); #endif // WORK_QUEUE_H \ No newline at end of file