Esempio n. 1
0
    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