Last formatting details troughout the codebase

This commit is contained in:
Sergi Delgado Segura
2019-12-13 16:05:52 +01:00
parent 008a71da3a
commit e2ca226b11
12 changed files with 272 additions and 249 deletions

View File

@@ -26,9 +26,9 @@ def add_appointment():
encoded and contain an ``appointment`` field and optionally a ``signature`` and ``public_key`` fields. encoded and contain an ``appointment`` field and optionally a ``signature`` and ``public_key`` fields.
Returns: Returns:
``tuple``: A tuple containing the response (``json``) and response code (``int``). For accepted appointments, the :obj:`tuple`: A tuple containing the response (``json``) and response code (``int``). For accepted appointments,
``rcode`` is always 0 and the response contains the signed receipt. For rejected appointments, the ``rcode`` is the ``rcode`` is always 0 and the response contains the signed receipt. For rejected appointments, the ``rcode``
a negative value and the response contains the error message. Error messages can be found at is a negative value and the response contains the error message. Error messages can be found at
:mod:`Errors <pisa.errors>`. :mod:`Errors <pisa.errors>`.
""" """
@@ -90,13 +90,13 @@ def get_appointment():
The information is requested by ``locator``. The information is requested by ``locator``.
Returns: Returns:
``dict``: A json formatted dictionary containing information about the requested appointment. :obj:`dict`: A json formatted dictionary containing information about the requested appointment.
A ``status`` flag is added to the data provided by either the :mod:`Watcher <pisa.watcher>` or the A ``status`` flag is added to the data provided by either the :obj:`Watcher <pisa.watcher.Watcher>` or the
:mod:`Responder <pisa.responder>` that signals the status of the appointment. :obj:`Responder <pisa.responder.Responder>` that signals the status of the appointment.
- Appointments hold by the :mod:`Watcher <pisa.watcher>` are flagged as ``being_watched``. - Appointments hold by the :obj:`Watcher <pisa.watcher.Watcher>` are flagged as ``being_watched``.
- Appointments hold by the :mod:`Responder <pisa.responder>` are flagged as ``dispute_triggered``. - Appointments hold by the :obj:`Responder <pisa.responder.Responder>` are flagged as ``dispute_triggered``.
- Unknown appointments are flagged as ``not_found``. - Unknown appointments are flagged as ``not_found``.
""" """
@@ -143,8 +143,9 @@ def get_all_appointments():
This endpoint should only be accessible by the administrator. Requests are only allowed from localhost. This endpoint should only be accessible by the administrator. Requests are only allowed from localhost.
Returns: Returns:
``dict``: A json formatted dictionary containing all the appointments hold by the :mod:`Watcher <pisa.watcher>` :obj:`dict`: A json formatted dictionary containing all the appointments hold by the
(``watcher_appointments``) and by the :mod:`Responder <pisa.responder>` (``responder_trackers``). :obj:`Watcher <pisa.watcher.Watcher>` (``watcher_appointments``) and by the
:obj:`Responder <pisa.responder.Responder>` (``responder_trackers``).
""" """
@@ -172,7 +173,7 @@ def get_block_count():
testers about the current block so they can define a dummy appointment without having to run a bitcoin node. testers about the current block so they can define a dummy appointment without having to run a bitcoin node.
Returns: Returns:
``dict``: A json encoded dictionary containing the block height. :obj:`dict`: A json encoded dictionary containing the block height.
""" """
@@ -184,7 +185,7 @@ def start_api(w):
This function starts the Flask server used to run the API. This function starts the Flask server used to run the API.
Args: Args:
w (Watcher): A :mod:`Watcher <pisa.watcher>` object. w (:obj:`Watcher <pisa.watcher.Watcher>`): A ``Watcher`` object.
""" """

View File

@@ -5,18 +5,18 @@ from pisa.encrypted_blob import EncryptedBlob
class Appointment: class Appointment:
""" """
The ``Appointment`` contains the information regarding an appointment between a client and the Watchtower. The :class:`Appointment` contains the information regarding an appointment between a client and the Watchtower.
Args: Args:
locator (str): A 16-byte hex-encoded value used by the tower to detect channel breaches. It serves as a trigger locator (:mod:`str`): A 16-byte hex-encoded value used by the tower to detect channel breaches. It serves as a trigger
for the tower to decrypt and broadcast the penalty transaction. for the tower to decrypt and broadcast the penalty transaction.
start_time (int): The block height at which the tower is hired to start watching for breaches. start_time (:mod:`int`): The block height where the tower is hired to start watching for breaches.
end_time (int): The block height at which the tower will stop watching for breaches. end_time (:mod:`int`): The block height where the tower will stop watching for breaches.
to_self_delay (int): The ``to_self_delay`` encoded in the ``csv`` of the ``htlc`` that this appointment is to_self_delay (:mod:`int`): The ``to_self_delay`` encoded in the ``csv`` of the ``htlc`` that this appointment is
covering. covering.
encrypted_blob (EncryptedBlob): An :mod:`EncryptedBlob <pisa.encrypted_blob>` object containing an encrypted encrypted_blob (:obj:`EncryptedBlob <pisa.encrypted_blob.EncryptedBlob>`): An ``EncryptedBlob`` object
penalty transaction. The tower will decrypt it and broadcast the penalty transaction upon seeing a breach on containing an encrypted penalty transaction. The tower will decrypt it and broadcast the penalty transaction
the blockchain. upon seeing a breach on the blockchain.
""" """
# DISCUSS: 35-appointment-checks # DISCUSS: 35-appointment-checks
@@ -35,11 +35,11 @@ class Appointment:
This method is useful to load data from a database. This method is useful to load data from a database.
Args: Args:
appointment_data (dict): a dictionary containing the following keys: appointment_data (:mod:`dict`): a dictionary containing the following keys:
``{locator, start_time, end_time, to_self_delay, encrypted_blob}`` ``{locator, start_time, end_time, to_self_delay, encrypted_blob}``
Returns: Returns:
``Appointment``: An appointment initialized using the provided data. :obj:`Appointment <pisa.appointment.Appointment>`: An appointment initialized using the provided data.
Raises: Raises:
ValueError: If one of the mandatory keys is missing in ``appointment_data``. ValueError: If one of the mandatory keys is missing in ``appointment_data``.
@@ -64,7 +64,7 @@ class Appointment:
Exports an appointment as a dictionary. Exports an appointment as a dictionary.
Returns: Returns:
``dict``: A dictionary containing the appointment attributes. :obj:`dict`: A dictionary containing the appointment attributes.
""" """
@@ -87,13 +87,13 @@ class Appointment:
to store appointments in the database. to store appointments in the database.
Args: Args:
triggered (bool): Whether the dispute has been triggered or not. When an appointment passes from the triggered (:mod:`bool`): Whether the dispute has been triggered or not. When an appointment passes from the
:mod:`Watcher <pisa.watcher>` to the :mod:`Responder <pisa.responder>` it is not deleted straightaway. :mod:`Watcher <pisa.watcher>` to the :mod:`Responder <pisa.responder>` it is not deleted straightaway.
Instead, the appointment is stored in the DB flagged as ``triggered``. This aims to ease handling block Instead, the appointment is stored in the DB flagged as ``triggered``. This aims to ease handling block
reorgs in the future. reorgs in the future.
Returns: Returns:
``str``: A json-encoded str representing the appointment. :obj:`str`: A json-encoded str representing the appointment.
""" """
appointment = self.to_dict() appointment = self.to_dict()

View File

