123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135(*****************************************************************************)(* *)(* MIT 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. *)(* *)(*****************************************************************************)openLang_stdlibopenLang_coremoduletypeHASH=Hash_sig.HASHmoduletypeMERKLE_NARITY=functor(H:HASH)(L:LIB)->sigopenLtypedirection=scalartypeproof=(scalar*(scalarlist*direction)list)reprtyperoot=scalarreprvalmerkle_proof:int->proof->root->boolreprtendmoduleP(Mec:Hash_sig.P_HASH)=structtypetree=LeafofS.t|BranchofS.t*treelistletroot=functionLeafh->h|Branch(h,_)->hletrecgenerate_treendepth=ifdepth=0thenLeaf(S.random())elseletchildren=List.initn(fun_->generate_treen(depth-1))inletroot=Mec.direct(Array.of_list(List.maprootchildren))inBranch(root,children)(* This function assumes that the length of pos and the depth of tree coincide.
Furthermore, that pos is a list of integers between 0 and n-1, where n is
the arity of the tree (which is consistent in arity).
*)letproof_path_naritypostree=letrecauxpathpos=function|Leafh->(path,h)|Branch(_,children)->letdirection=List.hdposinlett=List.nthchildrendirectioninletlevel_witnesses=List.filteri(funj_->direction<>j)children|>List.maprootinaux((level_witnesses,S.of_z(Z.of_intdirection))::path)(List.tlpos)tinaux[]postreeendmoduleV:MERKLE_NARITY=functor(H:HASH)(L:LIB)->structopenLopenH(L)typedirection=scalar(* leaf, path *)typeproof=(scalar*(scalarlist*direction)list)reprtyperoot=scalarreprletmerkle_proof:int->proof->root->boolreprt=funnwitnessexpected_root->with_label~label:"MerkleNArity.merkle_proof"@@letmoduleE=Enum(structletn=nend)inletleaf,path=of_pairwitnessinlet*root=foldM(funcomputed_hstep->letlevel_witnesses,direction=of_pairstepinletlevel_witnesses=of_listlevel_witnessesinlet*hash_inputs=foldiM(funhash_inputsi->lethash_inputs=of_listhash_inputsinletcand_i=ifi>0thenList.nthlevel_witnesses(i-1)elsecomputed_hinletcand_i'=ifi<n-1thenList.nthlevel_witnessesielsecomputed_hinletcandidates=to_list@@List.initn(funj->ifj<ithencand_ielseifj=ithencomputed_helsecand_i')inlet*input_i=E.switch_casedirectioncandidatesinlethash_inputs=to_list(input_i::hash_inputs)inrethash_inputs)(to_list[])nindigest(to_list@@List.rev(of_listhash_inputs)))leaf(of_listpath)inequalrootexpected_rootend