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()
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())
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())