@@ -7,8 +7,8 @@ logger = Logger("BlockProcessor")
class BlockProcessor: class BlockProcessor:
""" """
The ``BlockProcessor`` contains methods related to the blockchain. Most of its methods required communication with The :class:`BlockProcessor` contains methods related to the blockchain. Most of its methods require communication
``bitcoind``. with ``bitcoind``.
""" """
@staticmethod @staticmethod
@@ -17,10 +17,10 @@ class BlockProcessor:
Gives a block given a block hash by querying ``bitcoind``. Gives a block given a block hash by querying ``bitcoind``.
Args: Args:
block_hash (str): The block hash to be queried. block_hash (:obj:`str`): The block hash to be queried.
Returns: Returns:
``dict`` or ``None``: A dictionary containing the requested block data if the block is found. :obj:`dict` or :obj:`None`: A dictionary containing the requested block data if the block is found.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """
@@ -40,7 +40,7 @@ class BlockProcessor:
Returns the hash of the current best chain tip. Returns the hash of the current best chain tip.
Returns: Returns:
``str`` or ``None``: The hash of the block if it can be found. :obj:`str` or :obj:`None`: The hash of the block if it can be found.
Returns ``None`` otherwise (not even sure this can actually happen). Returns ``None`` otherwise (not even sure this can actually happen).
""" """
@@ -60,7 +60,7 @@ class BlockProcessor:
Returns the block height of the best chain. Returns the block height of the best chain.
Returns: Returns:
``int`` or ``None``: The block height if it can be computed. :obj:`int` or :obj:`None`: The block height if it can be computed.
Returns ``None`` otherwise (not even sure this can actually happen). Returns ``None`` otherwise (not even sure this can actually happen).
""" """
@@ -81,10 +81,10 @@ class BlockProcessor:
associated metadata given by ``bitcoind`` (e.g. confirmation count). associated metadata given by ``bitcoind`` (e.g. confirmation count).
Args: Args:
raw_tx (str): The hex representation of the transaction. raw_tx (:obj:`str`): The hex representation of the transaction.
Returns: Returns:
``dict`` or ``None``: The decoding of the given ``raw_tx`` if the transaction is well formatted. :obj:`dict` or :obj:`None`: The decoding of the given ``raw_tx`` if the transaction is well formatted.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """
@@ -105,16 +105,16 @@ class BlockProcessor:
This method is used to fetch all the missed information when recovering from a crash. Note that if the two This method is used to fetch all the missed information when recovering from a crash. Note that if the two
blocks are not part of the same chain, it would return all the blocks up to genesis. blocks are not part of the same chain, it would return all the blocks up to genesis.
FIXME: This needs to be integrated with the ChainMaester (soon TM) to allow dealing with forks.
Args: Args:
last_know_block_hash (hex): the hash of the last known block. last_know_block_hash (:obj:`str`): the hash of the last known block.
Returns: Returns:
``list``: A list of blocks between the last given block and the current best chain tip, starting from the :obj:`list`: A list of blocks between the last given block and the current best chain tip, starting from the
child of ``last_know_block_hash``. child of ``last_know_block_hash``.
""" """
# FIXME: This needs to be integrated with the ChainMaester (soon TM) to allow dealing with forks.
current_block_hash = self.get_best_block_hash() current_block_hash = self.get_best_block_hash()
missed_blocks = [] missed_blocks = []
@@ -131,11 +131,11 @@ class BlockProcessor:
Compute the distance between a given block hash and the best chain tip. Compute the distance between a given block hash and the best chain tip.
Args: Args:
target_block_hash (str): the hash of the target block (the one to compute the distance form the tip). target_block_hash (:obj:`str`): the hash of the target block (the one to compute the distance form the tip).
Returns: Returns:
``int`` or ``None``: The distance between the target and the best chain tip is the target block can be found :obj:`int` or :obj:`None`: The distance between the target and the best chain tip is the target block can be
on the blockchain. found on the blockchain.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """

View File

@@ -6,8 +6,8 @@ from pisa.appointment import Appointment
class Builder: class Builder:
""" """
The ``Builder`` class is in charge or reconstructing data loaded from the database and build the data structures The :class:`Builder` class is in charge or reconstructing data loaded from the database and build the data
of the :mod:`Watcher <pisa.watcher>` and the :mod:`Responder <pisa.responder>`. structures of the :obj:`Watcher <pisa.watcher.Watcher>` and the :obj:`Responder <pisa.responder.Responder>`.
""" """
@staticmethod @staticmethod
@@ -17,15 +17,15 @@ class Builder:
dictionary of appointments from the database. dictionary of appointments from the database.
Args: Args:
appointments_data (dict): a dictionary of dictionaries representing all the :mod:`Watcher <pisa.watcher>` appointments_data (:obj:`dict`): a dictionary of dictionaries representing all the
appointments stored in the database. The structure is as follows: :obj:`Watcher <pisa.watcher.Watcher>` appointments stored in the database. The structure is as follows:
``{uuid: {locator: str, start_time: int, ...}, uuid: {locator:...}}`` ``{uuid: {locator: str, start_time: int, ...}, uuid: {locator:...}}``
Returns: Returns:
``tuple``: A tuple with two dictionaries. ``appointments`` containing the appointment information in :obj:`tuple`: A tuple with two dictionaries. ``appointments`` containing the appointment information in
:mod:`Appointment <pisa.appointment>` objects and ``locator_uuid_map`` containing a map of appointment :obj:`Appointment <pisa.appointment.Appointment>` objects and ``locator_uuid_map`` containing a map of
(``uuid:locator``). appointment (``uuid:locator``).
""" """
appointments = {} appointments = {}
@@ -50,14 +50,15 @@ class Builder:
a dictionary of trackers from the database. a dictionary of trackers from the database.
Args: Args:
tracker_data (dict): a dictionary of dictionaries representing all the :mod:`Responder <pisa.responder>` tracker_data (:obj:`dict`): a dictionary of dictionaries representing all the
trackers stored in the database. The structure is as follows: :mod:`Responder <pisa.responder.Responder>` trackers stored in the database.
The structure is as follows:
``{uuid: {locator: str, dispute_txid: str, ...}, uuid: {locator:...}}`` ``{uuid: {locator: str, dispute_txid: str, ...}, uuid: {locator:...}}``
Returns: Returns:
``tuple``: A tuple with two dictionaries. ``trackers`` containing the trackers' information in :obj:`tuple`: A tuple with two dictionaries. ``trackers`` containing the trackers' information in
:class:`TransactionTracker <pisa.responder.TransactionTracker>` objects and a ``tx_tracker_map`` containing :obj:`TransactionTracker <pisa.responder.TransactionTracker>` objects and a ``tx_tracker_map`` containing
the map of trackers (``penalty_txid: uuid``). the map of trackers (``penalty_txid: uuid``).
""" """
@@ -80,14 +81,14 @@ class Builder:
@staticmethod @staticmethod
def build_block_queue(missed_blocks): def build_block_queue(missed_blocks):
""" """
Builds a ``Queue`` of block hashes to initialize the :mod:`Watcher <pisa.watcher>` or the Builds a ``Queue`` of block hashes to initialize the :mod:`Watcher <pisa.watcher.Watcher>` or the
:mod:`Responder <pisa.responder>` using backed up data. :mod:`Responder <pisa.responder.Responder>` using backed up data.
Args: Args:
missed_blocks (list): list of block hashes missed by the Watchtower (do to a crash or shutdown). missed_blocks (:obj:`list`): list of block hashes missed by the Watchtower (do to a crash or shutdown).
Returns: Returns:
``Queue``: A `Queue` containing all the missed blocks hashes. :obj:`Queue`: A ``Queue`` containing all the missed blocks hashes.
""" """
block_queue = Queue() block_queue = Queue()

View File

@@ -11,18 +11,18 @@ logger = Logger("Carrier")
class Receipt: class Receipt:
""" """
The ``Receipt`` class represent the interaction between the ``Carrier`` and ``bitcoind`` when broadcasting The :class:`Receipt` class represent the interaction between the :obj:`Carrier` and ``bitcoind`` when broadcasting
transactions. It is used to signal whether or not a transaction has been successfully broadcast and why. transactions. It is used to signal whether or not a transaction has been successfully broadcast and why.
Args: Args:
delivered (bool): whether or not the transaction has been successfully broadcast. delivered (:obj:`bool`): whether or not the transaction has been successfully broadcast.
confirmations (int): the number of confirmations of the transaction to broadcast. In certain situations the confirmations (:obj:`int`): the number of confirmations of the transaction to broadcast. In certain situations
``Carrier`` may fail to broadcast a transaction because it was already in the blockchain. This attribute the :obj:`Carrier` may fail to broadcast a transaction because it was already in the blockchain.
signals those situations. This attribute signals those situations.
reason (int): an error code describing why the transaction broadcast failed. reason (:obj:`int`): an error code describing why the transaction broadcast failed.
Returns: Returns:
``Receipt``: A receipt describing whether or not the transaction was delivered. Notice that transactions :obj:`Receipt`: A receipt describing whether or not the transaction was delivered. Notice that transactions
that are already on chain are flagged as delivered with a ``confirmations > 0`` whereas new transactions are so that are already on chain are flagged as delivered with a ``confirmations > 0`` whereas new transactions are so
with ``confirmations = 0``. with ``confirmations = 0``.
""" """
@@ -35,8 +35,8 @@ class Receipt:
class Carrier: class Carrier:
""" """
The ``Carrier`` is the class in charge of interacting with ``bitcoind`` to send/get transactions. It uses The :class:`Carrier` is the class in charge of interacting with ``bitcoind`` to send/get transactions. It uses
``Receipt`` objects to report about sending transactions. :obj:`Receipt` objects to report about the sending outcome.
""" """
# NOTCOVERED # NOTCOVERED
@@ -45,11 +45,11 @@ class Carrier:
Tries to send a given raw transaction to the Bitcoin network using ``bitcoind``. Tries to send a given raw transaction to the Bitcoin network using ``bitcoind``.
Args: Args:
rawtx (str): a (potentially) signed raw transaction ready to be broadcast. rawtx (:obj:`str`): a (potentially) signed raw transaction ready to be broadcast.
txid (str): the transaction id corresponding to ``rawtx``. txid (:obj:`str`): the transaction id corresponding to ``rawtx``.
Returns: Returns:
``Receipt``: A receipt reporting whether the transaction was successfully delivered or not and why. :obj:`Receipt`: A receipt reporting whether the transaction was successfully delivered or not and why.
""" """
try: try:
@@ -108,10 +108,11 @@ class Carrier:
Queries transaction data to ``bitcoind`` given a transaction id. Queries transaction data to ``bitcoind`` given a transaction id.
Args: Args:
txid (str): a 32-byte hex-formatted string representing the transaction id. txid (:obj:`str`): a 32-byte hex-formatted string representing the transaction id.
Returns: Returns:
``dict`` or ``None``: A dictionary with the transaction data if the transaction can be found on the chain. :obj:`dict` or :obj:`None`: A dictionary with the transaction data if the transaction can be found on the
chain.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """

