# package octez-libs

`Timelock`

is a set of functions to handle time-locking a value and opening time-locked values.

A time-locked value can be opened slowly by anyone doing a fixed number of sequential operations.

In the interface of this module, this fixed number is consistently named `time`

and is represented by an integer.

Once opened via the slow method a proof of opening can be produced to avoid having to do so again. This proof is verifiable in logarithmic time.

In order to time-lock an arbitrary sequence of bytes, we 1. encrypt the bytes with a symmetric key, and then 2. we time-lock the symmetric key itself.

This module implements a scheme inspired by: Time-lock puzzles and timed release - Rivest, Shamir, Wagner https://people.csail.mit.edu/rivest/pubs/RSW96.pdf

Locked value that can be accessed with a number of sequential operations. It is concretely a member of the RSA group.

`val to_locked_value_opt : string -> locked_value option`

Function taking as input a string and returning Some locked_value if the element is in the RSA group with RSA2048 as modulus, None otherwise.

`val to_locked_value_unsafe : string -> locked_value`

Function taking as input a string and returning a locked_value with no check.

Member of the RSA group that we will lock. In our case it represents a symmetric key.

A symmetric ciphertext and message authentication code, containing the bytes we want to protect

`type vdf_tuple = {`

`locked_value : locked_value;`

`unlocked_value : unlocked_value;`

`vdf_proof : vdf_proof;`

`}`

Tuple of the RSA group comprising the locked and unlocked values as well as a (Wesolowski) proof that the unlocked value indeed corresponds to the locked one.

Proof that the opening of a value is the claimed value. It is concretely a vdf_tuple and a member of the RSA group.

`val gen_locked_value_unsafe : unit -> locked_value`

Generates almost uniformly an integer mod n. It is in the RSA group with overwhelming probability. We use this since we want to lock symmetric keys, not pre-determined messages.

`val gen_locked_value_opt : unit -> locked_value option`

Returns None if `rsa_public`

is not RSA2048, otherwise returns Some `gen_locked_value_unsafe`

`rsa_public`

.

`val timelock_proof_to_symmetric_key : timelock_proof -> symmetric_key`

Hashes a number mod n to a symmetric key for authenticated encryption, where the number is unlocked_value**nonce mod rsa2048.

`val unlock_and_prove : time:int -> locked_value -> timelock_proof`

Unlock a timelock value and produces a proof certifying that the result is indeed what had been locked.

`val prove : time:int -> locked_value -> unlocked_value -> timelock_proof`

Produces a proof certifying that the result is indeed what had been locked.

`val verify : time:int -> locked_value -> timelock_proof -> bool`

Verifies that `locked_value`

indeed contains `unlocked_value`

with parameters `time:int`

.

```
val precompute_timelock :
?locked_value:locked_value option ->
?precompute_path:string option ->
time:int ->
unit ->
vdf_tuple
```

Precomputes a `vdf_tuple`

given a `time:int`

and optionally `locked_value`

. If `precompute_path`

is given, it will instead read `vdf_tuple`

locally and if not found, will write the newly computed `vdf_tuple`

there.

`val proof_of_vdf_tuple : time:int -> vdf_tuple -> locked_value * timelock_proof`

Randomizes a `vdf_tuple`

given a `time:int`

(to verify the `vdf_tuple`

is correct).

`val encrypt : symmetric_key -> bytes -> ciphertext`

encrypt using authenticated encryption, i.e. ciphertext contains a ciphertext and a message authentication code.

`val decrypt : symmetric_key -> ciphertext -> bytes option`

Checks the message authentication code. If correct decrypt the ciphertext, otherwise returns None.

`val ciphertext_encoding : ciphertext Data_encoding.t`

`val vdf_tuple_encoding : vdf_tuple Data_encoding.t`

`val proof_encoding : timelock_proof Data_encoding.t`

Contains a value (the decryption of the ciphertext) that can be provably recovered in `time`

sequential operation.

`val chest_encoding : chest Data_encoding.t`

`type chest_key = timelock_proof`

Provably opens a chest in a short time.

`val chest_key_encoding : chest_key Data_encoding.t`

Result of the opening of a chest. The opening can fail in two ways which we distinguish to blame the right party. One can provide a false unlocked_value or unlocked_proof, in which case we return `Bogus_opening`

and the provider of the chest key is at fault. Otherwise we return `Correct payload`

where `payload`

is the content that had originally been put in the chest.

`val open_chest : chest -> chest_key -> time:int -> opening_result`

Takes a chest, chest key and time and tries to recover the underlying plaintext. See the documentation of opening_result.

`val get_plaintext_size : chest -> int`

Gives the size of the underlying plaintext in a chest in bytes. Used for gas accounting

`module Internal_for_tests : sig ... end`

```
val create_chest_and_chest_key :
?precompute_path:string option ->
payload:Bytes.t ->
time:int ->
unit ->
chest * chest_key
```

High level function which given a `payload`

, `time`

and optionally a `precomputed_path`

, generates a `chest`

and `chest_key`

. The `payload`

corresponds to the message to timelock while the `time`

corresponds to the difficulty in opening the chest. Beware, it does not correspond to a duration per se but to the number of iteration needed. The optional `precomputation_path`

is a local path where to read or write some auxiliary information to generate the chest quickly.

High level function to unlock the value and create a proof.

```
val chest_sampler :
rng_state:Random.State.t ->
plaintext_size:int ->
time:int ->
chest * chest_key
```

----- !!!!! Do not use for wallets: the RNG is not safe !!!!---- Sampler for the gasbenchmarks. Takes an Ocaml RNG state as arg for reproducibility.