Skip to content

Latest commit

 

History

History
343 lines (194 loc) · 9.35 KB

File metadata and controls

343 lines (194 loc) · 9.35 KB

reclocks

Classes

HashClock

Implementation of the Reverse Entropy Hash Clock.

Annotations

  • uuid: bytes
  • state: tuple[int, bytes]
  • updater: HashClockUpdater

Methods

__init__(uuid: bytes = <factory>, state: tuple[int, bytes] = None, updater: HashClockUpdater = None):
setup(max_time: int, seed_size: int = 16) -> HashClockUpdater | None:

Set up the instance if it hasn't been set up yet and return the updater for the clock. If it has been set up (i.e. has a uuid), return the updater if there is one or None.

read() -> tuple[int, bytes]:

Read the current state of the clock.

@staticmethod happens_before(ts1: tuple, ts2: tuple) -> bool:

Determine if ts1 happens before ts2.

@staticmethod are_incomparable(ts1: tuple[int, bytes], ts2: tuple[int, bytes]) -> bool:

Determine if ts1 and ts2 are incomparable.

can_be_updated() -> bool:

Determines if the clock can possibly receive further updates.

has_terminated() -> bool:

Determines if the clock has provably terminated.

update(state: tuple[int, bytes]) -> HashClock:

Update the clock if the state verifies.

verify() -> bool:

Verifies the state.

verify_timestamp(timestamp: tuple[int, bytes]) -> bool:

Verifies the timestamp is valid for this clock.

pack() -> bytes:

Pack the clock down to bytes.

@classmethod unpack(data: bytes) -> HashClock:

Unpack a clock from bytes.

HashClockUpdater

Implementation of ClockUpdaterProtocol for the Reverse Entropy Hash Clock.

Annotations

  • seed: bytes
  • uuid: bytes
  • max_time: int

Methods

__init__(seed: bytes, uuid: bytes, max_time: int):
@classmethod setup(seed: bytes, max_time: int) -> HashClockUpdater:

Set up a new instance.

advance(time: int) -> tuple[int, bytes]:

Create an update that advances the clock to the given time.

pack() -> bytes:

Pack the clock updater into bytes.

@classmethod unpack(data: bytes) -> HashClockUpdater:

Unpack a clock updater from bytes.

VectorHashClock

A vector clock comprised of HashClocks.

Annotations

  • uuid: bytes
  • node_ids: list[bytes]
  • clocks: dict[bytes, HashClock]

Methods

__init__(uuid: bytes = <factory>, node_ids: list[bytes] = None, clocks: dict[bytes, HashClock] = <factory>):
setup(node_ids: list[bytes] = None, clock_uuids: dict[bytes, bytes] = {}) -> VectorHashClock:

Set up the vector clock. The clock_uuids parameter must be a dict that maps node_id to clock.uuid.

@classmethod create(uuid: bytes, node_ids: list[bytes], clock_uuids: dict[bytes, bytes] = {}) -> VectorHashClock:

Create a vector clock. The clock_uuids parameter must be a dict that maps node_id to clock.uuid.

read() -> dict:

Read the clock as dict mapping node_id to tuple[int, bytes]. Return value includes vector clock uuid at the key b'uuid' and is the timestamp used for causality comparisons.

advance(node_id: bytes, state: tuple[int, bytes]) -> dict:

Create an update to advance the clock given the output of a call to advance from the underlying HashClock associated with the given node_id.

update(state: dict) -> VectorHashClock:

Update the clock using a dict mapping node_id to tuple[int, bytes]. The state must also include the vector clock uuid at the key b'uuid'. The expected input is the output of the advance method.

verify() -> bool:

Verify that all underlying HashClocks are valid.

verify_timestamp(timestamp: dict[bytes, bytes | tuple]) -> bool:

Verify that the timestamp is valid. Expected input is the output of read or advance.

@staticmethod happens_before(ts1: dict, ts2: dict) -> bool:

Determine if ts1 happens before ts2. As long as at least one node_id contained in both timestamps has a higher value in ts1 and no node_id shared by both has a higher value in ts2, ts1 happened-before ts2. Valid timestamps are generated by the advance and read methods.

@staticmethod are_incomparable(ts1: dict, ts2: dict) -> bool:

Determine if ts1 and ts2 are incomparable. As long as the two timestamps share one node_id in common, they are comparable.

@staticmethod are_concurrent(ts1: dict, ts2: dict) -> bool:

Determine if ts1 and ts2 are concurrent.

pack() -> bytes:

Pack the clock into bytes.

@classmethod unpack(data: bytes) -> VectorHashClock:

Unpack a clock from bytes.

PointClock

Implementation of the Reverse Entropy Point Clock (Ed25519).

Annotations

  • uuid: bytes
  • state: tuple[int, bytes]
  • updater: PointClockUpdater

Methods

