teos.watcher

exception AppointmentAlreadyTriggered(msg, **kwargs)[source]

Bases: common.exceptions.BasicException

Raised when an appointment is sent to the Watcher but that same data has already been sent to the Responder.

exception AppointmentLimitReached(msg, **kwargs)[source]

Bases: common.exceptions.BasicException

Raised when the tower maximum appointment count has been reached.

exception AppointmentNotFound(msg, **kwargs)[source]

Bases: common.exceptions.BasicException

Raised when an appointment is not found on the tower.

class LocatorCache(blocks_in_cache)[source]

Bases: object

The LocatorCache keeps the data about the last cache_size blocks around so appointments can be checked against it. The data is indexed by locator and it’s mainly built during the normal Watcher operation so no extra steps are normally needed.

Parameters

blocks_in_cache (int) – the numbers of blocks to keep in the cache.

logger

The logger for this component.

Type

Logger

cache

A dictionary of locator:dispute_txid pairs that received appointments are checked against.

Type

dict

blocks

An ordered dictionary of the last blocks_in_cache blocks (block_hash:locators). Used to keep track of what data belongs to what block, so data can be pruned accordingly. Also needed to rebuild the cache in case of reorgs.

Type

OrderedDict

cache_size

The size of the cache in blocks.

Type

int

fix(last_known_block, block_processor)[source]

Fixes the cache after a reorg has been detected by feeding the most recent cache_size blocks to it.

Parameters
  • last_known_block (str) – the last known block hash after the reorg.

  • block_processor (BlockProcessor) – a block processor instance.

get_txid(locator)[source]

Gets a txid from the locator cache.

Parameters

locator (str) – the locator to lookup in the cache.

Returns

The txid linked to the given locator if found. None otherwise.

Return type

str or None

init(last_known_block, block_processor)[source]

Sets the initial state of the locator cache.

Parameters
  • last_known_block (str) – the last known block by the Watcher.

  • block_processor (BlockProcessor) – a block processor instance.

is_full()[source]

Returns whether the cache is full or not.

remove_oldest_block()[source]

Removes the oldest block from the cache.

update(block_hash, locator_txid_map)[source]

Updates the cache with data from a new block. Removes the oldest block if the cache is full after the addition.

Parameters
  • block_hash (str) – the hash of the new block.

  • locator_txid_map (dict) – the dictionary of locators (locator:txid) derived from a list of transaction ids.

class Watcher(db_manager, gatekeeper, block_processor, responder, sk, max_appointments, blocks_in_cache)[source]

Bases: object

The Watcher is in charge of watching for channel breaches for the appointments accepted by the tower.

The Watcher keeps track of the accepted appointments in appointments and, for new received blocks, checks if any breach has happened by comparing the txids with the appointment locators. If a breach is seen, the encrypted_blob of the corresponding appointment is decrypted and the data is passed to the Responder.

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 ChainMonitor.

Parameters
  • db_manager (AppointmentsDBM) – an instance of the appointment database manager to interact with the database.

  • block_processor (BlockProcessor) – a block processor instance to get block from bitcoind.

  • responder (Responder) – a responder instance.

  • sk (PrivateKey) – a private key used to sign accepted appointments.

  • max_appointments (int) – the maximum amount of appointments accepted by the Watcher at the same time.

  • blocks_in_cache (int) – the number of blocks to keep in cache so recently triggered appointments can be covered.

appointments

A dictionary containing a summary of the appointments (ExtendedAppointment instances) accepted by the tower (locator and user_id). It’s populated trough add_appointment.

Type

dict

locator_uuid_map

A locator:uuid map used to allow the Watcher to deal with several appointments with the same locator.

Type

dict

block_queue

A queue used by the Watcher to receive block hashes from bitcoind. It is populated by the ChainMonitor.

Type

Queue

db_manager

An instance of the appointment database manager to interact with the database.

Type

AppointmentsDBM

gatekeeper

A gatekeeper instance in charge to control the user access and subscription expiry.

Type

Gatekeeper

block_processor

A block processor instance to get block from bitcoind.

Type

BlockProcessor

responder

A responder instance.

Type

Responder

signing_key

A private key used to sign accepted appointments.

Type

PrivateKey

max_appointments

The maximum amount of appointments accepted by the Watcher at the same time.

Type

int

last_known_block

The last block known by the Watcher.

Type

str

locator_cache

