DMmO@` z5boF0hYNm9!}vnKc)rF=1pPLmN&A&S0T0q-QL$y}Ygd28&3^r}DlJGA%=KwV8c+zg zt(CFm8g{?vB5ypN70# zeYAcMTZ)~xPGsX+u0EY-DxD1rQ|IJetrXensK$G=u0Y??=1!{k%eN}fxUEyajguEt zWTT?!(91vL&n6@ougHQJflEQyWQct-v&MN?yA)KvdLHn{s M?bedOWm#lh}bT(TuXILAlxx-QJg#W32NsiQE5aYNhOB%`l{ zLIn_AAH9fEO?I*GTp{I&Z$~EvVx4};(~n>}8D-UAH`t}Zwn^bNFSrlX^@!p9@Ox1q zL|(*rx>lt;rXT&i!(sdSMP#*UaX*o02Pyn{lz?WpNVRzKLz=S!rX?jUur%<@&Wgg4 zoHLbQAjVBQK@e*_kzhRTquF}g4aT=B7`* qrY4n&XB&?t^HPfDu}u@J;{En zmlgX<<78uu#om?WhCR;3`DBpY?8k>2^F3MXCz>Dq>yFe4H+VQlE4?x|^jL61(ePXh z6YdHJrMy^RbgPNjr2G8_g`Mpv@Z!OMP2spo1P5sYwdFLnVxU+eZIlb=c|aj7AZbg* z@(KmC-pcKoV4-!dJZHi
nen |%Eq+XI|B z%&<}A(V_TMOymtfjVP1BS?m4l`i$L?YLPXtnn9@uSoj~iSP>Ey?a`)#z4J?IR+xL^ z+oDYRz&w#saMcyo7@;y50}k?E^_#EsbA-OTYi9^z>1r*?aK@-PgdRRF{Z$`=Ve{%{ z_)|)3cDZNl7^bfZM*EXC-RlBHx|9cXzlrSyp0iOX@@+n>iFQJT6-h1odyTBLnEfjm zc-O_goV2mR65%XWHzIUY^3ki+s$Es2ZRH##X2o?m)>!rdh~BNk?1D&lNMz%At}jXt zWIhUqy7q)-=2h3H9^I&97}uY*O$m_ZAh{`ppA@`CzP07>4)Y3ZT=tAyzl*#VqZe=X zdZuI#yG8}9VV#K9fs@gPNs1!xl2`Oyqp1IIl~8luRzYnJjoPRt7QquG+4-$|HQUZh z1Z#WcW5&84`Thc7(%Pwi RLXIAS_Ojq#+ zeZi5+n1>c!%a{j^5>l_Y`R9zyEF&J6*I#Kai0o>dV9rnKv`A4Tq*T!}V4@i4GXJ=k z P{n9E)9y? VR;zdc~{e zCy42^kl~;g>m<+NFVEHlZ{mV~)wLw$tfP_D2g*=7C*=j#(crss@=?PvR*EUCJ3|om zPceEsBog{ke};j{nQkbPgDInbUBfzJkSnP2y?FcjQ{4&|dGX##9&u9QNrz^fxLtI+ z$J5#5tWJ-_Wn#Jd%Qw*{I^ >CM$=WKhq>@H#jgHDO=-Gau`U(nC8TfGhq&)em1iTl|w~`WHNJV91|T?ElP(Q znsRii(Y)997y+IwF9EBP!r3W#*M+U~QBDufZ?m}?)Rirh1=c8lA|(vE6uy+SabtI< zy_XhDT@`?)WtZIN8IYG)-pe^Tk{b`qC}%kj4r|{Sswargw)jOqj*k;+YNoNTsKGFb zb?tMfm8n|rm|XChdj1KaO_B%FkpA^m {%4-?hHdAUdpBcNZ1!#p@i$3O(pm{U9U0%Xu<9Nu* zp3Yj}D}d4ThbT=a&sb@LG8!(86yyG0qo?l6;&hGy$u@Cr=45fZWIpBG$AXjElhYJV z#vZR5d3d-u95u>qmJX%w=C5aM#E#5RmH{-sQucW#O?h<#vk5bJF_}JhHIjr*B6Ikd z8$XFrvoP`%OGhRr5AjyFGxk{}l5!;+SwxrxV(K^Lfn&Odg>bn&-FiCtDLvyRXH&GZ zH(*%U!Mb#hI#WHCdNQQNb40N<_if$6tg2uc+4Hua9{kerpe82G*Idl26#UW-%JeBY z@D(k8^s358jc%d4^XZ0p%gngAlt>t{V@CG?lIliDHMD6Tu`D@c@7fmYd#Cv3?(-AG zW9vC!FYs(DVahtd8dZXRK~H!DeO1mBq_J62Mx4YIn0E(hTr6S2tvQr2dZ*W?n1D1O z`qu2lDGq>tC@P|Xi e!GctXb@SCRutx0qLF>t3 zuZ6#LFT;uFjXP=k4C!qh>}NN7LfA7LchHgR#r+pkA4~BDPah21X@MQdx0dx4S^&~t zs5656qWy-Laup<(2WfG}3fy=8y0=|o*d@<=5%vQR_(K{fhHVV623hb3REtl$V*MmU zM+9ZGYfQop*nUcZx8t;ND-o4gnv!__uRjvkY6I^@Fa(IF9Y>F=r`diElHi}J{<5g1 zM6TG=MY-%-DU7d)L3twUb=NKs#96z6jl!uS$%dKRf@d<%sn+m)$upYW6Ztp09;Nyj z=QJ}UUZli`d^R|naJ104>)e rvG(saURNh^PS)Q);FT4N`|8^J4=Q}%E5u=8O!1Vj?Jr40o~@7{ zTC9k`-( L#?BFR*LHU2K^(g4?f1@vbjid==3@`J_;1s` zQPJ+l!`AJYm_c4|!Crgv56rM+f|Dlr1aXl_+^B1X%GwpnWX&c)jzxO4vnOGZ`$NO= zl-LNI-XW@=%JlezT4jK8(yRor(EaN;mq=F4E1sVNpV7uTS`9@*l`jI`C|nr`9rCTT zr0-Zy7dnz|bf4Ayi6H{1RyIv%$m#L#KhzKKuF9)$bL6e)oa91t{t7|Tw_NbJXKli> zB&!itxxso;nyXz$*4@OS?!Wh!^=Y%<#8=!9zb5SB--LMI! pw z$BZvD@-del)7u%juZb@1DTe0fo`b%hTa7rgz+zCU;R(5jdJf`hGMgZPDBS*c1FnDL z|1J@quYr>Eu7=42>HMRXwpHw1_I;VuG>K$F*;@R!zgi83>^pj@DF`JSxmp!;MweX; zK3e<734jcJvp#@(@P}%;#asuNsLbGabFLHW#WkqoTv!?4S~fnD(YDAeSIvo6=*mUw zz7FfpztyQU+ZH(nR8XVZM6HUcTBU|-OMvp1(%kc}v$8{zx#5f05azfDVda`(>j$M? zJzs{k!rsfg(pDz&f5hE#UhWhVJp9WYbSxYBL}R|mY`7z5W;p66>#q #OGG69~7=vG#^vV`YcK=&$?!{piDS6~^*rea4L_tB-%yoIwXgPm@`u*8^V~b z*pf;}B$exe84i_1G9)5rlfS)kCL5{xJP_#wb@qF|&KS=pa`F6arR`)NU+!*E#E>P( za6!o}1}74Kbhkn6;7wTN$ ADunsj`Am%gfQm=$;+`LUu1eq6kxiH$i z6DX;(>30hbIZX1MikF&i)3 5= Z z$TP{;z!5G*XEM3Pw)H5t{$9NYqIIdEb~zL!m 4Fj ?*&-yjaY2Lq^EW+%abGt=Lj6$o&gayk4wzQ7M!@ zm6KW5((VvP0#(JouBH1vY^zgM;WyD?b357Ug+ua?Y1EyV6LcP)vGP%?Sl+>f9GtSH z&+vMVvbBJtkMFCCsX>rW>c(D$3Z$j+I{3x%9sg`*_5tyETu6xU>Usi6uefVAOkq## z#EQXdHeLqJUs)%l>@2ZjlYaD=PxvXhydNAi5XR{BdBMVn8u(4ZtqwT1l=)!|ide
+r8EV8Is9Kt`r*)n3t@89L*L*(8h+?W@%{x!-Fz3^2 zN?~wj=(T)1`L3bUzn!W7m7)_b3%|EX?H?uUPSe&!^L2W}D0MR*nphWY6O{Z^lZQo+ z#7pMSx>rvw$~`;jyK57NxO$s6R!&GPGDi{oWQI||DT2P86%Lz-NY{tC)g2y=B~p0g ztSas9TMo{v{%%wLB#jeAzbKN~(3I(-3xMke{MwO7xukfU(R zQR2r#Z)7|IXx5)>=aqZr{muZra@CvKbGuxBm0t2a+ z!{Cg+tIi{P?OZ E zq(ahG9tW~Vn xJ2d7S $S-F(Qisnze3QCfb^p+5X$38@4)grl{KgqN zbxPp@BkWFjhM?u7{U^DQE}n1i0i=UUr0ARZ)RrYouYwHLN9_#tGUwI4Vh6bhioI z6BE$ZIIRBL#q>v5?u6B`ND;c`wleA06u3HD0X0sRC1ioUM^TpyGIo8=Po6Ui#yX$D zeq2UZ@Bs!YqUP!j0dkN$qly##=}rA+=;P *?3LJ@t) R8cYBV8oXnCG{WW)g&cDz_d9DAU+L z{Q3*6pD%fgfG@-oQ1h~p=)p+_3_g>{C_+uHM-9QPZ>qQm!W=t~B$IWm$V)fCc_YO+ ztRSrc=R`B<4>4>OUS0;ZE4=?pM+E4eds*Kry(;W?kgGuj?? z;MvI%%_Q%eJDL`H$t)SEt)Ifn6hOXwq3!|r1%*4&zY5s8E~Aa(%qZOa2I-9+(}zvG zBw&gV%S)`3(aKpjCa|zkbKkRxjd+OEbfsWoNc-5@ojLzA1?&zAPKma7h1!Xv0`tK1 zr_C`U#vt~`qbe6pkf0oKhnuA%NX43@q?x>-eVpht?Vvhs!$&-6qy%`rsw2ze2h{!f z6sAr(E44|4xtH1)1|!kF)g7-u4y`v3WO$&liRpn#w`KTFVNQMUW}Uo02zdENKZ3b$ zqez$hiZe7z-HwJCvI)C1cHd8Wd1WsB&82DY3<-?SK;YApFfPOM(G^CYuzuLF2f@kF ztYydc)g8}Z|K&DC12>&7AxV*eL#xz|__QG!iyJ-rB&u7*gBDLNo_t$3Amsn*_vUZ< z2FI%{TN|!5Uc3so1ZHr!^3#Wtk3akIV*4<$4H3-i!3&k-eeSZ{o|KJ79dxqgkWM|L zg+{A(b^Oq5a ?2To>zKK75%opG&?`P|LF zC?wx5wk_rh)fO=WXi;4(rSOMGg_DZuw<@BnY2&7KRXx_S2DAy(iCxa{O&79lOKuO! zR-01_wF>-^GRi_HdC?{^Ixfzx0JccWvH8TinVmL1b!^4!tUKYNg!73IpYGr}A<`Qm z{J_>P `u7P4Z*t^4>-C4BLtcvNC-!6U+_Cym)8;$2(e{p4pG|a`SUDSS) zIv^&drkwojRxL&Fj$L@|dvjkB>tM98HP!|lf-0>b&d!Xfz6BoXJoD=@W=(a(@(iaR zawI9h_jiyLw*Ng>ZDXv Jpsdk~%keWxQMclTPyMep&F zU^ yuTu#S6t`# zEP~UFS{wA=L>Oj?vS}=mo!E2rKl=?ck-7941Kuq!JF~zx0I86zLmb2Ik#R#B%}oY7 zx{#u(aUnR`yK_&hq$a?C Y2@b}5QLox)7EPkpP^N%pYP>1e-H-zsCLhfF zD L(i^%f!aw^h;cfUHJ!lQ _pZrrga&?8Nx?PxR$)zh`Bo6v z2^CeQwiC4%^}c17xeYZfWI={S?%o2@@{y&FBGt&wmVY23Uy9RjM5N8jwogVc#zrKg z_=|rTe0tU^G)i(h+uz_7)r)pD%yG1Yh-oQ0p>eiSwVcp(xt(2oV;a>1)O%v_9W~a6 z^W@#AF}6#ks=myXTMY|iSiz7WTr*oWn7QkHXN3D|{kdfxP>-_D_k}~u+&ZSy<+CrF zN%0}d@l~_2hX(JWp)K?_|I2xDbw(rCTOHEDdfyk<%s9Y;+Y{jvj^J3@bc4(Z3YtLP z$vQ!FH(Dcl=!Zc{-E<-V>F7dTE=vCAGj??Gy>B`%2~B^ #kjWL1{jmUa)tvG5LO9hnPn+T~61tD*U9=MNO{eBSQ; zwpn<4nHRS?RQgY+4ng~N1W0aBMiHV#Q}ciB-mk)RF$P{H=VV*7E~`ATOf6YMq*~_g zP)TKZOUJ+V7n-yXmfzJuI5u=$Ev17`;T!2mv%{6(K}*srwgLp+U*}kBWo1gJM2Y#g z_8zaTaLXT!DFA$kJHY&VvWW$g$Z%(J+mF9*3|g;Lo0^=IRU@w(j@Ia9retR}w)q%w zUj`)Rmf(4!5>w72-z>R?2L=qEMFt)Z`KYq&1K}FGOQ{CLiD)D2 vPy;ATu zd*VgB7m?j&f1XA)KJXt9m)y&P3B%{y3kmY_;GRLhr57z_8Me}31*D~}qT7%r +;LsU;){ z_d}=i%|aXen2DP4{|UJcM)4x4b#WUc8u_8)LiV2wJG@F3pZA=*cO;k8yeoD|_GGO& zzA>>^@yeC<<4vvXrg6T+Q&bb?w}eZ6=(zFuVLbAQ5t{SR8US@EjC^Dzy)l_qPDV+i zr?HJ3A=>aLty2nv-9C#*qiOH?5T`po-jn!kITf$k*ttg! >@TC;y}sPECe^R9^~m JxM-#$0722_RHz)7CE3-Hx*^Z`nKVeH8H?U6Ak9(e#c8 zpL2NcLQeTi+<8HD2nHN$h6^TT<9%dJ7ZN2+3-O8RVkWemKQ9c6c(%4rXg?xh>NR2S z^ANSMkN)SQm0F*b>OOv*M7JiI!?rF+GHuYd6zjrGRdMaqw0uW?=Y!T){pWVdPutr0 zv4FvM^2*PH_}g*i6M ?@(>DI$K{pYb@^4)g;A8Vm@k_HjoQMFnL|L4}~0Z<#WSh zFK`(*>2&<~#MGBWk8Xng4J*aHgZUn ;2h`6gn|$JOcxIRB)N!zKj)oBy zM;919uU$If{#Q$JLhP~9D%R*Zc`esLt)ZOD vbQq5*;*4;^@dSPPr?U7$SRc&cIHm6&GKMePxK4{JLgw5x!RyzeQ&p~ zNCllYY-z<6-AA%$x6Tg3C+>1X`#{)CH?hh(#P!RCeP3d=C!*^Coa&=gPHXhtoyBz| zz-zh9-EySn0 e_*v&&j`LppW|O-_;oF&f2dQ|1 -^7_q?n}ju}g+T$w_LX*F7u4jlkYoP!~pDFjnhxACt?0J-N%< z4e9VZuqCg+J7^gpou(&cVcZ=G&16;H2b2`^ZrDio9#p5{;KYJt^Mg`BcVojRItEjN zIT{de(8{hrv6fhMUvq}{U`oqQN?hkC6 *O! k7r~rp$<0z|D?^l z7xLkIG(P?wB_nPE_T3oqiM|4iJ2=a(Gg!**t5-`BF|1fbLUJ@(hdKt<+4DXMoHRmq zIn7o2am9!iHr2Z(*r_cjZ dA_kQiJTRf9Fmm_Q9eBrpcdoLHEEe$2NQ@ zG%jniCxRPjX{ IZV3}7`U+ yK|BTR}dM|g+z<_j@DVS-6Ut;7VbU# zscMSUfks {xZ+|6L7WgUw>z2N>A@5?(pd z`xxoIo=L*#( 0UyW@ngwKDFl2WsB;9} z*58=@^#HbTh}iL;SwDOT_@^`CL$r^ti>r>=)Q6ybnO}P#Bi`sMq?ehe#pwJX7mf^D zEgW(>XvJ<=nQI?YtSR(9U B^r|0g-9|}; z@B`8oO$)wsQUF`)oPB&v%k{d-HJzCx-YMg4-cGIt{w%9BGsb6P^p5h_6wfWd3I3pm zNE76^Osb*IrWq$hI6Fyvh_LadM&}cn91pR`Pqp};GF5n^)by-^(ELZ&f>0ZMO6E}o z8$o-eF~VBWlW&?xRE&ty%-9P jFo9Vw1OMl`nG$}4bPhp6&yzexEy*lTL# zv7$BvYnDP#?W@mXwGGaL)5H%;p^4W!f~>XK;?NusR18`AA_3U~XEqZ>xNA5&fv>JT zSRXZlQ+nNiFb8;&)I(R}<%w+V-rbg~>s4HU{k~9gBh))ZWjlV+m*!AKC?*BCD%r(> zv_`}@cs^(Rp|qxk_NJf^#OWkUxprZ>$vGbEci-vTve>pYxS}kDfLf ~v*9f&SvjZWG~M3@gdL>9J{AITRKZ!C zs4uX5oVCB&LwJ7xwb3CR@; hLka*9U`WONmCaG>Nd5fNxr!*~ALFr#Y#0i+Ckw8r}#vxQZqwtVn8& zpU6XhhhLu?;FWL0n>wzZ5`LYb0r^Tr&A$)LJsF30#jIyYLSE+m-?u{#LGM@PNZ%9J z?|bV@TJgt(07)=XDk?uh%^6b+t4Z^ADlWuqSW=u6v1m&}vDmJ*@u2%;M?Mq1oQBVd z#eQBj)~V#9k*yPvfxiv0i5*?kVqd8Xup0#|&5LuT=?uE<1bX+5-1wH)P;EvDl-Cr= zK$paeLaB4%0E}zI>#aNk`y_&js1i ;y=wLZ$y2jGE}`>#pm{8 z5rzCtEmd7A-7DZ15ydP%m(cJ}n8DR}dyVEThV^x6oKq1^t!ijlBNcpSu#sD7)BA)= z*X)u*g}{)*uo>$jAOBb>uP7ku@e{FxzuYC?c29X-DfB11 Jzf8{zy&CvKFz| z>QiY+v`Mfz8!uq1RV78{+_PWxtXQz#%a+`|cNO>ei;bzy+v4iik>tC)^ns|~o?U)} zCC&(8cBlHkVgDlR-><+|A9a{5zES@g>U)%np7#cP2%0v^S-;R0TP*Q__LdLOZ`5Rd z+KuniN|iS5@;*{YlZ)BN0brJFW#y4OKFc~|0rnad;b_Xkhm-f%O>J_Yn&Kw{NSCEb z$8^Q*+}JQxts? edu#8C)qpH}<2?(Dqu>Q8bS8#&Bv9(z-P%0ti4b)FmFue|#h5_5>2 z_n(=HIYf8*jgp2NPu7h)eauy646)iA)CY|&lf-YhmsfnIoCGYUa4k4w8*^OU0v=u| zwMD-pmvat}*|@c >puK`=aAd(GB1 m(2aP zYQtN2%pp!YzG<-BJ9x|?p8O_PejJgxO@?{T?cM_%(g*Mlkqf@`_J0YH`LNSPN3#Yf zmHSNGX;v;p!CnlJ7|%(Fki)DURxL$FY>hMxpMc%$lj(ndMm}ca&R!FE#-0k}#p^2# z=EknI%FH#f8s{)s0XBKgD>Nk-wDcJf9*^rQyvvNilibEe9&?+|{y9p1+9|pYbmZGr zE+0c ZsVBi$I zW50ru4i3qM13`X-qFPu=AUZ4QCvsEUC*Hmo*NwiRSW6T*=q#}jw~|e2h^aFk!UP5{ zxl&2gu&Zau>N?QazY0D%%Jr~`J8R~iiLSBY7m}yUK1z=qD!@eeDDc0Ttqz~cOt}`s z?23qqJ3eotmx7S %3XTvqxb$H26$1??LnE4 z` w0Nf(D$ ks uF1dAC1pQN$qdWKdWBBE5ZstLR|Jz9KzNh%IJ^uO6KmP^bnK$Y`Is^b%YqY)q literal 0 HcmV?d00001 From 88a5b949040eecb00b462193ddcada2acd2adee7 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Wed, 17 Sep 2025 22:39:53 -0400 Subject: [PATCH 07/11] CR fixes --- crypto/batchverifier.go | 2 +- crypto/batchverifier_bench_test.go | 21 +++++++++++---------- crypto/gobatchverifier.go | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/crypto/batchverifier.go b/crypto/batchverifier.go index d494f62c13..cd0168ae1f 100644 --- a/crypto/batchverifier.go +++ b/crypto/batchverifier.go @@ -101,7 +101,7 @@ func MakeBatchVerifierWithHint(hint int) BatchVerifier { func makeLibsodiumBatchVerifier(hint int) BatchVerifier { // preallocate enough storage for the expected usage. We will reallocate as needed. - if hint < minBatchVerifierAlloc { + if hint <= 0 { hint = minBatchVerifierAlloc } return &cgoBatchVerifier{ diff --git a/crypto/batchverifier_bench_test.go b/crypto/batchverifier_bench_test.go index f293d4cb75..8bcb9ff69b 100644 --- a/crypto/batchverifier_bench_test.go +++ b/crypto/batchverifier_bench_test.go @@ -44,13 +44,13 @@ func randSignedMsg(t testing.TB, r io.Reader) (SignatureVerifier, Hashable, Sign func BenchmarkBatchVerifierImpls(b *testing.B) { partitiontest.PartitionTest(b) - bN := 100 + numBatches := 100 batchSize := 64 - msgs := make([][]Hashable, bN) - pks := make([][]SignatureVerifier, bN) - sigs := make([][]Signature, bN) + msgs := make([][]Hashable, numBatches) + pks := make([][]SignatureVerifier, numBatches) + sigs := make([][]Signature, numBatches) r := cryptorand.Reader - for i := 0; i < bN; i++ { + for i := 0; i < numBatches; i++ { for j := 0; j < batchSize; j++ { pk, msg, sig := randSignedMsg(b, r) msgs[i] = append(msgs[i], msg) @@ -59,14 +59,15 @@ func BenchmarkBatchVerifierImpls(b *testing.B) { } } - b.Log("running with", b.N, "signatures in", len(msgs), "batches of", batchSize, "signatures") + b.Log("running with", b.N, "iterations using", len(msgs), "batches of", batchSize, "signatures") runImpl := func(b *testing.B, bv BatchVerifier, msgs [][]Hashable, pks [][]SignatureVerifier, sigs [][]Signature) { - b.Logf("Running %T with %d batches", bv, min(b.N, len(msgs))) + b.Logf("Running %T with %d iterations", bv, b.N) b.StartTimer() - for i := 0; i < min(b.N, len(msgs)); i++ { - for j := range msgs[i] { - bv.EnqueueSignature(pks[i][j], msgs[i][j], sigs[i][j]) + for i := 0; i < b.N; i++ { + batchIdx := i % numBatches + for j := range msgs[batchIdx] { + bv.EnqueueSignature(pks[batchIdx][j], msgs[batchIdx][j], sigs[batchIdx][j]) } require.NoError(b, bv.Verify()) } diff --git a/crypto/gobatchverifier.go b/crypto/gobatchverifier.go index 43656ee260..11f0b0621d 100644 --- a/crypto/gobatchverifier.go +++ b/crypto/gobatchverifier.go @@ -47,7 +47,7 @@ type ed25519ConsensusBatchVerifier struct { } func makeEd25519ConsensusBatchVerifier(hint int) BatchVerifier { - if hint < minBatchVerifierAlloc { + if hint <= 0 { hint = minBatchVerifierAlloc } return &ed25519ConsensusBatchVerifier{ From acc256d8d5400558f3f0b67ec26f338e896e670d Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Wed, 17 Sep 2025 22:46:00 -0400 Subject: [PATCH 08/11] CR fixes --- crypto/batchverifier_bench_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crypto/batchverifier_bench_test.go b/crypto/batchverifier_bench_test.go index 8bcb9ff69b..63df5e8833 100644 --- a/crypto/batchverifier_bench_test.go +++ b/crypto/batchverifier_bench_test.go @@ -62,8 +62,7 @@ func BenchmarkBatchVerifierImpls(b *testing.B) { b.Log("running with", b.N, "iterations using", len(msgs), "batches of", batchSize, "signatures") runImpl := func(b *testing.B, bv BatchVerifier, msgs [][]Hashable, pks [][]SignatureVerifier, sigs [][]Signature) { - b.Logf("Running %T with %d iterations", bv, b.N) - b.StartTimer() + b.ResetTimer() for i := 0; i < b.N; i++ { batchIdx := i % numBatches for j := range msgs[batchIdx] { @@ -71,10 +70,7 @@ func BenchmarkBatchVerifierImpls(b *testing.B) { } require.NoError(b, bv.Verify()) } - b.StopTimer() } - b.StopTimer() - b.ResetTimer() b.Run("libsodium_single", func(b *testing.B) { bv := makeLibsodiumBatchVerifier(batchSize) From dd9c5305eebdfcaae2dbeac5581296c59822dc4d Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Wed, 17 Sep 2025 22:58:01 -0400 Subject: [PATCH 09/11] CR fixes --- crypto/gobatchverifier.go | 59 ++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/crypto/gobatchverifier.go b/crypto/gobatchverifier.go index 11f0b0621d..20ab92ed8a 100644 --- a/crypto/gobatchverifier.go +++ b/crypto/gobatchverifier.go @@ -140,23 +140,18 @@ func isCanonicalPoint(p []byte) bool { // Test for the two cases with a non-canonical sign bit not caught by the // non-canonical y-coordinate check above. They are points number 9 and 10 // from Table 1 of the "Taming the many EdDSAs" paper. - for _, invalidEncoding := range [][32]byte{ - { // (−0, 1) - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - }, - { // (-0, 2^255-20) - 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - } { - if bytes.Equal(p[:], invalidEncoding[:]) { - return false - } + if bytes.Equal(p, []byte{ // (−0, 1) + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + }) || bytes.Equal(p, []byte{ // (-0, 2^255-20) + 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }) { + return false } return true @@ -164,40 +159,40 @@ func isCanonicalPoint(p []byte) bool { // from libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c ge25519_has_small_order var smallOrderPoints = [][32]byte{ - /* 0 (order 4) */ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0 (order 4) */ { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - /* 1 (order 1) */ - {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 1 (order 1) */ { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 - (order 8) */ - {0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, + (order 8) */{ + 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05}, /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 - (order 8) */ - {0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, + (order 8) */{ + 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a}, - /* p-1 (order 2) */ - {0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* p-1 (order 2) */ { + 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, - /* p (=0, order 4) */ - {0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* p (=0, order 4) */ { + 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, - /* p+1 (=1, order 1) */ - {0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* p+1 (=1, order 1) */ { + 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, } // hasSmallOrder checks if a point is in the small-order blacklist. -// Based on libsodium ge25519_has_small_order. +// Based on libsodium ge25519_has_small_order, but this version is variable-time. func hasSmallOrder(p []byte) bool { if len(p) != 32 { return false From f317118dff61205851616d875e32e7f4362658d4 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Thu, 18 Sep 2025 14:32:12 -0400 Subject: [PATCH 10/11] use [32]byte for hasSmallOrder and isCanonicalPoint --- crypto/batchverifier_bench_test.go | 6 +++--- crypto/gobatchverifier.go | 24 ++++++++---------------- crypto/gobatchverifier_test.go | 8 ++++---- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/crypto/batchverifier_bench_test.go b/crypto/batchverifier_bench_test.go index 63df5e8833..c676a5265e 100644 --- a/crypto/batchverifier_bench_test.go +++ b/crypto/batchverifier_bench_test.go @@ -105,19 +105,19 @@ func BenchmarkCanonicalityCheck(b *testing.B) { b.Run("pubkey_check", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = isCanonicalPoint(pubkeys[i%maxN][:]) + _ = isCanonicalPoint(pubkeys[i%maxN]) } }) b.Run("signature_R_check", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = isCanonicalPoint(sigs[i%maxN][:32]) + _ = isCanonicalPoint([32]byte(sigs[i%maxN][:32])) } }) b.Run("both_checks", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = !isCanonicalPoint(pubkeys[i%maxN][:]) || !isCanonicalPoint(sigs[i%maxN][:32]) + _ = !isCanonicalPoint(pubkeys[i%maxN]) || !isCanonicalPoint([32]byte(sigs[i%maxN][:32])) } }) } diff --git a/crypto/gobatchverifier.go b/crypto/gobatchverifier.go index 20ab92ed8a..3c695eafa1 100644 --- a/crypto/gobatchverifier.go +++ b/crypto/gobatchverifier.go @@ -26,7 +26,7 @@ import ( // with additional checks to reject non-canonical encodings and small-order public keys. func ed25519ConsensusVerifySingle(publicKey []byte, message []byte, signature []byte) bool { // Check for non-canonical public key or R (first 32 bytes of signature), and reject small-order public keys - if !isCanonicalPoint(publicKey) || !isCanonicalPoint(signature[:32]) || hasSmallOrder(publicKey) { + if !isCanonicalPoint([32]byte(publicKey)) || !isCanonicalPoint([32]byte(signature[:32])) || hasSmallOrder([32]byte(publicKey)) { return false } @@ -58,7 +58,7 @@ func makeEd25519ConsensusBatchVerifier(hint int) BatchVerifier { func (b *ed25519ConsensusBatchVerifier) EnqueueSignature(sigVerifier SignatureVerifier, message Hashable, sig Signature) { msgHashRep := HashRep(message) - failedChecks := !isCanonicalPoint(sigVerifier[:]) || !isCanonicalPoint(sig[:32]) || hasSmallOrder(sigVerifier[:]) + failedChecks := !isCanonicalPoint(sigVerifier) || !isCanonicalPoint([32]byte(sig[:32])) || hasSmallOrder(sigVerifier) entry := ed25519ConsensusVerifyEntry{ msgHashRep: msgHashRep, @@ -114,11 +114,7 @@ func (b *ed25519ConsensusBatchVerifier) VerifyWithFeedback() (failed []bool, err // Check that Y is canonical, using the succeed-fast algorithm from // the "Taming the many EdDSAs" paper. -func isCanonicalY(p []byte) bool { - if len(p) != 32 { - return false - } - +func isCanonicalY(p [32]byte) bool { if p[0] < 237 { return true } @@ -132,7 +128,7 @@ func isCanonicalY(p []byte) bool { // isCanonicalPoint is a variable-time check that returns true if the // 32-byte ed25519 point encoding is canonical. -func isCanonicalPoint(p []byte) bool { +func isCanonicalPoint(p [32]byte) bool { if !isCanonicalY(p) { return false } @@ -140,17 +136,17 @@ func isCanonicalPoint(p []byte) bool { // Test for the two cases with a non-canonical sign bit not caught by the // non-canonical y-coordinate check above. They are points number 9 and 10 // from Table 1 of the "Taming the many EdDSAs" paper. - if bytes.Equal(p, []byte{ // (−0, 1) + if p == [32]byte{ // (−0, 1) 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - }) || bytes.Equal(p, []byte{ // (-0, 2^255-20) + } || p == [32]byte{ // (-0, 2^255-20) 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }) { + } { return false } @@ -193,11 +189,7 @@ var smallOrderPoints = [][32]byte{ // hasSmallOrder checks if a point is in the small-order blacklist. // Based on libsodium ge25519_has_small_order, but this version is variable-time. -func hasSmallOrder(p []byte) bool { - if len(p) != 32 { - return false - } - +func hasSmallOrder(p [32]byte) bool { for _, point := range smallOrderPoints { if !bytes.Equal(p[:31], point[:31]) { continue diff --git a/crypto/gobatchverifier_test.go b/crypto/gobatchverifier_test.go index ad94fb9855..36ed799fab 100644 --- a/crypto/gobatchverifier_test.go +++ b/crypto/gobatchverifier_test.go @@ -188,13 +188,13 @@ func TestBatchVerifierFilippoVectors(t *testing.T) { for _, v := range vectors { A, err := hex.DecodeString(v.A) require.NoError(t, err) - require.Equal(t, !slices.Contains(v.Flags, "NonCanonicalA"), isCanonicalPoint(A)) - require.Equal(t, slices.Contains(v.Flags, "LowOrderA"), hasSmallOrder(A)) + require.Equal(t, !slices.Contains(v.Flags, "NonCanonicalA"), isCanonicalPoint([32]byte(A))) + require.Equal(t, slices.Contains(v.Flags, "LowOrderA"), hasSmallOrder([32]byte(A))) R, err := hex.DecodeString(v.R) require.NoError(t, err) - require.Equal(t, !slices.Contains(v.Flags, "NonCanonicalR"), isCanonicalPoint(R)) - require.Equal(t, slices.Contains(v.Flags, "LowOrderR"), hasSmallOrder(R)) + require.Equal(t, !slices.Contains(v.Flags, "NonCanonicalR"), isCanonicalPoint([32]byte(R))) + require.Equal(t, slices.Contains(v.Flags, "LowOrderR"), hasSmallOrder([32]byte(R))) } }) From 0e95eacbf0ea10432d7003df9a849a74cb9965f8 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Thu, 18 Sep 2025 14:38:59 -0400 Subject: [PATCH 11/11] update ed25519ConsensusVerifySingle for [32]byte --- crypto/gobatchverifier.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/gobatchverifier.go b/crypto/gobatchverifier.go index 3c695eafa1..46fcd0cae5 100644 --- a/crypto/gobatchverifier.go +++ b/crypto/gobatchverifier.go @@ -24,13 +24,13 @@ import ( // ed25519ConsensusVerifySingle performs single signature verification using ed25519consensus, // with additional checks to reject non-canonical encodings and small-order public keys. -func ed25519ConsensusVerifySingle(publicKey []byte, message []byte, signature []byte) bool { +func ed25519ConsensusVerifySingle(publicKey [32]byte, message []byte, signature [64]byte) bool { // Check for non-canonical public key or R (first 32 bytes of signature), and reject small-order public keys - if !isCanonicalPoint([32]byte(publicKey)) || !isCanonicalPoint([32]byte(signature[:32])) || hasSmallOrder([32]byte(publicKey)) { + if !isCanonicalPoint(publicKey) || !isCanonicalPoint([32]byte(signature[:32])) || hasSmallOrder(publicKey) { return false } - return ed25519consensus.Verify(publicKey, message, signature) + return ed25519consensus.Verify(publicKey[:], message, signature[:]) } type ed25519ConsensusVerifyEntry struct { @@ -105,7 +105,7 @@ func (b *ed25519ConsensusBatchVerifier) VerifyWithFeedback() (failed []bool, err if b.entries[i].failedChecks { failed[i] = true } else { - failed[i] = !ed25519ConsensusVerifySingle(b.entries[i].publicKey[:], b.entries[i].msgHashRep, b.entries[i].signature[:]) + failed[i] = !ed25519ConsensusVerifySingle(b.entries[i].publicKey, b.entries[i].msgHashRep, b.entries[i].signature) } }