__init__(uuid: bytes = <factory>, state: tuple[int, bytes] = None, updater: PointClockUpdater = None):
setup(max_time: int, seed_size: int = 32) -> PointClockUpdater | None:

Set up the instance if it hasn't been setup yet and return the updater for the clock. If it has been setup (i.e. has a uuid), return the updater if there is one or None.

read() -> tuple[int, bytes]:

Read the current state of the clock.

@staticmethod happens_before(ts1: tuple, ts2: tuple) -> bool:

Determine if ts1 happens before ts2.

@staticmethod are_incomparable(ts1: tuple[int, bytes], ts2: tuple[int, bytes]) -> bool:

Determine if ts1 and ts2 are incomparable.

update(state: tuple[int, bytes]) -> PointClock:

Update the clock if the state verifies.

verify() -> bool:

Verifies the state.

verify_timestamp(timestamp: tuple) -> bool:

Verify the timestamp is valid for this clock.

verify_signed_timestamp(timestamp: tuple, message: bytes) -> bool:

Verify a signed timestamp contains both a valid timestamp and a valid signature from the pubkey in the timestamp.

pack() -> bytes:

Pack the clock down to bytes.

@classmethod unpack(data: bytes) -> PointClock:

Unpack a clock from bytes.

PointClockUpdater

Implementation of ClockUpdaterProtocol for the Reverse Entropy Point Clock.

Annotations

  • seed: bytes
  • uuid: bytes
  • max_time: int

Methods

__init__(seed: bytes, uuid: bytes, max_time: int):
@classmethod setup(seed: bytes, max_time: int) -> PointClockUpdater:

Set up a new instance.

advance(time: int) -> tuple[int, bytes]:

Create an update that advances the clock to the given time.

advance_and_sign(time: int, message: bytes) -> tuple[int, bytes, bytes]:

Create an update that advances the clock to the given time and provide a signature that verifies for the public key. Return format is (ts, pubkey, signature).

pack() -> bytes:

Pack the clock updater into bytes.

@classmethod unpack(data: bytes) -> PointClockUpdater:

Unpack a clock updater from bytes.

VectorPointClock

A vector clock comprised of PointClocks.

Annotations

  • uuid: bytes
  • node_ids: list[bytes]
  • clocks: dict[bytes, PointClock]

Methods

__init__(uuid: bytes = <factory>, node_ids: list[bytes] = None, clocks: dict[bytes, PointClock] = <factory>):
setup(node_ids: list[bytes] = None, clock_uuids: dict[bytes, bytes] = {}) -> VectorPointClock:

Set up the vector clock. The clock_uuids parameter must be a dict that maps node_id to clock.uuid.

@classmethod create(uuid: bytes, node_ids: list[bytes], clock_uuids: dict[bytes, bytes] = {}) -> VectorPointClock:

Create a vector clock. The clock_uuids parameter must be a dict that maps node_id to clock.uuid.

read() -> dict:

Read the clock as dict mapping node_id to tuple[int, bytes]. Return value includes vector clock uuid at the key b'uuid' and is the timestamp used for causality comparisons.

advance(node_id: bytes, state: tuple[int, bytes]) -> dict:

Create an update to advance the clock given the output of a call to advance or advance_and_sign from the underlying PointClock associated with the given node_id.

update(state: dict[bytes, tuple]) -> VectorPointClock:

Update the clock using a dict mapping node_id to tuple[int, bytes] or tuple[int, bytes, bytes]. The state must also include the vector clock uuid at the key b'uuid'. The expected input is the output of the advance method.

verify() -> bool:

Verify that all underlying PointClocks are valid.

verify_timestamp(timestamp: dict[bytes, bytes | tuple]) -> bool:

Verify that the timestamp is valid. Expected input is the output of read or advance.

verify_signed_timestamp(timestamp: dict[bytes, bytes | tuple], message: bytes) -> bool:

Verify that a timestamp which includes a signature is valid. This timestamp must be produced by passing the output of advance_and_sign from an underlying PointClock to the advance method on the VectorPointClock.

@staticmethod happens_before(ts1: dict, ts2: dict) -> bool:

Determine if ts1 happens before ts2. As long as at least one node_id contained in both timestamps has a higher value in ts1 and no node_id shared by both has a higher value in ts2, ts1 happened-before ts2. Valid timestamps are generated by the advance and read methods.

@staticmethod are_incomparable(ts1: dict, ts2: dict) -> bool:

Determine if ts1 and ts2 are incomparable. As long as the two timestamps share one node_id in common, they are comparable.

@staticmethod are_concurrent(ts1: dict, ts2: dict) -> bool:

Determine if ts1 and ts2 are concurrent.

pack() -> bytes:

Pack the clock into bytes.

@classmethod unpack(data: bytes) -> VectorPointClock:

Unpack a clock from bytes.