A cache of locators for the last blocks_in_cache blocks.

Type

LocatorCache

Raises

InvalidKey – if teos sk cannot be loaded.

add_appointment(appointment, user_signature)[source]

Adds a new appointment to the appointments dictionary if max_appointments has not been reached.

add_appointment is the entry point of the Watcher. Upon receiving a new appointment it will start monitoring the blockchain (do_watch) until appointments is empty.

Once a breach is seen on the blockchain, the Watcher will decrypt the corresponding encrypted_blob and pass the information to the Responder.

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 the tower has no way of verifying whether or not they have been properly derived. Therefore, appointments are identified by uuid and stored in appointments and locator_uuid_map.

Parameters
  • appointment (Appointment) – the appointment to be added to the Watcher.

  • user_signature (str) – the user’s appointment signature (hex-encoded).

Returns

The tower response as a dict, containing: locator, signature, available_slots and subscription_expiry.

Return type

dict

Raises
awake()[source]

Starts a new thread to monitor the blockchain for channel breaches. The thread will run until the ChainMonitor adds the "END" message to the queue.

Returns

The thread object that was just created and is already running.

Return type

Thread

check_breach(uuid, appointment, dispute_txid)[source]

Checks if a breach is valid. Valid breaches should decrypt to a valid transaction.

Parameters
  • uuid (str) – the uuid of the appointment that was triggered by the breach.

  • appointment (ExtendedAppointment) – the appointment data.

  • dispute_txid (str) – the id of the transaction that triggered the breach.

Returns

A tuple containing the penalty txid and the raw penalty tx.

Return type

tuple

Raises
  • EncryptionError – if the encrypted blob from the provided appointment cannot be decrypted with the key derived from the breach transaction id.

  • InvalidTransactionFormat – if the decrypted data does not have a valid transaction format.

do_watch()[source]

Monitors the blockchain for channel breaches.

This is the main method of the Watcher and the one in charge to pass appointments to the Responder upon detecting a breach.

filter_breaches(breaches)[source]

Filters the valid from the invalid channel breaches.

The Watcher cannot know if an encrypted_blob contains a valid transaction until a breach is seen. Blobs that contain arbitrary data are dropped and not sent to the Responder.

Parameters

breaches (dict) – a dictionary containing channel breaches (locator:txid).

Returns

A dictionary and a list. The former contains the valid breaches, while the latter contain the invalid ones.

The valid breaches dictionary has the following structure:

{locator, dispute_txid, penalty_txid, penalty_rawtx}

Return type

tuple

get_all_responder_trackers()[source]

Returns a dictionary with all the trackers stored in the db for the responder.

get_all_watcher_appointments()[source]

Returns a dictionary with all the appointment stored in the db for the watcher.

get_appointment(locator, user_signature)[source]

Gets information about an appointment.

The appointment can either be in the watcher, the responder, or not found.

Parameters
  • locator (str) – a 16-byte hex-encoded value used by the tower to detect channel breaches.

  • user_signature (str) – the signature of the request by the user.

Returns

A tuple containing the appointment data and the status (either "being_watched" or "dispute_responded").

Return type

tuple

Raises

AppointmentNotFound – if the appointment is not found in the tower.

get_breaches(locator_txid_map)[source]

Gets a dictionary of channel breaches given a map of locator:dispute_txid.

Parameters

locator_txid_map (dict) – the dictionary of locators (locator:txid) derived from a list of transaction ids.

Returns

A dictionary (locator:txid) with all the breaches found. An empty dictionary if none are found.

Return type

dict

get_registered_user_ids()[source]

Returns the list of user ids of all the registered users.

get_user_info(user_id)[source]

Returns the data hold by the tower about the user given an user_id.

Parameters

user_id (str) – the id of the requested user.

Returns

The user data if found. None if not found, or the user_id is invalid.

Return type

UserInfo <teos.gatekeeper.UserInfo> or :obj:`None

property n_registered_users

Get the number of users currently registered to the tower.

property n_responder_trackers

Get the total number of trackers in the responder.

property n_watcher_appointments

Get the total number of appointments stored in the watcher.

register(user_id)[source]

Registers a user.

Parameters

user_id (str) – the public key that identifies the user (33-bytes hex str).

Returns

A tuple containing the available slots, the subscription expiry, and the signature of the registration receipt by the Watcher.

Return type

tuple

property tower_id

Get the id of this tower, as a hex string.