View File

@@ -5,7 +5,7 @@ logger = Logger("Cleaner")
class Cleaner: class Cleaner:
""" """
The ``Cleaner`` is the class in charge of removing expired / completed data from the tower. The :class:`Cleaner` is the class in charge of removing expired/completed data from the tower.
Mutable objects (like dicts) are passed-by-reference in Python, so no return is needed for the Cleaner. Mutable objects (like dicts) are passed-by-reference in Python, so no return is needed for the Cleaner.
""" """
@@ -14,13 +14,16 @@ class Cleaner:
def delete_expired_appointment(expired_appointments, appointments, locator_uuid_map, db_manager): def delete_expired_appointment(expired_appointments, appointments, locator_uuid_map, db_manager):
""" """
Deletes appointments which ``end_time`` has been reached (with no trigger) both from memory Deletes appointments which ``end_time`` has been reached (with no trigger) both from memory
(:mod:`Watcher <pisa.watcher>`) and disk. (:obj:`Watcher <pisa.watcher.Watcher>`) and disk.
Args: Args:
expired_appointments (list): a list of appointments to be deleted. expired_appointments (:obj:`list`): a list of appointments to be deleted.
appointments (dict): a dictionary containing all the :mod:`Watcher <pisa.watcher>` appointments. appointments (:obj:`dict`): a dictionary containing all the :mod:`Watcher <pisa.watcher.Watcher>`
locator_uuid_map (dict): a ``locator:uuid`` map for the :mod:`Watcher <pisa.watcher>` appointments. appointments.
db_manager (DBManager): a :mod:`DBManager <pisa.db_manager>` instance to interact with the database. locator_uuid_map (:obj:`dict`): a ``locator:uuid`` map for the :obj:`Watcher <pisa.watcher.Watcher>`
appointments.
db_manager (:obj:`DBManager <pisa.db_manager.DBManager>`): a ``DBManager`` instance to interact with the
database.
""" """
for uuid in expired_appointments: for uuid in expired_appointments:
@@ -34,7 +37,7 @@ class Cleaner:
else: else:
locator_uuid_map[locator].remove(uuid) locator_uuid_map[locator].remove(uuid)
logger.info("End time reached with no match. Deleting appointment.", locator=locator, uuid=uuid) logger.info("End time reached with no breach. Deleting appointment.", locator=locator, uuid=uuid)
# Delete appointment from the db # Delete appointment from the db
db_manager.delete_watcher_appointment(uuid) db_manager.delete_watcher_appointment(uuid)
@@ -42,13 +45,17 @@ class Cleaner:
@staticmethod @staticmethod
def delete_completed_appointment(uuid, appointments, locator_uuid_map, db_manager): def delete_completed_appointment(uuid, appointments, locator_uuid_map, db_manager):
""" """
Deletes a triggered appointment from memory (:mod:`Watcher <pisa.watcher>`) and flags it as triggered in disk. Deletes a triggered appointment from memory (:obj:`Watcher <pisa.watcher.Watcher>`) and flags it as triggered in
disk.
Args: Args:
uuid (str): a unique 16-byte hex-encoded str that identifies the appointment. uuid (:obj:`str`): a unique 16-byte hex-encoded str that identifies the appointment.
appointments (dict): a dictionary containing all the :mod:`Watcher <pisa.watcher>` appointments. appointments (:obj:`dict`): a dictionary containing all the :obj:`Watcher <pisa.watcher.Watcher>`
locator_uuid_map (dict): a ``locator:uuid`` map for the :mod:`Watcher <pisa.watcher>` appointments. appointments.
db_manager (DBManager): a :mod:`DBManager <pisa.db_manager>` instance to interact with the database. locator_uuid_map (:obj:`dict`): a ``locator:uuid`` map for the :obj:`Watcher <pisa.watcher.Watcher>`
appointments.
db_manager (:obj:`DBManager <pisa.db_manager.DBManager>`): a ``DBManager`` instance to interact with the
database.
""" """
# Delete the appointment # Delete the appointment
@@ -69,15 +76,18 @@ class Cleaner:
@staticmethod @staticmethod
def delete_completed_trackers(completed_trackers, height, trackers, tx_tracker_map, db_manager): def delete_completed_trackers(completed_trackers, height, trackers, tx_tracker_map, db_manager):
""" """
Deletes a completed tracker both from memory (:mod:`Responder <pisa.responder>`) and disk (from the Deletes a completed tracker both from memory (:obj:`Responder <pisa.responder.Responder>`) and disk (from the
:mod:`Responder <pisa.responder>` and :mod:`Watcher <pisa.watcher>` databases). Responder's and Watcher's databases).
Args: Args:
trackers (dict): a dictionary containing all the :mod:`Responder <pisa.responder>` trackers. trackers (:obj:`dict`): a dictionary containing all the :obj:`Responder <pisa.responder.Responder>`
tx_tracker_map (dict): a ``penalty_txid:uuid`` map for the :mod:`Responder <pisa.responder>` trackers. trackers.
completed_trackers (list): a list of completed trackers to be deleted. tx_tracker_map (:obj:`dict`): a ``penalty_txid:uuid`` map for the :obj:`Responder
height (int): the block height at which the trackers were completed. <pisa.responder.Responder>` trackers.
db_manager (DBManager): a :mod:`DBManager <pisa.db_manager>` instance to interact with the database. completed_trackers (:obj:`list`): a list of completed trackers to be deleted.
height (:obj:`int`): the block height at which the trackers were completed.
db_manager (:obj:`DBManager <pisa.db_manager.DBManager>`): a ``DBManager`` instance to interact with the
database.
""" """
for uuid, confirmations in completed_trackers: for uuid, confirmations in completed_trackers:

View File

