1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* Copyright (c) 2019-2020 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. *)(* *)(*****************************************************************************)openStorage_sigsmoduleRegistered=structletghost=falseendmoduleGhost=structletghost=trueendmoduletypeENCODER=sigtypetvalof_bytes:key:(unit->stringlist)->bytes->ttzresultvalto_bytes:t->bytesendmoduleMake_encoder(V:VALUE):ENCODERwithtypet:=V.t=structletof_bytes~keyb=matchData_encoding.Binary.of_bytes_optV.encodingbwith|None->error(Raw_context.Storage_error(Corrupted_data(key())))|Somev->Okvletto_bytesv=matchData_encoding.Binary.to_bytes_optV.encodingvwith|Someb->b|None->Bytes.emptyendletlen_name="len"letdata_name="data"letencode_len_valuebytes=letlength=Bytes.lengthbytesinData_encoding.(Binary.to_bytes_exnint31)lengthletdecode_len_valuekeylen=matchData_encoding.(Binary.of_bytes_optint31)lenwith|None->error(Raw_context.Storage_error(Corrupted_datakey))|Somelen->oklenmoduleMake_subcontext(R:REGISTER)(C:Raw_context.T)(N:NAME):Raw_context.Twithtypet=C.t=structtypet=C.tletto_keyk=N.name@kletmemtk=C.memt(to_keyk)letmem_treetk=C.mem_treet(to_keyk)letgettk=C.gett(to_keyk)letget_treetk=C.get_treet(to_keyk)letfindtk=C.findt(to_keyk)letfind_treetk=C.find_treet(to_keyk)letaddtkv=C.addt(to_keyk)vletadd_treetkv=C.add_treet(to_keyk)vletinittkv=C.initt(to_keyk)vletinit_treetkv=C.init_treet(to_keyk)vletupdatetkv=C.updatet(to_keyk)vletupdate_treetkv=C.update_treet(to_keyk)vletadd_or_removetkv=C.add_or_removet(to_keyk)vletadd_or_remove_treetkv=C.add_or_remove_treet(to_keyk)vletremove_existingtk=C.remove_existingt(to_keyk)letremove_existing_treetk=C.remove_existing_treet(to_keyk)letremovetk=C.removet(to_keyk)letlistt?offset?lengthk=C.listt?offset?length(to_keyk)letfold?depthtk~order~init~f=C.fold?deptht(to_keyk)~order~init~fmoduleTree=C.Treeletproject=C.projectletabsolute_keyck=C.absolute_keyc(to_keyk)typeerror+=Block_quota_exceeded=C.Block_quota_exceededtypeerror+=Operation_quota_exceeded=C.Operation_quota_exceededletconsume_gas=C.consume_gasletcheck_enough_gas=C.check_enough_gasletdescription=letdescription=ifR.ghostthenStorage_description.create()elseC.descriptioninStorage_description.register_named_subcontextdescriptionN.nameendmoduleMake_single_data_storage(R:REGISTER)(C:Raw_context.T)(N:NAME)(V:VALUE):Single_data_storagewithtypet=C.tandtypevalue=V.t=structtypet=C.ttypecontext=ttypevalue=V.tletmemt=C.memtN.nameincludeMake_encoder(V)letgett=C.gettN.name>>=?funb->letkey()=C.absolute_keytN.nameinLwt.return(of_bytes~keyb)letfindt=C.findtN.name>|=function|None->Result.return_none|Someb->letkey()=C.absolute_keytN.nameinof_bytes~keyb>|?funv->Somevletinittv=C.inittN.name(to_bytesv)>|=?funt->C.projecttletupdatetv=C.updatetN.name(to_bytesv)>|=?funt->C.projecttletaddtv=C.addtN.name(to_bytesv)>|=funt->C.projecttletadd_or_removetv=C.add_or_removetN.name(Option.mapto_bytesv)>|=funt->C.projecttletremovet=C.removetN.name>|=funt->C.projecttletremove_existingt=C.remove_existingtN.name>|=?funt->C.projecttlet()=letopenStorage_descriptioninletdescription=ifR.ghostthenStorage_description.create()elseC.descriptioninregister_value~get:find(register_named_subcontextdescriptionN.name)V.encoding[@@coq_axiom_with_reason"stack overflow in Coq"]endmoduletypeINDEX=sigtypetincludePath_encoding.Swithtypet:=ttype'aipathvalargs:('a,t,'aipath)Storage_description.argsendmodulePair(I1:INDEX)(I2:INDEX):INDEXwithtypet=I1.t*I2.t=structtypet=I1.t*I2.tletpath_length=I1.path_length+I2.path_lengthletto_path(x,y)l=I1.to_pathx(I2.to_pathyl)letof_pathl=matchMisc.takeI1.path_lengthlwith|None->None|Some(l1,l2)->(match(I1.of_pathl1,I2.of_pathl2)with|(Somex,Somey)->Some(x,y)|_->None)type'aipath='aI1.ipathI2.ipathletargs=Storage_description.Pair(I1.args,I2.args)endmoduleMake_data_set_storage(C:Raw_context.T)(I:INDEX):Data_set_storagewithtypet=C.tandtypeelt=I.t=structtypet=C.ttypecontext=ttypeelt=I.tletinited=Bytes.of_string"inited"letmemsi=C.mems(I.to_pathi[])letaddsi=C.adds(I.to_pathi[])inited>|=funt->C.projecttletremovesi=C.removes(I.to_pathi[])>|=funt->C.projecttletclears=C.removes[]>|=funt->C.projecttletfolds~order~init~f=C.fold~depth:(`EqI.path_length)s[]~order~init~f:(funfiletreeacc->matchC.Tree.kindtreewith|`Value->(matchI.of_pathfilewithNone->assertfalse|Somep->fpacc)|`Tree->Lwt.returnacc)letelementss=folds~order:`Sorted~init:[]~f:(funpacc->Lwt.return(p::acc))let()=letopenStorage_descriptioninletunpack=unpackI.argsinregister_value(* TODO fixme 'elements...' *)~get:(func->let(c,k)=unpackcinmemck>>=functiontrue->return_sometrue|false->return_none)(register_indexed_subcontext~list:(func->elementsc>|=ok)C.descriptionI.args)Data_encoding.bool[@@coq_axiom_with_reason"stack overflow in Coq"]endmoduleMake_indexed_data_storage(C:Raw_context.T)(I:INDEX)(V:VALUE):Indexed_data_storagewithtypet=C.tandtypekey=I.tandtypevalue=V.t=structtypet=C.ttypecontext=ttypekey=I.ttypevalue=V.tincludeMake_encoder(V)letmemsi=C.mems(I.to_pathi[])letgetsi=C.gets(I.to_pathi[])>>=?funb->letkey()=C.absolute_keys(I.to_pathi[])inLwt.return(of_bytes~keyb)letfindsi=C.finds(I.to_pathi[])>|=function|None->Result.return_none|Someb->letkey()=C.absolute_keys(I.to_pathi[])inof_bytes~keyb>|?funv->Somevletupdatesiv=C.updates(I.to_pathi[])(to_bytesv)>|=?funt->C.projecttletinitsiv=C.inits(I.to_pathi[])(to_bytesv)>|=?funt->C.projecttletaddsiv=C.adds(I.to_pathi[])(to_bytesv)>|=funt->C.projecttletadd_or_removesiv=C.add_or_removes(I.to_pathi[])(Option.mapto_bytesv)>|=funt->C.projecttletremovesi=C.removes(I.to_pathi[])>|=funt->C.projecttletremove_existingsi=C.remove_existings(I.to_pathi[])>|=?funt->C.projecttletclears=C.removes[]>|=funt->C.projecttletfolds~order~init~f=C.fold~depth:(`EqI.path_length)s[]~order~init~f:(funfiletreeacc->C.Tree.to_valuetree>>=function|Somev->(matchI.of_pathfilewith|None->assertfalse|Somepath->(letkey()=C.absolute_keysfileinmatchof_bytes~keyvwith|Okv->fpathvacc|Error_->Lwt.returnacc))|None->Lwt.returnacc)letfold_keyss~order~init~f=folds~order~init~f:(funk_acc->fkacc)letbindingss=folds~order:`Sorted~init:[]~f:(funpvacc->Lwt.return((p,v)::acc))letkeyss=fold_keyss~order:`Sorted~init:[]~f:(funpacc->Lwt.return(p::acc))let()=letopenStorage_descriptioninletunpack=unpackI.argsinregister_value~get:(func->let(c,k)=unpackcinfindck)(register_indexed_subcontext~list:(func->keysc>|=ok)C.descriptionI.args)V.encoding[@@coq_axiom_with_reason"stack overflow in Coq"]end(* Internal-use-only version of {!Make_indexed_carbonated_data_storage} to
expose fold_keys_unaccounted *)moduleMake_indexed_carbonated_data_storage_INTERNAL(C:Raw_context.T)(I:INDEX)(V:VALUE):Non_iterable_indexed_carbonated_data_storage_INTERNALwithtypet=C.tandtypekey=I.tandtypevalue=V.t=structtypet=C.ttypecontext=ttypekey=I.ttypevalue=V.tincludeMake_encoder(V)letdata_keyi=I.to_pathi[data_name]letlen_keyi=I.to_pathi[len_name]letconsume_mem_gasckey=C.consume_gasc(Storage_costs.read_access~path_length:(List.lengthkey)~read_bytes:0)letexisting_sizeci=C.findc(len_keyi)>|=function|None->ok(0,false)|Somelen->decode_len_value(len_keyi)len>|?funlen->(len,true)letconsume_read_gasgetci=letlen_key=len_keyiingetclen_key>>=?funlen->Lwt.return(decode_len_valuelen_keylen>>?funread_bytes->letcost=Storage_costs.read_access~path_length:(List.lengthlen_key)~read_bytesinC.consume_gasccost)(* For the future: here, we bill a generic cost for encoding the value
to bytes. It would be cleaner for users of this functor to provide
gas costs for the encoding. *)letconsume_serialize_write_gassetciv=letbytes=to_bytesvinletlen=Bytes.lengthbytesinC.consume_gasc(Gas_limit_repr.alloc_mbytes_costlen)>>?=func->letcost=Storage_costs.write_access~written_bytes:leninC.consume_gasccost>>?=func->setc(len_keyi)(encode_len_valuebytes)>|=?func->(c,bytes)letconsume_remove_gasdelci=C.consume_gasc(Storage_costs.write_access~written_bytes:0)>>?=func->delc(len_keyi)letmemsi=letkey=data_keyiinconsume_mem_gasskey>>?=funs->C.memskey>|=funexists->ok(C.projects,exists)letget_unprojectedsi=consume_read_gasC.getsi>>=?funs->C.gets(data_keyi)>>=?funb->letkey()=C.absolute_keys(data_keyi)inLwt.return(of_bytes~keyb>|?funv->(s,v))letgetsi=get_unprojectedsi>|=?fun(s,v)->(C.projects,v)letfindsi=letkey=data_keyiinconsume_mem_gasskey>>?=funs->C.memskey>>=funexists->ifexiststhengetsi>|=?fun(s,v)->(s,Somev)elsereturn(C.projects,None)letupdatesiv=existing_sizesi>>=?fun(prev_size,_)->consume_serialize_write_gasC.updatesiv>>=?fun(s,bytes)->C.updates(data_keyi)bytes>|=?funt->letsize_diff=Bytes.lengthbytes-prev_sizein(C.projectt,size_diff)letinitsiv=consume_serialize_write_gasC.initsiv>>=?fun(s,bytes)->C.inits(data_keyi)bytes>|=?funt->letsize=Bytes.lengthbytesin(C.projectt,size)letaddsiv=letaddsiv=C.addsiv>|=okinexisting_sizesi>>=?fun(prev_size,existed)->consume_serialize_write_gasaddsiv>>=?fun(s,bytes)->adds(data_keyi)bytes>|=?funt->letsize_diff=Bytes.lengthbytes-prev_sizein(C.projectt,size_diff,existed)letremovesi=letremovesi=C.removesi>|=okinexisting_sizesi>>=?fun(prev_size,existed)->consume_remove_gasremovesi>>=?funs->removes(data_keyi)>|=?funt->(C.projectt,prev_size,existed)letremove_existingsi=existing_sizesi>>=?fun(prev_size,_)->consume_remove_gasC.remove_existingsi>>=?funs->C.remove_existings(data_keyi)>|=?funt->(C.projectt,prev_size)letadd_or_removesiv=matchvwithNone->removesi|Somev->addsiv(** Because big map values are not stored under some common key,
we have no choice but to fold over all nodes with a path of length
[I.path_length] to retrieve actual keys and then paginate.
While this is inefficient and will traverse the whole tree ([O(n)]), there
currently isn't a better decent alternative.
Once https://gitlab.com/tezos/tezos/-/merge_requests/2771 which flattens paths is done,
{!C.list} could be used instead here. *)letlist_values?(offset=0)?(length=max_int)s=letroot=[]inletdepth=`EqI.path_lengthinC.foldsroot~depth~order:`Sorted~init:(ok(s,[],offset,length))~f:(funfiletreeacc->match(C.Tree.kindtree,acc)with|(`Tree,Ok(s,rev_values,offset,length))->(ifCompare.Int.(length<=0)then(* Keep going until the end, we have no means of short-circuiting *)Lwt.returnaccelseifCompare.Int.(offset>0)then(* Offset (first element) not reached yet *)letoffset=predoffsetinLwt.return(Ok(s,rev_values,offset,length))else(* Nominal case *)matchI.of_pathfilewith|None->assertfalse|Somekey->get_unprojectedskey>|=?fun(s,value)->(s,value::rev_values,0,predlength))|_->Lwt.returnacc)>|=?fun(s,rev_values,_offset,_length)->(C.projects,List.revrev_values)letfold_keys_unaccounteds~order~init~f=C.fold~depth:(`EqI.path_length)s[]~order~init~f:(funfiletreeacc->matchC.Tree.kindtreewith|`Value->(matchList.revfilewith|last::_whenCompare.String.(last=len_name)->Lwt.returnacc|last::restwhenCompare.String.(last=data_name)->(letfile=List.revrestinmatchI.of_pathfilewith|None->assertfalse|Somepath->fpathacc)|_->assertfalse)|`Tree->Lwt.returnacc)letkeys_unaccounteds=fold_keys_unaccounteds~order:`Sorted~init:[]~f:(funpacc->Lwt.return(p::acc))let()=letopenStorage_descriptioninletunpack=unpackI.argsinregister_value(* TODO export consumed gas ?? *)~get:(func->let(c,k)=unpackcinfindck>|=?fun(_,v)->v)(register_indexed_subcontext~list:(func->keys_unaccountedc>|=ok)C.descriptionI.args)V.encoding[@@coq_axiom_with_reason"stack overflow in Coq"]endmoduleMake_indexed_carbonated_data_storage:functor(C:Raw_context.T)(I:INDEX)(V:VALUE)->Non_iterable_indexed_carbonated_data_storage_with_valueswithtypet=C.tandtypekey=I.tandtypevalue=V.t=Make_indexed_carbonated_data_storage_INTERNALmoduleMake_carbonated_data_set_storage(C:Raw_context.T)(I:INDEX):Carbonated_data_set_storagewithtypet=C.tandtypeelt=I.t=structmoduleV=structtypet=unitletencoding=Data_encoding.unitendmoduleM=Make_indexed_carbonated_data_storage_INTERNAL(C)(I)(V)typet=M.ttypecontext=ttypeelt=I.tletmem=M.memletinitsi=M.initsi()letremovesi=M.removesiletfold_keys_unaccounted=M.fold_keys_unaccountedendmoduleMake_indexed_data_snapshotable_storage(C:Raw_context.T)(Snapshot_index:INDEX)(I:INDEX)(V:VALUE):Indexed_data_snapshotable_storagewithtypet=C.tandtypesnapshot=Snapshot_index.tandtypekey=I.tandtypevalue=V.t=structtypesnapshot=Snapshot_index.tletdata_name=["current"]letsnapshot_name=["snapshot"]moduleC_data=Make_subcontext(Registered)(C)(structletname=data_nameend)moduleC_snapshot=Make_subcontext(Registered)(C)(structletname=snapshot_nameend)moduleV_encoder=Make_encoder(V)includeMake_indexed_data_storage(C_data)(I)(V)moduleSnapshot=Make_indexed_data_storage(C_snapshot)(Pair(Snapshot_index)(I))(V)letsnapshot_pathid=snapshot_name@Snapshot_index.to_pathid[]letsnapshot_existssid=C.mem_trees(snapshot_pathid)leterr_missing_keykey=Raw_context.storage_error(Missing_key(key,Copy))letsnapshotsid=C.find_treesdata_name>>=function|None->Lwt.return(err_missing_keydata_name)|Sometree->C.add_trees(snapshot_pathid)tree>|=(funt->C.projectt)>|=okletfold_snapshotsid~order~init~f=C.find_trees(snapshot_pathid)>>=function|None->Lwt.return(err_missing_keydata_name)|Sometree->C_data.Tree.foldtree~depth:(`EqI.path_length)[]~order~init:(Okinit)~f:(funfiletreeacc->acc>>?=funacc->C.Tree.to_valuetree>>=function|Somev->(matchI.of_pathfilewith|None->assertfalse|Somepath->(letkey()=C.absolute_keysfileinmatchV_encoder.of_bytes~keyvwith|Okv->fpathvacc|Error_->returnacc))|None->returnacc)letdelete_snapshotsid=C.removes(snapshot_pathid)>|=funt->C.projecttendmoduleMake_indexed_subcontext(C:Raw_context.T)(I:INDEX):Indexed_raw_contextwithtypet=C.tandtypekey=I.tandtype'aipath='aI.ipath=structtypet=C.ttypecontext=ttypekey=I.ttype'aipath='aI.ipathletcleart=C.removet[]>|=funt->C.projecttletfold_keyst~order~init~f=C.fold~depth:(`EqI.path_length)t[]~order~init~f:(funpathtreeacc->matchC.Tree.kindtreewith|`Tree->(matchI.of_pathpathwith|None->assertfalse|Somepath->fpathacc)|`Value->Lwt.returnacc)letkeyst=fold_keyst~order:`Sorted~init:[]~f:(funiacc->Lwt.return(i::acc))leterr_missing_keykey=Raw_context.storage_error(Missing_key(key,Copy))letcopyt~from~to_=letfrom=I.to_pathfrom[]inletto_=I.to_pathto_[]inC.find_treetfrom>>=function|None->Lwt.return(err_missing_keyfrom)|Sometree->C.add_treetto_tree>|=okletremovetk=C.removet(I.to_pathk[])letdescription=Storage_description.register_indexed_subcontext~list:(func->keysc>|=ok)C.descriptionI.argsletunpack=Storage_description.unpackI.argsletpack=Storage_description.packI.argsmoduleRaw_context:Raw_context.Twithtypet=C.tI.ipath=structtypet=C.tI.ipathletto_keyik=I.to_pathikletmemck=let(t,i)=unpackcinC.memt(to_keyik)letmem_treeck=let(t,i)=unpackcinC.mem_treet(to_keyik)letgetck=let(t,i)=unpackcinC.gett(to_keyik)letget_treeck=let(t,i)=unpackcinC.get_treet(to_keyik)letfindck=let(t,i)=unpackcinC.findt(to_keyik)letfind_treeck=let(t,i)=unpackcinC.find_treet(to_keyik)letlistc?offset?lengthk=let(t,i)=unpackcinC.listt?offset?length(to_keyik)letinitckv=let(t,i)=unpackcinC.initt(to_keyik)v>|=?funt->packtiletinit_treeckv=let(t,i)=unpackcinC.init_treet(to_keyik)v>|=?funt->packtiletupdateckv=let(t,i)=unpackcinC.updatet(to_keyik)v>|=?funt->packtiletupdate_treeckv=let(t,i)=unpackcinC.update_treet(to_keyik)v>|=?funt->packtiletaddckv=let(t,i)=unpackcinC.addt(to_keyik)v>|=funt->packtiletadd_treeckv=let(t,i)=unpackcinC.add_treet(to_keyik)v>|=funt->packtiletadd_or_removeckv=let(t,i)=unpackcinC.add_or_removet(to_keyik)v>|=funt->packtiletadd_or_remove_treeckv=let(t,i)=unpackcinC.add_or_remove_treet(to_keyik)v>|=funt->packtiletremove_existingck=let(t,i)=unpackcinC.remove_existingt(to_keyik)>|=?funt->packtiletremove_existing_treeck=let(t,i)=unpackcinC.remove_existing_treet(to_keyik)>|=?funt->packtiletremoveck=let(t,i)=unpackcinC.removet(to_keyik)>|=funt->packtiletfold?depthck~order~init~f=let(t,i)=unpackcinC.fold?deptht(to_keyik)~order~init~fmoduleTree=structincludeC.Treeletemptyc=let(t,_)=unpackcinC.Tree.emptytendletprojectc=let(t,_)=unpackcinC.projecttletabsolute_keyck=let(t,i)=unpackcinC.absolute_keyt(to_keyik)typeerror+=Block_quota_exceeded=C.Block_quota_exceededtypeerror+=Operation_quota_exceeded=C.Operation_quota_exceededletconsume_gascg=let(t,i)=unpackcinC.consume_gastg>>?funt->ok(packti)letcheck_enough_gascg=let(t,_i)=unpackcinC.check_enough_gastgletdescription=descriptionendmoduleMake_set(R:REGISTER)(N:NAME):Data_set_storagewithtypet=tandtypeelt=key=structtypet=C.ttypecontext=ttypeelt=I.tletinited=Bytes.of_string"inited"letmemsi=Raw_context.mem(packsi)N.nameletaddsi=Raw_context.add(packsi)N.nameinited>|=func->let(s,_)=unpackcinC.projectsletremovesi=Raw_context.remove(packsi)N.name>|=func->let(s,_)=unpackcinC.projectsletclears=fold_keyss~init:s~order:`Sorted~f:(funis->Raw_context.remove(packsi)N.name>|=func->let(s,_)=unpackcins)>|=funt->C.projecttletfolds~order~init~f=fold_keyss~order~init~f:(funiacc->memsi>>=functiontrue->fiacc|false->Lwt.returnacc)letelementss=folds~order:`Sorted~init:[]~f:(funpacc->Lwt.return(p::acc))let()=letopenStorage_descriptioninletunpack=unpackI.argsinletdescription=ifR.ghostthenStorage_description.create()elseRaw_context.descriptioninregister_value~get:(func->let(c,k)=unpackcinmemck>>=functiontrue->return_sometrue|false->return_none)(register_named_subcontextdescriptionN.name)Data_encoding.bool[@@coq_axiom_with_reason"stack overflow in Coq"]endmoduleMake_map(N:NAME)(V:VALUE):Indexed_data_storagewithtypet=tandtypekey=keyandtypevalue=V.t=structtypet=C.ttypecontext=ttypekey=I.ttypevalue=V.tincludeMake_encoder(V)letmemsi=Raw_context.mem(packsi)N.nameletgetsi=Raw_context.get(packsi)N.name>>=?funb->letkey()=Raw_context.absolute_key(packsi)N.nameinLwt.return(of_bytes~keyb)letfindsi=Raw_context.find(packsi)N.name>|=function|None->Result.return_none|Someb->letkey()=Raw_context.absolute_key(packsi)N.nameinof_bytes~keyb>|?funv->Somevletupdatesiv=Raw_context.update(packsi)N.name(to_bytesv)>|=?func->let(s,_)=unpackcinC.projectsletinitsiv=Raw_context.init(packsi)N.name(to_bytesv)>|=?func->let(s,_)=unpackcinC.projectsletaddsiv=Raw_context.add(packsi)N.name(to_bytesv)>|=func->let(s,_)=unpackcinC.projectsletadd_or_removesiv=Raw_context.add_or_remove(packsi)N.name(Option.mapto_bytesv)>|=func->let(s,_)=unpackcinC.projectsletremovesi=Raw_context.remove(packsi)N.name>|=func->let(s,_)=unpackcinC.projectsletremove_existingsi=Raw_context.remove_existing(packsi)N.name>|=?func->let(s,_)=unpackcinC.projectsletclears=fold_keyss~order:`Sorted~init:s~f:(funis->Raw_context.remove(packsi)N.name>|=func->let(s,_)=unpackcins)>|=funt->C.projecttletfolds~order~init~f=fold_keyss~order~init~f:(funiacc->getsi>>=functionError_->Lwt.returnacc|Okv->fivacc)letbindingss=folds~order:`Sorted~init:[]~f:(funpvacc->Lwt.return((p,v)::acc))letfold_keyss~order~init~f=fold_keyss~order~init~f:(funiacc->memsi>>=functionfalse->Lwt.returnacc|true->fiacc)letkeyss=fold_keyss~order:`Sorted~init:[]~f:(funpacc->Lwt.return(p::acc))let()=letopenStorage_descriptioninletunpack=unpackI.argsinregister_value~get:(func->let(c,k)=unpackcinfindck)(register_named_subcontextRaw_context.descriptionN.name)V.encoding[@@coq_axiom_with_reason"stack overflow in Coq"]endmoduleMake_carbonated_map(N:NAME)(V:VALUE):Non_iterable_indexed_carbonated_data_storagewithtypet=tandtypekey=keyandtypevalue=V.t=structtypet=C.ttypecontext=ttypekey=I.ttypevalue=V.tincludeMake_encoder(V)letlen_name=len_name::N.nameletdata_name=data_name::N.nameletpath_length=List.lengthN.name+1letconsume_mem_gasc=Raw_context.consume_gasc(Storage_costs.read_access~path_length~read_bytes:0)letexisting_sizec=Raw_context.findclen_name>|=function|None->ok(0,false)|Somelen->decode_len_valuelen_namelen>|?funlen->(len,true)letconsume_read_gasgetc=getclen_name>>=?funlen->Lwt.return(decode_len_valuelen_namelen>>?funread_bytes->Raw_context.consume_gasc(Storage_costs.read_access~path_length~read_bytes))letconsume_write_gassetcv=letbytes=to_bytesvinletlen=Bytes.lengthbytesinRaw_context.consume_gasc(Storage_costs.write_access~written_bytes:len)>>?=func->setclen_name(encode_len_valuebytes)>|=?func->(c,bytes)letconsume_remove_gasdelc=Raw_context.consume_gasc(Storage_costs.write_access~written_bytes:0)>>?=func->delclen_nameletmemsi=consume_mem_gas(packsi)>>?=func->Raw_context.memcdata_name>|=funres->ok(Raw_context.projectc,res)letgetsi=consume_read_gasRaw_context.get(packsi)>>=?func->Raw_context.getcdata_name>>=?funb->letkey()=Raw_context.absolute_keycdata_nameinLwt.return(of_bytes~keyb>|?funv->(Raw_context.projectc,v))letfindsi=consume_mem_gas(packsi)>>?=func->let(s,_)=unpackcinRaw_context.mem(packsi)data_name>>=funexists->ifexiststhengetsi>|=?fun(s,v)->(s,Somev)elsereturn(C.projects,None)letupdatesiv=existing_size(packsi)>>=?fun(prev_size,_)->consume_write_gasRaw_context.update(packsi)v>>=?fun(c,bytes)->Raw_context.updatecdata_namebytes>|=?func->letsize_diff=Bytes.lengthbytes-prev_sizein(Raw_context.projectc,size_diff)letinitsiv=consume_write_gasRaw_context.init(packsi)v>>=?fun(c,bytes)->Raw_context.initcdata_namebytes>|=?func->letsize=Bytes.lengthbytesin(Raw_context.projectc,size)letaddsiv=letaddckv=Raw_context.addckv>|=okinexisting_size(packsi)>>=?fun(prev_size,existed)->consume_write_gasadd(packsi)v>>=?fun(c,bytes)->addcdata_namebytes>|=?func->letsize_diff=Bytes.lengthbytes-prev_sizein(Raw_context.projectc,size_diff,existed)letremovesi=letremoveck=Raw_context.removeck>|=okinexisting_size(packsi)>>=?fun(prev_size,existed)->consume_remove_gasremove(packsi)>>=?func->removecdata_name>|=?func->(Raw_context.projectc,prev_size,existed)letremove_existingsi=existing_size(packsi)>>=?fun(prev_size,_)->consume_remove_gasRaw_context.remove_existing(packsi)>>=?func->Raw_context.remove_existingcdata_name>|=?func->(Raw_context.projectc,prev_size)letadd_or_removesiv=matchvwithNone->removesi|Somev->addsivlet()=letopenStorage_descriptioninletunpack=unpackI.argsinregister_value~get:(func->let(c,k)=unpackcinfindck>|=?fun(_,v)->v)(register_named_subcontextRaw_context.descriptionN.name)V.encoding[@@coq_axiom_with_reason"stack overflow in Coq"]endendmoduletypeWRAPPER=sigtypettypekeyvalwrap:t->keyvalunwrap:key->toptionendmoduleWrap_indexed_data_storage(C:Indexed_data_storage)(K:WRAPPERwithtypekey:=C.key):Indexed_data_storagewithtypet=C.tandtypekey=K.tandtypevalue=C.value=structtypet=C.ttypecontext=C.ttypekey=K.ttypevalue=C.valueletmemctxtk=C.memctxt(K.wrapk)letgetctxtk=C.getctxt(K.wrapk)letfindctxtk=C.findctxt(K.wrapk)letupdatectxtkv=C.updatectxt(K.wrapk)vletinitctxtkv=C.initctxt(K.wrapk)vletaddctxtkv=C.addctxt(K.wrapk)vletadd_or_removectxtkv=C.add_or_removectxt(K.wrapk)vletremove_existingctxtk=C.remove_existingctxt(K.wrapk)letremovectxtk=C.removectxt(K.wrapk)letclearctxt=C.clearctxtletfoldctxt~order~init~f=C.foldctxt~order~init~f:(funkvacc->matchK.unwrapkwithNone->Lwt.returnacc|Somek->fkvacc)letbindingss=folds~order:`Sorted~init:[]~f:(funpvacc->Lwt.return((p,v)::acc))letfold_keyss~order~init~f=C.fold_keyss~order~init~f:(funkacc->matchK.unwrapkwithNone->Lwt.returnacc|Somek->fkacc)letkeyss=fold_keyss~order:`Sorted~init:[]~f:(funpacc->Lwt.return(p::acc))end