mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-03-26 17:51:45 +01:00
bm1397: integrate with stratum WIP
This commit is contained in:
parent
1468a47359
commit
27b24d3c3e
@ -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);
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
88
main/miner.c
88
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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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_ */
|
@ -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--;
|
||||
|
@ -2,12 +2,11 @@
|
||||
#define WORK_QUEUE_H
|
||||
|
||||
#include <pthread.h>
|
||||
#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
|
Loading…
x
Reference in New Issue
Block a user