@@ -14,19 +14,19 @@ LOCATOR_MAP_PREFIX = "m"
class DBManager: class DBManager:
""" """
The ``DBManager`` is the class in charge of interacting with the appointments database (``LevelDB``). The :class:`DBManager` is the class in charge of interacting with the appointments database (``LevelDB``).
Keys and values are stored as bytes in the database but processed as strings by the manager. Keys and values are stored as bytes in the database but processed as strings by the manager.
The database is split in five prefixes: The database is split in five prefixes:
- ``WATCHER_PREFIX``, defined as ``b'w``, is used to store :mod:`Watcher <pisa.watcher>` appointments. - ``WATCHER_PREFIX``, defined as ``b'w``, is used to store :obj:`Watcher <pisa.watcher.Watcher>` appointments.
- ``RESPONDER_PREFIX``, defines as ``b'r``, is used to store :mod:`Responder <pisa.responder>` trackers. - ``RESPONDER_PREFIX``, defines as ``b'r``, is used to store :obj:`Responder <pisa.responder.Responder>` trackers.
- ``WATCHER_LAST_BLOCK_KEY``, defined as ``b'bw``, is used to store the last block hash known by the :mod:`Watcher <pisa.watcher>`. - ``WATCHER_LAST_BLOCK_KEY``, defined as ``b'bw``, is used to store the last block hash known by the :obj:`Watcher <pisa.watcher.Watcher>`.
- ``RESPONDER_LAST_BLOCK_KEY``, defined as ``b'br``, is used to store the last block hash known by the :mod:`Responder <pisa.responder>`. - ``RESPONDER_LAST_BLOCK_KEY``, defined as ``b'br``, is used to store the last block hash known by the :obj:`Responder <pisa.responder.Responder>`.
- ``LOCATOR_MAP_PREFIX``, defined as ``b'm``, is used to store the ``locator:uuid`` maps. - ``LOCATOR_MAP_PREFIX``, defined as ``b'm``, is used to store the ``locator:uuid`` maps.
Args: Args:
db_path (str): the path (relative or absolute) to the system folder containing the database. A fresh new db_path (:obj:`str`): the path (relative or absolute) to the system folder containing the database. A fresh
database will be create if the specified path does not contain one. database will be create if the specified path does not contain one.
""" """
@@ -48,10 +48,10 @@ class DBManager:
``RESPONDER_PREFIX``. ``RESPONDER_PREFIX``.
Args: Args:
prefix (str): the prefix of the data to load. prefix (:obj:`str`): the prefix of the data to load.
Returns: Returns:
(``dict``): A dictionary containing the requested data (appointments or trackers) indexed by ``uuid``. :obj:`dict`: A dictionary containing the requested data (appointments or trackers) indexed by ``uuid``.
Returns an empty dictionary if no data is found. Returns an empty dictionary if no data is found.
""" """
@@ -70,7 +70,7 @@ class DBManager:
Loads the last known block given a key (either ``WATCHER_LAST_BLOCK_KEY`` or ``RESPONDER_LAST_BLOCK_KEY``). Loads the last known block given a key (either ``WATCHER_LAST_BLOCK_KEY`` or ``RESPONDER_LAST_BLOCK_KEY``).
Returns: Returns:
(``str`` or ``None``): A 16-byte hex-encoded str representing the last known block hash. :obj:`str` or :obj:`None`: A 16-byte hex-encoded str representing the last known block hash.
Returns ``None`` if the entry is not found. Returns ``None`` if the entry is not found.
""" """
@@ -87,9 +87,9 @@ class DBManager:
Creates a new entry in the database. Creates a new entry in the database.
Args: Args:
key (str): the key of the new entry, used to identify it. key (:obj:`str`): the key of the new entry, used to identify it.
value (str): the data stored under the given ``key``. value (:obj:`str`): the data stored under the given ``key``.
prefix (str): an optional prefix added to the ``key``. prefix (:obj:`str`): an optional prefix added to the ``key``.
""" """
if isinstance(prefix, str): if isinstance(prefix, str):
@@ -105,10 +105,10 @@ class DBManager:
Loads an entry from the database given a ``key``. Loads an entry from the database given a ``key``.
Args: Args:
key (str): the key that identifies the entry to be loaded. key (:obj:`str`): the key that identifies the entry to be loaded.
Returns: Returns:
(``dict`` or ``None``): A dictionary containing the requested data (an appointment or a tracker). :obj:`dict` or :obj:`None`: A dictionary containing the requested data (an appointment or a tracker).
Returns ``None`` if the entry is not found. Returns ``None`` if the entry is not found.
""" """
@@ -122,8 +122,8 @@ class DBManager:
Deletes an entry from the database given an ``key`` (and optionally a ``prefix``) Deletes an entry from the database given an ``key`` (and optionally a ``prefix``)
Args: Args:
key (str): the key that identifies the data to be deleted. key (:obj:`str`): the key that identifies the data to be deleted.
prefix (str): an optional prefix to be prepended to the ``key``. prefix (:obj:`str`): an optional prefix to be prepended to the ``key``.
""" """
if isinstance(prefix, str): if isinstance(prefix, str):
@@ -138,7 +138,7 @@ class DBManager:
Loads an appointment from the database using ``WATCHER_PREFIX`` as prefix to the given ``key``. Loads an appointment from the database using ``WATCHER_PREFIX`` as prefix to the given ``key``.
Returns: Returns:
(``dict``): A dictionary containing the appointment data if they ``key`` is found. :obj:`dict`: A dictionary containing the appointment data if they ``key`` is found.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """
@@ -150,7 +150,7 @@ class DBManager:
Loads a tracker from the database using ``RESPONDER_PREFIX`` as a prefix to the given ``key``. Loads a tracker from the database using ``RESPONDER_PREFIX`` as a prefix to the given ``key``.
Returns: Returns:
(``dict``): A dictionary containing the tracker data if they ``key`` is found. :obj:`dict`: A dictionary containing the tracker data if they ``key`` is found.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """
@@ -162,12 +162,12 @@ class DBManager:
Loads all the appointments from the database (all entries with the ``WATCHER_PREFIX`` prefix). Loads all the appointments from the database (all entries with the ``WATCHER_PREFIX`` prefix).
Args: Args:
include_triggered (bool): Whether to include the appointments flagged as triggered or not. ``False`` by include_triggered (:obj:`bool`): Whether to include the appointments flagged as triggered or not. ``False`` by
default. default.
Returns: Returns:
(``dict``): A dictionary with all the appointments stored in the database. An empty dictionary is there are :obj:`dict`: A dictionary with all the appointments stored in the database. An empty dictionary is there
none. are none.
""" """
appointments = self.load_appointments_db(prefix=WATCHER_PREFIX) appointments = self.load_appointments_db(prefix=WATCHER_PREFIX)
@@ -184,7 +184,7 @@ class DBManager:
Loads all the trackers from the database (all entries with the ``RESPONDER_PREFIX`` prefix). Loads all the trackers from the database (all entries with the ``RESPONDER_PREFIX`` prefix).
Returns: Returns:
(``dict``): A dictionary with all the trackers stored in the database. An empty dictionary is there are :obj:`dict`: A dictionary with all the trackers stored in the database. An empty dictionary is there are
none. none.
""" """
@@ -211,10 +211,10 @@ class DBManager:
Loads the ``locator:uuid`` map of a given ``locator`` from the database. Loads the ``locator:uuid`` map of a given ``locator`` from the database.
Args: Args:
locator (str): a 16-byte hex-encoded string representing the appointment locator. locator (:obj:`str`): a 16-byte hex-encoded string representing the appointment locator.
Returns: Returns:
(``dict`` or ``None``): The requested ``locator:uuid`` map if found. :obj:`dict` or :obj:`None`: The requested ``locator:uuid`` map if found.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """
@@ -237,8 +237,8 @@ class DBManager:
If the map already exists, the new ``uuid`` is appended to the existing ones (if it is not already there). If the map already exists, the new ``uuid`` is appended to the existing ones (if it is not already there).
Args: Args:
locator (str): a 16-byte hex-encoded string used as the key of the map. locator (:obj:`str`): a 16-byte hex-encoded string used as the key of the map.
uuid (str): a 16-byte hex-encoded unique id to create (or add to) the map. uuid (:obj:`str`): a 16-byte hex-encoded unique id to create (or add to) the map.
""" """
locator_map = self.load_locator_map(locator) locator_map = self.load_locator_map(locator)
@@ -263,7 +263,7 @@ class DBManager:
Deletes a ``locator:uuid`` map. Deletes a ``locator:uuid`` map.
Args: Args:
locator (str): a 16-byte hex-encoded string identifying the map to delete. locator (:obj:`str`): a 16-byte hex-encoded string identifying the map to delete.
""" """
self.delete_entry(locator, prefix=LOCATOR_MAP_PREFIX) self.delete_entry(locator, prefix=LOCATOR_MAP_PREFIX)
@@ -274,7 +274,7 @@ class DBManager:
Deletes an appointment from the database. Deletes an appointment from the database.
Args: Args:
uuid (str): a 16-byte hex-encoded string identifying the appointment to be deleted. uuid (:obj:`str`): a 16-byte hex-encoded string identifying the appointment to be deleted.
""" """
self.delete_entry(uuid, prefix=WATCHER_PREFIX) self.delete_entry(uuid, prefix=WATCHER_PREFIX)
@@ -285,7 +285,7 @@ class DBManager:
Deletes a tracker from the database. Deletes a tracker from the database.
Args: Args:
uuid (str): a 16-byte hex-encoded string identifying the tracker to be deleted. uuid (:obj:`str`): a 16-byte hex-encoded string identifying the tracker to be deleted.
""" """
self.delete_entry(uuid, prefix=RESPONDER_PREFIX) self.delete_entry(uuid, prefix=RESPONDER_PREFIX)
@@ -293,10 +293,10 @@ class DBManager:
def load_last_block_hash_watcher(self): def load_last_block_hash_watcher(self):
""" """
Loads the last known block hash of the :mod:`Watcher <pisa.watcher>` from the database. Loads the last known block hash of the :obj:`Watcher <pisa.watcher.Watcher>` from the database.
Returns: Returns:
(``str`` or ``None``): A 32-byte hex-encoded string representing the last known block hash if found. :obj:`str` or :obj:`None`: A 32-byte hex-encoded string representing the last known block hash if found.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """
@@ -304,10 +304,10 @@ class DBManager:
def load_last_block_hash_responder(self): def load_last_block_hash_responder(self):
""" """
Loads the last known block hash of the :mod:`Responder <pisa.responder>` from the database. Loads the last known block hash of the :obj:`Responder <pisa.responder.Responder>` from the database.
Returns: Returns:
(``str`` or ``None``): A 32-byte hex-encoded string representing the last known block hash if found. :obj:`str` or :obj:`None`: A 32-byte hex-encoded string representing the last known block hash if found.
Returns ``None`` otherwise. Returns ``None`` otherwise.
""" """
@@ -315,20 +315,20 @@ class DBManager:
def store_last_block_hash_watcher(self, block_hash): def store_last_block_hash_watcher(self, block_hash):
""" """
Stores a block hash as the last known block of the :mod:`Watcher <pisa.watcher>`. Stores a block hash as the last known block of the :obj:`Watcher <pisa.watcher.Watcher>`.
Args: Args:
block_hash (str): the block hash to be stored (32-byte hex-encoded) block_hash (:obj:`str`): the block hash to be stored (32-byte hex-encoded)
""" """
self.create_entry(WATCHER_LAST_BLOCK_KEY, block_hash) self.create_entry(WATCHER_LAST_BLOCK_KEY, block_hash)
def store_last_block_hash_responder(self, block_hash): def store_last_block_hash_responder(self, block_hash):
""" """
Stores a block hash as the last known block of the :mod:`Responder <pisa.responder>`. Stores a block hash as the last known block of the :obj:`Responder <pisa.responder.Responder>`.
Args: Args:
block_hash (str): the block hash to be stored (32-byte hex-encoded) block_hash (:obj:`str`): the block hash to be stored (32-byte hex-encoded)
""" """
self.create_entry(RESPONDER_LAST_BLOCK_KEY, block_hash) self.create_entry(RESPONDER_LAST_BLOCK_KEY, block_hash)

