diff --git a/pisa/block_processor.py b/pisa/block_processor.py new file mode 100644 index 0000000..b6d9882 --- /dev/null +++ b/pisa/block_processor.py @@ -0,0 +1,57 @@ +import binascii +from hashlib import sha256 + +from pisa import logging, bitcoin_cli +from pisa.utils.auth_proxy import JSONRPCException + + +class BlockProcessor: + @staticmethod + def getblock(block_hash): + block = None + + try: + block = bitcoin_cli.getblock(block_hash) + + except JSONRPCException as e: + logging.error("[BlockProcessor] couldn't get block from bitcoind. Error code {}".format(e)) + + return block + + @staticmethod + def get_potential_matches(txids, locator_uuid_map): + potential_locators = {sha256(binascii.unhexlify(txid)).hexdigest(): txid for txid in txids} + + # Check is any of the tx_ids in the received block is an actual match + intersection = set(locator_uuid_map.keys()).intersection(potential_locators.keys()) + potential_matches = {locator: potential_locators[locator] for locator in intersection} + + if len(potential_matches) > 0: + logging.info("[BlockProcessor] list of potential matches: {}".format(potential_matches)) + + else: + logging.info("[BlockProcessor] no potential matches found") + + @staticmethod + def get_matches(potential_matches, locator_uuid_map, appointments): + matches = [] + + for locator, dispute_txid in potential_matches.items(): + for uuid in locator_uuid_map[locator]: + try: + # ToDo: #20-test-tx-decrypting-edge-cases + justice_rawtx = appointments[uuid].encrypted_blob.decrypt(binascii.unhexlify(dispute_txid)) + justice_rawtx = binascii.hexlify(justice_rawtx).decode() + justice_txid = bitcoin_cli.decoderawtransaction(justice_rawtx).get('txid') + matches.append((locator, uuid, dispute_txid, justice_txid, justice_rawtx)) + + logging.info("[BlockProcessor] match found for locator {} (uuid: {}): {}".format( + locator, uuid, justice_txid)) + + except JSONRPCException as e: + # Tx decode failed returns error code -22, maybe we should be more strict here. Leaving it simple + # for the POC + logging.error("[BlockProcessor] can't build transaction from decoded data. Error code {}".format(e)) + + return matches + diff --git a/pisa/cleaner.py b/pisa/cleaner.py new file mode 100644 index 0000000..d7808b9 --- /dev/null +++ b/pisa/cleaner.py @@ -0,0 +1,45 @@ +import pisa.conf as conf +from pisa import logging + + +class Cleaner: + @staticmethod + def delete_expired_appointment(block, appointments, locator_uuid_map): + to_delete = [uuid for uuid, appointment in appointments.items() + if block["height"] > appointment.end_time + conf.EXPIRY_DELTA] + + for uuid in to_delete: + locator = appointments[uuid].locator + + appointments.pop(uuid) + + if len(locator_uuid_map[locator]) == 1: + locator_uuid_map.pop(locator) + + else: + locator_uuid_map[locator].remove(uuid) + + logging.info("[Cleaner] end time reached with no match! Deleting appointment {} (uuid: {})".format(locator, + uuid)) + + return appointments, locator_uuid_map + + @staticmethod + def delete_completed_jobs(jobs, tx_job_map, completed_jobs, height): + for uuid in completed_jobs: + logging.info("[Cleaner] job completed (uuid = {}). Appointment ended at block {} after {} confirmations" + .format(uuid, jobs[uuid].justice_txid, height, jobs[uuid].confirmations)) + + # ToDo: #9-add-data-persistence + justice_txid = jobs[uuid].justice_txid + jobs.pop(uuid) + + if len(tx_job_map[justice_txid]) == 1: + tx_job_map.pop(justice_txid) + + logging.info("[Cleaner] no more jobs for justice_txid {}".format(justice_txid)) + + else: + tx_job_map[justice_txid].remove(uuid) + + return jobs, tx_job_map