class Ethash(MiningAlgorithm): def __init__(self, block: Block, **kwargs): is_test = kwargs.get("is_test", False) self.miner = EthashMiner( block.header.height, block.header.difficulty, block.header.get_hash_for_mining(), is_test=is_test, ) self.nonce_found, self.mixhash = None, None def mine(self, start_nonce: int, end_nonce: int) -> bool: nonce_found, mixhash = self.miner.mine(end_nonce - start_nonce, start_nonce) if not nonce_found: return False self.nonce_found = nonce_found self.mixhash = mixhash return True def post_process_mined_block(self, block: Block): if not self.nonce_found: raise RuntimeError("cannot post process since no nonce found") block.header.nonce = int.from_bytes(self.nonce_found, byteorder="big") block.header.mixhash = self.mixhash super().post_process_mined_block(block)
class Ethash(MiningAlgorithm): def __init__(self, work: MiningWork, **kwargs): is_test = kwargs.get("is_test", False) self.miner = EthashMiner(work.height, work.difficulty, work.hash, is_test=is_test) def mine(self, start_nonce: int, end_nonce: int) -> Optional[MiningResult]: nonce_found, mixhash = self.miner.mine(end_nonce - start_nonce, start_nonce) if not nonce_found: return None return MiningResult( self.miner.header_hash, int.from_bytes(nonce_found, byteorder="big"), mixhash, )
def mine_ethash( block: Union[MinorBlock, RootBlock], input_q: MultiProcessingQueue, output_q: MultiProcessingQueue, mining_params: Dict, ): # TODO: maybe add rounds to config json rounds = mining_params.get("rounds", 100) is_test = mining_params.get("is_test", False) # outer loop for mining forever while True: # `None` block means termination if not block: output_q.put(None) return header_hash = block.header.get_hash_for_mining() block_number = block.header.height difficulty = block.header.difficulty miner = EthashMiner(block_number, difficulty, header_hash, is_test) start_nonce = 0 # inner loop for iterating nonce while True: nonce_found, mixhash = miner.mine(rounds, start_nonce) # best case if nonce_found: block.header.nonce = int.from_bytes(nonce_found, byteorder="big") block.header.mixhash = mixhash Miner._post_process_mined_block(block) output_q.put(block) block, _ = input_q.get(block=True) # blocking break # break inner loop to refresh mining params # check if new block arrives. if yes, discard current progress and restart try: block, _ = input_q.get_nowait() break # break inner loop to refresh mining params except Exception: # queue empty pass # update param and keep mining start_nonce += rounds