def mine( difficulty: int, header_hash: bytes, start_nonce: int = 0, rounds: int = 1000, native: Optional[QkcHashNative] = None, ) -> Tuple[Optional[bytes], Optional[bytes]]: cache = (make_cache(CACHE_ENTRIES, CACHE_SEED) if native is None else native.make_cache(CACHE_ENTRIES, CACHE_SEED)) nonce = start_nonce target = 2**256 // (difficulty or 1) for i in range(1, rounds + 1): # hashimoto expected big-indian byte representation bin_nonce = (nonce + i).to_bytes(8, byteorder="big") if native is None: mining_output = qkchash(header_hash, bin_nonce, cache) else: dup_cache = native.dup_cache(cache) mining_output = native.calculate_hash(header_hash, bin_nonce, dup_cache) result = int.from_bytes(mining_output["result"], byteorder="big") if result <= target: assert len(bin_nonce) == 8 assert len(mining_output["mix digest"]) == 32 return bin_nonce, mining_output["mix digest"] return None, None
def get_mining_output(block_number: int, header_hash: bytes, nonce: bytes) -> Dict[str, bytes]: seed = get_seed_from_block_number(block_number) if QKC_HASH_NATIVE is None: current_cache = make_cache(CACHE_ENTRIES, seed) mining_output = qkchash(header_hash, nonce, current_cache) else: current_cache = QKC_HASH_NATIVE.make_cache(CACHE_ENTRIES, seed) mining_output = QKC_HASH_NATIVE.calculate_hash(header_hash, nonce, current_cache) return mining_output
def get_qkchashlib_path(): """Assuming libqkchash.so is in the same dir as this file""" return os.path.join(os.path.dirname(__file__), "libqkchash.so") def init_qkc_hash_native(): try: return QkcHashNative(get_qkchashlib_path()) except Exception: return None QKC_HASH_NATIVE = init_qkc_hash_native() QKC_HASH_CACHE = (QKC_HASH_NATIVE.make_cache(CACHE_ENTRIES, CACHE_SEED) if QKC_HASH_NATIVE else make_cache(CACHE_ENTRIES, CACHE_SEED)) @lru_cache(maxsize=32) def check_pow(header_hash: bytes, mixhash: bytes, nonce: bytes, difficulty: int) -> bool: """Check if the proof-of-work of the block is valid.""" if len(mixhash) != 32 or len(header_hash) != 32 or len(nonce) != 8: return False if QKC_HASH_NATIVE is None: mining_output = qkchash(header_hash, nonce, QKC_HASH_CACHE) else: dup_cache = QKC_HASH_NATIVE.dup_cache(QKC_HASH_CACHE) mining_output = QKC_HASH_NATIVE.calculate_hash(header_hash, nonce, dup_cache)
def make_cache_fast(entries, seed): return make_cache(entries, seed)