Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file tx_rollup_l2_context_sig.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374(* *)(* Open Source License *)(* Copyright (c) 2022 Marigold <contact@marigold.dev> *)(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.com> *)(* Copyright (c) 2022 Oxhead Alpha <info@oxheadalpha.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)typesignature=Bls.tmoduleTicket_indexable=Indexable.Make(Alpha_context.Ticket_hash)(** An integer used to identified a layer-2 address. See
{!Tx_rollup_l2_address.index}. *)typeaddress_index=Tx_rollup_l2_address.Indexable.index(** An integer used to identified a layer-1 ticket deposited in a
transaction rollup. *)typeticket_index=Ticket_indexable.index(** The metadata associated to a layer-2 address.
The counter is an counter-measure against replay attack. Each
operation is signed with an integer (its counter). The counter
is incremented when the operation is applied. This prevents the
operation to be applied once again, since its integer will not
be in sync with the counter of the account. The choice of [int64]
for the type of the counter theoretically prevents the rollup to
an integer overflow. However, it can only happen if a single account
makes more than [1.8446744e+19] operations. If an account sends 1000
operations per seconds, it would take them more than 5845420
centuries to achieve that.
The [public_key] allows to authenticate the owner of the address,
by verifying BLS signatures. *)typemetadata={counter:int64;public_key:Bls.Public_key.t}typeerror+=|Balance_too_low|Balance_overflow|Invalid_quantity|Unknown_address_indexofaddress_index|Metadata_already_initializedofaddress_index|Too_many_l2_addresses|Too_many_l2_tickets|Counter_overflowlet()=letopenData_encodingin(* Unknown address index *)register_error_kind`Temporary~id:"tx_rollup_unknown_address_index"~title:"Unknown address index"~description:"Tried to increment the counter of an unknown address index"(obj1(req"index"Tx_rollup_l2_address.Indexable.index_encoding))(functionUnknown_address_indexx->Somex|_->None)(funx->Unknown_address_indexx);(* Balance too low *)register_error_kind`Temporary~id:"tx_rollup_balance_too_low"~title:"Balance too low"~description:"Tried to spend a ticket index from an index without the required balance"empty(functionBalance_too_low->Some()|_->None)(fun()->Balance_too_low);(* Balance overflow *)register_error_kind`Temporary~id:"tx_rollup_balance_overflow"~title:"Balance overflow"~description:"Tried to credit a ticket index to an index to a new balance greater \
than the integer 32 limit"empty(functionBalance_overflow->Some()|_->None)(fun()->Balance_overflow);(* Invalid_quantity *)register_error_kind`Permanent~id:"tx_rollup_invalid_quantity"~title:"Invalid quantity"~description:"Tried to credit a ticket index to an index with a quantity non-strictly \
positive"empty(functionInvalid_quantity->Some()|_->None)(fun()->Invalid_quantity);(* Metadata already initialized *)register_error_kind`Branch~id:"tx_rollup_metadata_already_initialized"~title:"Metadata already initiliazed"~description:"Tried to initialize a metadata for an index which was already \
initiliazed"(obj1(req"index"Tx_rollup_l2_address.Indexable.index_encoding))(functionMetadata_already_initializedx->Somex|_->None)(funx->Metadata_already_initializedx);(* Too many l2 addresses associated *)register_error_kind`Branch~id:"tx_rollup_too_many_l2_addresses"~title:"Too many l2 addresses"~description:"The number of l2 addresses has reached the integer 32 limit"empty(functionToo_many_l2_addresses->Some()|_->None)(fun()->Too_many_l2_addresses);(* Too many l2 tickets associated *)register_error_kind`Branch~id:"tx_rollup_too_many_l2_tickets"~title:"Too many l2 tickets"~description:"The number of l2 tickets has reached the integer 32 limit"empty(functionToo_many_l2_tickets->Some()|_->None)(fun()->Too_many_l2_tickets);(* Counter overflow *)register_error_kind`Branch~id:"tx_rollup_counter_overflow"~title:"Counter overflow"~description:"Tried to increment the counter of an address and reached the integer 64 \
limit"empty(functionCounter_overflow->Some()|_->None)(fun()->Counter_overflow)(** This module type describes the API of the [Tx_rollup] context,
which is used to implement the semantics of the L2 operations. *)moduletypeCONTEXT=sig(** The state of the [Tx_rollup] context.
The context provides a type-safe, functional API to interact
with the state of a transaction rollup. The functions of this
module, manipulating and creating values of type [t] are called
“context operations” afterwards. *)typet(** The monad used by the context.
{b Note:} It is likely to be the monad of the underlying
storage. In the case of the proof verifier, as it is expected to
be run into the L1, the monad will also be used to perform gas
accounting. This is why all the functions of this module type
needs to be inside the monad [m]. *)type'am(** The necessary monadic operators the storage monad is required to
provide. *)moduleSyntax:sigval(let+):'am->('a->'b)->'bmval(let*):'am->('a->'bm)->'bm(** [let*?] is for binding the value from Result-only
expressions into the storage monad. *)val(let*?):('a,error)result->('a->'bm)->'bm(** [fail err] shortcuts the current computation by raising an
error.
Said error can be handled with the [catch] combinator. *)valfail:error->'am(** [catch p k h] tries to executes the monadic computation [p].
If [p] terminates without an error, then its result is passed
to the continuation [k]. On the contrary, if an error [err] is
raised, it is passed to the error handler [h]. *)valcatch:'am->('a->'bm)->(error->'bm)->'bm(** [return x] is the simplest computation inside the monad [m] which simply
computes [x] and nothing else. *)valreturn:'a->'am(** [list_fold_left_m f] is a monadic version of [List.fold_left
f], wherein [f] is not a pure computation, but a computation
in the monad [m]. *)vallist_fold_left_m:('a->'b->'am)->'a->'blist->'am(** [fail_unless cond err] raises [err] iff [cond] is [false]. *)valfail_unless:bool->error->unitm(** [fail_when cond err] raises [err] iff [cond] is [true]. *)valfail_when:bool->error->unitmend(** [bls_aggregate_verify] allows to verify the aggregated signature
of a batch. *)valbls_verify:(Bls.Public_key.t*bytes)list->signature->boolm(** The metadata associated to an address. *)moduleAddress_metadata:sig(** [get ctxt idx] returns the current metadata associated to the
address indexed by [idx]. *)valget:t->address_index->metadataoptionm(** [incr_counter ctxt idx] increments the counter of the
address indexed by [idx].
This function can fail with [Counter_overflow] iff the counter
has reached the [Int64.max_int] limit.
This function can fail with [Unknown_address_index] if [idx]
has not been associated with a layer-2 address already. *)valincr_counter:t->address_index->tm(** [init_with_public_key ctxt idx pk] initializes the metadata
associated to the address indexed by [idx].
This can fails with [Metadata_already_initialized] if this
function has already been called with [idx]. *)valinit_with_public_key:t->address_index->Bls.Public_key.t->tm(**/**)moduleInternal_for_tests:sigvalset:t->address_index->metadata->tmendend(** Mapping between {!Tx_rollup_l2_address.address} and {!address_index}.
Addresses are supposed to be associated to a {!address_index} in
order to reduce the batches' size submitted from the layer1 to the
layer2. Therefore, the first time an address is used in a layer2
operation, we associate it to a address_index that should be use
in future layer2 operations.
*)moduleAddress_index:sig(** [init_counter ctxt] writes the default counter (i.e. [0L]) in
the context. *)valinit_counter:t->tm(** [get ctxt addr] returns the index associated to [addr], if
any. *)valget:t->Tx_rollup_l2_address.t->address_indexoptionm(** [get_or_associate_index ctxt addr] associates a fresh [address_index]
to [addr], and returns it. If the [addr] has already been associated to
an index, it returns it.
It also returns the information on whether the index was created or
already existed.
This function can fail with [Too_many_l2_addresses] iff there
is no fresh index available. *)valget_or_associate_index:t->Tx_rollup_l2_address.t->(t*[`Created|`Existed]*address_index)m(** [count ctxt] returns the number of addresses that have been
involved in the transaction rollup. *)valcount:t->int32m(**/**)moduleInternal_for_tests:sig(** [set ctxt count] sets the [count] in [ctxt]. It is used to test
the behavior of [Too_many_l2_addresses]. *)valset_count:t->int32->tmendend(** Mapping between {!Ticket_hash.t} and {!ticket_index}.
Ticket hashes are supposed to be associated to a {!ticket_index} in
order to reduce the batches' size submitted from the layer1 to the
layer2. Therefore, the first time a ticket hash is used in a layer2
operation, we associate it to a ticket_index that should be use
in future layer2 operations.
*)moduleTicket_index:sig(** [init_counter ctxt] writes the default counter (i.e. [0L]) in
the context. *)valinit_counter:t->tm(** [get ctxt ticket] returns the index associated to [ticket], if
any. *)valget:t->Alpha_context.Ticket_hash.t->ticket_indexoptionm(** [get_or_associate_index ctxt ticket] associates a fresh [ticket_index]
to [ticket], and returns it. If the [ticket] has already been associated
to an index, it returns it.
It also returns the information on whether the index was created or
already existed.
This function can fail with [Too_many_l2_tickets] iff there
is no fresh index available. *)valget_or_associate_index:t->Alpha_context.Ticket_hash.t->(t*[`Created|`Existed]*ticket_index)m(** [count ctxt] returns the number of tickets that have been
involved in the transaction rollup. *)valcount:t->int32m(**/**)moduleInternal_for_tests:sig(** [set_count ctxt count] sets the [count] in [ctxt]. It is used to test
the behavior of [Too_many_l2_addresses]. *)valset_count:t->int32->tmendend(** The ledger of the layer 2 where are registered the amount of a
given ticket a L2 [account] has in its possession. *)moduleTicket_ledger:sig(** [get ctxt tidx aidx] returns the quantity of tickets ([tidx]) [aidx]
owns.
{b Note:} It is the responsibility of the caller to verify that [aidx]
and [tidx] have been associated to an address and
a ticket respectively. The function will return zero when the address
has no such ticket. *)valget:t->ticket_index->address_index->Tx_rollup_l2_qty.tm(** [credit ctxt tidx aidx qty] updates the ledger to
increase the number of tickets indexed by [tidx] the address
[aidx] owns by [qty] units.
This function can fail with [Balance_overflow] if adding
[qty] to the current balance of [aidx] causes an integer
overflow.
This function can fail with [Invalid_quantity] if [qty]
is not strictly positive.
{b Note:} It is the responsibility of the caller to verify that [aidx]
and [tidx] have been associated to an address and
a ticket respectively. *)valcredit:t->ticket_index->address_index->Tx_rollup_l2_qty.t->tm(** [spend ctxt tidx aidx qty] updates the ledger to
decrease the number of tickets indexed by [tidx] the address
[aidx] owns by [qty] units.
This function can fail with [Balance_too_low] if [aidx]
does not own at least [qty] ticket.
{b Note:} It is the responsibility of the caller to verify
that [aidx] and [tidx] have been associated to an address and
a ticket respectively. *)valspend:t->ticket_index->address_index->Tx_rollup_l2_qty.t->tmmoduleInternal_for_tests:sigvalget_opt:t->ticket_index->address_index->Tx_rollup_l2_qty.toptionmendendend