Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file dal_slot_repr.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.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. *)(* *)(*****************************************************************************)moduleHeader=struct(* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3389
It is not clear whether the size of the slot associated to the
commitment should be given here. *)typet=Dal.commitmentletequal=Dal.Commitment.equalletencoding=Dal.Commitment.encodingletppppfcommitment=Format.fprintfppf"%s"(Dal.Commitment.to_b58checkcommitment)letzero=Dal.Commitment.zeroendmoduleIndex=structtypet=intletmax_value=255letencoding=Data_encoding.uint8letpp=Format.pp_print_intletzero=0letof_intslot_index=ifCompare.Int.(slot_index<=max_value&&slot_index>=zero)thenSomeslot_indexelseNoneletto_intslot_index=slot_index[@@ocaml.inlinealways]letcompare=Compare.Int.compareletequal=Compare.Int.equalendtypeid={published_level:Raw_level_repr.t;index:Index.t}typet={id:id;header:Header.t}typeslot=ttypeslot_index=Index.tletslot_id_equal({published_level;index}:id)s2=Raw_level_repr.equalpublished_levels2.published_level&&Index.equalindexs2.indexletslot_equal({id;header}:t)s2=slot_id_equalids2.id&&Header.equalheaders2.headerletcompare_slot_id({published_level;index}:id)s2=letc=Raw_level_repr.comparepublished_levels2.published_levelinifCompare.Int.(c<>0)thencelseIndex.compareindexs2.indexletzero_id={(* We don't expect to have any published slot at level
Raw_level_repr.root. *)published_level=Raw_level_repr.root;index=Index.zero;}letzero={id=zero_id;header=Header.zero}moduleSlot_index=IndexmodulePage=structtypecontent=Bytes.tmoduleIndex=structtypet=intletzero=0letencoding=Data_encoding.int16letpp=Format.pp_print_intletcompare=Compare.Int.compareletequal=Compare.Int.equalendtypet={slot_index:Slot_index.t;page_index:Index.t}letencoding=letopenData_encodinginconv(fun{slot_index;page_index}->(slot_index,page_index))(fun(slot_index,page_index)->{slot_index;page_index})(obj2(req"slot_index"Slot_index.encoding)(req"page_index"Index.encoding))letequalpagepage'=Slot_index.equalpage.slot_indexpage'.slot_index&&Index.equalpage.page_indexpage'.page_indexletppfmt{slot_index;page_index}=Format.fprintffmt"(slot_index: %a, page_index: %a)"Slot_index.ppslot_indexIndex.pppage_indexendletslot_encoding=letopenData_encodinginconv(fun{id={published_level;index};header}->(published_level,index,header))(fun(published_level,index,header)->{id={published_level;index};header})(obj3(req"level"Raw_level_repr.encoding)(req"index"Data_encoding.uint8)(req"header"Header.encoding))letpp_slotfmt{id={published_level;index};header}=Format.fprintffmt"published_level: %a index: %a header: %a"Raw_level_repr.pppublished_levelFormat.pp_print_intindexHeader.ppheadermoduleSlot_market=struct(* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3108
Think harder about this data structure and whether it can be
optimized. *)moduleSlot_index_map=Map.Make(Index)typet={length:int;slots:slotSlot_index_map.t}letinit~length=ifCompare.Int.(length<0)theninvalid_arg"Dal_slot_repr.Slot_market.init: length cannot be negative";letslots=Slot_index_map.emptyin{length;slots}letlength{length;_}=lengthletregistertnew_slot=ifnotCompare.Int.(0<=new_slot.id.index&&new_slot.id.index<t.length)thenNoneelselethas_changed=reffalseinletupdate=function|None->has_changed:=true;Somenew_slot|Somex->Somexinletslots=Slot_index_map.updatenew_slot.id.indexupdatet.slotsinlett={twithslots}inSome(t,!has_changed)letcandidatest=t.slots|>Slot_index_map.to_seq|>Seq.mapsnd|>List.of_seqendmoduleSlots_history=struct(* History is represented via a skip list. The content of the cell
is the hash of a merkle proof. *)(* A leaf of the merkle tree is a slot. *)moduleLeaf=structtypet=slotletto_bytes=Data_encoding.Binary.to_bytes_exnslot_encodingendmoduleContent_prefix=structlet_prefix="dash1"(* 32 *)letb58check_prefix="\002\224\072\094\219"(* dash1(55) *)letsize=Some32letname="dal_skip_list_content"lettitle="A hash to represent the content of a cell in the skip list"endmoduleContent_hash=Blake2B.Make(Base58)(Content_prefix)moduleMerkle_list=Merkle_list.Make(Leaf)(Content_hash)(* Pointers of the skip lists are used to encode the content and the
backpointers. *)modulePointer_prefix=structlet_prefix="dask1"(* 32 *)letb58check_prefix="\002\224\072\115\035"(* dask1(55) *)letsize=Some32letname="dal_skip_list_pointer"lettitle="A hash that represents the skip list pointers"endmodulePointer_hash=Blake2B.Make(Base58)(Pointer_prefix)moduleSkip_list_parameters=structletbasis=2endmoduleSkip_list=structincludeSkip_list_repr.Make(Skip_list_parameters)(** All confirmed DAL slots will be stored in a skip list, where only the
last cell is remembered in the L1 context. The skip list is used in
the proof phase of a refutation game to verify whether a given slot
exists (i.e., confirmed) or not in the skip list. The skip list is
supposed to be sorted, as its 'search' function explicitly uses a given
`compare` function during the list traversal to quickly (in log(size))
reach the target if any.
In our case, we will store one slot per cell in the skip list and
maintain that the list is well sorted (and without redundancy) w.r.t.
the [compare_slot_id] function.
Below, we redefine the [next] function (that allows adding elements
on top of the list) to enforce that the constructed skip list is
well-sorted. We also define a wrapper around the search function to
guarantee that it can only be called with the adequate compare function.
*)letcompare=compare_slot_idletcompare_lwtab=Lwt.return@@compareabtypeerror+=Add_element_in_slots_skip_list_violates_orderinglet()=register_error_kind`Temporary~id:"Dal_slot_repr.add_element_in_slots_skip_list_violates_ordering"~title:"Add an element in slots skip list that violates ordering"~description:"Attempting to add an element on top of the Dal confirmed slots skip \
list that violates the ordering."Data_encoding.unit(function|Add_element_in_slots_skip_list_violates_ordering->Some()|_->None)(fun()->Add_element_in_slots_skip_list_violates_ordering)letnext~prev_cell~prev_cell_ptrelt=letopenTzresult_syntaxinlet*()=error_when(Compare.Int.(<=)(compareelt.id(contentprev_cell).id)0)Add_element_in_slots_skip_list_violates_orderinginreturn@@next~prev_cell~prev_cell_ptreltletsearch~deref~cell~id_target=search~deref~cell~compare:(compare_lwtid_target)(* FIXME/DAL: search will be used in refutation proof. But we need to
introduce it here to explain why we need an ordering on the skip list's
elements. *)let_=ignoresearchendmoduleV1=struct(* The content of a cell is the hash of all the slot headers
represented as a merkle list. *)(* TODO/DAL: https://gitlab.com/tezos/tezos/-/issues/3765
Decide how to store attested slots in the skip list's content. *)typecontent=slot(* A pointer to a cell is the hash of its content and all the back
pointers. *)typeptr=Pointer_hash.ttypehistory=(content,ptr)Skip_list.celltypet=historylethistory_encoding=Skip_list.encodingPointer_hash.encodingslot_encodingletequal_history:history->history->bool=Skip_list.equalPointer_hash.equalslot_equalletencoding=history_encodingletequal:t->t->bool=equal_historyletgenesis:t=Skip_list.genesis(zero:slot)lethash_skip_list_cellcell=letcurrent_slot=Skip_list.contentcellinletback_pointers_hashes=Skip_list.back_pointerscellinData_encoding.Binary.to_bytes_exnslot_encodingcurrent_slot::List.mapPointer_hash.to_bytesback_pointers_hashes|>Pointer_hash.hash_bytesletpp_historyfmt(history:history)=lethistory_hash=hash_skip_list_cellhistoryinFormat.fprintffmt"@[hash : %a@;%a@]"Pointer_hash.pphistory_hash(Skip_list.pp~pp_content:pp_slot~pp_ptr:Pointer_hash.pp)historymoduleHistory_cache=Bounded_history_repr.Make(structletname="dal_slots_cache"end)(Pointer_hash)(structtypet=historyletencoding=history_encodingletpp=pp_historyletequal=equal_historyend)letadd_confirmed_slot(t,cache)slot=letopenTzresult_syntaxinletprev_cell_ptr=hash_skip_list_celltinlet*cache=History_cache.rememberprev_cell_ptrtcacheinlet*new_cell=Skip_list.next~prev_cell:t~prev_cell_ptrslotinreturn(new_cell,cache)letadd_confirmed_slots(t:t)cacheslots=List.fold_left_eadd_confirmed_slot(t,cache)slotsletadd_confirmed_slots_no_cache=letno_cache=History_cache.empty~capacity:0Linfuntslots->List.fold_left_eadd_confirmed_slot(t,no_cache)slots>|?fstendincludeV1endletencoding=slot_encodingletpp=pp_slotletequal=slot_equal