View File

@@ -20,7 +20,7 @@ logger = Logger("Inspector")
class Inspector: class Inspector:
""" """
The ``Inspector`` class is in charge of verifying that the appointment data provided by the user is correct. The :class:`Inspector` class is in charge of verifying that the appointment data provided by the user is correct.
""" """
def inspect(self, appointment_data, signature, public_key): def inspect(self, appointment_data, signature, public_key):
@@ -28,16 +28,17 @@ class Inspector:
Inspects whether the data provided by the user is correct. Inspects whether the data provided by the user is correct.
Args: Args:
appointment_data (dict): a dictionary containing the appointment data. appointment_data (:obj:`dict`): a dictionary containing the appointment data.
signature (str): the appointment signature provided by the user (hex encoded). signature (:obj:`str`): the appointment signature provided by the user (hex encoded).
public_key (str): the user's public key (hex encoded). public_key (:obj:`str`): the user's public key (hex encoded).
Returns: Returns:
``Appointment`` or ``tuple``: An appointment initialized with the provided data if it is correct. :obj:`Appointment <pisa.appointment.Appointment>` or :obj:`tuple`: An appointment initialized with the
provided data if it is correct.
Returns a tuple (`return code`, `message`) describing the error otherwise. Returns a tuple ``(return code, message)`` describing the error otherwise.
Errors are defined in :mod:`errors <pisa.errors>`. Errors are defined in :mod:`Errors <pisa.errors>`.
""" """
block_height = BlockProcessor.get_block_count() block_height = BlockProcessor.get_block_count()
@@ -77,10 +78,10 @@ class Inspector:
Locators must be 16-byte hex encoded strings. Locators must be 16-byte hex encoded strings.
Args: Args:
locator (str): the locator to be checked. locator (:obj:`str`): the locator to be checked.
Returns: Returns:
``tuple``: A tuple (return code, message) as follows: :obj:`tuple`: A tuple (return code, message) as follows:
- ``(0, None)`` if the ``locator`` is correct. - ``(0, None)`` if the ``locator`` is correct.
- ``!= (0, None)`` otherwise. - ``!= (0, None)`` otherwise.
@@ -122,11 +123,11 @@ class Inspector:
Start times must be ahead the current best chain tip. Start times must be ahead the current best chain tip.
Args: Args:
start_time (int): the block height at which the tower is requested to start watching for breaches. start_time (:obj:`int`): the block height at which the tower is requested to start watching for breaches.
block_height (int): the chain height. block_height (:obj:`int`): the chain height.
Returns: Returns:
``tuple``: A tuple (return code, message) as follows: :obj:`tuple`: A tuple (return code, message) as follows:
- ``(0, None)`` if the ``start_time`` is correct. - ``(0, None)`` if the ``start_time`` is correct.
- ``!= (0, None)`` otherwise. - ``!= (0, None)`` otherwise.
@@ -171,12 +172,12 @@ class Inspector:
End times must be ahead both the ``start_time`` and the current best chain tip. End times must be ahead both the ``start_time`` and the current best chain tip.
Args: Args:
end_time (int): the block height at which the tower is requested to stop watching for breaches. end_time (:obj:`int`): the block height at which the tower is requested to stop watching for breaches.
start_time (int): the block height at which the tower is requested to start watching for breaches. start_time (:obj:`int`): the block height at which the tower is requested to start watching for breaches.
block_height (int): the chain height. block_height (:obj:`int`): the chain height.
Returns: Returns:
``tuple``: A tuple (return code, message) as follows: :obj:`tuple`: A tuple (return code, message) as follows:
- ``(0, None)`` if the ``end_time`` is correct. - ``(0, None)`` if the ``end_time`` is correct.
- ``!= (0, None)`` otherwise. - ``!= (0, None)`` otherwise.
@@ -228,11 +229,11 @@ class Inspector:
To self delays must be greater or equal to ``MIN_TO_SELF_DELAY``. To self delays must be greater or equal to ``MIN_TO_SELF_DELAY``.
Args: Args:
to_self_delay (int): The ``to_self_delay`` encoded in the ``csv`` of the ``htlc`` that this appointment is to_self_delay (:obj:`int`): The ``to_self_delay`` encoded in the ``csv`` of the ``htlc`` that this
covering. appointment is covering.
Returns: Returns:
``tuple``: A tuple (return code, message) as follows: :obj:`tuple`: A tuple (return code, message) as follows:
- ``(0, None)`` if the ``to_self_delay`` is correct. - ``(0, None)`` if the ``to_self_delay`` is correct.
- ``!= (0, None)`` otherwise. - ``!= (0, None)`` otherwise.
@@ -271,13 +272,11 @@ class Inspector:
""" """
Checks if the provided ``encrypted_blob`` may be correct. Checks if the provided ``encrypted_blob`` may be correct.
FIXME: Currently this only checks format and not empty. It must be improved.
Args: Args:
encrypted_blob (str): the encrypted blob to be checked (hex encoded). encrypted_blob (:obj:`str`): the encrypted blob to be checked (hex encoded).
Returns: Returns:
``tuple``: A tuple (return code, message) as follows: :obj:`tuple`: A tuple (return code, message) as follows:
- ``(0, None)`` if the ``encrypted_blob`` is correct. - ``(0, None)`` if the ``encrypted_blob`` is correct.
- ``!= (0, None)`` otherwise. - ``!= (0, None)`` otherwise.
@@ -315,12 +314,12 @@ class Inspector:
Checks if the provided user signature is correct. Checks if the provided user signature is correct.
Args: Args:
appointment (dict): the appointment that was signed by the user. appointment (:obj:`dict`): the appointment that was signed by the user.
signature (str): the user's signature (hex encoded). signature (:obj:`str`): the user's signature (hex encoded).
pk_der (str): the user's public key (hex encoded, DER format). pk_der (:obj:`str`): the user's public key (hex encoded, DER format).
Returns: Returns:
``tuple``: A tuple (return code, message) as follows: :obj:`tuple`: A tuple (return code, message) as follows:
- ``(0, None)`` if the ``signature`` is correct. - ``(0, None)`` if the ``signature`` is correct.
- ``!= (0, None)`` otherwise. - ``!= (0, None)`` otherwise.

