123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134(*****************************************************************************)(* *)(* 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]modulePriority_map:Map.Swithtypekey=priority=Map.Make(structtypet=prioritymoduleCompareListQ=Compare.List(Q)letcompare_low_priop1p2=(* A higher priority operation should appear before in the map. So we use
the pointwise comparison of p2 and p1 *)CompareListQ.comparep2p1letcomparep1p2=(* - 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_priop1p2|`High,(`Low_|`Medium)->-1|(`Low_|`Medium),`High->1|`Low_,`Medium->1|`Medium,`Low_->-1end)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 priority of each hash, to be used when removing
without providing the priority *)priority_of:priorityMap.t;}letempty={pending=Priority_map.empty;hashes=Sized_set.empty;priority_of=Map.empty;}letis_empty{pending=_;priority_of=_;hashes}=Sized_set.is_emptyhasheslethashes{pending=_;priority_of=_;hashes}=Sized_set.to_sethashesletoperations{pending;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;priority_of=_;pending=_}=Sized_set.memophhashesletget_priority_mappriopending=matchPriority_map.findpriopendingwithNone->Map.empty|Somemp->mpletaddopprio{pending;hashes;priority_of}=letoph=op.hashinletmp=get_priority_mappriopending|>Map.addophopin{pending=Priority_map.addpriomppending;hashes=Sized_set.addophhashes;priority_of=Map.addophpriopriority_of;}letremoveoph({pending;hashes;priority_of}ast)=matchMap.findophpriority_ofwith|None->t|Someprio->letmp=get_priority_mappriopending|>Map.removeophin{pending=(ifMap.is_emptympthenPriority_map.removepriopendingelsePriority_map.addpriomppending);hashes=Sized_set.removeophhashes;priority_of=Map.removeophpriority_of;}letcardinal{pending=_;hashes;priority_of=_}=Sized_set.cardinalhashesletfold_esf{pending;hashes=_;priority_of=_}acc=Priority_map.fold_es(funpriompacc->Map.fold_es(fprio)mpacc)pendingaccletfoldf{pending;hashes=_;priority_of=_}acc=Priority_map.fold(funpriompacc->Map.fold(fprio)mpacc)pendingaccletiterf{pending;hashes=_;priority_of=_}=Priority_map.iter(funpriomp->Map.iter(fprio)mp)pending