From 8c124a4a853272e83b47c21316663f2df4b5faac Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Mon, 30 Mar 2026 01:20:50 +0200 Subject: [PATCH] perf(miner): optimize sha256d nonce loop with precomputed blocks --- miner.c | 68 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/miner.c b/miner.c index bd13932..5adca91 100644 --- a/miner.c +++ b/miner.c @@ -8,6 +8,8 @@ #include "utils.h" +static const double RATE_INTERVAL_SEC = 5.0; + static int hash_meets_target(const uint8_t digest[32], const uint8_t target_be[32]) { int i; @@ -24,6 +26,21 @@ static int hash_meets_target(const uint8_t digest[32], const uint8_t target_be[3 return 1; } +static void write_u32_be(uint8_t *dst, uint32_t v) { + dst[0] = (uint8_t)((v >> 24) & 0xFF); + dst[1] = (uint8_t)((v >> 16) & 0xFF); + dst[2] = (uint8_t)((v >> 8) & 0xFF); + dst[3] = (uint8_t)(v & 0xFF); +} + +static void sha256_ctx_to_digest(const SHA256_CTX *ctx, uint8_t out[32]) { + int i; + + for (i = 0; i < 8; i++) { + write_u32_be(out + i * 4, ctx->h[i]); + } +} + static int compute_hash_batch( const uint8_t header_76[76], uint32_t start_nonce, @@ -32,30 +49,47 @@ static int compute_hash_batch( uint32_t *found_nonce, uint8_t found_digest[32] ) { - SHA256_CTX base; - uint8_t tail[16]; + SHA256_CTX init_ctx; + SHA256_CTX first_chunk_ctx; + uint8_t block1[64]; + uint8_t block2[64]; + uint8_t digest1[32]; + uint8_t digest2[32]; uint32_t i; - SHA256_Init(&base); - SHA256_Update(&base, header_76, 64); + SHA256_Init(&init_ctx); + first_chunk_ctx = init_ctx; + SHA256_Transform(&first_chunk_ctx, header_76); - memcpy(tail, header_76 + 64, 12); + memset(block1, 0, sizeof(block1)); + memcpy(block1, header_76 + 64, 12); + block1[16] = 0x80; + block1[62] = 0x02; + block1[63] = 0x80; + + memset(block2, 0, sizeof(block2)); + block2[32] = 0x80; + block2[62] = 0x01; + block2[63] = 0x00; for (i = 0; i < batch_size; i++) { - SHA256_CTX ctx; - uint8_t digest1[32]; - uint8_t digest2[32]; + SHA256_CTX ctx1; + SHA256_CTX ctx2; uint32_t n = start_nonce + i; - tail[12] = (uint8_t)(n & 0xFF); - tail[13] = (uint8_t)((n >> 8) & 0xFF); - tail[14] = (uint8_t)((n >> 16) & 0xFF); - tail[15] = (uint8_t)((n >> 24) & 0xFF); + block1[12] = (uint8_t)(n & 0xFF); + block1[13] = (uint8_t)((n >> 8) & 0xFF); + block1[14] = (uint8_t)((n >> 16) & 0xFF); + block1[15] = (uint8_t)((n >> 24) & 0xFF); - ctx = base; - SHA256_Update(&ctx, tail, 16); - SHA256_Final(digest1, &ctx); - SHA256(digest1, 32, digest2); + ctx1 = first_chunk_ctx; + SHA256_Transform(&ctx1, block1); + sha256_ctx_to_digest(&ctx1, digest1); + + memcpy(block2, digest1, 32); + ctx2 = init_ctx; + SHA256_Transform(&ctx2, block2); + sha256_ctx_to_digest(&ctx2, digest2); if (hash_meets_target(digest2, target_be)) { *found_nonce = n; @@ -149,7 +183,7 @@ int mine_block( nonce += batch_size; now = (double)time(NULL); - if ((now - last_rate_t) >= 2.0) { + if ((now - last_rate_t) >= RATE_INTERVAL_SEC) { double dt = now - last_rate_t; if (dt <= 0.0) { dt = 1e-6;