diff --git a/pisa/api.py b/pisa/api.py index 6b0e6e5..1b26404 100644 --- a/pisa/api.py +++ b/pisa/api.py @@ -5,7 +5,6 @@ from binascii import hexlify from pisa import HOST, PORT, logging from pisa.logger import Logger -from pisa.watcher import Watcher from pisa.inspector import Inspector from pisa.appointment import Appointment from pisa.block_processor import BlockProcessor diff --git a/pisa/appointment.py b/pisa/appointment.py index 9f5db8f..8203977 100644 --- a/pisa/appointment.py +++ b/pisa/appointment.py @@ -14,6 +14,7 @@ class Appointment: self.encrypted_blob = EncryptedBlob(encrypted_blob) self.cipher = cipher self.hash_function = hash_function + self.triggered = False @classmethod def from_dict(cls, appointment_data): diff --git a/pisa/cleaner.py b/pisa/cleaner.py index 8e18ce9..6234643 100644 --- a/pisa/cleaner.py +++ b/pisa/cleaner.py @@ -44,5 +44,5 @@ class Cleaner: tx_job_map[justice_txid].remove(uuid) # Delete appointment from the db (both watchers's and responder's) - db_manager.ddelete_watcher_appointment(uuid) + db_manager.delete_watcher_appointment(uuid) db_manager.delete_responder_job(uuid) diff --git a/pisa/responder.py b/pisa/responder.py index 6589df7..0947aa0 100644 --- a/pisa/responder.py +++ b/pisa/responder.py @@ -108,7 +108,7 @@ class Responder: if confirmations == 0: self.unconfirmed_txs.append(justice_txid) - self.db_manager.store_responder_job(uuid.encode, job.to_json()) + self.db_manager.store_responder_job(uuid, job.to_json()) logger.info("New job added.", dispute_txid=dispute_txid, justice_txid=justice_txid, appointment_end=appointment_end) @@ -151,7 +151,7 @@ class Responder: completed_jobs = self.get_completed_jobs(height) Cleaner.delete_completed_jobs(self.jobs, self.tx_job_map, completed_jobs, height, self.db_manager) - self.rebroadcast(txs_to_rebroadcast) + self.rebroadcast(txs_to_rebroadcast, block_hash) # NOTCOVERED else: @@ -199,7 +199,7 @@ class Responder: return completed_jobs - def rebroadcast(self, txs_to_rebroadcast): + def rebroadcast(self, txs_to_rebroadcast, block_hash): # DISCUSS: #22-discuss-confirmations-before-retry # ToDo: #23-define-behaviour-approaching-end @@ -211,7 +211,7 @@ class Responder: for uuid in self.tx_job_map[txid]: job = self.jobs[uuid] receipt = self.add_response(uuid, job.dispute_txid, job.justice_txid, job.justice_rawtx, - job.appointment_end, retry=True) + job.appointment_end, block_hash, retry=True) logger.warning("Transaction has missed many confirmations. Rebroadcasting.", justice_txid=job.justice_txid, confirmations_missed=CONFIRMATIONS_BEFORE_RETRY) diff --git a/pisa/watcher.py b/pisa/watcher.py index ad6dcb3..944d0c9 100644 --- a/pisa/watcher.py +++ b/pisa/watcher.py @@ -137,7 +137,7 @@ class Watcher: # DISCUSS: instead of deleting the appointment, we will mark it as triggered and delete it from both # the watcher's and responder's db after fulfilled # Update appointment in the db - appointment["triggered"] = True + appointment.triggered = True self.db_manager.store_watcher_appointment(uuid, appointment.to_json()) # Register the last processed block for the watcher diff --git a/test/unit/conftest.py b/test/unit/conftest.py index 5fd697c..182e170 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -4,7 +4,10 @@ import requests from time import sleep from threading import Thread +from pisa.conf import DB_PATH from pisa.api import start_api +from pisa.watcher import Watcher +from pisa.db_manager import DBManager from test.simulator.bitcoind_sim import run_simulator, HOST, PORT @@ -20,7 +23,10 @@ def run_bitcoind(): @pytest.fixture(scope='session') def run_api(): - api_thread = Thread(target=start_api) + db_manager = DBManager(DB_PATH) + watcher = Watcher(db_manager) + + api_thread = Thread(target=start_api, args=[watcher]) api_thread.daemon = True api_thread.start() @@ -33,6 +39,11 @@ def prng_seed(): random.seed(0) +@pytest.fixture(scope='session') +def db_manager(): + return DBManager('test_db') + + def get_random_value_hex(nbytes): pseudo_random_value = random.getrandbits(8*nbytes) prv_hex = '{:x}'.format(pseudo_random_value) diff --git a/test/unit/test_cleaner.py b/test/unit/test_cleaner.py index 92c2a35..27cc126 100644 --- a/test/unit/test_cleaner.py +++ b/test/unit/test_cleaner.py @@ -1,5 +1,4 @@ import random -from os import urandom from uuid import uuid4 from pisa import logging @@ -59,23 +58,26 @@ def set_up_jobs(total_jobs): return jobs, tx_job_map -def test_delete_expired_appointment(): +def test_delete_expired_appointment(db_manager): + for _ in range(ITERATIONS): appointments, locator_uuid_map = set_up_appointments(MAX_ITEMS) expired_appointments = random.sample(list(appointments.keys()), k=ITEMS) - Cleaner.delete_expired_appointment(expired_appointments, appointments, locator_uuid_map) + Cleaner.delete_expired_appointment(expired_appointments, appointments, locator_uuid_map, db_manager) assert not set(expired_appointments).issubset(appointments.keys()) -def test_delete_completed_jobs(): +def test_delete_completed_jobs(db_manager): + height = 0 + for _ in range(ITERATIONS): jobs, tx_job_map = set_up_jobs(MAX_ITEMS) selected_jobs = random.sample(list(jobs.keys()), k=ITEMS) completed_jobs = [(job, 6) for job in selected_jobs] - Cleaner.delete_completed_jobs(jobs, tx_job_map, completed_jobs, 0) + Cleaner.delete_completed_jobs(jobs, tx_job_map, completed_jobs, height, db_manager) assert not set(completed_jobs).issubset(jobs.keys()) diff --git a/test/unit/test_responder.py b/test/unit/test_responder.py index af1fefd..2a38c7e 100644 --- a/test/unit/test_responder.py +++ b/test/unit/test_responder.py @@ -15,8 +15,8 @@ from pisa.conf import BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT @pytest.fixture(scope="module") -def responder(): - return Responder() +def responder(db_manager): + return Responder(db_manager) def create_dummy_job_data(random_txid=False, justice_rawtx=None): @@ -94,7 +94,9 @@ def test_add_response(responder): # setting the state to awake. responder.asleep = False - receipt = responder.add_response(uuid, job.dispute_txid, job.justice_txid, job.justice_rawtx, job.appointment_end) + # The block_hash passed to add_response does not matter much now. It will in the future to deal with errors + receipt = responder.add_response(uuid, job.dispute_txid, job.justice_txid, job.justice_rawtx, job.appointment_end, + block_hash=get_random_value_hex(32)) assert receipt.delivered is True @@ -235,12 +237,12 @@ def test_get_txs_to_rebroadcast(responder): assert txs_to_rebroadcast == list(txs_missing_too_many_conf.keys()) -def test_get_completed_jobs(): +def test_get_completed_jobs(db_manager): bitcoin_cli = AuthServiceProxy("http://%s:%s@%s:%d" % (BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT)) initial_height = bitcoin_cli.getblockcount() # Let's use a fresh responder for this to make it easier to compare the results - responder = Responder() + responder = Responder(db_manager) # A complete job is a job that has reached the appointment end with enough confirmations (> MIN_CONFIRMATIONS) # We'll create three type of transactions: end reached + enough conf, end reached + no enough conf, end not reached @@ -285,8 +287,8 @@ def test_get_completed_jobs(): assert set(completed_jobs_ids) == set(ended_jobs_keys) -def test_rebroadcast(): - responder = Responder() +def test_rebroadcast(db_manager): + responder = Responder(db_manager) responder.asleep = False txs_to_rebroadcast = [] @@ -305,7 +307,8 @@ def test_rebroadcast(): if (i % 2) == 0: txs_to_rebroadcast.append(justice_txid) - receipts = responder.rebroadcast(txs_to_rebroadcast) + # The block_hash passed to rebroadcast does not matter much now. It will in the future to deal with errors + receipts = responder.rebroadcast(txs_to_rebroadcast, get_random_value_hex(32)) # All txs should have been delivered and the missed confirmation reset for txid, receipt in receipts: diff --git a/test/unit/test_watcher.py b/test/unit/test_watcher.py index afe1f59..0d95956 100644 --- a/test/unit/test_watcher.py +++ b/test/unit/test_watcher.py @@ -38,8 +38,8 @@ with open(PISA_SECRET_KEY, "r") as key_file: @pytest.fixture(scope="module") -def watcher(): - return Watcher() +def watcher(db_manager): + return Watcher(db_manager) def generate_dummy_appointment():