def mine(self): """ Mine a new block featuring the latest incoming messages. This method waits for enough messages to be received from the server, then forms them into blocks, mines the block, adds the block to the blockchain, and prepares the block to be broadcast by the server. The mining of a block may be interrupted by a superceding add_block_str() call. In this case the miner should do its best to move on to mine another block and not lose any messages it was previously attempting to mine. This process repeats forever, and this function never runs. This function is called in blockchain_bbs.py as a new thread. """ self.log.debug("Miner %s : Mining on thread %d", self.miner_id[:6], threading.get_ident() % 10000) while True: # Make sure we have enough new messages in the queue if self.get_message_queue_size() < MSGS_PER_BLOCK: continue self.log.info("Thread: %d - "+ RED +"Starting to mine a block!" + NC, threading.get_ident() % 10000) with self.lock: if self.message_list is None: self.message_list = [self.message_queue.pop(0) for i in range(MSGS_PER_BLOCK)] while self.mining_flag != CONTINUE_MINING or self.latest_block is None: pass while self.mining_flag == CONTINUE_MINING: nonce = hexlify(str(random.getrandbits(NONCE_BIT_LENGTH)).encode()).decode() # Parent hash is 64 '0's if we are mining the genesis block parent_hash = self.latest_block.block.block_hash if self.latest_block is not None else '0' * 36 block = Block(nonce=nonce, parent=parent_hash, create_time=time.time(), miner=self.miner_id, posts=self.message_list) if block.verify_pow(): self.log.info("Thread: %d - " + GREEN + "Mined a block !!!" + NC + "\n", threading.get_ident() % 10000) self.mined_block = block self._add_block(block, write_to_ledger=True, mined_ourselves=True) self.message_list = None break if self.mining_flag == GIVEN_BLOCK: self.log.debug("Mining interrupted - given a block from a peer") self._add_all_to_message_queue(self.message_list) self.mining_flag = CONTINUE_MINING