123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* Copyright (c) 2018-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. *)(* *)(*****************************************************************************)openShell_operation(* Ordering is important, as it is used below in map keys comparison *)typepriority=High|Medium|LowofQ.tlist(* This type is used to know if the operation has already been classified in the
past *)typestatus=Fresh|Reclassifiedtypestatus_and_priority={priority:priority;status:status}modulePriority_map:Map.Swithtypekey=status_and_priority=Map.Make(structtypet=status_and_prioritymoduleCompareListQ=Compare.List(Q)letcompare_low_priorityp1p2=(* A higher priority operation should appear before in the map. So we use
the pointwise comparison of p2 and p1 *)CompareListQ.comparep2p1letcompare_priorityp1p2=(* - Explicit comparison, High is smaller,
- Avoid fragile patterns in case the type is extended in the future *)match(p1,p2)with|High,High|Medium,Medium->0|Lowp1,Lowp2->compare_low_priorityp1p2|High,(Low_|Medium)->-1|(Low_|Medium),High->1|Low_,Medium->1|Medium,Low_->-1letcomparep1p2=(* - Explicit comparison, Fresh is smaller *)match(p1.status,p2.status)with|Fresh,Fresh->compare_priorityp1.priorityp2.priority|Fresh,Reclassified->-1|Reclassified,Fresh->1|Reclassified,Reclassified->compare_priorityp1.priorityp2.priorityend)moduleMap=Operation_hash.MapmoduleSized_set=Tezos_base.Sized.MakeSizedSet(Operation_hash.Set)(*
The type below is used for representing pending operations data of the
prevalidator. The functions of this module (should) maintain the
following invariants:
1 - Union (preimage(pending(prio))) = hashes, for each prio in dom(pending)
2 - preimage (priority_of) = hashes
3 - image(priority_of) = preimage (pending)
4 - map in pending(priority) => map <> empty
*)type'at={(* The main map *)pending:'aoperationMap.tPriority_map.t;(* Used for advertising *)hashes:Sized_set.t;(* We need to remember the status and priority of each hash, to be used when
removing without providing the status and priority *)status_and_priority_of:status_and_priorityMap.t;}letempty={pending=Priority_map.empty;hashes=Sized_set.empty;status_and_priority_of=Map.empty;}letis_empty{pending=_;status_and_priority_of=_;hashes}=Sized_set.is_emptyhasheslethashes{pending=_;status_and_priority_of=_;hashes}=Sized_set.to_sethashesletoperations{pending;status_and_priority_of=_;hashes=_}=(* Build a flag map [oph -> op] from pending. Needed when re-cycling
operations *)Priority_map.fold(fun_prio->Map.union(fun__b->Someb))pendingMap.emptyletmemoph{hashes;status_and_priority_of=_;pending=_}=Sized_set.memophhashesletget_priority_mapstatus_and_prioritypending=matchPriority_map.findstatus_and_prioritypendingwith|None->Map.empty|Somemp->mpletaddopstatus_and_priority{pending;hashes;status_and_priority_of}=letoph=op.hashinletmp=get_priority_mapstatus_and_prioritypending|>Map.addophopin{pending=Priority_map.addstatus_and_prioritymppending;hashes=Sized_set.addophhashes;status_and_priority_of=Map.addophstatus_and_prioritystatus_and_priority_of;}letremoveoph({pending;hashes;status_and_priority_of}ast)=matchMap.findophstatus_and_priority_ofwith|None->t|Somestatus_and_priority->letmp=get_priority_mapstatus_and_prioritypending|>Map.removeophin{pending=(ifMap.is_emptympthenPriority_map.removestatus_and_prioritypendingelsePriority_map.addstatus_and_prioritymppending);hashes=Sized_set.removeophhashes;status_and_priority_of=Map.removeophstatus_and_priority_of;}letcardinal{pending=_;hashes;status_and_priority_of=_}=Sized_set.cardinalhashesletfold_esf{pending;hashes=_;status_and_priority_of=_}acc=Priority_map.fold_es(funpriompacc->Map.fold_es(fprio)mpacc)pendingaccletfoldf{pending;hashes=_;status_and_priority_of=_}acc=Priority_map.fold(funpriompacc->Map.fold(fprio)mpacc)pendingaccletiterf{pending;hashes=_;status_and_priority_of=_}=Priority_map.iter(funpriomp->Map.iter(fprio)mp)pending