Includes Appointment docstrings and redesigns triggered flag

The triggered flag is only used to interact with the DB but it was kept as an Appointment attribute. Now it is only used when exporting to json, which is used to store data into the db.
This commit is contained in:
Sergi Delgado Segura
2019-12-09 14:28:00 +01:00
parent 641cc3be4f
commit add5d262b6
5 changed files with 91 additions and 25 deletions

View File

@@ -3,36 +3,69 @@ import json
from pisa.encrypted_blob import EncryptedBlob
# Basic appointment structure
class Appointment:
"""
The Appointment class contains the information regarding an appointment between a client and the Watchtower.
Args:
locator (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.
start_time (int): The block height at which the tower is hired to start watching for breaches.
end_time (int): The block height at which the tower will stop watching for breaches.
dispute_delta (int): The `to_self_delay` encoded in the CSV of the HTLC that this appointment is covering.
encrypted_blob (EncryptedBlob): An `EncryptedBlob` object containing an encrypted penalty transaction. The tower
will decrypt it and broadcast the penalty transaction upon seeing a breach on the blockchain.
"""
# DISCUSS: 35-appointment-checks
def __init__(self, locator, start_time, end_time, dispute_delta, encrypted_blob, triggered=False):
def __init__(self, locator, start_time, end_time, dispute_delta, encrypted_blob):
self.locator = locator
self.start_time = start_time # ToDo: #4-standardize-appointment-fields
self.end_time = end_time # ToDo: #4-standardize-appointment-fields
self.dispute_delta = dispute_delta
self.encrypted_blob = EncryptedBlob(encrypted_blob)
self.triggered = triggered
@classmethod
def from_dict(cls, appointment_data):
"""
Builds an appointment from a dictionary.
This method is useful to load data from a database.
Args:
appointment_data (dict): a dictionary containing the following keys:
`{locator, start_time, end_time, dispute_delta, encrypted_blob}`
Returns:
Appointment: An appointment initialized using the provided data.
Raises:
ValueError: If one of the mandatory keys is missing in `appointment_data`.
"""
locator = appointment_data.get("locator")
start_time = appointment_data.get("start_time") # ToDo: #4-standardize-appointment-fields
end_time = appointment_data.get("end_time") # ToDo: #4-standardize-appointment-fields
dispute_delta = appointment_data.get("dispute_delta")
encrypted_blob_data = appointment_data.get("encrypted_blob")
triggered = True if appointment_data.get("triggered") is True else False
if any(v is None for v in [locator, start_time, end_time, dispute_delta, encrypted_blob_data, triggered]):
if any(v is None for v in [locator, start_time, end_time, dispute_delta, encrypted_blob_data]):
raise ValueError("Wrong appointment data, some fields are missing")
else:
appointment = cls(locator, start_time, end_time, dispute_delta, encrypted_blob_data, triggered)
appointment = cls(locator, start_time, end_time, dispute_delta, encrypted_blob_data)
return appointment
def to_dict(self, include_triggered=True):
def to_dict(self):
"""
Exports an `Appointment` as a dictionary.
Returns:
appointment (dict): A dictionary containing the `Appointment` attributes.
"""
# ToDO: #3-improve-appointment-structure
appointment = {
"locator": self.locator,
@@ -42,10 +75,26 @@ class Appointment:
"encrypted_blob": self.encrypted_blob.data,
}
if include_triggered:
appointment["triggered"] = self.triggered
return appointment
def to_json(self):
return json.dumps(self.to_dict(), sort_keys=True, separators=(",", ":"))
def to_json(self, triggered=False):
"""
Exports an `Appointment` as a deterministic json encoded string.
This method ensures that multiple invocations with the same data yield the same value. This is the format used
to store appointments in the database.
Args:
triggered (bool): Whether the dispute has been triggered or not. When an appointment passes from the
`Watcher` to the `Responder` it is not deleted straightaway. Instead, the appointment is stored in the DB
flagged as triggered. This aims to ease handling block reorgs in the future.
Returns:
appointment (str): A json-encoded str representing the appointment.
"""
appointment = self.to_dict()
appointment["triggered"] = triggered
return json.dumps(appointment, sort_keys=True, separators=(",", ":"))