123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249(*****************************************************************************)(* *)(* 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. *)(* *)(*****************************************************************************)typeerror+=(* `Permanent *)Merkelized_payload_hashes_proof_errorofstringlet()=letopenData_encodinginregister_error_kind`Permanent~id:"internal.smart_rollup_merklized_payload_hashes_proof"~title:"Internal error: error occurred during proof production or validation"~description:"A merkelized payload hashes proof error."~pp:(funppfe->Format.fprintfppf"Proof error: %s"e)(obj1(req"error"(stringPlain)))(functionMerkelized_payload_hashes_proof_errore->Somee|_->None)(fune->Merkelized_payload_hashes_proof_errore)moduleSkip_list_parameters=structletbasis=4endmoduleSkip_list=Skip_list_repr.Make(Skip_list_parameters)(* 32 *)lethash_prefix="\003\255\138\145\140"(* srib2(55) *)moduleHash=structletprefix="srib2"letencoded_size=55moduleH=Blake2B.Make(Base58)(structletname="Smart_rollup_merkelized_payload_hashes_hash"lettitle="The merkelized payload hashes' hash of the smart rollup inbox"letb58check_prefix=hash_prefix(* defaults to 32 *)letsize=Noneend)includeHlet()=Base58.check_encoded_prefixb58check_encodingprefixencoded_sizeendtypet=(Sc_rollup_inbox_message_repr.Hash.t,Hash.t)Skip_list.cellletequal=Skip_list.equalHash.equalSc_rollup_inbox_message_repr.Hash.equallethashmerkelized=letpayload_hash=Skip_list.contentmerkelizedinletback_pointers_hashes=Skip_list.back_pointersmerkelizedinSc_rollup_inbox_message_repr.Hash.to_bytespayload_hash::List.mapHash.to_bytesback_pointers_hashes|>Hash.hash_bytesletpp=Skip_list.pp~pp_content:Sc_rollup_inbox_message_repr.Hash.pp~pp_ptr:Hash.ppletencoding=Skip_list.encodingHash.encodingSc_rollup_inbox_message_repr.Hash.encodingtypemerkelized_and_payload={merkelized:t;payload:Sc_rollup_inbox_message_repr.serialized;}letequal_merkelized_and_payload{merkelized;payload}mp2=equalmerkelizedmp2.merkelized&&String.equal(payload:>string)(mp2.payload:>string)letpp_merkelized_and_payloadfmt{merkelized;payload}=Format.fprintffmt"@[<hv 2>merkelized:@,%a@,payload: %a@]"ppmerkelizedFormat.pp_print_string(payload:>string)letmerkelized_and_payload_encoding=letopenData_encodinginconv(fun{merkelized;payload}->(merkelized,(payload:>string)))(fun(merkelized,payload)->{merkelized;payload=Sc_rollup_inbox_message_repr.unsafe_of_stringpayload;})(merge_objsencoding(obj1(req"payload"(stringHex))))moduleHistory=structincludeBounded_history_repr.Make(structletname="Smart_rollup_level_inbox_history"end)(Hash)(structtypenonrect=merkelized_and_payloadletpp=pp_merkelized_and_payloadletequal=equal_merkelized_and_payloadletencoding=merkelized_and_payload_encodingend)letno_history=empty~capacity:0Lendletrememberhistorymerkelizedpayload=letprev_cell_ptr=hashmerkelizedinHistory.rememberprev_cell_ptr{merkelized;payload}historyletgenesishistorypayload=letopenResult_syntaxinletpayload_hash=Sc_rollup_inbox_message_repr.hash_serialized_messagepayloadinletmerkelized=Skip_list.genesispayload_hashinlet+history=rememberhistorymerkelizedpayloadin(history,merkelized)letadd_payloadhistoryprev_merkelizedpayload=letopenResult_syntaxinletprev_merkelized_ptr=hashprev_merkelizedinletmerkelized=Skip_list.next~prev_cell:prev_merkelized~prev_cell_ptr:prev_merkelized_ptr(Sc_rollup_inbox_message_repr.hash_serialized_messagepayload)inlet*history=rememberhistorymerkelizedpayloadinreturn(history,merkelized)letget_payload_hash=Skip_list.contentletget_index=Skip_list.indextypeproof=tlistletpp_proof=Format.pp_print_listppletproof_encoding=Data_encoding.listencodingletproduce_proofhistory~indexmerkelized=letopenOption_syntaxinletderefptr=let*{merkelized;payload=_}=History.findptrhistoryinreturnmerkelizedinletcurrent_ptr=hashmerkelizedinletlift_ptr=letrecauxacc=function|[]->None|[last_ptr]->let+({merkelized;_}asmerkelized_and_payload)=History.findlast_ptrhistoryin(merkelized_and_payload,List.rev(merkelized::acc))|ptr::rest->let*merkelized=derefptrinaux(merkelized::acc)restinaux[]inlet*ptr_path=Skip_list.back_path~deref~cell_ptr:current_ptr~target_index:indexinlift_ptrptr_pathletverify_proofinclusion_proof=letopenResult_syntaxinlet*cell=matchinclusion_proofwith|cell::_->okcell|[]->error(Merkelized_payload_hashes_proof_error"inclusion proof is empty")inletrecaux(hash_map,ptr_list)=function|[]->error(Merkelized_payload_hashes_proof_error"inclusion proof is empty")|[target]->lettarget_ptr=hashtargetinlethash_map=Hash.Map.addtarget_ptrtargethash_mapinletptr_list=List.rev(target_ptr::ptr_list)inok(hash_map,ptr_list,target,target_ptr)|merkelized::tail->letptr=hashmerkelizedinaux(Hash.Map.addptrmerkelizedhash_map,ptr::ptr_list)tailinlet*hash_map,ptr_list,target,target_ptr=aux(Hash.Map.empty,[])inclusion_proofinletderefptr=Hash.Map.findptrhash_mapinletcell_ptr=hashcellinlet*()=error_unless(Skip_list.valid_back_path~equal_ptr:Hash.equal~deref~cell_ptr~target_ptrptr_list)(Merkelized_payload_hashes_proof_error"invalid inclusion proof")inreturn(target,cell)moduleInternal_for_tests=structletfind_predecessor_payloadpayloads_history~indexpayloads=letopenOption_syntaxinletderefptr=let*{merkelized;_}=History.findptrpayloads_historyinreturnmerkelizedinletcell_ptr=hashpayloadsinSkip_list.find~deref~cell_ptr~target_index:indexletmake_proofproof=proofend