mirror of
https://github.com/aljazceru/python-teos.git
synced 2025-12-17 06:04:21 +01:00
Removes start/end time from appointment
This commit is contained in:
@@ -49,10 +49,10 @@ for opt, arg in opts:
|
|||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
if rcode == 0:
|
if appointment_data is None:
|
||||||
rcode, message = self.check_start_time(start_time, block_height)
|
raise InspectionFailed(errors.APPOINTMENT_EMPTY_FIELD, "empty appointment received")
|
||||||
if rcode == 0:
|
elif not isinstance(appointment_data, dict):
|
||||||
rcode, message = self.check_end_time(end_time, start_time, block_height)
|
raise InspectionFailed(errors.APPOINTMENT_WRONG_FIELD, "wrong appointment format")
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dev Requirements
|
## Dev Requirements
|
||||||
|
|||||||
@@ -44,8 +44,6 @@ This command is used to send appointments to the watchtower. Appointments **must
|
|||||||
|
|
||||||
{ "tx": tx,
|
{ "tx": tx,
|
||||||
"tx_id": tx_id,
|
"tx_id": tx_id,
|
||||||
"start_time": s,
|
|
||||||
"end_time": e,
|
|
||||||
"to_self_delay": d }
|
"to_self_delay": d }
|
||||||
|
|
||||||
`tx` **must** be the raw penalty transaction that will be encrypted before sent to the watchtower. `type(tx) = hex encoded str`
|
`tx` **must** be the raw penalty transaction that will be encrypted before sent to the watchtower. `type(tx) = hex encoded str`
|
||||||
@@ -60,12 +58,6 @@ This command is used to send appointments to the watchtower. Appointments **must
|
|||||||
|
|
||||||
The API will return a `application/json` HTTP response code `200/OK` if the appointment is accepted, with the locator encoded in the response text, or a `400/Bad Request` if the appointment is rejected, with the rejection reason encoded in the response text.
|
The API will return a `application/json` HTTP response code `200/OK` if the appointment is accepted, with the locator encoded in the response text, or a `400/Bad Request` if the appointment is rejected, with the rejection reason encoded in the response text.
|
||||||
|
|
||||||
### Alpha release restrictions
|
|
||||||
The alpha release does not have authentication, payments nor rate limiting, therefore some self imposed restrictions apply:
|
|
||||||
|
|
||||||
- `start_time` should be within the next 6 blocks `[current_time+1, current_time+6]`.
|
|
||||||
- `end_time` cannot be bigger than (roughly) a month. That is `4320` blocks on top of `start_time`.
|
|
||||||
|
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
@@ -103,9 +95,7 @@ if `-f, --file` **is** specified, then the command expects a path to a json file
|
|||||||
"appointment":
|
"appointment":
|
||||||
{
|
{
|
||||||
"encrypted_blob": eb,
|
"encrypted_blob": eb,
|
||||||
"end_time": e,
|
|
||||||
"locator": appointment_locator,
|
"locator": appointment_locator,
|
||||||
"start_time": s,
|
|
||||||
"status": "being_watched",
|
"status": "being_watched",
|
||||||
"to_self_delay": d
|
"to_self_delay": d
|
||||||
}
|
}
|
||||||
@@ -118,7 +108,6 @@ if `-f, --file` **is** specified, then the command expects a path to a json file
|
|||||||
"status": "dispute_responded",
|
"status": "dispute_responded",
|
||||||
"appointment":
|
"appointment":
|
||||||
{
|
{
|
||||||
"appointment_end": e,
|
|
||||||
"dispute_txid": dispute_txid,
|
"dispute_txid": dispute_txid,
|
||||||
"locator": appointment_locator,
|
"locator": appointment_locator,
|
||||||
"penalty_rawtx": penalty_rawtx,
|
"penalty_rawtx": penalty_rawtx,
|
||||||
@@ -164,10 +153,10 @@ python teos_cli.py register
|
|||||||
2. Generate a new dummy appointment. **Note:** this appointment will never be fulfilled (it will eventually expire) since it does not correspond to a valid transaction. However it can be used to interact with the Eye of Satoshi's API.
|
2. Generate a new dummy appointment. **Note:** this appointment will never be fulfilled (it will eventually expire) since it does not correspond to a valid transaction. However it can be used to interact with the Eye of Satoshi's API.
|
||||||
|
|
||||||
```
|
```
|
||||||
echo '{"tx": "4615a58815475ab8145b6bb90b1268a0dbb02e344ddd483f45052bec1f15b1951c1ee7f070a0993da395a5ee92ea3a1c184b5ffdb2507164bf1f8c1364155d48bdbc882eee0868ca69864a807f213f538990ad16f56d7dfb28a18e69e3f31ae9adad229e3244073b7d643b4597ec88bf247b9f73f301b0f25ae8207b02b7709c271da98af19f1db276ac48ba64f099644af1ae2c90edb7def5e8589a1bb17cc72ac42ecf07dd29cff91823938fd0d772c2c92b7ab050f8837efd46197c9b2b3f", "tx_id": "0b9510d92a50c1d67c6f7fc5d47908d96b3eccdea093d89bcbaf05bcfebdd951", "start_time": 0, "end_time": 0, "to_self_delay": 20}' > dummy_appointment_data.json
|
echo '{"tx": "4615a58815475ab8145b6bb90b1268a0dbb02e344ddd483f45052bec1f15b1951c1ee7f070a0993da395a5ee92ea3a1c184b5ffdb2507164bf1f8c1364155d48bdbc882eee0868ca69864a807f213f538990ad16f56d7dfb28a18e69e3f31ae9adad229e3244073b7d643b4597ec88bf247b9f73f301b0f25ae8207b02b7709c271da98af19f1db276ac48ba64f099644af1ae2c90edb7def5e8589a1bb17cc72ac42ecf07dd29cff91823938fd0d772c2c92b7ab050f8837efd46197c9b2b3f", "tx_id": "0b9510d92a50c1d67c6f7fc5d47908d96b3eccdea093d89bcbaf05bcfebdd951", "to_self_delay": 20}' > dummy_appointment_data.json
|
||||||
```
|
```
|
||||||
|
|
||||||
That will create a json file that follows the appointment data structure filled with dummy data and store it in `dummy_appointment_data.json`. **Note**: You'll need to update the `start_time` and `end_time` to match valid block heights.
|
That will create a json file that follows the appointment data structure filled with dummy data and store it in `dummy_appointment_data.json`.
|
||||||
|
|
||||||
3. Send the appointment to the tower API. Which will then start monitoring for matching transactions.
|
3. Send the appointment to the tower API. Which will then start monitoring for matching transactions.
|
||||||
|
|
||||||
|
|||||||
@@ -9,18 +9,14 @@ class Appointment:
|
|||||||
Args:
|
Args:
|
||||||
locator (:obj:`str`): A 16-byte hex-encoded value used by the tower to detect channel breaches. It serves as a
|
locator (:obj:`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.
|
trigger for the tower to decrypt and broadcast the penalty transaction.
|
||||||
start_time (:obj:`int`): The block height where the tower is hired to start watching for breaches.
|
|
||||||
end_time (:obj:`int`): The block height where the tower will stop watching for breaches.
|
|
||||||
to_self_delay (:obj:`int`): The ``to_self_delay`` encoded in the ``csv`` of the ``to_remote`` output of the
|
to_self_delay (:obj:`int`): The ``to_self_delay`` encoded in the ``csv`` of the ``to_remote`` output of the
|
||||||
commitment transaction that this appointment is covering.
|
commitment transaction that this appointment is covering.
|
||||||
encrypted_blob (:obj:`str`): An encrypted blob of data containing a penalty transaction. The tower will decrypt
|
encrypted_blob (:obj:`str`): An encrypted blob of data containing a penalty transaction. The tower will decrypt
|
||||||
it and broadcast the penalty transaction upon seeing a breach on the blockchain.
|
it and broadcast the penalty transaction upon seeing a breach on the blockchain.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, locator, start_time, end_time, to_self_delay, encrypted_blob):
|
def __init__(self, locator, to_self_delay, encrypted_blob):
|
||||||
self.locator = locator
|
self.locator = locator
|
||||||
self.start_time = start_time # ToDo: #4-standardize-appointment-fields
|
|
||||||
self.end_time = end_time # ToDo: #4-standardize-appointment-fields
|
|
||||||
self.to_self_delay = to_self_delay
|
self.to_self_delay = to_self_delay
|
||||||
self.encrypted_blob = encrypted_blob
|
self.encrypted_blob = encrypted_blob
|
||||||
|
|
||||||
@@ -33,7 +29,7 @@ class Appointment:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
appointment_data (:obj:`dict`): a dictionary containing the following keys:
|
appointment_data (:obj:`dict`): a dictionary containing the following keys:
|
||||||
``{locator, start_time, end_time, to_self_delay, encrypted_blob}``
|
``{locator, to_self_delay, encrypted_blob}``
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Appointment <teos.appointment.Appointment>`: An appointment initialized using the provided data.
|
:obj:`Appointment <teos.appointment.Appointment>`: An appointment initialized using the provided data.
|
||||||
@@ -43,16 +39,14 @@ class Appointment:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
locator = appointment_data.get("locator")
|
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
|
|
||||||
to_self_delay = appointment_data.get("to_self_delay")
|
to_self_delay = appointment_data.get("to_self_delay")
|
||||||
encrypted_blob_data = appointment_data.get("encrypted_blob")
|
encrypted_blob_data = appointment_data.get("encrypted_blob")
|
||||||
|
|
||||||
if any(v is None for v in [locator, start_time, end_time, to_self_delay, encrypted_blob_data]):
|
if any(v is None for v in [locator, to_self_delay, encrypted_blob_data]):
|
||||||
raise ValueError("Wrong appointment data, some fields are missing")
|
raise ValueError("Wrong appointment data, some fields are missing")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
appointment = cls(locator, start_time, end_time, to_self_delay, encrypted_blob_data)
|
appointment = cls(locator, to_self_delay, encrypted_blob_data)
|
||||||
|
|
||||||
return appointment
|
return appointment
|
||||||
|
|
||||||
@@ -67,8 +61,6 @@ class Appointment:
|
|||||||
# ToDO: #3-improve-appointment-structure
|
# ToDO: #3-improve-appointment-structure
|
||||||
appointment = {
|
appointment = {
|
||||||
"locator": self.locator,
|
"locator": self.locator,
|
||||||
"start_time": self.start_time,
|
|
||||||
"end_time": self.end_time,
|
|
||||||
"to_self_delay": self.to_self_delay,
|
"to_self_delay": self.to_self_delay,
|
||||||
"encrypted_blob": self.encrypted_blob,
|
"encrypted_blob": self.encrypted_blob,
|
||||||
}
|
}
|
||||||
@@ -80,17 +72,11 @@ class Appointment:
|
|||||||
Serializes an appointment to be signed.
|
Serializes an appointment to be signed.
|
||||||
|
|
||||||
The serialization follows the same ordering as the fields in the appointment:
|
The serialization follows the same ordering as the fields in the appointment:
|
||||||
locator:start_time:end_time:to_self_delay:encrypted_blob
|
locator:to_self_delay:encrypted_blob
|
||||||
|
|
||||||
All values are big endian.
|
All values are big endian.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`bytes`: The serialized data to be signed.
|
:obj:`bytes`: The serialized data to be signed.
|
||||||
"""
|
"""
|
||||||
return (
|
return unhexlify(self.locator) + struct.pack(">I", self.to_self_delay) + unhexlify(self.encrypted_blob)
|
||||||
unhexlify(self.locator)
|
|
||||||
+ struct.pack(">I", self.start_time)
|
|
||||||
+ struct.pack(">I", self.end_time)
|
|
||||||
+ struct.pack(">I", self.to_self_delay)
|
|
||||||
+ unhexlify(self.encrypted_blob)
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ class Inspector:
|
|||||||
raise InspectionFailed(errors.UNKNOWN_JSON_RPC_EXCEPTION, "unexpected error occurred")
|
raise InspectionFailed(errors.UNKNOWN_JSON_RPC_EXCEPTION, "unexpected error occurred")
|
||||||
|
|
||||||
self.check_locator(appointment_data.get("locator"))
|
self.check_locator(appointment_data.get("locator"))
|
||||||
self.check_start_time(appointment_data.get("start_time"), block_height)
|
|
||||||
self.check_end_time(appointment_data.get("end_time"), appointment_data.get("start_time"), block_height)
|
|
||||||
self.check_to_self_delay(appointment_data.get("to_self_delay"))
|
self.check_to_self_delay(appointment_data.get("to_self_delay"))
|
||||||
self.check_blob(appointment_data.get("encrypted_blob"))
|
self.check_blob(appointment_data.get("encrypted_blob"))
|
||||||
|
|
||||||
@@ -100,87 +98,6 @@ class Inspector:
|
|||||||
elif not is_locator(locator):
|
elif not is_locator(locator):
|
||||||
raise InspectionFailed(errors.APPOINTMENT_WRONG_FIELD_FORMAT, "wrong locator format ({})".format(locator))
|
raise InspectionFailed(errors.APPOINTMENT_WRONG_FIELD_FORMAT, "wrong locator format ({})".format(locator))
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def check_start_time(start_time, block_height):
|
|
||||||
"""
|
|
||||||
Checks if the provided ``start_time`` is correct.
|
|
||||||
|
|
||||||
Start times must be ahead the current best chain tip.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
start_time (:obj:`int`): the block height at which the tower is requested to start watching for breaches.
|
|
||||||
block_height (:obj:`int`): the chain height.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
:obj:`InspectionFailed`: if any of the fields is wrong.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if start_time is None:
|
|
||||||
raise InspectionFailed(errors.APPOINTMENT_EMPTY_FIELD, "empty start_time received")
|
|
||||||
|
|
||||||
elif type(start_time) != int:
|
|
||||||
raise InspectionFailed(
|
|
||||||
errors.APPOINTMENT_WRONG_FIELD_TYPE, "wrong start_time data type ({})".format(type(start_time))
|
|
||||||
)
|
|
||||||
|
|
||||||
elif start_time < block_height:
|
|
||||||
raise InspectionFailed(errors.APPOINTMENT_FIELD_TOO_SMALL, "start_time is in the past")
|
|
||||||
|
|
||||||
elif start_time == block_height:
|
|
||||||
raise InspectionFailed(
|
|
||||||
errors.APPOINTMENT_FIELD_TOO_SMALL,
|
|
||||||
"start_time is too close to current height. Accepted times are: [current_height+1, current_height+6]",
|
|
||||||
)
|
|
||||||
|
|
||||||
elif start_time > block_height + 6:
|
|
||||||
raise InspectionFailed(
|
|
||||||
errors.APPOINTMENT_FIELD_TOO_BIG,
|
|
||||||
"start_time is too far in the future. Accepted start times are up to 6 blocks in the future",
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def check_end_time(end_time, start_time, block_height):
|
|
||||||
"""
|
|
||||||
Checks if the provided ``end_time`` is correct.
|
|
||||||
|
|
||||||
End times must be ahead both the ``start_time`` and the current best chain tip.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
end_time (:obj:`int`): the block height at which the tower is requested to stop watching for breaches.
|
|
||||||
start_time (:obj:`int`): the block height at which the tower is requested to start watching for breaches.
|
|
||||||
block_height (:obj:`int`): the chain height.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
:obj:`InspectionFailed`: if any of the fields is wrong.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# TODO: What's too close to the current height is not properly defined. Right now any appointment that ends in
|
|
||||||
# the future will be accepted (even if it's only one block away).
|
|
||||||
|
|
||||||
if end_time is None:
|
|
||||||
raise InspectionFailed(errors.APPOINTMENT_EMPTY_FIELD, "empty end_time received")
|
|
||||||
|
|
||||||
elif type(end_time) != int:
|
|
||||||
raise InspectionFailed(
|
|
||||||
errors.APPOINTMENT_WRONG_FIELD_TYPE, "wrong end_time data type ({})".format(type(end_time))
|
|
||||||
)
|
|
||||||
|
|
||||||
elif end_time > block_height + BLOCKS_IN_A_MONTH: # 4320 = roughly a month in blocks
|
|
||||||
raise InspectionFailed(
|
|
||||||
errors.APPOINTMENT_FIELD_TOO_BIG, "end_time should be within the next month (<= current_height + 4320)"
|
|
||||||
)
|
|
||||||
elif start_time > end_time:
|
|
||||||
raise InspectionFailed(errors.APPOINTMENT_FIELD_TOO_SMALL, "end_time is smaller than start_time")
|
|
||||||
|
|
||||||
elif start_time == end_time:
|
|
||||||
raise InspectionFailed(errors.APPOINTMENT_FIELD_TOO_SMALL, "end_time is equal to start_time")
|
|
||||||
|
|
||||||
elif block_height > end_time:
|
|
||||||
raise InspectionFailed(errors.APPOINTMENT_FIELD_TOO_SMALL, "end_time is in the past")
|
|
||||||
|
|
||||||
elif block_height == end_time:
|
|
||||||
raise InspectionFailed(errors.APPOINTMENT_FIELD_TOO_SMALL, "end_time is too close to current height")
|
|
||||||
|
|
||||||
def check_to_self_delay(self, to_self_delay):
|
def check_to_self_delay(self, to_self_delay):
|
||||||
"""
|
"""
|
||||||
Checks if the provided ``to_self_delay`` is correct.
|
Checks if the provided ``to_self_delay`` is correct.
|
||||||
|
|||||||
Reference in New Issue
Block a user