12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085(*****************************************************************************)(* *)(* 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~init~f=C.fold?deptht(to_keyk)~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->ok_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~init~f=C.fold~depth:(`EqI.path_length)s[]~init~f:(funfiletreeacc->matchC.Tree.kindtreewith|`Value->(matchI.of_pathfilewithNone->assertfalse|Somep->fpacc)|`Tree->Lwt.returnacc)letelementss=folds~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->ok_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~init~f=C.fold~depth:(`EqI.path_length)s[]~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~init~f=folds~init~f:(funk_acc->fkacc)letbindingss=folds~init:[]~f:(funpvacc->Lwt.return((p,v)::acc))letkeyss=fold_keyss~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~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~init~f=C.fold~depth:(`EqI.path_length)s[]~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~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)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)>|=okletdelete_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~init~f=C.fold~depth:(`EqI.path_length)t[]~init~f:(funpathtreeacc->matchC.Tree.kindtreewith|`Tree->(matchI.of_pathpathwith|None->assertfalse|Somepath->fpathacc)|`Value->Lwt.returnacc)letkeyst=fold_keyst~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~init~f=let(t,i)=unpackcinC.fold?deptht(to_keyik)~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~f:(funis->Raw_context.remove(packsi)N.name>|=func->let(s,_)=unpackcins)>|=funt->C.projecttletfolds~init~f=fold_keyss~init~f:(funiacc->memsi>>=functiontrue->fiacc|false->Lwt.returnacc)letelementss=folds~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->ok_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~init:s~f:(funis->Raw_context.remove(packsi)N.name>|=func->let(s,_)=unpackcins)>|=funt->C.projecttletfolds~init~f=fold_keyss~init~f:(funiacc->getsi>>=functionError_->Lwt.returnacc|Okv->fivacc)letbindingss=folds~init:[]~f:(funpvacc->Lwt.return((p,v)::acc))letfold_keyss~init~f=fold_keyss~init~f:(funiacc->memsi>>=functionfalse->Lwt.returnacc|true->fiacc)letkeyss=fold_keyss~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~init~f=C.foldctxt~init~f:(funkvacc->matchK.unwrapkwithNone->Lwt.returnacc|Somek->fkvacc)letbindingss=folds~init:[]~f:(funpvacc->Lwt.return((p,v)::acc))letfold_keyss~init~f=C.fold_keyss~init~f:(funkacc->matchK.unwrapkwithNone->Lwt.returnacc|Somek->fkacc)letkeyss=fold_keyss~init:[]~f:(funpacc->Lwt.return(p::acc))end