123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380(*****************************************************************************)(* *)(* 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. *)(* *)(*****************************************************************************)includeLang_coretypescalar=XofS.ttype'arepr=|U:unitrepr|S:scalar->scalarrepr|B:bool->boolrepr|P:'arepr*'brepr->('a*'b)repr|L:'areprlist->'alistreprtypestate=boolreprlisttype'at=state->state*'aletretxs=(s,x)let(let*)mfs=lets,o=msinfoslet(>*)mf=let*U=minfletrecmapMfls=matchlswith|[]->ret@@[]|l::ls->let*o=flinlet*rest=mapMflsinret@@(o::rest)letwith_bool_check:boolreprt->unitreprt=funchecks->lets,b=checksin(b::s,U)moduleInput=structtype'aimplicit_check='arepr->unitreprttype'at'='areprtype'ainput='at'*'aimplicit_checktype'at='ainputletdefault_check_=retUletsx:scalart'=S(Xx)letscalarx=(sx,default_check)letto_scalar(S(Xx),_)=xletboolb=(Bb,default_check)letto_bool(Bb,_)=bletunit=(U,default_check)letpair:'at->'bt->('a*'b)t=fun(a,check_a)(b,check_b)->(P(a,b),fun(P(ar,br))->check_aar>*check_bbr)letto_pair(P(a,b),_)=((a,default_check),(b,default_check))letlist:'atlist->'alistt=funl->(L(List.mapfstl),fun(Llr)->let*_l=mapM(fun((_,asssertion),r)->asssertionr)(List.combinellr)inretU)letto_list(Ll,_)=List.map(funi->(i,default_check))lletwith_implicit_bool_checkbc(i,a)=(i,funrepr->arepr>*with_bool_check(bcrepr))letwith_assertionna(i,a)=(i,funrepr->arepr>*narepr)endletrecencode:typea.aInput.t'->S.tlist=funinput->matchinputwith|U->[]|S(Xs)->[s]|Bb->ifbthen[S.one]else[S.zero]|P(l,r)->encodel@encoder|Ll->List.concat_mapencodelletserializei=Array.of_list@@encode(fsti)letreceq:typea.arepr->arepr->bool=funab->match(a,b)with|S(Xa),S(Xb)->S.eqab|Ba,Bb->a=b|P(al,ar),P(bl,br)->eqalbl&&eqarbr|Ll1,Ll2->List.for_all2eql1l2|U,U->trueletinput:typea.?public:bool->aInput.t->areprt=fun?(public=false)(input,check)->ignorepublic;checkinput>*retinputletto_listl=Llletof_list(Ll)=lletof_pair(P(l,r))=(l,r)letpairlr=P(l,r)letunit=Uletof_s(S(Xs))=sletmap2fxy=X(fxy)letrecfoldMfel=matchlwith|[]->rete|x::xs->let*y=fexinfoldMfyxsletscalar_of_bool(Bb)=ifbthenS(XS.one)elseS(XS.zero)letconstant_scalarx=ret@@Input.sxletunsafe_bool_of_scalar(S(Xs))=ifS.(eqsone)thenBtrueelseBfalsemoduleNum=structtypenonrecscalar=scalartypenonrec'arepr='areprtypenonrec'at='atletassert_nonzerosx=letx=of_ssxinassert(notS.(x=zero));retUletis_zero(S(Xx))=ret@@BS.(x=zero)letis_not_zero(S(Xx))=ret@@B(notS.(x=zero))letcustom?(qc=S.zero)?(ql=S.zero)?(qr=S.zero)?(qo=S.mone)?(qm=S.zero)slsr=letl,r=(of_ssl,of_ssr)inleto=S.(((ql*l)+(qr*r)+(qm*l*r)+qc)/negateqo)inret@@S(Xo)letassert_custom?(qc=S.zero)?(ql=S.zero)?(qr=S.zero)?(qo=S.zero)?(qm=S.zero)slsrso=letl,r,o=(of_ssl,of_ssr,of_sso)inleto=S.((ql*l)+(qr*r)+(qo*o)+(qm*l*r)+qc)inassert(S.(o=zero));retUletadd?(qc=S.zero)?(ql=S.one)?(qr=S.one)slsr=letl,r=(of_ssl,of_ssr)inleto=S.((ql*l)+(qr*r)+qc)inret@@S(Xo)letsubslsr=letl,r=(of_ssl,of_ssr)inret@@S(map2S.sublr)letmul?(qm=S.one)slsr=letl,r=(of_ssl,of_ssr)inletlr=S.mullrinret@@S(map2S.mulqmlr)letadd_constant?(ql=S.one)ksl=letl=of_sslinleto=S.(k+(ql*l))inret@@S(Xo)letdiv?(qm=S.one)slsr=letl,r=(of_ssl,of_ssr)inassert(notS.(is_zeror));assert(notS.(is_zeroqm));letqmr=S.mulqmrinret@@S(map2S.div_exnlqmr)letpow5sl=letl=of_sslinret@@S(XS.(powl(Z.of_int5)))letadd5?(k1=S.one)?(k2=S.one)?(k3=S.one)?(k4=S.one)?(k5=S.one)s1s2s3s4s5=letx1,x2,x3,x4,x5=(of_ss1,of_ss2,of_ss3,of_ss4,of_ss5)inret@@S(XS.((k1*x1)+(k2*x2)+(k3*x3)+(k4*x4)+(k5*x5)))endmoduleBool=structincludeNumlets_of_bb=ifbthenXS.oneelseXS.zeroletassert_true(Bb)=assertb;retUletassert_false(Bb)=assert(notb);retUletconstant_bool:bool->boolreprt=funb->ret(Bb)letband(Bl)(Br)=ret@@B(l&&r)letxor(Bl)(Br)=leto=match(l,r)with|true,true->false|false,true->true|true,false->true|false,false->falseinret@@Boletbor(Bl)(Br)=ret@@B(l||r)letbor_lookup(Bl)(Br)=bor(Bl)(Br)letbnot(Bb)=ret@@B(notb)letifthenelse(Bb)lr=ifbthenretlelseretrletband_listl:boolreprt=ret@@List.fold_left(fun(Ba)(Bb)->B(a&&b))(Btrue)lendletpointxy=P(S(Xx),S(Xy))letof_point(P(S(Xx),S(Xy)))=(x,y)moduleEcc=structletweierstrass_addp1p2=letmoduleW=Mec.Curve.Jubjub.AffineWeierstrassinletx1,y1=of_pointp1inletx2,y2=of_pointp2inlets_to_bases=W.Base.of_z(S.to_zs)inlets_of_bases=S.of_z(W.Base.to_zs)inletp1=W.from_coordinates_exn~x:(s_to_basex1)~y:(s_to_basey1)inletp2=W.from_coordinates_exn~x:(s_to_basex2)~y:(s_to_basey2)inletp3=W.addp1p2inret@@point(s_of_base@@W.get_x_coordinatep3)(s_of_base@@W.get_y_coordinatep3)letedwards_addp1p2=letmoduleW=Mec.Curve.Jubjub.AffineEdwardsinletx1,y1=of_pointp1inletx2,y2=of_pointp2inlets_to_bases=W.Base.of_z(S.to_zs)inlets_of_bases=S.of_z(W.Base.to_zs)inletp1=W.from_coordinates_exn~u:(s_to_basex1)~v:(s_to_basey1)inletp2=W.from_coordinates_exn~u:(s_to_basex2)~v:(s_to_basey2)inletp3=W.addp1p2inret@@point(s_of_base@@W.get_u_coordinatep3)(s_of_base@@W.get_v_coordinatep3)endmodulePoseidon=structmoduleVS=Linear_algebra.Make_VectorSpace(S)letposeidon128_full_round~matrix~k~variant:_(x0,x1,x2)=letpow5x=S.pow(of_sx)(Z.of_int5)inletx_vec=[|Array.mappow5[|x0;x1;x2|]|]|>VS.transposeinlety_vec=VS.mulmatrixx_vecinlety0=S.addk.(0)@@y_vec.(0).(0)inlety1=S.addk.(1)@@y_vec.(1).(0)inlety2=S.addk.(2)@@y_vec.(2).(0)inret@@to_list[S(Xy0);S(Xy1);S(Xy2)]letposeidon128_four_partial_rounds~matrix~ks~variant:_(x0,x1,x2)=letk0=VS.filter_cols(Int.equal0)ksinletk1=VS.filter_cols(Int.equal1)ksinletk2=VS.filter_cols(Int.equal2)ksinletk3=VS.filter_cols(Int.equal3)ksinletppow5v=[|v.(0);v.(1);[|S.powv.(2).(0)(Z.of_int5)|]|]inletx_vec=[|[|of_sx0;of_sx1;of_sx2|]|]|>VS.transposeinleta_vec=VS.(add(mulmatrix@@ppow5x_vec)k0)inletb_vec=VS.(add(mulmatrix@@ppow5a_vec)k1)inletc_vec=VS.(add(mulmatrix@@ppow5b_vec)k2)inlety_vec=VS.(add(mulmatrix@@ppow5c_vec)k3)inret@@to_list[S(Xy_vec.(0).(0));S(Xy_vec.(1).(0));S(Xy_vec.(2).(0))]endmoduleAnemoi=structletbeta=S.of_string(Bls12_381.Fr.to_stringBls12_381_hash.Anemoi.Parameters.beta)letgamma=S.of_string(Bls12_381.Fr.to_stringBls12_381_hash.Anemoi.Parameters.gamma)letg=S.of_string(Bls12_381.Fr.to_stringBls12_381_hash.Anemoi.Parameters.g)letdelta=S.of_string(Bls12_381.Fr.to_stringBls12_381_hash.Anemoi.Parameters.delta)letalpha_inv=S.of_string(Bls12_381.Fr.to_stringBls12_381_hash.Anemoi.Parameters.alpha_inv)letanemoi_round~kx~ky(x0,y0)=letx0=of_sx0inlety0=of_sy0inletg2_p_1=S.((g*g)+one)inletw_5=S.(subx0((beta*y0*y0)+gamma))in(* (1/5) *)letw=S.(poww_5(to_zalpha_inv))inletv=S.suby0winletu=S.(w_5+((beta*v*v)+delta))inletx1=S.(u+kx+(g*(v+ky)))inlety1=S.((g*(u+kx))+(g2_p_1*(v+ky)))inret@@pair(S(Xx1))(S(Xy1))letanemoi_double_round~kx1~ky1~kx2~ky2(x0,y0)=let*res1=anemoi_round~kx:kx1~ky:ky1(x0,y0)inletx1,y1=of_pairres1inlet*res2=anemoi_round~kx:kx2~ky:ky2(x1,y1)inletx2,y2=of_pairres2inret@@pairx2y2endlethd(Ll)=matchlwith[]->assertfalse|x::_->retxletassert_equallr=assert(eqlr);retUletequal:typea.arepr->arepr->boolreprt=funlr->ret@@B(eqlr)letbits_of_scalar?(shift=Z.zero)~nb_bitssx=letx=of_ssx|>S.to_zinletx=Z.addshiftxinletsx=S(X(S.of_zx))inletbinary_decomposition=Utils.bool_list_of_z~nb_bitsxinletbits=L(List.map(funx->Bx)binary_decomposition)inletpowers=List.initnb_bits(funi->S.of_zZ.(pow(of_int2)i))inletsbits=List.mapscalar_of_bool(of_listbits)inlet*sum=foldM(funacc(qr,w)->Num.add~qraccw)(List.hdsbits)List.(tl@@combinepowerssbits)inwith_bool_check(equalsxsum)>*retbitsletof_b(Bx)=xletget_checks_wire:boolreprt=funs->([],B(List.for_all(fun(Bx)->x)s))letinit_state=[]letwith_label~labelt=ignorelabel;tletget_result:'areprt->'aInput.t=funm->lets,r=minit_stateinletc=List.fold_left(funab->a&&b)true(List.mapof_bs)inassertc;(r,Input.default_check)