Refactord Watcher and BlockProcessor. Closes #36.

Brings back check_potential_matches and check_matches to the Watcher.

The methods have now been renamed to check_matches (old check_potential_matches) and filter_valid_matches (old check_matches) to provide a better description of their purpose.

decode_raw_transaction has been added to BlockProcessor
This commit is contained in:
Sergi Delgado Segura
2019-11-08 14:16:02 +00:00
parent c08013abd0
commit 20faa04c4c
2 changed files with 83 additions and 61 deletions

View File

@@ -1,18 +1,22 @@
from uuid import uuid4
from queue import Queue
from hashlib import sha256
from threading import Thread
from binascii import unhexlify
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from pisa.logger import Logger
from pisa.cleaner import Cleaner
from pisa.conf import EXPIRY_DELTA, MAX_APPOINTMENTS, PISA_SECRET_KEY
from pisa.responder import Responder
from pisa.appointment import Appointment
from pisa.cryptographer import Cryptographer
from pisa.block_processor import BlockProcessor
from pisa.utils.zmq_subscriber import ZMQHandler
from pisa.conf import EXPIRY_DELTA, MAX_APPOINTMENTS, PISA_SECRET_KEY
logger = Logger("Watcher")
@@ -115,35 +119,35 @@ class Watcher:
expired_appointments, self.appointments, self.locator_uuid_map, self.db_manager
)
potential_matches = BlockProcessor.get_potential_matches(txids, self.locator_uuid_map)
matches = BlockProcessor.get_matches(potential_matches, self.locator_uuid_map, self.appointments)
matches = self.get_matches(txids, self.locator_uuid_map)
filtered_matches = self.filter_valid_matches(matches, self.locator_uuid_map, self.appointments)
for locator, uuid, dispute_txid, justice_txid, justice_rawtx in matches:
for uuid, filtered_match in filtered_matches.items():
# Errors decrypting the Blob will result in a None justice_txid
if justice_txid is not None:
if filtered_match["valid_match"] is True:
logger.info(
"Notifying responder and deleting appointment.",
justice_txid=justice_txid,
locator=locator,
justice_txid=filtered_match["justice_txid"],
locator=filtered_match["locator"],
uuid=uuid,
)
self.responder.add_response(
uuid,
dispute_txid,
justice_txid,
justice_rawtx,
filtered_match["dispute_txid"],
filtered_match["justice_txid"],
filtered_match["justice_rawtx"],
self.appointments[uuid].end_time,
block_hash,
)
# Delete the appointment and update db
Cleaner.delete_complete_appointment(
self.appointments, self.locator_uuid_map, locator, uuid, self.db_manager
self.appointments, self.locator_uuid_map, filtered_match["locator"], uuid, self.db_manager
)
# Register the last processed block for the watcher
self.db_manager.store_last_block_hash_watcher(block_hash)
# Register the last processed block for the watcher
self.db_manager.store_last_block_hash_watcher(block_hash)
# Go back to sleep if there are no more appointments
self.asleep = True
@@ -151,3 +155,55 @@ class Watcher:
self.block_queue = Queue()
logger.info("No more pending appointments, going back to sleep")
@staticmethod
def compute_locator(tx_id):
return sha256(unhexlify(tx_id)).hexdigest()
# DISCUSS: 36-who-should-check-appointment-trigger
@staticmethod
def get_matches(txids, locator_uuid_map):
potential_locators = {Watcher.compute_locator(txid): 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())
matches = {locator: potential_locators[locator] for locator in intersection}
if len(matches) > 0:
logger.info("List of matches", potential_matches=matches)
else:
logger.info("No matches found")
return matches
@staticmethod
# NOTCOVERED
def filter_valid_matches(matches, locator_uuid_map, appointments):
filtered_matches = {}
for locator, dispute_txid in matches.items():
for uuid in locator_uuid_map[locator]:
justice_rawtx = Cryptographer.decrypt(appointments[uuid].encrypted_blob, dispute_txid)
justice_tx = BlockProcessor.decode_raw_transaction(justice_rawtx)
if justice_rawtx is not None:
justice_txid = justice_tx.get("txid")
valid_match = True
logger.info("Match found for locator.", locator=locator, uuid=uuid, justice_txid=justice_txid)
else:
justice_txid = None
valid_match = False
filtered_matches[uuid] = {
"locator": locator,
"dispute_txid": dispute_txid,
"justice_txid": justice_txid,
"justice_rawtx": justice_rawtx,
"valid_match": valid_match,
}
return filtered_matches