View File

@@ -16,10 +16,10 @@ class _StructuredMessage:
class Logger: class Logger:
""" """
The ``Logger`` is the class in charge of logging events into the log file. The :class:`Logger` is the class in charge of logging events into the log file.
Args: Args:
actor (str): the system actor that is logging the event (e.g. ``Watcher``, ``Cryptographer``, ...). actor (:obj:`str`): the system actor that is logging the event (e.g. ``Watcher``, ``Cryptographer``, ...).
""" """
def __init__(self, actor=None): def __init__(self, actor=None):
@@ -39,7 +39,7 @@ class Logger:
Logs an ``INFO`` level message to stdout and file. Logs an ``INFO`` level message to stdout and file.
Args: Args:
msg (str): the message to be logged. msg (:obj:`str`): the message to be logged.
kwargs: a ``key:value`` collection parameters to be added to the output. kwargs: a ``key:value`` collection parameters to be added to the output.
""" """
@@ -51,7 +51,7 @@ class Logger:
Logs an ``DEBUG`` level message to stdout and file. Logs an ``DEBUG`` level message to stdout and file.
Args: Args:
msg (str): the message to be logged. msg (:obj:`str`): the message to be logged.
kwargs: a ``key:value`` collection parameters to be added to the output. kwargs: a ``key:value`` collection parameters to be added to the output.
""" """
@@ -63,7 +63,7 @@ class Logger:
Logs an ``ERROR`` level message to stdout and file. Logs an ``ERROR`` level message to stdout and file.
Args: Args:
msg (str): the message to be logged. msg (:obj:`str`): the message to be logged.
kwargs: a ``key:value`` collection parameters to be added to the output. kwargs: a ``key:value`` collection parameters to be added to the output.
""" """
@@ -75,7 +75,7 @@ class Logger:
Logs an ``WARNING`` level message to stdout and file. Logs an ``WARNING`` level message to stdout and file.
Args: Args:
msg (str): the message to be logged. msg (:obj:`str`): the message to be logged.
kwargs: a ``key:value`` collection parameters to be added to the output. kwargs: a ``key:value`` collection parameters to be added to the output.
""" """

View File

