Example #1
0
    def do_watch(self):
        """
        Monitors the blockchain whilst there are pending trackers.

        This is the main method of the :obj:`Responder` and triggers tracker cleaning, rebroadcasting, reorg managing,
        etc.
        """

        # Distinguish fresh bootstraps from bootstraps from db
        if self.last_known_block is None:
            self.last_known_block = self.block_processor.get_best_block_hash()

        while True:
            block_hash = self.block_queue.get()
            block = self.block_processor.get_block(block_hash)
            logger.info("New block received",
                        block_hash=block_hash,
                        prev_block_hash=block.get("previousblockhash"))

            if len(self.trackers) > 0 and block is not None:
                txids = block.get("tx")

                if self.last_known_block == block.get("previousblockhash"):
                    self.check_confirmations(txids)

                    height = block.get("height")
                    completed_trackers = self.get_completed_trackers(height)
                    Cleaner.delete_completed_trackers(completed_trackers,
                                                      height, self.trackers,
                                                      self.tx_tracker_map,
                                                      self.db_manager)

                    txs_to_rebroadcast = self.get_txs_to_rebroadcast()
                    self.rebroadcast(txs_to_rebroadcast)

                # NOTCOVERED
                else:
                    logger.warning(
                        "Reorg found",
                        local_prev_block_hash=self.last_known_block,
                        remote_prev_block_hash=block.get("previousblockhash"),
                    )

                    # ToDo: #24-properly-handle-reorgs
                    self.handle_reorgs(block_hash)

                # Clear the receipts issued in this block
                self.carrier.issued_receipts = {}

                if len(self.trackers) is 0:
                    logger.info("No more pending trackers")

            # Register the last processed block for the responder
            self.db_manager.store_last_block_hash_responder(block_hash)
            self.last_known_block = block.get("hash")
            self.block_queue.task_done()
Example #2
0
def test_delete_completed_trackers_db_match(db_manager):
    height = 0

    for _ in range(ITERATIONS):
        trackers, tx_tracker_map = set_up_trackers(db_manager, MAX_ITEMS)
        selected_trackers = random.sample(list(trackers.keys()), k=ITEMS)

        completed_trackers = {tracker: 6 for tracker in selected_trackers}

        Cleaner.delete_completed_trackers(completed_trackers, height, trackers,
                                          tx_tracker_map, db_manager)

        assert not set(completed_trackers).issubset(trackers.keys())
Example #3
0
def test_delete_completed_trackers_no_db_match(db_manager):
    height = 0

    for _ in range(ITERATIONS):
        trackers, tx_tracker_map = set_up_trackers(db_manager, MAX_ITEMS)
        selected_trackers = random.sample(list(trackers.keys()), k=ITEMS)

        # Let's change some uuid's by creating new trackers that are not included in the db and share a penalty_txid
        # with another tracker that is stored in the db.
        for uuid in selected_trackers[:ITEMS // 2]:
            penalty_txid = trackers[uuid].get("penalty_txid")
            dispute_txid = get_random_value_hex(32)
            locator = dispute_txid[:LOCATOR_LEN_HEX]
            new_uuid = uuid4().hex

            trackers[new_uuid] = {
                "locator": locator,
                "penalty_txid": penalty_txid
            }
            tx_tracker_map[penalty_txid].append(new_uuid)
            selected_trackers.append(new_uuid)

        # Let's add some random data
        for i in range(ITEMS // 2):
            uuid = uuid4().hex
            penalty_txid = get_random_value_hex(32)
            dispute_txid = get_random_value_hex(32)
            locator = dispute_txid[:LOCATOR_LEN_HEX]

            trackers[uuid] = {"locator": locator, "penalty_txid": penalty_txid}
            tx_tracker_map[penalty_txid] = [uuid]
            selected_trackers.append(uuid)

        completed_trackers = {tracker: 6 for tracker in selected_trackers}

        # We should be able to delete the correct ones and not fail in the others
        Cleaner.delete_completed_trackers(completed_trackers, height, trackers,
                                          tx_tracker_map, db_manager)
        assert not set(completed_trackers).issubset(trackers.keys())