diff --git a/components/stratum/CMakeLists.txt b/components/stratum/CMakeLists.txt index f9581ed9..79497696 100644 --- a/components/stratum/CMakeLists.txt +++ b/components/stratum/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "mining.c" "stratum_api.c" +idf_component_register(SRCS "utils.c" "mining.c" "stratum_api.c" INCLUDE_DIRS "include" - REQUIRES json) \ No newline at end of file + REQUIRES json mbedtls) \ No newline at end of file diff --git a/components/stratum/include/mining.h b/components/stratum/include/mining.h index 95ec610c..cc29abb4 100644 --- a/components/stratum/include/mining.h +++ b/components/stratum/include/mining.h @@ -1,4 +1,11 @@ +#ifndef MINING_H +#define MINING_H + #include "stratum_api.h" char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2, const char * extranonce, int extranonce_2_len); + +char * calculate_merkle_hash(const char * coinbase_tx, const uint8_t ** merkle_branches); + +#endif // MINING_H \ No newline at end of file diff --git a/components/stratum/include/utils.h b/components/stratum/include/utils.h new file mode 100644 index 00000000..a37a2d61 --- /dev/null +++ b/components/stratum/include/utils.h @@ -0,0 +1,19 @@ +#ifndef STRATUM_UTILS_H +#define STRATUM_UTILS_H + +#include +#include + +int hex2char(uint8_t x, char *c); + +size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen); + +uint8_t hex2val(char c); + +size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len); + +char * double_sha256(const char * hex_string); + +uint8_t * double_sha256_bin(const uint8_t * data, const size_t data_len); + +#endif // STRATUM_UTILS_H \ No newline at end of file diff --git a/components/stratum/mining.c b/components/stratum/mining.c index d1d01202..b3839037 100644 --- a/components/stratum/mining.c +++ b/components/stratum/mining.c @@ -1,4 +1,5 @@ #include +#include "mining.h" char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2, const char * extranonce, int extranonce_2_len) @@ -18,3 +19,8 @@ char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2, return coinbase_tx; } + +char * calculate_merkle_hash(const char * coinbase_tx, const uint8_t ** merkle_branches) +{ + return NULL; +} \ No newline at end of file diff --git a/components/stratum/stratum_api.c b/components/stratum/stratum_api.c index 4dc66f5b..9f20c692 100644 --- a/components/stratum/stratum_api.c +++ b/components/stratum/stratum_api.c @@ -4,6 +4,7 @@ #include #include "esp_log.h" #include "lwip/sockets.h" +#include "utils.h" #define BUFFER_SIZE 1024 @@ -95,37 +96,6 @@ char * receive_jsonrpc_line(int sockfd) return line; } -static uint8_t hex2val(char c) -{ - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } else { - return 0; - } -} - -static size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len) -{ - size_t len = 0; - - while (*hex && len < bin_len) { - bin[len] = hex2val(*hex++) << 4; - - if (!*hex) { - len++; - break; - } - - bin[len++] |= hex2val(*hex++); - } - - return len; -} - work parse_notify_work(cJSON * params) { work new_work; new_work.job_id = (uint32_t) strtoul(cJSON_GetArrayItem(params, 0)->valuestring, NULL, 16); diff --git a/components/stratum/test/test_utils.c b/components/stratum/test/test_utils.c new file mode 100644 index 00000000..326df86d --- /dev/null +++ b/components/stratum/test/test_utils.c @@ -0,0 +1,47 @@ +#include "unity.h" +#include "utils.h" +#include + +TEST_CASE("Test double sha", "[utils]") +{ + const char * input = "68656c6c6f"; + char * output = double_sha256(input); + TEST_ASSERT_EQUAL_STRING("9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50", output); +} + +TEST_CASE("Test hex2bin", "[utils]") +{ + char * hex_string = "48454c4c4f"; + size_t bin_len = strlen(hex_string) / 2; + uint8_t * bin = malloc(bin_len); + hex2bin(hex_string, bin, bin_len); + TEST_ASSERT_EQUAL(72, bin[0]); + TEST_ASSERT_EQUAL(69, bin[1]); + TEST_ASSERT_EQUAL(76, bin[2]); + TEST_ASSERT_EQUAL(76, bin[3]); + TEST_ASSERT_EQUAL(79, bin[4]); +} + +TEST_CASE("Test bin2hex", "[utils]") +{ + uint8_t bin[5] = {72, 69, 76, 76, 79}; + char hex_string[11]; + bin2hex(bin, 5, hex_string, 11); + TEST_ASSERT_EQUAL_STRING("48454c4c4f", hex_string); +} + + +TEST_CASE("Test hex2char", "[utils]") +{ + char output; + int result = hex2char(1, &output); + TEST_ASSERT_EQUAL(0, result); + TEST_ASSERT_EQUAL('1', output); + + result = hex2char(15, &output); + TEST_ASSERT_EQUAL(0, result); + TEST_ASSERT_EQUAL('f', output); + + result = hex2char(16, &output); + TEST_ASSERT_EQUAL(-1, result); +} diff --git a/components/stratum/utils.c b/components/stratum/utils.c new file mode 100644 index 00000000..1e298cb5 --- /dev/null +++ b/components/stratum/utils.c @@ -0,0 +1,123 @@ +#include "utils.h" + +#include +#include + +#include "mbedtls/sha256.h" + + +int hex2char(uint8_t x, char *c) +{ + if (x <= 9) { + *c = x + '0'; + } else if (x <= 15) { + *c = x - 10 + 'a'; + } else { + return -1; + } + + return 0; +} + +size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) +{ + if ((hexlen + 1) < buflen * 2) { + return 0; + } + + for (size_t i = 0; i < buflen; i++) { + if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) { + return 0; + } + if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) { + return 0; + } + } + + hex[2 * buflen] = '\0'; + return 2 * buflen; +} + +uint8_t hex2val(char c) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } else { + return 0; + } +} + +size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len) +{ + size_t len = 0; + + while (*hex && len < bin_len) { + bin[len] = hex2val(*hex++) << 4; + + if (!*hex) { + len++; + break; + } + + bin[len++] |= hex2val(*hex++); + } + + return len; +} + +static void print_hex( const uint8_t *b, size_t len, + const size_t in_line, const char *prefix ) +{ + size_t i = 0; + const uint8_t *end = b + len; + + if( prefix == NULL ) + { + prefix = ""; + } + + while( b < end ) + { + if( ++i > in_line ) + { + printf( "\n%s", prefix ); + i = 1; + } + printf( "%02X ", (uint8_t) *b++ ); + } + printf("\n"); + 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; +} + +uint8_t * double_sha256_bin(const uint8_t * data, const size_t data_len) +{ + uint8_t first_hash_output[32]; + uint8_t * second_hash_output = malloc(32); + + mbedtls_sha256(data, data_len, first_hash_output, 0); + mbedtls_sha256(first_hash_output, 32, second_hash_output, 0); + + return second_hash_output; +} \ No newline at end of file