@@ -16,20 +16,21 @@ logger = Logger("Responder")
class TransactionTracker: class TransactionTracker:
""" """
A ``TransactionTracker`` is used to monitor a ``penalty_tx``. Once the dispute is seen by the A :class:`TransactionTracker` is used to monitor a ``penalty_tx``. Once the dispute is seen by the
:mod:`Watcher <pisa.watcher>` the penalty transaction is decrypted and the relevant appointment data is passed :obj:`Watcher <pisa.watcher.Watcher>` the penalty transaction is decrypted and the relevant appointment data is
along to the ``Responder``. passed along to the :obj:`Responder`.
Once the ``Responder`` has succeeded on broadcasting the penalty transaction it will create a ``TransactionTracker`` Once the :obj:`Responder` has succeeded on broadcasting the penalty transaction it will create a
and monitor the blockchain until the end of the appointment. :obj:`TransactionTracker` and monitor the blockchain until the end of the appointment.
Args: Args:
locator (str): A 16-byte hex-encoded value used by the tower to detect channel breaches. It serves as a trigger locator (:obj:`str`): A 16-byte hex-encoded value used by the tower to detect channel breaches. It serves as a
for the tower to decrypt and broadcast the penalty transaction. trigger for the tower to decrypt and broadcast the penalty transaction.
dispute_txid (str): the id of the transaction that created the channel breach and triggered the penalty. dispute_txid (:obj:`str`): the id of the transaction that created the channel breach and triggered the penalty.
penalty_txid (str): the id of the transaction that was encrypted under ``dispute_txid``. penalty_txid (:obj:`str`): the id of the transaction that was encrypted under ``dispute_txid``.
penalty_rawtx (str): the raw transaction that was broadcast as a consequence of the channel breach. penalty_rawtx (:obj:`str`): the raw transaction that was broadcast as a consequence of the channel breach.
appointment_end (int): the block at which the tower will stop monitoring the blockchain for this appointment. appointment_end (:obj:`int`): the block at which the tower will stop monitoring the blockchain for this
appointment.
""" """
def __init__(self, locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end): def __init__(self, locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end):
@@ -42,17 +43,17 @@ class TransactionTracker:
@classmethod @classmethod
def from_dict(cls, tx_tracker_data): def from_dict(cls, tx_tracker_data):
""" """
Constructs a ``TransactionTracker`` instance from a dictionary. Requires that all the fields are populated Constructs a :obj:`TransactionTracker` instance from a dictionary. Requires that all the fields are populated
(``not None``). (``not None``).
Useful to load data from the database. Useful to load data from the database.
Args: Args:
tx_tracker_data (dict): a dictionary with an entry per each field required to create the tx_tracker_data (:obj:`dict`): a dictionary with an entry per each field required to create the
``TransactionTracker``. :obj:`TransactionTracker`.
Returns: Returns:
``TransactionTracker``: A ``TransactionTracker`` instantiated with the provided data. :obj:`TransactionTracker`: A ``TransactionTracker`` instantiated with the provided data.
Raises: Raises:
ValueError: if any of the required fields is missing. ValueError: if any of the required fields is missing.
@@ -74,10 +75,10 @@ class TransactionTracker:
def to_dict(self): def to_dict(self):
""" """
Exports a ``TransactionTracker`` as a dictionary. Exports a :obj:`TransactionTracker` as a dictionary.
Returns: Returns:
``dict``: A dictionary containing the ``TransactionTracker`` data. :obj:`dict`: A dictionary containing the :obj:`TransactionTracker` data.
""" """
tx_tracker = { tx_tracker = {
@@ -92,10 +93,10 @@ class TransactionTracker:
def to_json(self): def to_json(self):
""" """
Exports a ``TransactionTracker`` as a json-encoded dictionary. Exports a :obj:`TransactionTracker` as a json-encoded dictionary.
Returns: Returns:
``str``: A json-encoded dictionary containing the ``TransactionTracker`` data. :obj:`str`: A json-encoded dictionary containing the :obj:`TransactionTracker` data.
""" """
return json.dumps(self.to_dict()) return json.dumps(self.to_dict())
@@ -103,29 +104,34 @@ class TransactionTracker:
class Responder: class Responder:
""" """
The ``Responder`` is the class in charge of ensuring that channel breaches are dealt with. It does so handling the The :class:`Responder` is the class in charge of ensuring that channel breaches are dealt with. It does so handling
decrypted ``penalty_txs`` handed by the :mod:`Watcher <pisa.watcher>` and ensuring the they make it to the the decrypted ``penalty_txs`` handed by the :obj:`Watcher <pisa.watcher.Watcher>` and ensuring the they make it to
blockchain. the blockchain.
The :class:`Responder` can be in two states:
The ``Responder`` can be in two states:
- Asleep (``self.asleep = True)`` when there are no trackers to take care of (``self.trackers`` is empty). - Asleep (``self.asleep = True)`` when there are no trackers to take care of (``self.trackers`` is empty).
- Awake (``self.asleep = False)`` when there are trackers to take care of (actively monitoring the blockchain). - Awake (``self.asleep = False)`` when there are trackers to take care of (actively monitoring the blockchain).
Args: Args:
db_manager (DBManager): a :mod:`DBManager <pisa.db_manager>` instance to interact with the database. db_manager (:obj:`DBManager <pisa.db_manager.DBManager>`): a ``DBManager`` instance to interact with the
database.
Attributes: Attributes:
trackers (``dict``): A dictionary containing all the ``TransactionTrackers`` handled by the ``Responder``. trackers (:obj:`dict`): A dictionary containing all the :obj:`TransactionTracker` handled by the
Each entry is identified by a ``uuid``. :obj:`Responder`. Each entry is identified by a ``uuid``.
tx_tracker_map (``dict``): A ``penalty_txid:uuid`` map used to allow the ``Responder`` to deal with several tx_tracker_map (:obj:`dict`): A ``penalty_txid:uuid`` map used to allow the :obj:`Responder` to deal with
trackers triggered by the same ``penalty_txid``. several trackers triggered by the same ``penalty_txid``.
unconfirmed_txs (``list``): A list that keeps track of all unconfirmed ``penalty_txs``. unconfirmed_txs (:obj:`list`): A list that keeps track of all unconfirmed ``penalty_txs``.
missed_confirmations (``dict``): a dictionary that keeps count of how many confirmations each ``penalty_tx`` has missed_confirmations (:obj:`dict`): A dictionary that keeps count of how many confirmations each ``penalty_tx``
missed. Used to trigger rebroadcast if needed. has missed. Used to trigger rebroadcast if needed.
asleep (``bool``): A flag that signals whether the ``Responder`` is asleep or awake. asleep (:obj:`bool`): A flag that signals whether the :obj:`Responder` is asleep or awake.
block_queue (``Queue``): A queue used by the ``Responder`` to receive block hashes from ``bitcoind``. It is block_queue (:obj:`Queue`): A queue used by the :obj:`Responder` to receive block hashes from ``bitcoind``. It
populated by the ``ZMQSubscriber``. is populated by the :obj:`ZMQSubscriber <pisa.utils.zmq_subscriber.ZMQSubscriber>`.
db_manager (``DBManager``): A :mod:`DBManager <pisa.db_manager>` instance to interact with the database. zmq_subscriber (:obj:`ZMQSubscriber <pisa.utils.zmq_subscriber.ZMQSubscriber>`): a ``ZMQSubscriber`` instance
used to receive new block notifications from ``bitcoind``.
db_manager (:obj:`DBManager <pisa.db_manager.DBManager>`): A ``DBManager`` instance to interact with the
database.
""" """
@@ -142,22 +148,22 @@ class Responder:
@staticmethod @staticmethod
def on_sync(block_hash): def on_sync(block_hash):
""" """
Whether the ``Responder`` is on sync with ``bitcoind`` or not. Used when recovering from a crash. Whether the :obj:`Responder` is on sync with ``bitcoind`` or not. Used when recovering from a crash.
The Watchtower can be instantiated with fresh or with backed up data. In the later, some triggers may have been The Watchtower can be instantiated with fresh or with backed up data. In the later, some triggers may have been
missed. In order to go back on sync both the ``Watcher`` and the ``Responder`` need to perform the state missed. In order to go back on sync both the :obj:`Watcher <pisa.watcher.Watcher>` and the :obj:`Responder`
transitions until they catch up. need to perform the state transitions until they catch up.
If a transaction is broadcast by the ``Responder`` and it is rejected (due to a double-spending for example) If a transaction is broadcast by the :obj:`Responder` and it is rejected (due to a double-spending for example)
and the ``Responder`` is off-sync then the ``TransactionTracker`` is abandoned. and the :obj:`Responder` is off-sync then the :obj:`TransactionTracker` is abandoned.
This method helps making that decision. This method helps making that decision.
Args: Args:
block_hash (str): the block hash passed to the ``Responder`` in the ``handle_breach`` request. block_hash (:obj:`str`): the block hash passed to the :obj:`Responder` in the ``handle_breach`` request.
Returns: Returns:
``bool``: Whether or not the ``Responder`` and ``bitcoind`` are on sync. :obj:`bool`: Whether or not the :obj:`Responder` and ``bitcoind`` are on sync.
""" """
block_processor = BlockProcessor() block_processor = BlockProcessor()
@@ -173,20 +179,20 @@ class Responder:
def handle_breach(self, uuid, locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end, block_hash): def handle_breach(self, uuid, locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end, block_hash):
""" """
Requests the ``Responder`` to handle a channel breach. This is the entry point of the ``Responder``. Requests the :obj:`Responder` to handle a channel breach. This is the entry point of the :obj:`Responder`.
Args: Args:
uuid (str): a unique identifier for the appointment. uuid (:obj:`str`): a unique identifier for the appointment.
locator (str): the appointment locator provided by the user (16-byte hex-encoded). locator (:obj:`str`): the appointment locator provided by the user (16-byte hex-encoded).
dispute_txid (str): the id of the transaction that created the channel breach. dispute_txid (:obj:`str`): the id of the transaction that created the channel breach.
penalty_txid (str): the id of the decrypted transaction included in the appointment. penalty_txid (:obj:`str`): the id of the decrypted transaction included in the appointment.
penalty_rawtx (str): the raw transaction to be broadcast in response of the breach. penalty_rawtx (:obj:`str`): the raw transaction to be broadcast in response of the breach.
appointment_end (int): the block height at which the ``Responder`` will stop monitoring for this penalty appointment_end (:obj:`int`): the block height at which the :obj:`Responder` will stop monitoring for this
transaction. penalty transaction.
block_hash (str): the block hash at which the breach was seen (used to see if we are on sync). block_hash (:obj:`str`): the block hash at which the breach was seen (used to see if we are on sync).
Returns: Returns:
``Receipt``: A :mod:`Receipt <pisa.carrier.Receipt>` indicating whether or not the ``penalty_tx`` made it :obj:`Receipt <pisa.carrier.Receipt>`: A ``Receipt`` indicating whether or not the ``penalty_tx`` made it
into the blockchain. into the blockchain.
""" """
@@ -213,22 +219,24 @@ class Responder:
def add_tracker(self, uuid, locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end, confirmations=0): def add_tracker(self, uuid, locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end, confirmations=0):
""" """
Creates a ``TransactionTracker`` after successfully broadcasting a ``penalty_tx``. Creates a :obj:`TransactionTracker` after successfully broadcasting a ``penalty_tx``.
The ``TransactionTracker`` is stored in ``trackers`` and ``tx_tracker_map`` and the ``penalty_txid`` added to The :obj:`TransactionTracker` is stored in ``trackers`` and ``tx_tracker_map`` and the ``penalty_txid`` added to
``unconfirmed_txs`` if ``confirmations=0``. Finally, the data is also stored in the database. ``unconfirmed_txs`` if ``confirmations=0``. Finally, the data is also stored in the database.
``add_tracker`` awakes the ``Responder`` and creates a connection with the ``ZMQSubscriber`` if he is asleep. ``add_tracker`` awakes the :obj:`Responder` and creates a connection with the
:obj:`ZMQSubscriber <pisa.utils.zmq_subscriber.ZMQSubscriber>` if he is asleep.
Args: Args:
uuid (str): a unique identifier for the appointment. uuid (:obj:`str`): a unique identifier for the appointment.
locator (str): the appointment locator provided by the user (16-byte hex-encoded). locator (:obj:`str`): the appointment locator provided by the user (16-byte hex-encoded).
dispute_txid (str): the id of the transaction that created the channel breach. dispute_txid (:obj:`str`): the id of the transaction that created the channel breach.
penalty_txid (str): the id of the decrypted transaction included in the appointment. penalty_txid (:obj:`str`): the id of the decrypted transaction included in the appointment.
penalty_rawtx (str): the raw transaction to be broadcast. penalty_rawtx (:obj:`str`): the raw transaction to be broadcast.
appointment_end (int): the block height at which the ``Responder`` will stop monitoring for the tracker. appointment_end (:obj:`int`): the block height at which the :obj:`Responder` will stop monitoring for the
confirmations (int): the confirmation count of the ``penalty_tx``. In normal conditions it will be zero, but tracker.
if the transaction is already on the blockchain this won't be the case. confirmations (:obj:`int`): the confirmation count of the ``penalty_tx``. In normal conditions it will be
zero, but if the transaction is already on the blockchain this won't be the case.
""" """
tracker = TransactionTracker(locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end) tracker = TransactionTracker(locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end)
@@ -259,8 +267,8 @@ class Responder:
def do_subscribe(self): def do_subscribe(self):
""" """
Initializes a ``ZMQSubscriber`` instance to listen to new blocks from ``bitcoind``. Block ids are received Initializes a :obj:`ZMQSubscriber <pisa.utils.zmq_subscriber.ZMQSubscriber>` instance to listen to new blocks
trough the ``block_queue``. from ``bitcoind``. Block ids are received trough the ``block_queue``.
""" """
self.zmq_subscriber = ZMQSubscriber(parent="Responder") self.zmq_subscriber = ZMQSubscriber(parent="Responder")
@@ -270,7 +278,8 @@ class Responder:
""" """
Monitors the blockchain whilst there are pending trackers. Monitors the blockchain whilst there are pending trackers.
This is the main method of the ``Responder`` and triggers tracker cleaning, rebroadcasting, reorg managing, etc. This is the main method of the :obj:`Responder` and triggers tracker cleaning, rebroadcasting, reorg managing,
etc.
""" """
# ToDo: change prev_block_hash to the last known tip when bootstrapping # ToDo: change prev_block_hash to the last known tip when bootstrapping
@@ -316,7 +325,7 @@ class Responder:
prev_block_hash = block.get("hash") prev_block_hash = block.get("hash")
# Go back to sleep if there are no more pendong trackers # Go back to sleep if there are no more pending trackers
self.asleep = True self.asleep = True
self.zmq_subscriber.terminate = True self.zmq_subscriber.terminate = True
self.block_queue = Queue() self.block_queue = Queue()
@@ -330,7 +339,8 @@ class Responder:
This method manages ``unconfirmed_txs`` and ``missed_confirmations``. This method manages ``unconfirmed_txs`` and ``missed_confirmations``.
Args: Args:
txs (list): A list of confirmed tx ids (the list of transactions included in the last received block). txs (:obj:`list`): A list of confirmed tx ids (the list of transactions included in the last received
block).
""" """
# If a new confirmed tx matches a tx we are watching, then we remove it from the unconfirmed txs map # If a new confirmed tx matches a tx we are watching, then we remove it from the unconfirmed txs map
@@ -356,7 +366,7 @@ class Responder:
Gets the transactions to be rebroadcast based on their ``missed_confirmation`` count. Gets the transactions to be rebroadcast based on their ``missed_confirmation`` count.
Returns: Returns:
``list``: A list with all the ids of the transaction that have to be rebroadcast. :obj:`list`: A list with all the ids of the transaction that have to be rebroadcast.
""" """
txs_to_rebroadcast = [] txs_to_rebroadcast = []
@@ -374,10 +384,10 @@ class Responder:
minimum confirmation count). minimum confirmation count).
Args: Args:
height (int): the height of the last received block. height (:obj:`int`): the height of the last received block.
Returns: Returns:
``list``: a list of tuples ``uuid:confirmations`` for the completed trackers. :obj:`list`: a list of tuples ``uuid:confirmations`` for the completed trackers.
""" """
completed_trackers = [] completed_trackers = []
@@ -402,14 +412,14 @@ class Responder:
forever si the transaction keeps not getting it. forever si the transaction keeps not getting it.
Potentially the fees could be bumped here if the transaction has some tower dedicated outputs (or allows it Potentially the fees could be bumped here if the transaction has some tower dedicated outputs (or allows it
trough ``ANYONECANSPEND`` or something similar). trough ``ANYONECANPAY`` or something similar).
Args: Args:
txs_to_rebroadcast (list): a list of transactions to be rebroadcast. txs_to_rebroadcast (:obj:`list`): a list of transactions to be rebroadcast.
Returns: Returns:
``list``: A list of ``Receipts`` with information about whether or not every transaction made it trough the :obj:`list`: A list of :obj:`Receipts <pisa.carrier.Receipt>` with information about whether or not every
network. transaction made it trough the network.
""" """
# DISCUSS: #22-discuss-confirmations-before-retry # DISCUSS: #22-discuss-confirmations-before-retry
@@ -442,10 +452,10 @@ class Responder:
def handle_reorgs(self, block_hash): def handle_reorgs(self, block_hash):
""" """
Basic reorg handle. It deals with situations where a reorg has been found but the ``dispute_tx`` is still Basic reorg handle. It deals with situations where a reorg has been found but the ``dispute_tx`` is still
on the chain. If the ``dispute_tx`` is reverted, it need to call the ``ReorgManager`` (not implemented yet). on the chain. If the ``dispute_tx`` is reverted, it need to call the :obj:`ReorgManager` (Soon TM).
Args: Args:
block_hash (str): the hash of the last block received (which triggered the reorg). block_hash (:obj:`str`): the hash of the last block received (which triggered the reorg).
""" """
carrier = Carrier() carrier = Carrier()

