perf(miner): optimize sha256d nonce loop with precomputed blocks

This commit is contained in:
2026-03-30 01:20:50 +02:00
parent 41bfecd0d8
commit 8c124a4a85

68
miner.c
View File

@@ -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;