import random import struct import time import hashlib import logging from binascii import hexlify, unhexlify from threading import Event from typing import Callable import config log = logging.getLogger(__name__) # Seconds between hashrate logs _RATE_INT = 2 def _compute_hash_batch( header_76: bytes, start_nonce: int, batch_size: int, target_be: bytes, ): """ Compute hashes for a nonce batch and return the first valid nonce found. Optimizations: - Precompute first chunk (64 bytes) with sha256.copy() to avoid re-updating the invariant portion on each nonce. - Preallocate a 16-byte tail and update only the nonce field with struct.pack_into to minimize allocations. - Local function binding to reduce lookups in the hot loop. """ first_chunk = header_76[:64] tail_static = header_76[64:] # 12 bytes: merkle[28:32] + ts(4) + bits(4) sha_base = hashlib.sha256() sha_base.update(first_chunk) tail = bytearray(16) tail[0:12] = tail_static sha_copy = sha_base.copy sha256 = hashlib.sha256 pack_into = struct.pack_into for i in range(batch_size): n = (start_nonce + i) & 0xFFFFFFFF pack_into("= ts_interval: ts_bytes = struct.pack("= _RATE_INT: hashrate = (attempts - last_rate_n) / (now - last_rate_t) last_rate_t = now last_rate_n = attempts log.info( "Mining status - hashrate=%.2f kH/s attempts=%d nonce=%d", hashrate / 1000, attempts, nonce, ) if status_callback: status_callback(attempts, hashrate)