View File

@@ -14,8 +14,8 @@ def bitcoin_cli():
An ``http`` connection with ``bitcoind`` using the ``json-rpc`` interface. An ``http`` connection with ``bitcoind`` using the ``json-rpc`` interface.
Returns: Returns:
``AuthServiceProxy``: An authenticated service proxy to ``bitcoind`` that can be used to send ``json-rpc`` :obj:`AuthServiceProxy <pisa.utils.auth_proxy.AuthServiceProxy>`: An authenticated service proxy to ``bitcoind``
commands. that can be used to send ``json-rpc`` commands.
""" """
return AuthServiceProxy( return AuthServiceProxy(
@@ -29,7 +29,7 @@ def can_connect_to_bitcoind():
Checks if the tower has connection to ``bitcoind``. Checks if the tower has connection to ``bitcoind``.
Returns: Returns:
``bool``: ``True`` if the connection can be established. ``False`` otherwise. :obj:`bool`: ``True`` if the connection can be established. ``False`` otherwise.
""" """
can_connect = True can_connect = True
@@ -48,7 +48,7 @@ def in_correct_network(network):
``regtest``) ``regtest``)
Returns: Returns:
``bool``: ``True`` if the network configuration matches. ``False`` otherwise. :obj:`bool`: ``True`` if the network configuration matches. ``False`` otherwise.
""" """
mainnet_genesis_block_hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" mainnet_genesis_block_hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"

View File

@@ -17,17 +17,18 @@ logger = Logger("Watcher")
class Watcher: class Watcher:
""" """
The ``Watcher`` is the class in charge to watch for channel breaches for the appointments accepted by the tower. The :class:`Watcher` is the class in charge to watch for channel breaches for the appointments accepted by the
tower.
The ``Watcher`` keeps track of the accepted appointments in ``appointments`` and, for new received block, checks The :class:`Watcher` keeps track of the accepted appointments in ``appointments`` and, for new received block,
if any breach has happened by comparing the txids with the appointment locators. If a breach is seen, the checks if any breach has happened by comparing the txids with the appointment locators. If a breach is seen, the
:mod:`EncryptedBlob <pisa.encrypted_blob>` of the corresponding appointment is decrypted and the data is passed :obj:`EncryptedBlob <pisa.encrypted_blob.EncryptedBlob>` of the corresponding appointment is decrypted and the data
to the :mod:`Responder <pisa.responder>`. is passed to the :obj:`Responder <pisa.responder.Responder>`.
If an appointment reaches its end with no breach, the data is simply deleted. If an appointment reaches its end with no breach, the data is simply deleted.
The ``Watcher`` receives information about new received blocks via the ``block_queue`` that is populated by the The :class:`Watcher` receives information about new received blocks via the ``block_queue`` that is populated by the
:mod:`ZMQSubscriber <pisa.utils.zmq_subscriber>`. :obj:`ZMQSubscriber <pisa.utils.zmq_subscriber>`.
Args: Args:
db_manager (:obj:`DBManager <pisa.db_manager>`): a ``DBManager`` instance to interact with the database. db_manager (:obj:`DBManager <pisa.db_manager>`): a ``DBManager`` instance to interact with the database.
@@ -99,8 +100,8 @@ class Watcher:
It will go back to sleep once there are no more pending appointments. It will go back to sleep once there are no more pending appointments.
Once a breach is seen on the blockchain, the :obj:`Watcher` will decrypt the corresponding Once a breach is seen on the blockchain, the :obj:`Watcher` will decrypt the corresponding
:mod:`EncryptedBlob <pisa.encrypted_blob.EncryptedBlob` and pass the information to the :obj:`EncryptedBlob <pisa.encrypted_blob.EncryptedBlob>` and pass the information to the
:mod:`Responder <pisa.responder.Responder>`. :obj:`Responder <pisa.responder.Responder>`.
The tower may store multiple appointments with the same ``locator`` to avoid DoS attacks based on data The tower may store multiple appointments with the same ``locator`` to avoid DoS attacks based on data
rewriting. `locators`` should be derived from the ``dispute_txid``, but that task is performed by the user, and rewriting. `locators`` should be derived from the ``dispute_txid``, but that task is performed by the user, and