diff --git a/components/asic/bm1366.c b/components/asic/bm1366.c index eacd821c4..be36dec00 100644 --- a/components/asic/bm1366.c +++ b/components/asic/bm1366.c @@ -289,8 +289,8 @@ void BM1366_send_work(void * pvParameters, bm_job * next_bm_job) 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.merkle_root, next_bm_job->merkle_root_be, 32); - memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32); + memcpy(job.merkle_root, next_bm_job->merkle_root, 32); + memcpy(job.prev_block_hash, next_bm_job->prev_block_hash, 32); memcpy(&job.version, &next_bm_job->version, 4); if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) { diff --git a/components/asic/bm1368.c b/components/asic/bm1368.c index dba3b1187..18694656e 100644 --- a/components/asic/bm1368.c +++ b/components/asic/bm1368.c @@ -233,8 +233,8 @@ void BM1368_send_work(void * pvParameters, bm_job * next_bm_job) 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.merkle_root, next_bm_job->merkle_root_be, 32); - memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32); + memcpy(job.merkle_root, next_bm_job->merkle_root, 32); + memcpy(job.prev_block_hash, next_bm_job->prev_block_hash, 32); memcpy(&job.version, &next_bm_job->version, 4); if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) { diff --git a/components/asic/bm1370.c b/components/asic/bm1370.c index 38aa2e731..1ff6f838b 100644 --- a/components/asic/bm1370.c +++ b/components/asic/bm1370.c @@ -309,8 +309,8 @@ void BM1370_send_work(void * pvParameters, bm_job * next_bm_job) 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.merkle_root, next_bm_job->merkle_root_be, 32); - memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32); + memcpy(job.merkle_root, next_bm_job->merkle_root, 32); + memcpy(job.prev_block_hash, next_bm_job->prev_block_hash, 32); memcpy(&job.version, &next_bm_job->version, 4); if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) { diff --git a/components/asic/bm1397.c b/components/asic/bm1397.c index d02519504..487494d7a 100644 --- a/components/asic/bm1397.c +++ b/components/asic/bm1397.c @@ -332,7 +332,7 @@ void BM1397_send_work(void *pvParameters, bm_job *next_bm_job) 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 + 28, 4); + memcpy(&job.merkle4, next_bm_job->merkle_root, 4); memcpy(job.midstate, next_bm_job->midstate, 32); if (job.num_midstates == 4) diff --git a/components/stratum/include/mining.h b/components/stratum/include/mining.h index dc4f76538..4e8f75524 100644 --- a/components/stratum/include/mining.h +++ b/components/stratum/include/mining.h @@ -8,9 +8,7 @@ typedef struct uint32_t version; uint32_t version_mask; uint8_t prev_block_hash[32]; - uint8_t prev_block_hash_be[32]; uint8_t merkle_root[32]; - uint8_t merkle_root_be[32]; uint32_t ntime; uint32_t target; // aka difficulty, aka nbits uint32_t starting_nonce; @@ -27,12 +25,12 @@ typedef struct void free_bm_job(bm_job *job); -char *construct_coinbase_tx(const char *coinbase_1, const char *coinbase_2, - const char *extranonce, const char *extranonce_2); +void calculate_coinbase_tx_hash(const char *coinbase_1, const char *coinbase_2, + const char *extranonce, const char *extranonce_2, uint8_t dest[32]); -void calculate_merkle_root_hash(const char *coinbase_tx, const uint8_t merkle_branches[][32], const int num_merkle_branches, char dest[65]); +void calculate_merkle_root_hash(const uint8_t coinbase_tx_hash[32], const uint8_t merkle_branches[][32], const int num_merkle_branches, uint8_t dest[32]); -bm_job construct_bm_job(mining_notify *params, const char *merkle_root, const uint32_t version_mask, uint32_t difficulty); +void construct_bm_job(mining_notify *params, const uint8_t merkle_root[32], const uint32_t version_mask, const uint32_t difficulty, bm_job* new_job); double test_nonce_value(const bm_job *job, const uint32_t nonce, const uint32_t rolled_version); diff --git a/components/stratum/include/utils.h b/components/stratum/include/utils.h index e3a12fb86..4fd9502af 100644 --- a/components/stratum/include/utils.h +++ b/components/stratum/include/utils.h @@ -6,31 +6,23 @@ size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen); -void flip80bytes(void *dest_p, const void *src_p); -void flip32bytes(void *dest_p, const void *src_p); - size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len); void print_hex(const uint8_t *b, size_t len, const size_t in_line, const char *prefix); -char *double_sha256(const char *hex_string); - void double_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t dest[32]); -void single_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t dest[32]); void midstate_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t dest[32]); -void swap_endian_words(const char *hex, uint8_t *output); +void reverse_32bit_words(const uint8_t src[32], uint8_t dest[32]); -void reverse_bytes(uint8_t *data, size_t len); +void reverse_endianness_per_word(uint8_t data[32]); double le256todouble(const void *target); void prettyHex(unsigned char *buf, int len); -uint32_t flip32(uint32_t val); - double networkDifficulty(uint32_t nBits); void suffixString(uint64_t val, char * buf, size_t bufsiz, int sigdigits); diff --git a/components/stratum/mining.c b/components/stratum/mining.c index 82a50a8c6..2c80cfae8 100644 --- a/components/stratum/mining.c +++ b/components/stratum/mining.c @@ -13,94 +13,87 @@ void free_bm_job(bm_job *job) free(job); } -char *construct_coinbase_tx(const char *coinbase_1, const char *coinbase_2, - const char *extranonce, const char *extranonce_2) +void calculate_coinbase_tx_hash(const char *coinbase_1, const char *coinbase_2, const char *extranonce, const char *extranonce_2, uint8_t dest[32]) { - int coinbase_tx_len = strlen(coinbase_1) + strlen(coinbase_2) + strlen(extranonce) + strlen(extranonce_2) + 1; + size_t len1 = strlen(coinbase_1); + size_t len2 = strlen(extranonce); + size_t len3 = strlen(extranonce_2); + size_t len4 = strlen(coinbase_2); - char *coinbase_tx = malloc(coinbase_tx_len); - strcpy(coinbase_tx, coinbase_1); - strcat(coinbase_tx, extranonce); - strcat(coinbase_tx, extranonce_2); - strcat(coinbase_tx, coinbase_2); - coinbase_tx[coinbase_tx_len - 1] = '\0'; + size_t coinbase_tx_bin_len = (len1 + len2 + len3 + len4) / 2; - return coinbase_tx; + uint8_t coinbase_tx_bin[coinbase_tx_bin_len]; + + size_t bin_offset = 0; + bin_offset += hex2bin(coinbase_1, coinbase_tx_bin + bin_offset, coinbase_tx_bin_len - bin_offset); + bin_offset += hex2bin(extranonce, coinbase_tx_bin + bin_offset, coinbase_tx_bin_len - bin_offset); + bin_offset += hex2bin(extranonce_2, coinbase_tx_bin + bin_offset, coinbase_tx_bin_len - bin_offset); + bin_offset += hex2bin(coinbase_2, coinbase_tx_bin + bin_offset, coinbase_tx_bin_len - bin_offset); + + double_sha256_bin(coinbase_tx_bin, coinbase_tx_bin_len, dest); } -void calculate_merkle_root_hash(const char *coinbase_tx, const uint8_t merkle_branches[][32], const int num_merkle_branches, char dest[65]) +void calculate_merkle_root_hash(const uint8_t coinbase_tx_hash[32], const uint8_t merkle_branches[][32], const int num_merkle_branches, uint8_t dest[32]) { - size_t coinbase_tx_bin_len = strlen(coinbase_tx) / 2; - uint8_t coinbase_tx_bin[coinbase_tx_bin_len]; - hex2bin(coinbase_tx, coinbase_tx_bin, coinbase_tx_bin_len); - uint8_t both_merkles[64]; - double_sha256_bin(coinbase_tx_bin, coinbase_tx_bin_len, both_merkles); + memcpy(both_merkles, coinbase_tx_hash, 32); for (int i = 0; i < num_merkle_branches; i++) { memcpy(both_merkles + 32, merkle_branches[i], 32); double_sha256_bin(both_merkles, 64, both_merkles); } - bin2hex(both_merkles, 32, dest, 65); + memcpy(dest, both_merkles, 32); } // take a mining_notify struct with ascii hex strings and convert it to a bm_job struct -bm_job construct_bm_job(mining_notify *params, const char *merkle_root, const uint32_t version_mask, const uint32_t difficulty) +void construct_bm_job(mining_notify *params, const uint8_t merkle_root[32], const uint32_t version_mask, const uint32_t difficulty, bm_job *new_job) { - bm_job new_job; - - new_job.version = params->version; - new_job.target = params->target; - new_job.ntime = params->ntime; - new_job.starting_nonce = 0; - new_job.pool_diff = difficulty; - - hex2bin(merkle_root, new_job.merkle_root, 32); - - // hex2bin(merkle_root, new_job.merkle_root_be, 32); - swap_endian_words(merkle_root, new_job.merkle_root_be); - reverse_bytes(new_job.merkle_root_be, 32); - - swap_endian_words(params->prev_block_hash, new_job.prev_block_hash); - - hex2bin(params->prev_block_hash, new_job.prev_block_hash_be, 32); - reverse_bytes(new_job.prev_block_hash_be, 32); - - ////make the midstate hash + new_job->version = params->version; + new_job->target = params->target; + new_job->ntime = params->ntime; + new_job->starting_nonce = 0; + new_job->pool_diff = difficulty; + reverse_32bit_words(merkle_root, new_job->merkle_root); + + uint8_t prev_block_hash[32]; + hex2bin(params->prev_block_hash, prev_block_hash, 32); + reverse_endianness_per_word(prev_block_hash); + reverse_32bit_words(prev_block_hash, new_job->prev_block_hash); + + // make the midstate hash uint8_t midstate_data[64]; // copy 68 bytes header data into midstate (and deal with endianess) - memcpy(midstate_data, &new_job.version, 4); // copy version - memcpy(midstate_data + 4, new_job.prev_block_hash, 32); // copy prev_block_hash - memcpy(midstate_data + 36, new_job.merkle_root, 28); // copy merkle_root + memcpy(midstate_data, &new_job->version, 4); // copy version + memcpy(midstate_data + 4, prev_block_hash, 32); // copy prev_block_hash + memcpy(midstate_data + 36, merkle_root, 28); // copy merkle_root - midstate_sha256_bin(midstate_data, 64, new_job.midstate); // make the midstate hash - reverse_bytes(new_job.midstate, 32); // reverse the midstate bytes for the BM job packet + uint8_t midstate[32]; + midstate_sha256_bin(midstate_data, 64, midstate); // make the midstate hash + reverse_32bit_words(midstate, new_job->midstate); // reverse the midstate words for the BM job packet if (version_mask != 0) { - uint32_t rolled_version = increment_bitmask(new_job.version, version_mask); + uint32_t rolled_version = increment_bitmask(new_job->version, version_mask); memcpy(midstate_data, &rolled_version, 4); - midstate_sha256_bin(midstate_data, 64, new_job.midstate1); - reverse_bytes(new_job.midstate1, 32); + midstate_sha256_bin(midstate_data, 64, midstate); + reverse_32bit_words(midstate, new_job->midstate1); rolled_version = increment_bitmask(rolled_version, version_mask); memcpy(midstate_data, &rolled_version, 4); - midstate_sha256_bin(midstate_data, 64, new_job.midstate2); - reverse_bytes(new_job.midstate2, 32); + midstate_sha256_bin(midstate_data, 64, midstate); + reverse_32bit_words(midstate, new_job->midstate2); rolled_version = increment_bitmask(rolled_version, version_mask); memcpy(midstate_data, &rolled_version, 4); - midstate_sha256_bin(midstate_data, 64, new_job.midstate3); - reverse_bytes(new_job.midstate3, 32); - new_job.num_midstates = 4; + midstate_sha256_bin(midstate_data, 64, midstate); + reverse_32bit_words(midstate, new_job->midstate3); + new_job->num_midstates = 4; } else { - new_job.num_midstates = 1; + new_job->num_midstates = 1; } - - return new_job; } void extranonce_2_generate(uint64_t extranonce_2, uint32_t length, char dest[static length * 2 + 1]) @@ -126,8 +119,7 @@ static const double truediffone = 2695953529101130949315647634472399133601089873 /* testing a nonce and return the diff - 0 means invalid */ double test_nonce_value(const bm_job *job, const uint32_t nonce, const uint32_t rolled_version) { - double d64, s64, ds; - unsigned char header[80]; + uint8_t header[80]; // // TODO: use the midstate hash instead of hashing the whole header // uint32_t rolled_version = job->version; @@ -137,24 +129,18 @@ double test_nonce_value(const bm_job *job, const uint32_t nonce, const uint32_t // copy data from job to header memcpy(header, &rolled_version, 4); - memcpy(header + 4, job->prev_block_hash, 32); - memcpy(header + 36, job->merkle_root, 32); + reverse_32bit_words(job->prev_block_hash, header + 4); + reverse_32bit_words(job->merkle_root, header + 36); memcpy(header + 68, &job->ntime, 4); memcpy(header + 72, &job->target, 4); memcpy(header + 76, &nonce, 4); - unsigned char hash_buffer[32]; - unsigned char hash_result[32]; - - // double hash the header - mbedtls_sha256(header, 80, hash_buffer, 0); - mbedtls_sha256(hash_buffer, 32, hash_result, 0); - - d64 = truediffone; - s64 = le256todouble(hash_result); - ds = d64 / s64; + uint8_t hash_result[32]; + double_sha256_bin(header, 80, hash_result); - return ds; + double d64 = truediffone; + double s64 = le256todouble(hash_result); + return d64 / s64; } uint32_t increment_bitmask(const uint32_t value, const uint32_t mask) diff --git a/components/stratum/test/test_mining.c b/components/stratum/test/test_mining.c index 89799df3f..dbe06f698 100644 --- a/components/stratum/test/test_mining.c +++ b/components/stratum/test/test_mining.c @@ -3,22 +3,38 @@ #include "utils.h" #include +#include TEST_CASE("Check coinbase tx construction", "[mining]") { const char *coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008"; const char *coinbase_2 = "072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000"; const char *extranonce = "e9695791"; - const char *extranonce_2 = "99999999"; - char *coinbase_tx = construct_coinbase_tx(coinbase_1, coinbase_2, extranonce, extranonce_2); - TEST_ASSERT_EQUAL_STRING(coinbase_tx, "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008e969579199999999072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000"); - free(coinbase_tx); + const char *extranonce_2 = "99999999"; + uint8_t coinbase_tx_hash[32]; + calculate_coinbase_tx_hash(coinbase_1, coinbase_2, extranonce, extranonce_2, coinbase_tx_hash); + + char expected_coinbase_tx[] = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008e969579199999999072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000"; + size_t expected_coinbase_tx_len = strlen(expected_coinbase_tx) / 2; + uint8_t expected_coinbase_tx_bin[expected_coinbase_tx_len]; + hex2bin(expected_coinbase_tx, expected_coinbase_tx_bin, expected_coinbase_tx_len); + + uint8_t expected_coinbase_tx_hash[32]; + double_sha256_bin(expected_coinbase_tx_bin, expected_coinbase_tx_len, expected_coinbase_tx_hash); + + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_coinbase_tx_hash, coinbase_tx_hash, 32); } // Values calculated from esp-miner/components/stratum/test/verifiers/merklecalc.py TEST_CASE("Validate merkle root calculation", "[mining]") { - const char *coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008e969579199999999072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000"; + const char *coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008e969579199999999072f736c7573682f0000000001"; + const char *coinbase_2 = "1976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000"; + const char *extranonce = "00f2052a"; + const char *extranonce_2 = "01000000"; + uint8_t coinbase_tx_hash[32]; + calculate_coinbase_tx_hash(coinbase_1, coinbase_2, extranonce, extranonce_2, coinbase_tx_hash); + uint8_t merkles[12][32]; int num_merkles = 12; @@ -35,14 +51,22 @@ TEST_CASE("Validate merkle root calculation", "[mining]") hex2bin("463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758", merkles[10], 32); hex2bin("03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76", merkles[11], 32); + uint8_t root_hash_bin[32]; + calculate_merkle_root_hash(coinbase_tx_hash, merkles, num_merkles, root_hash_bin); char root_hash[65]; - calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles, root_hash); + bin2hex(root_hash_bin, 32, root_hash, 65); TEST_ASSERT_EQUAL_STRING("adbcbc21e20388422198a55957aedfa0e61be0b8f2b87d7c08510bb9f099a893", root_hash); } TEST_CASE("Validate another merkle root calculation", "[mining]") { - const char *coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2503777d07062f503253482f0405b8c75208f800880e000000000b2f436f696e48756e74722f0000000001603f352a010000001976a914c633315d376c20a973a758f7422d67f7bfed9c5888ac00000000"; + const char *coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2503777d07062f503253482f0405b8c75208f800880e000000000b2f436f696e48756e74722f0000000001"; + const char *coinbase_2 = "1976a914c633315d376c20a973a758f7422d67f7bfed9c5888ac00000000"; + const char *extranonce = "603f352a"; + const char *extranonce_2 = "01000000"; + uint8_t coinbase_tx_hash[32]; + calculate_coinbase_tx_hash(coinbase_1, coinbase_2, extranonce, extranonce_2, coinbase_tx_hash); + uint8_t merkles[5][32]; int num_merkles = 5; @@ -52,8 +76,10 @@ TEST_CASE("Validate another merkle root calculation", "[mining]") hex2bin("9f64f3b0d9edddb14be6f71c3ac2e80455916e207ffc003316c6a515452aa7b4", merkles[3], 32); hex2bin("2d0b54af60fad4ae59ec02031f661d026f2bb95e2eeb1e6657a35036c017c595", merkles[4], 32); + uint8_t root_hash_bin[32]; + calculate_merkle_root_hash(coinbase_tx_hash, merkles, num_merkles, root_hash_bin); char root_hash[65]; - calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles, root_hash); + bin2hex(root_hash_bin, 32, root_hash, 65); TEST_ASSERT_EQUAL_STRING("5cc58f5e84aafc740d521b92a7bf72f4e56c4cc3ad1c2159f1d094f97ac34eee", root_hash); } @@ -65,14 +91,18 @@ TEST_CASE("Validate bm job construction", "[mining]") notify_message.version = 0x20000004; notify_message.target = 0x1705dd01; notify_message.ntime = 0x64658bd8; - const char *merkle_root = "cd1be82132ef0d12053dcece1fa0247fcfdb61d4dbd3eb32ea9ef9b4c604a846"; - bm_job job = construct_bm_job(¬ify_message, merkle_root, 0, 1000); + uint8_t merkle_root[32]; + hex2bin("cd1be82132ef0d12053dcece1fa0247fcfdb61d4dbd3eb32ea9ef9b4c604a846", merkle_root, 32); + bm_job job = { 0 }; + construct_bm_job(¬ify_message, merkle_root, 0, 1000, &job); uint8_t expected_midstate_bin[32]; hex2bin("91DFEA528A9F73683D0D495DD6DD7415E1CA21CB411759E3E05D7D5FF285314D", 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); + uint8_t expected_midstate_bin_reversed[32]; + reverse_32bit_words(expected_midstate_bin, expected_midstate_bin_reversed); + reverse_endianness_per_word(expected_midstate_bin_reversed); + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_midstate_bin_reversed, job.midstate, 32); } TEST_CASE("Validate version mask incrementing", "[mining]") @@ -101,12 +131,13 @@ TEST_CASE("Validate version mask incrementing", "[mining]") // char * coinbase_tx = construct_coinbase_tx(params->coinbase_1, params->coinbase_2, "336508070fca95", "0000000000000000"); // char merkle_root[65] // calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])params->merkle_branches, params->n_merkle_branches, merkle_root); -// bm_job job = construct_bm_job(params, merkle_root, 1000); +// bm_job job = { 0 }; +// construct_bm_job(params, merkle_root, 1000, &job); // 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); +// reverse_32bit_words(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); @@ -146,8 +177,10 @@ TEST_CASE("Test nonce diff checking", "[mining test_nonce][not-on-qemu]") notify_message.version = 0x20000004; notify_message.target = 0x1705ae3a; notify_message.ntime = 0x646ff1a9; - const char *merkle_root = "6d0359c451434605c52a5a9ce074340be47c2c63840731f9edf1db3f26b1cdd9a9f16f64"; - bm_job job = construct_bm_job(¬ify_message, merkle_root, 0, 1000); + uint8_t merkle_root[32]; + hex2bin("6d0359c451434605c52a5a9ce074340be47c2c63840731f9edf1db3f26b1cdd9a9f16f64", merkle_root, 32); + bm_job job = { 0 }; + construct_bm_job(¬ify_message, merkle_root, 0, 1000, &job); uint32_t nonce = 0x276E8947; double diff = test_nonce_value(&job, nonce, 0); @@ -162,7 +195,13 @@ TEST_CASE("Test nonce diff checking 2", "[mining test_nonce][not-on-qemu]") notify_message.target = 0x1705ae3a; notify_message.ntime = 0x647025b5; - const char *coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b0389130cfabe6d6d5cbab26a2599e92916edec5657a94a0708ddb970f5c45b5d12905085617eff8e010000000000000031650707758de07b010000000000001cfd7038212f736c7573682f000000000379ad0c2a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae725d3994b811572c1f345deb98b56b465ef8e153ecbbd27fa37bf1b005161380000000000000000266a24aa21a9ed63b06a7946b190a3fda1d76165b25c9b883bcc6621b040773050ee2a1bb18f1800000000"; + uint8_t coinbase_tx_hash[32]; + calculate_coinbase_tx_hash( + "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b0389130cfabe6d6d5cbab26a2599e92916edec5657a94a0708ddb970f5c45b5d12905085617eff8e", + "31650707758de07b010000000000001cfd7038212f736c7573682f000000000379ad0c2a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae725d3994b811572c1f345deb98b56b465ef8e153ecbbd27fa37bf1b005161380000000000000000266a24aa21a9ed63b06a7946b190a3fda1d76165b25c9b883bcc6621b040773050ee2a1bb18f1800000000", + "01000000", + "00000000", + coinbase_tx_hash); uint8_t merkles[13][32]; int num_merkles = 13; @@ -180,11 +219,14 @@ TEST_CASE("Test nonce diff checking 2", "[mining test_nonce][not-on-qemu]") hex2bin("c4f5ab01913fc186d550c1a28f3f3e9ffaca2016b961a6a751f8cca0089df924", merkles[11], 32); hex2bin("cff737e1d00176dd6bbfa73071adbb370f227cfb5fba186562e4060fcec877e1", merkles[12], 32); + uint8_t merkle_root_hash[32]; + calculate_merkle_root_hash(coinbase_tx_hash, merkles, num_merkles, merkle_root_hash); char merkle_root[65]; - calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles, merkle_root); + bin2hex(merkle_root_hash, 32, merkle_root, 65); TEST_ASSERT_EQUAL_STRING("5bdc1968499c3393873edf8e07a1c3a50a97fc3a9d1a376bbf77087dd63778eb", merkle_root); - bm_job job = construct_bm_job(¬ify_message, merkle_root, 0, 1000); + bm_job job = { 0 }; + construct_bm_job(¬ify_message, merkle_root_hash, 0, 1000, &job); uint32_t nonce = 0x0a029ed1; double diff = test_nonce_value(&job, nonce, 0); diff --git a/components/stratum/test/test_utils.c b/components/stratum/test/test_utils.c index d71b828c3..2bf148ceb 100644 --- a/components/stratum/test/test_utils.c +++ b/components/stratum/test/test_utils.c @@ -2,10 +2,13 @@ #include "utils.h" #include -TEST_CASE("Test double sha", "[utils]") +TEST_CASE("Test double_sha256_bin", "[utils]") { - const char *input = "68656c6c6f"; - char *output = double_sha256(input); + const char input[] = "hello"; + uint8_t hash[32]; + double_sha256_bin((uint8_t *)input, 5, hash); + char output[65]; + bin2hex(hash, 32, output, 65); TEST_ASSERT_EQUAL_STRING("9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50", output); } @@ -29,3 +32,51 @@ TEST_CASE("Test bin2hex", "[utils]") bin2hex(bin, 5, hex_string, 11); TEST_ASSERT_EQUAL_STRING("48454c4c4f", hex_string); } + +TEST_CASE("reverse_32bit_words", "[utils]") +{ + uint8_t input[32]; + for (int i = 0; i < 32; i++) input[i] = i; + + uint8_t actual[32]; + reverse_32bit_words(input, actual); + + uint8_t expected[32] = {28, 29, 30, 31, + 24, 25, 26, 27, + 20, 21, 22, 23, + 16, 17, 18, 19, + 12, 13, 14, 15, + 8, 9, 10, 11, + 4, 5, 6, 7, + 0, 1, 2, 3}; + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, 32); +} + +TEST_CASE("reverse_endianness_per_word", "[utils]") +{ + uint8_t data[32]; + for (int i = 0; i < 32; i++) data[i] = i; + + reverse_endianness_per_word(data); + + uint8_t expected[32] = { 3, 2, 1, 0, + 7, 6, 5, 4, + 11, 10, 9, 8, + 15, 14, 13, 12, + 19, 18, 17, 16, + 23, 22, 21, 20, + 27, 26, 25, 24, + 31, 30, 29, 28}; + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, data, 32); +} + +TEST_CASE("networkDifficulty", "[utils]") +{ + uint32_t nBits = 0x1701cdfb; + + double actual = networkDifficulty(nBits); + + double expected = 155973032196071.9; + + TEST_ASSERT_EQUAL_DOUBLE(expected, actual); +} diff --git a/components/stratum/utils.c b/components/stratum/utils.c index a11c0a32c..ee2dfb98a 100644 --- a/components/stratum/utils.c +++ b/components/stratum/utils.c @@ -17,60 +17,6 @@ static const uint8_t hex_val_table[256] = { ['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15 }; -#ifndef bswap_16 -#define bswap_16(a) ((((uint16_t)(a) << 8) & 0xff00) | (((uint16_t)(a) >> 8) & 0xff)) -#endif - -#ifndef bswap_32 -#define bswap_32(a) ((((uint32_t)(a) << 24) & 0xff000000) | \ - (((uint32_t)(a) << 8) & 0xff0000) | \ - (((uint32_t)(a) >> 8) & 0xff00) | \ - (((uint32_t)(a) >> 24) & 0xff)) -#endif - -/* - * General byte order swapping functions. - */ -#define bswap16(x) __bswap16(x) -#define bswap32(x) __bswap32(x) -#define bswap64(x) __bswap64(x) - -uint32_t swab32(uint32_t v) -{ - return bswap_32(v); -} - -// takes 80 bytes and flips every 4 bytes -void flip80bytes(void *dest_p, const void *src_p) -{ - uint32_t *dest = dest_p; - const uint32_t *src = src_p; - int i; - - for (i = 0; i < 20; i++) - dest[i] = swab32(src[i]); -} - -void flip64bytes(void *dest_p, const void *src_p) -{ - uint32_t *dest = dest_p; - const uint32_t *src = src_p; - int i; - - for (i = 0; i < 16; i++) - dest[i] = swab32(src[i]); -} - -void flip32bytes(void *dest_p, const void *src_p) -{ - uint32_t *dest = dest_p; - const uint32_t *src = src_p; - int i; - - for (i = 0; i < 8; i++) - dest[i] = swab32(src[i]); -} - size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) { if (hexlen < buflen * 2) { @@ -126,24 +72,6 @@ void print_hex(const uint8_t *b, size_t len, fflush(stdout); } -char *double_sha256(const char *hex_string) -{ - size_t bin_len = strlen(hex_string) / 2; - uint8_t *bin = malloc(bin_len); - hex2bin(hex_string, bin, bin_len); - - unsigned char first_hash_output[32], second_hash_output[32]; - - mbedtls_sha256(bin, bin_len, first_hash_output, 0); - mbedtls_sha256(first_hash_output, 32, second_hash_output, 0); - - free(bin); - - char *output_hash = malloc(64 + 1); - bin2hex(second_hash_output, 32, output_hash, 65); - return output_hash; -} - void double_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t dest[32]) { uint8_t first_hash_output[32]; @@ -152,24 +80,6 @@ void double_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t dest[ mbedtls_sha256(first_hash_output, 32, dest, 0); } -void single_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t dest[32]) -{ - // mbedtls_sha256(data, data_len, dest, 0); - - // Initialize SHA256 context - mbedtls_sha256_context sha256_ctx; - mbedtls_sha256_init(&sha256_ctx); - mbedtls_sha256_starts(&sha256_ctx, 0); - - // Compute first SHA256 hash of header - mbedtls_sha256_update(&sha256_ctx, data, 64); - unsigned char hash[32]; - mbedtls_sha256_finish(&sha256_ctx, hash); - - // Compute midstate from hash - memcpy(dest, hash, 32); -} - void midstate_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t dest[32]) { mbedtls_sha256_context midstate; @@ -179,40 +89,36 @@ void midstate_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t des mbedtls_sha256_starts(&midstate, 0); mbedtls_sha256_update(&midstate, data, 64); - // memcpy(dest, midstate.state, 32); - flip32bytes(dest, midstate.state); + memcpy(dest, midstate.state, 32); } -void swap_endian_words(const char *hex_words, uint8_t *output) +void reverse_32bit_words(const uint8_t src[32], uint8_t dest[32]) { - size_t hex_length = strlen(hex_words); - if (hex_length % 8 != 0) - { - fprintf(stderr, "Must be 4-byte word aligned\n"); - exit(EXIT_FAILURE); - } - - size_t binary_length = hex_length / 2; - - for (size_t i = 0; i < binary_length; i += 4) - { - for (int j = 0; j < 4; j++) - { - unsigned int byte_val; - sscanf(hex_words + (i + j) * 2, "%2x", &byte_val); - output[i + (3 - j)] = byte_val; - } - } + const uint32_t *s = (const uint32_t *)src; + uint32_t *d = (uint32_t *)dest; + + d[0] = s[7]; + d[1] = s[6]; + d[2] = s[5]; + d[3] = s[4]; + d[4] = s[3]; + d[5] = s[2]; + d[6] = s[1]; + d[7] = s[0]; } -void reverse_bytes(uint8_t *data, size_t len) +void reverse_endianness_per_word(uint8_t data[32]) { - for (int i = 0; i < len / 2; ++i) - { - uint8_t temp = data[i]; - data[i] = data[len - 1 - i]; - data[len - 1 - i] = temp; - } + uint32_t *d = (uint32_t *)data; + + d[0] = __builtin_bswap32(d[0]); + d[1] = __builtin_bswap32(d[1]); + d[2] = __builtin_bswap32(d[2]); + d[3] = __builtin_bswap32(d[3]); + d[4] = __builtin_bswap32(d[4]); + d[5] = __builtin_bswap32(d[5]); + d[6] = __builtin_bswap32(d[6]); + d[7] = __builtin_bswap32(d[7]); } // static const double truediffone = 26959535291011309493156476344723991336010898738574164086137773096960.0; @@ -252,16 +158,6 @@ void prettyHex(unsigned char *buf, int len) printf("%02X]", buf[len - 1]); } -uint32_t flip32(uint32_t val) -{ - uint32_t ret = 0; - ret |= (val & 0xFF) << 24; - ret |= (val & 0xFF00) << 8; - ret |= (val & 0xFF0000) >> 8; - ret |= (val & 0xFF000000) >> 24; - return ret; -} - /* Calculate the network difficulty from nBits */ double networkDifficulty(uint32_t nBits) { diff --git a/main/self_test/self_test.c b/main/self_test/self_test.c index 1fd20f880..2ba5124e8 100644 --- a/main/self_test/self_test.c +++ b/main/self_test/self_test.c @@ -361,15 +361,20 @@ bool self_test(void * pvParameters) notify_message.target = 0x1705ae3a; notify_message.ntime = 0x647025b5; - const char * coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b0389130cfab" - "e6d6d5cbab26a2599e92916edec" - "5657a94a0708ddb970f5c45b5d12905085617eff8e010000000000000031650707758de07b010000000000001cfd703" - "8212f736c7573682f0000000003" - "79ad0c2a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c29525" - "34b424c4f434b3ae725d3994b81" - "1572c1f345deb98b56b465ef8e153ecbbd27fa37bf1b005161380000000000000000266a24aa21a9ed63b06a7946b19" - "0a3fda1d76165b25c9b883bcc66" - "21b040773050ee2a1bb18f1800000000"; + char extranonce_2_str[17]; + extranonce_2_generate(1, 8, extranonce_2_str); + + uint8_t coinbase_tx_hash[32]; + calculate_coinbase_tx_hash("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b0389130cfab" + "e6d6d5cbab26a2599e92916edec5657a94a0708ddb970f5c45b5d", + "31650707758de07b010000000000001cfd7038212f736c7573682f000000000379ad0c2a000000001976a9147c154ed" + "1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae725d3994b811572" + "c1f345deb98b56b465ef8e153ecbbd27fa37bf1b005161380000000000000000266a24aa21a9ed63b06a7946b190a3f" + "da1d76165b25c9b883bcc6621b040773050ee2a1bb18f1800000000", + "12905085617eff8e", + extranonce_2_str, + coinbase_tx_hash); + uint8_t merkles[13][32]; int num_merkles = 13; @@ -387,11 +392,11 @@ bool self_test(void * pvParameters) hex2bin("c4f5ab01913fc186d550c1a28f3f3e9ffaca2016b961a6a751f8cca0089df924", merkles[11], 32); hex2bin("cff737e1d00176dd6bbfa73071adbb370f227cfb5fba186562e4060fcec877e1", merkles[12], 32); - char merkle_root[65]; - - calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles, merkle_root); + uint8_t merkle_root[32]; + calculate_merkle_root_hash(coinbase_tx_hash, merkles, num_merkles, merkle_root); - bm_job job = construct_bm_job(¬ify_message, merkle_root, 0x1fffe000, 1000000); + bm_job job = {0}; + construct_bm_job(¬ify_message, merkle_root, 0x1fffe000, 1000000, &job); ESP_LOGI(TAG, "Sending work"); diff --git a/main/tasks/create_jobs_task.c b/main/tasks/create_jobs_task.c index 65d3857e5..299925ff0 100644 --- a/main/tasks/create_jobs_task.c +++ b/main/tasks/create_jobs_task.c @@ -87,30 +87,24 @@ static void generate_work(GlobalState *GLOBAL_STATE, mining_notify *notification //print generated extranonce_2 //ESP_LOGI(TAG, "Generated extranonce_2: %s", extranonce_2_str); - char *coinbase_tx = construct_coinbase_tx(notification->coinbase_1, notification->coinbase_2, GLOBAL_STATE->extranonce_str, extranonce_2_str); - if (coinbase_tx == NULL) { - ESP_LOGE(TAG, "Failed to construct coinbase_tx"); - return; - } + uint8_t coinbase_tx_hash[32]; + calculate_coinbase_tx_hash(notification->coinbase_1, notification->coinbase_2, GLOBAL_STATE->extranonce_str, extranonce_2_str, coinbase_tx_hash); - char merkle_root[65]; - calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])notification->merkle_branches, notification->n_merkle_branches, merkle_root); - - bm_job next_job = construct_bm_job(notification, merkle_root, GLOBAL_STATE->version_mask, difficulty); + uint8_t merkle_root[32]; + calculate_merkle_root_hash(coinbase_tx_hash, (uint8_t(*)[32])notification->merkle_branches, notification->n_merkle_branches, merkle_root); bm_job *queued_next_job = malloc(sizeof(bm_job)); + if (queued_next_job == NULL) { - ESP_LOGE(TAG, "Failed to allocate memory for queued_next_job"); - free(coinbase_tx); + ESP_LOGE(TAG, "Failed to allocate memory for new job"); return; } - memcpy(queued_next_job, &next_job, sizeof(bm_job)); + construct_bm_job(notification, merkle_root, GLOBAL_STATE->version_mask, difficulty, queued_next_job); + queued_next_job->extranonce2 = strdup(extranonce_2_str); queued_next_job->jobid = strdup(notification->job_id); queued_next_job->version_mask = GLOBAL_STATE->version_mask; queue_enqueue(&GLOBAL_STATE->ASIC_jobs_queue, queued_next_job); - - free(coinbase_tx); -} \ No newline at end of file +}