def test_delete_trackers(db_manager): # Tests de deletion of trackers # Completed and outdated trackers are deleted using the same method. The only difference is the logging message 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) # Delete the selected trackers {uuid:confirmation_count} completed_trackers = {tracker: 6 for tracker in selected_trackers} Cleaner.delete_trackers(completed_trackers, height, trackers, tx_tracker_map, db_manager) # Check that the data is not in memory anymore all_trackers = list(flatten(tx_tracker_map.values())) assert not set(completed_trackers).issubset(trackers) assert not set(completed_trackers).issubset(all_trackers) # And neither is in the db db_trackers = db_manager.load_responder_trackers() assert not set(completed_trackers).issubset(db_trackers) # Check that the data has also been removed from the Watchers db (appointment and triggered flag) all_appointments = db_manager.load_watcher_appointments( include_triggered=True) all_flags = db_manager.load_all_triggered_flags() assert not set(completed_trackers).issubset(all_appointments) assert not set(completed_trackers).issubset(all_flags)
def test_delete_trackers_db_match(db_manager): # Completed and expired trackers are deleted using the same method. The only difference is the logging message 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_trackers(completed_trackers, height, trackers, tx_tracker_map, db_manager) assert not set(completed_trackers).issubset(trackers.keys())
def test_delete_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_trackers(completed_trackers, height, trackers, tx_tracker_map, db_manager) assert not set(completed_trackers).issubset(trackers.keys())
def do_watch(self): """ Monitors the blockchain for reorgs and appointment ends. 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() self.db_manager.store_last_block_hash_responder(self.last_known_block) 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") completed_trackers = self.get_completed_trackers() expired_trackers = self.get_expired_trackers(block.get("height")) trackers_to_delete_gatekeeper = { uuid: self.trackers[uuid].get("user_id") for uuid in completed_trackers + expired_trackers } if self.last_known_block == block.get("previousblockhash"): self.check_confirmations(txids) Cleaner.delete_trackers( completed_trackers, block.get("height"), self.trackers, self.tx_tracker_map, self.db_manager ) Cleaner.delete_trackers( expired_trackers, block.get("height"), self.trackers, self.tx_tracker_map, self.db_manager, expired=True, ) Cleaner.delete_gatekeeper_appointments(self.gatekeeper, trackers_to_delete_gatekeeper) self.rebroadcast(self.get_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) == 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()